#======================================================================= # Purpose: Compare production and test version SEASABS/TSUpdate products # for a group of series for acceptance testing. # # Required: It is assumed that you have a version of Perl installed from # the ABS software portal. # # Examples: For all command line arguments and options, see the tutorial # and examples by executing this script at the DOS command prompt # with no input arguments, e.g. simply type "acctest_cmpproducts.pl". # #======================================================================= # Force all variables to be declared. use strict; # Import module for command-line inputs. use Getopt::Std; my (%options, $iam, $version, $lastmod, $who, $lineh, $infprod1, $infprod2, $inftest1, $inftest2, $infsknprod, $infskntest, $outfile, @infprod1lines, @infprod2lines, @inftest1lines, @inftest2lines, @infsknprodlines, $line, @infskntestlines, @results, $line1, @series1, @series2, $i1, $j1, $k1, @sknlines1, @sknlines2, $ii1, $ii2, $line2, $i2, $j2, $k2, $i, $j, $k, @numsknlines1, @numsknlines2, @a, @b, $sknresults, @diff, %count, $e, $numdiff, $sknstatus, $sknaction, $prodresults, @series_pd1, @pdlines1, @numpdlines1, @series_pd2, @pdlines2, @numpdlines2, $prodaction, $prodstatus, $Ys1, $Ps1, $Os1, $Cs1, $Ss1, $Ts1, $Ye1, $Pe1, $Oe1, $Ce1, $Se1, $Te1, $Ys2, $Ps2, $Os2, $Cs2, $Ss2, $Ts2, $Ye2, $Pe2, $Oe2, $Ce2, $Se2, $Te2, $Y1, $Y2, $P1, $P2, $O1, $O2, $C1, $C2, $S1, $S2, $T1, $T2, $diffresults, @pdiff, $tdresults, @series_td1, @series_td2, @tdlines1, @tdlines2, @numtdlines1, @numtdlines2, $tdstatus, $tdaction, $tdresults, @tdiff, $tdiffresults); #----------------------------------------------------------------- # Specify command-line inputs. %options = (); getopts("a:b:c:d:e:f:o:",\%options); # Print software description. $iam = 'acctest_cmpproducts.pl'; $version = '1.0'; $lastmod = 'last modified 05-04-2006'; $who = 'Frank Masci'; if (!%options) { print "_________________________________________________________________________\n"; print "$iam, Version $version\: $lastmod by $who\n"; while (defined ($lineh = )) { if ($lineh =~ /RRR/) { next; } $lineh =~ s/^#\s(.*)/$1/; if (! $lineh) { $lineh = " \n"; } print "$lineh"; } print "_________________________________________________________________________\n"; exit 0; } print "\n Executing $iam; Version $version\: $lastmod\n"; #----------------------------------------------------------------- # Define variables from command-line inputs. $infprod1 = $options{'a'} || die "\n*** Input products file 1 from production " . "version not given (-a ); quitting...\n"; $infprod2 = $options{'b'} || 'null'; $inftest1 = $options{'c'} || die "\n*** Input products file 1 from test " . "version not given (-c ); quitting...\n"; $inftest2 = $options{'d'} || 'null'; $infsknprod = $options{'e'} || die "\n*** Input series knowledge file from " . "production version not given (-e ); quitting...\n"; $infskntest = $options{'f'} || die "\n*** Input series knowledge file from " . "test version not given (-f ); quitting...\n"; $outfile = $options{'o'} || die "\n*** Output results filename not given " . "(-o ); quitting...\n"; #----------------------------------------------------------------- # Check existence of all input files. if( !(-e $infprod1) ) { die "\n*** Input products file 1 from production version " . "doesn't exist, please check; quitting...\n"; } if( ($infprod2 ne 'null') && (!(-e $infprod2)) ) { die "\n*** Input products file 2 from production version " . "was specified but doesn't exist, please check; quitting...\n"; } if( !(-e $inftest1) ) { die "\n*** Input products file 1 from test version " . "doesn't exist, please check; quitting...\n"; } if( ($inftest2 ne 'null') && (!(-e $inftest2)) ) { die "\n*** Input products file 2 from test version " . "was specified but doesn't exist, please check; quitting...\n"; } if( !(-e $infsknprod) ) { die "\n*** Input series knowledge file from production version " . "doesn't exist, please check; quitting...\n"; } if( !(-e $infskntest) ) { die "\n*** Input series knowledge file from test version " . "doesn't exist, please check; quitting...\n"; } #----------------------------------------------------------------- # Store contents of all input files. if( !open(INF1, "<$infprod1") ) { die "\n*** Couldn't open $infprod1 file for reading, quitting...\n"; } else { @infprod1lines = ; $infprod1lines[0] =~ s/^\s+|\s+$//g; if(!$infprod1lines[0]) { print "\n*** Warning: $infprod1 contains no lines; continuing...\n"; } } close(INF1); if( $infprod2 ne 'null' ) { if( !open(INF2, "<$infprod2") ) { die "\n*** Couldn't open $infprod2 file for reading, quitting...\n"; } else { @infprod2lines = ; $infprod2lines[0] =~ s/^\s+|\s+$//g; if(!$infprod2lines[0]) { print "\n*** Warning: $infprod2 contains no lines; continuing...\n"; } } close(INF2); } if( !open(INF3, "<$inftest1") ) { die "\n*** Couldn't open $inftest1 file for reading, quitting...\n"; } else { @inftest1lines = ; $inftest1lines[0] =~ s/^\s+|\s+$//g; if(!$inftest1lines[0]) { print "\n*** Warning: $inftest1 contains no lines; continuing...\n"; } } close(INF3); if( $inftest2 ne 'null' ) { if( !open(INF4, "<$inftest2") ) { die "\n*** Couldn't open $inftest2 file for reading, quitting...\n"; } else { @inftest2lines = ; $inftest2lines[0] =~ s/^\s+|\s+$//g; if(!$inftest2lines[0]) { print "\n*** Warning: $inftest2 contains no lines; continuing...\n"; } } close(INF4); } if( !open(INF5, "<$infsknprod") ) { die "\n*** Couldn't open $infsknprod file for reading, quitting...\n"; } else { @infsknprodlines = ; $infsknprodlines[0] =~ s/^\s+|\s+$//g; if(!$infsknprodlines[0]) { print "\n*** Warning: $infsknprod contains no lines; continuing...\n"; } } close(INF5); if( !open(INF6, "<$infskntest") ) { die "\n*** Couldn't open $infskntest file for reading, quitting...\n"; } else { @infskntestlines = ; $infskntestlines[0] =~ s/^\s+|\s+$//g; if(!$infskntestlines[0]) { print "\n*** Warning: $infskntest contains no lines; continuing...\n"; } } close(INF6); #----------------------------------------------------------------- # Compare series knowledge "TSA-download" files from production and # test versions. Store differences and suggested action string. print "\n Comparing series knowledge...\n"; $sknresults = "\n/////////////////////////////////////////" . "//////////////////////////////\n" . "Comparison of Series Knowledge written by " . "Production and Test Versions:\n" . "/////////////////////////////////////////" . "//////////////////////////////\n"; # Store prod. knowledge for each series in 2d array. $i1 = 0; for($k1 = 0; $k1 <= $#infsknprodlines; $k1++) { $line1 = $infsknprodlines[$k1]; chomp($line1); if( $line1 =~ m/SERIES-NAME/ ) { ($series1[$i1] = $line1) =~ s/SERIES-NAME //; $ii1 = 0; for($j1 = $k1 + 1; $j1 <= $#infsknprodlines; $j1++ ) { ($sknlines1[$i1][$ii1] = $infsknprodlines[$j1]) =~ s/^\s+|\s+$//g; #print "$series1[$i1] $ii1 $sknlines1[$i1][$ii1]\n"; if( $sknlines1[$i1][$ii1] =~ m/DATA / ) { last; } $ii1++; } $numsknlines1[$i1] = $ii1; $i1++; } } # Store test knowledge for each series in 2d array. $i2 = 0; for($k2 = 0; $k2 <= $#infskntestlines; $k2++) { $line2 = $infskntestlines[$k2]; chomp($line2); if( $line2 =~ m/SERIES-NAME/ ) { ($series2[$i2] = $line2) =~ s/SERIES-NAME //; $ii2 = 0; for($j2 = $k2 + 1; $j2 <= $#infskntestlines; $j2++ ) { ($sknlines2[$i2][$ii2] = $infskntestlines[$j2]) =~ s/^\s+|\s+$//g; #print "$series2[$i2] $ii2 $sknlines2[$i2][$ii2]\n"; if( $sknlines2[$i2][$ii2] =~ m/DATA / ) { last; } $ii2++; } $numsknlines2[$i2] = $ii2; $i2++; } } # Check number of series match in input knowledge files. if( $i1 != $i2 ) { die "\n*** Error: number of series in \"$infsknprod\" ($i1) not equal to " . "number in \"$infskntest\" ($i2); quitting...\n"; } # Comparison step. for($i = 0; $i < $i1; $i++) { for($j = 0; $j < $i2; $j++) { if( ($series1[$i] eq $series2[$j]) && ($i == $j) ) { @a = (); @b = (); for($k = 0; $k < $numsknlines1[$i]; $k++) { $a[$k] = $sknlines1[$i][$k]; } for($k = 0; $k < $numsknlines2[$j]; $k++) { $b[$k] = $sknlines2[$j][$k]; } @diff = (); %count = (); foreach $e (@a, @b) { $count{$e}++ } foreach $e (keys %count) { if ($count{$e} != 2) { push @diff, $e; } } if( ($diff[0] eq 'START_SBRK') && ($diff[1] eq 'END_SBRK') ) { # Since occurances of seasonal breaks can repeat. @diff = (); } $numdiff = $#diff + 1; $sknstatus = "All okay!\n"; $sknaction = ""; if( $numdiff > 0 ) { $sknstatus = "*** Number of inconsistent series knowledge " . "records = $numdiff\:\n"; $sknaction = "\n*** Please review SEASABS processing parameters " . "and settings.\n"; } $sknresults = $sknresults . "\nSeries: $series1[$i]\n" . "----------------------------\n" . $sknstatus; foreach $line (@diff) { $sknresults = $sknresults . "$line\n"; } $sknresults = $sknresults . $sknaction; last; } elsif( ($series1[$i] ne $series2[$j]) && ($i == $j) ) { die "\n*** Error: unexpected mismatch in series names " . "($series1[$i] .NE. $series2[$j]) in " . "\"$infsknprod\" and \"$infskntest\" files; quitting...\n"; } } } #----------------------------------------------------------------- # Compare (O, C, S, T) "Download" files from production and test # versions. Store differences and suggested action string. print "\n Comparing series products and combined factors...\n"; $prodresults = "\n\n///////////////////////////////////////" . "//////////////////\n" . "Comparison of Series Data Products\n" . "(Original, Combined Factors, Seasonally Adjusted, " . "Trend):\n" . "///////////////////////////////////////" . "//////////////////\n"; # Store prod. version series products in 2d array. $i1 = 0; for($k1 = 0; $k1 <= $#infprod1lines; $k1++) { $line1 = $infprod1lines[$k1]; chomp($line1); if( $line1 =~ m/^\*\S+\*$/ ) { ($series_pd1[$i1] = $line1) =~ s/\*//g; $ii1 = 0; for($j1 = $k1 + 1; $j1 <= $#infprod1lines; $j1++ ) { ($pdlines1[$i1][$ii1] = $infprod1lines[$j1]) =~ s/^\s+|\s+$//g; #print "$series_pd1[$i1] $ii1 $pdlines1[$i1][$ii1]\n"; if( $pdlines1[$i1][$ii1] =~ m/^\*\S+\*$/ ) { last; } $ii1++; } $numpdlines1[$i1] = $ii1 - 1; $i1++; } } # Store test version series products in 2d array. $i2 = 0; for($k2 = 0; $k2 <= $#inftest1lines; $k2++) { $line2 = $inftest1lines[$k2]; chomp($line2); if( $line2 =~ m/^\*\S+\*$/ ) { ($series_pd2[$i2] = $line2) =~ s/\*//g; $ii2 = 0; for($j2 = $k2 + 1; $j2 <= $#inftest1lines; $j2++ ) { ($pdlines2[$i2][$ii2] = $inftest1lines[$j2]) =~ s/^\s+|\s+$//g; #print "$series_pd2[$i2] $ii2 $pdlines2[$i2][$ii2]\n"; if( $pdlines2[$i2][$ii2] =~ m/^\*\S+\*$/ ) { last; } $ii2++; } $numpdlines2[$i2] = $ii2 - 1; $i2++; } } # Check number of series match in input product files. if( $i1 != $i2 ) { die "\n*** Error: number of series in \"$infprod1\" ($i1) not equal to " . "number in \"$inftest1\" ($i2); quitting...\n"; } # Comparison step. for($i = 0; $i < $i1; $i++) { for($j = 0; $j < $i2; $j++) { if( ($series_pd1[$i] eq $series_pd2[$j]) && ($i == $j) ) { # Store start/end dates so can check below. ($Ys1,$Ps1,$Os1,$Cs1,$Ss1,$Ts1) = split(/\,/,$pdlines1[$i][0]); ($Ye1,$Pe1,$Oe1,$Ce1,$Se1,$Te1) = split(/\,/,$pdlines1[$i][$numpdlines1[$i]]); ($Ys2,$Ps2,$Os2,$Cs2,$Ss2,$Ts2) = split(/\,/,$pdlines2[$j][0]); ($Ye2,$Pe2,$Oe2,$Ce2,$Se2,$Te2) = split(/\,/,$pdlines2[$j][$numpdlines2[$j]]); $prodstatus = "All okay!\n"; $prodaction = ""; $diffresults = ""; if( ($numpdlines1[$i] != $numpdlines2[$j]) || ($Ys1 != $Ys2) || ($Ps1 ne $Ps2) || ($Ye1 != $Ye2) || ($Pe1 ne $Pe2) ) { $prodstatus = "*** Number of time-points between prod. and test " . "versions are either inconsistent or start or " . "end times don't match!\n"; $prodaction = "\n*** Ensure analysis timespans in prod. and test " . "runs for this series are consistent and rerun.\n"; } else { # Report only non-zero differences between prod. and # test verson outputs. $diffresults = ""; for($k = 0; $k <= $numpdlines1[$i]; $k++) { ($Y1,$P1,$O1,$C1,$S1,$T1) = split(/\,/,$pdlines1[$i][$k]); ($Y2,$P2,$O2,$C2,$S2,$T2) = split(/\,/,$pdlines2[$j][$k]); @pdiff = (); @pdiff = ($Y1-$Y2, $P1-$P2, sprintf("%.3e",$O1-$O2), sprintf("%.3e",$C1-$C2), sprintf("%.3e",$S1-$S2), sprintf("%.3e",$T1-$T2)); if( ($pdiff[0] != 0) || ($pdiff[1] != 0) || ($pdiff[2] != 0) || ($pdiff[3] != 0) || ($pdiff[4] != 0) || ($pdiff[5] != 0) ) { $prodstatus = "*** Differences were found (prod - test):\n" . "[Yr, Prd: dYr; dPrd; dOrig; dCombFact; dSeasAdj; dTrend]:\n\n"; $diffresults = $diffresults . "$Y1, $P1\: @pdiff\n"; $prodaction = "\n*** Are these expected according to " . "service requests implemented in test " . "version? Please check!\n"; } } } $prodresults = $prodresults . "\nSeries: $series_pd1[$i]\n" . "----------------------------------------------\n" . $prodstatus . $diffresults . $prodaction; last; } elsif( ($series_pd1[$i] ne $series_pd2[$j]) && ($i == $j) ) { die "\n*** Error: unexpected mismatch in series names " . "($series_pd1[$i] .NE. $series_pd2[$j]) in " . "\"$infprod1\" and \"$inftest1\" files; quitting...\n"; } } } #----------------------------------------------------------------- # If exist, compare Trading day "Download" files from production and # test versions. Store differences and suggested action string. if( ($infprod2 ne 'null') && ($inftest2 ne 'null') ) { print "\n Comparing Trading Day factors...\n"; $tdresults = "\n\n//////////////////////////////////\n" . "Comparison of Trading Day factors:\n" . "//////////////////////////////////\n"; # Store trading day factors in 2d array. $i1 = 0; for($k1 = 0; $k1 <= $#infprod2lines; $k1++) { $line1 = $infprod2lines[$k1]; chomp($line1); if( $line1 =~ m/^\*\S+\*$/ ) { ($series_td1[$i1] = $line1) =~ s/\*//g; $ii1 = 0; for($j1 = $k1 + 1; $j1 <= $#infprod2lines; $j1++ ) { ($tdlines1[$i1][$ii1] = $infprod2lines[$j1]) =~ s/^\s+|\s+$//g; #print "$series_td1[$i1] $ii1 $tdlines1[$i1][$ii1]\n"; if( $tdlines1[$i1][$ii1] =~ m/^\*\S+\*$/ ) { last; } $ii1++; } $numtdlines1[$i1] = $ii1 - 1; $i1++; } } # Store test version series products in 2d array. $i2 = 0; for($k2 = 0; $k2 <= $#inftest2lines; $k2++) { $line2 = $inftest2lines[$k2]; chomp($line2); if( $line2 =~ m/^\*\S+\*$/ ) { ($series_td2[$i2] = $line2) =~ s/\*//g; $ii2 = 0; for($j2 = $k2 + 1; $j2 <= $#inftest2lines; $j2++ ) { ($tdlines2[$i2][$ii2] = $inftest2lines[$j2]) =~ s/^\s+|\s+$//g; #print "$series_td2[$i2] $ii2 $tdlines2[$i2][$ii2]\n"; if( $tdlines2[$i2][$ii2] =~ m/^\*\S+\*$/ ) { last; } $ii2++; } $numtdlines2[$i2] = $ii2 - 1; $i2++; } } # Check number of series match in input product files. if( $i1 != $i2 ) { die "\n*** Error: number of series in \"$infprod2\" ($i1) not equal to " . "number in \"$inftest2\" ($i2); quitting...\n"; } # Comparison step. for($i = 0; $i < $i1; $i++) { for($j = 0; $j < $i2; $j++) { if( ($series_td1[$i] eq $series_td2[$j]) && ($i == $j) ) { # Store start/end dates so can check below. ($Ys1,$Ps1,$Os1) = split(/\s+/,$tdlines1[$i][0]); ($Ye1,$Pe1,$Oe1) = split(/\s+/,$tdlines1[$i][$numtdlines1[$i]]); ($Ys2,$Ps2,$Os2) = split(/\s+/,$tdlines2[$j][0]); ($Ye2,$Pe2,$Oe2) = split(/\s+/,$tdlines2[$j][$numtdlines2[$j]]); $tdstatus = "All okay!\n"; $tdaction = ""; $tdiffresults = ""; if( ($numtdlines1[$i] != $numtdlines2[$j]) || ($Ys1 != $Ys2) || ($Ps1 ne $Ps2) || ($Ye1 != $Ye2) || ($Pe1 ne $Pe2) ) { $tdstatus = "*** Number of time-points between prod. and test " . "versions are either inconsistent or start or " . "end times don't match!\n"; $tdaction = "\n*** Ensure analysis timespans in prod. and test " . "runs for this series are consistent and rerun.\n"; } else { # Report only non-zero differences between prod. and # test verson outputs. $tdiffresults = ""; for($k = 0; $k <= $numtdlines1[$i]; $k++) { ($Y1,$P1,$O1) = split(/\s+/,$tdlines1[$i][$k]); ($Y2,$P2,$O2) = split(/\s+/,$tdlines2[$j][$k]); @tdiff = (); @tdiff = ($Y1-$Y2, $P1-$P2, sprintf("%.3e",$O1-$O2)); if( ($tdiff[0] != 0) || ($tdiff[1] != 0) || ($tdiff[2] != 0) ) { $tdstatus = "*** Differences were found (prod - test):\n" . "[Yr, Prd: delta_Yr; delta_Prd; delta_TDfactors]:\n\n"; $tdiffresults = $tdiffresults . "$Y1, $P1\: @tdiff\n"; $tdaction = "\n*** Are these expected according to " . "service requests implemented in test " . "version? Please check!\n"; } } } $tdresults = $tdresults . "\nSeries: $series_td1[$i]\n" . "----------------------------------------------\n" . $tdstatus . $tdiffresults . $tdaction; last; } elsif( ($series_td1[$i] ne $series_td2[$j]) && ($i == $j) ) { die "\n*** Error: unexpected mismatch in series names " . "($series_td1[$i] .NE. $series_td2[$j]) in " . "\"$infprod2\" and \"$inftest2\" files; quitting...\n"; } } } } #----------------------------------------------------------------- # Output results to specified file. if( !open(OUT, ">$outfile") ) { die "\n*** Couldn't create $outfile for writing, quitting...\n"; } else { print "\n Writing results to file: \"$outfile\"...\n"; print "\n Good luck!\n"; print OUT "$sknresults $prodresults"; if( ($infprod2 ne 'null') && ($inftest2 ne 'null') ) { print OUT "$tdresults"; } } close(OUT); exit(0); #-----------------END OF acctest_cmpproducts.pl------------------- __DATA__ Purpose: -------- Compare production and test version SEASABS/TSUpdate products for a group of series for acceptance testing. There are six input files (as specified in the command-line usage below). : [Required] file 1 from "Download" tool on production version series products: i.e. file generated from download option "All Except Trading day factors (O, C, S, T)" with format: "year, period, obs." : [Optional] file 2 from "Download" tool on production version products: i.e. file generated from download option "Trading Day Factors" with format: "year, period, obs." : [Required] file 1 from "Download" tool on test version series products: i.e. file generated from download option "All Except Trading day factors (O, C, S, T)" with format: "year, period, obs." : [Optional] file 2 from "Download" tool on test version products: i.e. file generated from download option "Trading Day Factors" with format: "year, period, obs." : [Required] file from "TSA-download" tool on production version series knowledge. : [Required] file from "TSA-download" tool on test version series knowledge. A summary of differences and suggested actions on how to resolve them are written to an output file specified by the "-o " option. Usage: ------ acctest_cmpproducts.pl -a [Required] -b [Optional] -c [Required] -d [Optional] -e [Required] -f [Required] -o [Required] Example: -------- Execute the following at the DOS command prompt. Directory paths are allowed if your input files do not reside in the execution directory. The "-b <...>" and "-d <...>" options can be omitted if your series had no Trading Day factors. acctest_cmpproducts.pl -a MnthConcSeriesData_prod.txt -b MnthConcTDfact_prod.txt -c MnthConcSeriesData_test.txt -d MnthConcTDfact_test.txt -e MnthConcSeriesKdge_prod.txt -f MnthConcSeriesKdge_test.txt -o Results.txt