5
\$\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;
}
dfhwze
14.1k3 gold badges40 silver badges101 bronze badges
asked Aug 14, 2016 at 14:49
\$\endgroup\$

1 Answer 1

5
\$\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
community wiki

\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.