4
\$\begingroup\$

I am working on a project to automate utilities of our application on Linux. The utilities are basically chunks of programs with specific options for specific tasks. They are run like UNIX commands. We need to validate command outputs and at times the files generated by them.

The automation needs to cover all options for each utility. As per the plan each utility will have its own .pl script and each option will be in a subroutine. The common functions like checking command output and verifying output files are in a separate module.

Please comment on how this can be made better.

This is a function to test one of the utility options:

sub exportMeasUtil01 {
    my $test      = 'exportMeasUtil01';
    my $test_name = "exportMeasure meas, intx intxstring, out";
    begin_log( $test, $test_name );

    #use the copy function from the File::Copy module
    copy ("$INPUT/exportMeasure/DESSTEPS_32138_salesv.csv.rpl",           "$DOMAINCOPY/input/salesv.csv.rpl") or die "Copy failed: $!";

    #remove all in processed dir
    unlink glob "$DOMAINCOPY/input/processed/*";

    my $command1 = "loadmeasure -d $DOMAINCOPY -measure salesv";
    my $output1 = `$command1`;
    my $pattern1 = "loadmeasure completed successfully";
    my $check1   = check_output( $output1, $pattern1, $test, $command1 );
    do { check_teststatus( $test, $test_name ); return; } if $check1 != 0;

    my $check2 = checkFilePattern($test, "$DOMAINCOPY/input/processed", "salesv");
    do { check_teststatus( $test, $test_name ); return; } if $check2 != 0;

    my $command2 = "exportMeasure -d $DOMAINCOPY -out $OUTPUT/exportMeasure/$test.out -meas salesv -intx clssweek";
    my $output2 = `$command2`;
    my $pattern2 = "exportMeasure completed successfully";
    my $check3 = check_output( $output2, $pattern2, $test, $command2 );
    do { check_teststatus( $test, $test_name ); return; } if $check3 != 0;

    checkFilePattern($test, "$OUTPUT/exportMeasure", "$test");
    check_teststatus( $test, $test_name );
}

Sharing some of the module functions:

### Verify command output. Look for a pattern in the Output, if found test status is Pass else failed. Log the status and output ###
sub check_output {
    my ( $output, $pattern, $test, $command ) = @_;
    my @notFound;
    my @pattern = split( /\,/, $pattern );
    foreach (@pattern) {
        if ( $output !~ /$_/s ) {
            push @notFound, $_;
        }
    }
    if ( @notFound != 0 ) {
        rename "$logDir/$test.log", "$logDir/$test.err.log";
        open my $FH, ">>", "$logDir/$test.err.log"
          or die "Cannot open '$logDir/$test.err.log'\n";
        print $FH "TEST COMMAND :  $command \n";
        print $FH "Test Command failed\n";
        print $FH "$HRLINE\n";
        print $FH
          "The pattern : @notFound was not found in the command output\n";
        print $FH "OUTPUT :\n $output\n";
        print $FH "$HRLINE\n";
        close $FH;
    }
    else {
        open my $FH, ">>", "$logDir/$test.log"
          or die "Cannot open '$logDir/$test.log'\n";
        print $FH "TEST COMMAND :  $command\n";
        print $FH "Test Command passed\n";
        print $FH "$HRLINE\n";
        print $FH "Command Output :\n $output\n";
        print $FH "$HRLINE\n";
        close $FH;
    }
    return @notFound;
}

sub checkFileExists {
    my ( $test, $dir, @files ) = @_;

        foreach $file (@files) {

                if ( -f "$dir/$file" ) {
                        open( LOG, ">>$logDir/$test.log" );
                        print LOG "$file exists in $dir\n";
                        close(LOG);
                        return;
                }
                else {
                        rename "$logDir/$test.log", "$logDir/$test.err.log";
                        open( LOG, "$logDir/$test.err.log" );
                        print LOG "$file not found in $dir";
                        close(LOG);
                        return 1;
                }
        }

}
sub checkFilePattern {
  my ($test,$dir,$filePattern) = @_;
  opendir(MYDIR, $dir) or die "$!";
  if (grep {"$filePattern"}  readdir (MYDIR)){
      open( LOG, ">>$logDir/$test.log" );
            print LOG "file with pattern $filePattern exists in $dir\n";
            close(LOG);
            return;
        }
  else {
            rename "$logDir/$test.log", "$logDir/$test.err.log";
            open( LOG, "$logDir/$test.err.log" );
            print LOG "file with pattern $filePattern not found in $dir";
            close(LOG);
            return 1;
        }

close MYDIR;
}
\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

Aside from various style issues which are almost trivial to fix, the big issue is the command that you run in backticks. You construct a single string with variables from outside the scope. You can use a module such as Capture::Tiny to handle all the security and cross platform issues. Since you look like you might be passing data between external sources, taint checking may be appropriate. I cover some of this in Mastering Perl.

You can also reduce some print statements with here docs:

         print $FH <<"HERE"
     TEST COMMAND :  $command
     Test Command passed
     $HRLINE
     Command Output :
     $output
     $HRLINE
     HERE
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.