1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
|
#!/usr/bin/perl
#Perform tests on nasm
use strict;
use warnings;
use Getopt::Long qw(GetOptions);
use Pod::Usage qw(pod2usage);
use File::Basename qw(fileparse);
use File::Compare qw(compare compare_text);
use File::Copy qw(move);
use File::Path qw(mkpath rmtree);
#sub debugprint { print (pop() . "\n"); }
sub debugprint { }
my $globalresult = 0;
#Process one testfile
sub perform {
my ($clean, $diff, $golden, $nasm, $quiet, $testpath) = @_;
my ($stdoutfile, $stderrfile) = ("stdout", "stderr");
my ($testname, $ignoredpath, $ignoredsuffix) = fileparse($testpath, ".asm");
debugprint $testname;
my $outputdir = $golden ? "golden" : "testresults";
mkdir "$outputdir" unless -d "$outputdir";
if ($clean) {
rmtree "$outputdir/$testname";
return;
}
if(-d "$outputdir/$testname") {
rmtree "$outputdir/$testname";
}
open(TESTFILE, '<', $testpath) or (warn "Can't open $testpath\n", return);
TEST:
while(<TESTFILE>) {
#See if there is a test case
last unless /Testname=(.*);\s*Arguments=(.*);\s*Files=(.*)/;
my ($subname, $arguments, $files) = ($1, $2, $3);
debugprint("$subname | $arguments | $files");
#Call nasm with this test case
system("$nasm $arguments $testpath > $stdoutfile 2> $stderrfile");
debugprint("$nasm $arguments $testpath > $stdoutfile 2> $stderrfile ----> $?");
#Move the output to the test dir
mkpath("$outputdir/$testname/$subname");
foreach(split / /,$files) {
if (-f $_) {
move($_, "$outputdir/$testname/$subname/$_") or die $!
}
}
unlink ("$stdoutfile", "$stderrfile"); #Just to be sure
if($golden) {
print "Test $testname/$subname created.\n" unless $quiet;
} else {
#Compare them with the golden files
my $result = 0;
my @failedfiles = ();
foreach(split / /, $files) {
if(-f "$outputdir/$testname/$subname/$_") {
my $temp;
if($_ eq $stdoutfile or $_ eq $stderrfile) {
#Compare stdout and stderr in text mode so line ending changes won't matter
$temp = compare_text("$outputdir/$testname/$subname/$_", "golden/$testname/$subname/$_",
sub { my ($a, $b) = @_;
$a =~ s/\r//g;
$b =~ s/\r//g;
$a ne $b; } );
} else {
$temp = compare("$outputdir/$testname/$subname/$_", "golden/$testname/$subname/$_");
}
if($temp == 1) {
#different
$result = 1;
$globalresult = 1;
push @failedfiles, $_;
} elsif($temp == -1) {
#error
print "Can't compare at $testname/$subname file $_\n";
next TEST;
}
} elsif (-f "golden/$testname/$subname/$_") {
#File exists in golden but not in output
$result = 1;
$globalresult = 1;
push @failedfiles, $_;
}
}
if($result == 0) {
print "Test $testname/$subname succeeded.\n" unless $quiet;
} elsif ($result == 1) {
print "Test $testname/$subname failed on @failedfiles.\n";
if($diff) {
for(@failedfiles) {
if($_ eq $stdoutfile or $_ eq $stderrfile) {
system "diff -u golden/$testname/$subname/$_ $outputdir/$testname/$subname/$_";
print "\n";
}
}
}
} else {
die "Impossible result";
}
}
}
close(TESTFILE);
}
my $nasm;
my $clean = 0;
my $diff = 0;
my $golden = 0;
my $help = 0;
my $verbose = 0;
GetOptions('clean' => \$clean,
'diff'=> \$diff,
'golden' => \$golden,
'help' => \$help,
'verbose' => \$verbose,
'nasm=s' => \$nasm
) or pod2usage();
pod2usage() if $help;
die "Please specify either --nasm or --clean. Use --help for help.\n"
unless $nasm or $clean;
die "Please specify the test files, e.g. *.asm\n" unless @ARGV;
unless (!defined $nasm or -x $nasm) {
warn "Warning: $nasm may not be executable. Expect problems.\n\n";
sleep 5;
}
perform($clean, $diff, $golden, $nasm, ! $verbose, $_) foreach @ARGV;
exit $globalresult;
__END__
=head1 NAME
performtest.pl - NASM regression tester based on golden files
=head1 SYNOPSIS
performtest.pl [options] [testfile.asm ...]
Runs NASM on the specified test files and compare the results
with "golden" output files.
Options:
--clean Clean up test results (or golden files with --golden)
--diff Execute diff when stdout or stderr don't match
--golden Create golden files
--help Get this help
--nasm=file Specify the file name for the NASM executable, e.g. ../nasm
--verbose Get more output
If --clean is not specified, --nasm is required.
testfile.asm ...:
One or more files that NASM should be tested with,
often *.asm in the test directory.
It should contain one or more option lines at the start,
in the following format:
;Testname=<testname>; Arguments=<arguments to nasm>; Files=<output files>
If no such lines are found at the start, the file is skipped.
testname should ideally describe the arguments, eg. unoptimized for -O0.
arguments can be an optimization level (-O), an output format (-f),
an output file specifier (-o) etc.
The output files should be a space separated list of files that will
be checked for regressions. This should often be the output file
and the special files stdout and stderr.
Any mismatch could be a regression,
but it doesn't have to be. COFF files have a timestamp which
makes this method useless. ELF files have a comment section
with the current version of NASM, so they will change each version number.
=cut
|