summaryrefslogtreecommitdiff
path: root/runtest.pl.in
diff options
context:
space:
mode:
Diffstat (limited to 'runtest.pl.in')
-rwxr-xr-xruntest.pl.in219
1 files changed, 203 insertions, 16 deletions
diff --git a/runtest.pl.in b/runtest.pl.in
index b4f59c1f..a864336b 100755
--- a/runtest.pl.in
+++ b/runtest.pl.in
@@ -3,12 +3,46 @@
use strict;
use warnings;
-use lib 'infrastructure';
+use Cwd;
+use File::Basename;
+use Getopt::Std;
+
+chdir(dirname($0));
+my $base_dir = getcwd();
+use lib dirname($0)."/infrastructure";
+
use BoxPlatform;
-my ($test_name,$test_mode) = @ARGV;
+my %opts;
+getopts('acnv', \%opts);
+
+# Don't actually run the test, just prepare for it.
+my $cmake_build = $opts{'c'};
+my $prepare_only = $opts{'n'};
+my $verbose_build = $opts{'v'};
+my $appveyor_mode = $opts{'a'};
+
+my $test_name = shift @ARGV;
+my $test_mode = shift @ARGV;
+my $test_src_exe;
+my $test_dst_exe;
+
+if($cmake_build)
+{
+ # To support different build environments (Windows/MSVC and Linux/Makefile) which
+ # place compiled executables in different locations, we need to accept the name of
+ # the compiled test executable as an additional command-line parameter.
+ die "test name is required in cmake mode" unless $test_name;
+ die "test mode is required in cmake mode" unless $test_mode;
+ die "only a single test name is supported in cmake mode" if $test_name =~ /,/;
+ $test_src_exe = shift @ARGV;
+ die "test project source executable path is required in cmake mode" unless $test_src_exe;
+ $test_dst_exe = shift @ARGV;
+ die "test project destination executable name is required in cmake mode" unless $test_dst_exe;
+}
$test_mode = 'debug' if not defined $test_mode or $test_mode eq '';
+$test_mode = lc($test_mode);
if($test_name eq '' || ($test_mode ne 'debug' && $test_mode ne 'release'))
{
@@ -38,7 +72,7 @@ if($test_name ne 'ALL')
}
else
{
- runtest($test_name);
+ runtest($test_name, $test_src_exe, $test_dst_exe);
}
}
else
@@ -52,7 +86,7 @@ else
next if m/\AEND-OMIT/;
if(m/\AOMIT:(.+)/)
{
- if($1 eq $build_os or $1 eq $target_os)
+ if($1 eq $build_os or $1 eq $ac_target_os)
{
while(<MODULES>)
{
@@ -93,25 +127,159 @@ __E
exit $exit_code;
+sub appveyor_test_status
+{
+ my ($test_name, $status, $duration, $message, $stdout) = @_;
+
+ if(!$appveyor_mode)
+ {
+ return;
+ }
+
+ # Assume that the test was already "Added" by CMakeLists.txt.
+ my $cmdline = "appveyor UpdateTest -Name $test_name -Framework Custom ".
+ "-FileName \"\" -Outcome $status";
+ if(defined $duration)
+ {
+ $cmdline .= " -Duration ".($duration * 1000);
+ }
+
+ if($message)
+ {
+ $cmdline .= " -ErrorMessage \"$message\"";
+ }
+
+ if(system($cmdline))
+ {
+ warn "AppVeyor test command failed: $cmdline";
+ }
+ else
+ {
+ print "Notified: $cmdline\n";
+ }
+}
+
sub runtest
{
- my ($t) = @_;
+ my ($t, $test_src_exe, $test_dst_exe) = @_;
- # attempt to make this test
+ # Attempt to make this test.
my $flag = ($test_mode eq 'release')?(BoxPlatform::make_flag('RELEASE')):'';
- my $make_res = system("cd test/$t && $make_command $flag");
+ my $make_res;
+ my $test_dst_dir = "$test_mode/test/$t";
+ my $start_time = time();
+
+ if($cmake_build)
+ {
+ appveyor_test_status($t, "Running", 0);
+
+ # Test executables have a different name on Windows to work around
+ # restrictions on running different executables with the same name.
+ my $test_src_dir = "test/$t";
+
+ my @commands = (
+ "cmake -E remove_directory $test_dst_dir",
+ "cmake -E copy_directory $test_src_dir $test_dst_dir",
+ "cmake -E copy $test_src_exe $test_dst_dir/$test_dst_exe",
+ # We could do a "make install" here, to ensure that everything
+ # is up to date, but it's really slow, verbose and wasteful:
+ # "cmake --build infrastructure/cmake/build --target install",
+ );
+
+ # Our CMake buildsystem doesn't do anything to support testextra files
+ # (Makfile syntax), so fake it.
+ if (-r "$test_src_dir/testextra")
+ {
+ open EXTRA, "$test_src_dir/testextra"
+ or die "$test_src_dir/testextra: $!";
+ foreach my $line (<EXTRA>)
+ {
+ chomp $line;
+ if ($line =~ m/^mkdir (.*)/)
+ {
+ push @commands, "cmake -E make_directory $test_dst_dir/$1";
+ }
+ elsif ($line =~ m/^rm -rf (.*)/)
+ {
+ push @commands, "cmake -E remove_directory $test_dst_dir/$1";
+ }
+ elsif ($line =~ m/^cp (.*)\*\.\* (.*)/)
+ {
+ my ($src, $dst) = ($1, $2);
+ push @commands, "cmake -E copy_directory ".
+ "$test_dst_dir/$src $test_dst_dir/$dst";
+ }
+ else
+ {
+ die "Unsupported command in ".
+ "$test_src_dir/testextra: $line";
+ }
+ }
+ }
+
+ foreach my $command (@commands)
+ {
+ $make_res = system($command);
+ if ($make_res != 0)
+ {
+ push @results, "$t: pre-test command failed: $command";
+ appveyor_test_status($t, "NotRunnable", time() - $start_time,
+ "pre-test command failed: $command");
+ last;
+ }
+ }
+ }
+ else
+ {
+ my $quiet = $verbose_build ? "VERBOSE=1" : "";
+ $make_res = system("cd test/$t && $make_command $quiet $flag");
+ $test_dst_exe = "_test$platform_exe_ext";
+ }
+
if($make_res != 0)
{
push @results,"$t: make failed";
+ appveyor_test_status($t, "NotRunnable", time() - $start_time,
+ "pre-test commands failed");
$exit_code = 2;
return;
}
my $logfile = "test-$t.log";
+ my $test_res;
+
+ if($prepare_only)
+ {
+ appveyor_test_status($t, "Skipped", time() - $start_time,
+ "we are only preparing this test");
+ return;
+ }
# run it
- my $test_res = system("cd $test_mode/test/$t ; ./t 2>&1 " .
- "| tee ../../../$logfile");
+ if($cmake_build)
+ {
+ # no tee.exe on Windows, so let's do it ourselves.
+ open LOG, ">$logfile" or die "$logfile: $!";
+ chdir("$base_dir/$test_mode/test/$t");
+
+ open TEE, "$test_dst_exe |"
+ or die "$test_dst_dir/$test_dst_exe: $!";
+
+ while (my $line = <TEE>)
+ {
+ print $line;
+ print LOG $line;
+ }
+ close LOG;
+ close TEE;
+ chdir($base_dir);
+ }
+ else
+ {
+ chdir($base_dir);
+ $test_res = system("cd $test_mode/test/$t ; sh t 2>&1 " .
+ "| tee ../../../$logfile");
+ }
# open test results
if(open RESULTS, $logfile)
@@ -123,19 +291,38 @@ sub runtest
}
close RESULTS;
- chomp $last;
- $last =~ s/\r//;
- push @results, "$t: $last";
-
- if ($last ne "PASSED")
- {
+ if(!defined $last)
+ {
+ push @results, "$t: test produced no output";
+ appveyor_test_status($t, "Failed", time() - $start_time,
+ "test produced no output");
$exit_code = 1;
}
+ else
+ {
+ chomp $last;
+ $last =~ s/\r//;
+ push @results, "$t: $last";
+
+ if ($last ne "PASSED")
+ {
+ $exit_code = 1;
+ appveyor_test_status($t, "Failed", time() - $start_time,
+ "test ended with: $last");
+ }
+ else
+ {
+ appveyor_test_status($t, "Passed", time() - $start_time);
+ }
+ }
}
else
{
+ my $cwd = getcwd();
push @results,
- "$t: failed to open test log file: $logfile: $!";
+ "$t: failed to open test log file: $logfile: $! (in $cwd)";
+ appveyor_test_status($t, "Inconclusive", time() - $start_time,
+ "failed to open test log file: $logfile: $!");
}
# delete test results