| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- #!/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 seperated 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
|