#!/usr/bin/perl -w # keine_test.pl - Don Yang (uguu.org) # # ./keine_test.pl # # Do blackbox testing on and check that it matched the # reference implementation of Keine. # # 09/16/07 use strict; use constant DATA_DIR => "tests"; use constant OUTPUT_PREFIX => "keine_test_output."; # Remove time/run specific tokens from output lines sub UnifyLogLine($) { my ($s) = @_; $s =~ s/keine_test_output\.\d+\.txt/keine_test_output.####.txt/; $s =~ s/^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/####-##-## ##:##:##/; return $s; } # Compare two sets of lines. If different, print differences and abort sub CompareLines($$) { my ($expected, $actual) = @_; # Compare lines my $mismatched = 0; for(my $i = 0; $i <= $#$expected && $i <= $#$actual; $i++) { # Remove trailing whitespaces before comparing lines, to account # for EOL differences. my ($expected_line, $actual_line) = ($$expected[$i], $$actual[$i]); $expected_line =~ s/[ \t\r\n]*$//s; $actual_line =~ s/[ \t\r\n]*$//s; if( $expected_line ne $actual_line ) { print "< $expected_line\n> $actual_line\n"; $mismatched = 1; } } if( $#$expected != $#$actual ) { print "Expected: ", $#$expected + 1, " lines\n", "Actual: ", $#$actual + 1, " lines\n"; $mismatched = 1; } # If mismatched, save actual output to a file and abort if( $mismatched ) { my $saved_output = OUTPUT_PREFIX . "actual"; my $outfile; open $outfile, "> $saved_output" or die $!; print $outfile $_ foreach @$actual; close $outfile; die "Output mismatched, saved actual output to $saved_output\n"; } } # Run a single batch test case sub RunBatchTest($$) { my ($binary, $test) = @_; print "testing batch-$test\n"; # Check input files my $test_input = DATA_DIR . "/batch-$test.input"; my $test_output = DATA_DIR . "/batch-$test.output"; die "$test_input not readable" unless -r $test_input; die "$test_output not readable" unless -r $test_output; my $infile; open $infile, "< $test_output" or die $!; my @expected_stdout = <$infile>; close $infile; # Run command my @run_stdout = `$binary < $test_input`; if( $? != 0 ) { die "Command returned $?\n"; } # Check that stdout matched expected data CompareLines(\@expected_stdout, \@run_stdout); } # Run a single interactive test case sub RunInteractiveTest($$) { my ($binary, $test) = @_; print "testing interactive-$test\n"; # Check input files my $test_input = DATA_DIR . "/interactive-$test.input"; my $test_input_log = DATA_DIR . "/interactive-$test.input-log"; my $test_output = DATA_DIR . "/interactive-$test.output"; my $test_output_log = DATA_DIR . "/interactive-$test.output-log"; die "$test_input not readable" unless -r $test_input; die "$test_input_log not readable" unless -r $test_input_log; die "$test_output not readable" unless -r $test_output; die "$test_output_log not readable" unless -r $test_output_log; # Create input data my $run_log = OUTPUT_PREFIX . "$$.txt"; my ($infile, $outfile); open $infile, "< $test_input_log" or die $!; open $outfile, "> $run_log" or die $!; print $outfile $_ while(<$infile>); close $infile; close $outfile; # Run command and unify output my @run_stdout = map UnifyLogLine($_), `$binary $run_log < $test_input`; if( $? != 0 ) { die "Command returned $?\n"; } # Check that stdout contains expected data open $infile, "< $test_output" or die $!; my @expected_output = <$infile>; close $infile; CompareLines(\@expected_output, \@run_stdout); # Unify data file and check that it matched expected output open $infile, "< $test_output_log" or die $!; @expected_output = <$infile>; close $infile; open $infile, "< $run_log" or die $!; my @actual_output = map UnifyLogLine($_), <$infile>; close $infile; CompareLines(\@expected_output, \@actual_output); unlink $run_log; } # Find all tests and run them sub RunTests($) { my ($binary) = @_; # Find all test data, group them by type my $dir; my (%batch_tests, %interactive_tests); opendir $dir, DATA_DIR or die $!; while(my $file = readdir $dir) { next unless $file =~ /^(batch|interactive)-(\S+)\.\S+/; if( $1 eq "batch" ) { $batch_tests{$2} = 1; } else { $interactive_tests{$2} = 1; } } closedir $dir; # Run all tests RunBatchTest($binary, $_) foreach keys %batch_tests; RunInteractiveTest($binary, $_) foreach keys %interactive_tests; } die "$0 \n" unless $#ARGV == 0; RunTests($ARGV[0]);