use strict;
use Config;
use Cwd 'abs_path';
use File::Basename;
my $mydir = dirname(abs_path($0));
my $is_CI = 0;
my $is_aarchxx = $Config{archname} =~ /(aarch64)|(arm)/;
my $is_x86_64 = $Config{archname} =~ /x86_64/;
my $is_long = $ENV{'CI_TRIGGER'} eq 'push' && $ENV{'CI_BRANCH'} eq 'refs/heads/master';
my $args = '';
for (my $i = 0; $i <= $#ARGV; $i++) {
my $arg = $ARGV[$i];
$arg = 'automated_ci' if ($arg eq 'travis');
$is_CI = 1 if ($arg eq 'automated_ci');
if ($i == 0) {
$args .= ",$arg";
} else {
$args .= ";$arg";
}
}
my $osdir = $mydir;
if ($^O eq 'cygwin') {
$osdir = `/usr/bin/cygpath -wi \"$mydir\"`;
chomp $osdir;
}
my $res = '';
my $child = 0;
my $outfile = '';
if ($^O ne 'MSWin32') {
print "Forking child for stdout tee\n";
$child = open(CHILD, '-|');
die "Failed to fork: $!" if (!defined($child));
} else {
$outfile = "runsuite_output.txt";
}
if ($child) {
if ($^O ne 'cygwin') {
print "Parent tee-ing child stdout...\n";
local $SIG{ALRM} = sub {
print "\nxxxxxxxxxx 30s elapsed xxxxxxxxxxx\n";
alarm(30);
};
alarm(30);
while (<CHILD>) {
print STDOUT $_;
$res .= $_;
}
} else {
while (<CHILD>) {
print STDOUT $_;
$res .= $_;
}
}
close(CHILD);
} elsif ($ENV{'CI_TARGET'} eq 'package') {
my $build = "0";
if ($ENV{'VERSION_NUMBER'} =~ /-(\d+)$/) {
$build = $1;
}
if ($args eq '') {
$args = ",";
} else {
$args .= ";";
}
$args .= "build=${build}";
if ($ENV{'VERSION_NUMBER'} =~ /^(\d+\.\d+\.\d+)/) {
my $version = $1;
$args .= ";version=${version}";
}
if ($ENV{'DEPLOY_DOCS'} eq 'yes') {
$args .= ";copy_docs";
}
if (($is_aarchxx || $ENV{'DYNAMORIO_CROSS_AARCHXX_LINUX_ONLY'} eq 'yes') &&
$args =~ /64_only/) {
} else {
$args .= ";invoke=${osdir}/../drmemory/package.cmake;drmem_only";
}
my $cmd = "ctest -VV -S \"${osdir}/../make/package.cmake${args}\"";
print "Running ${cmd}\n";
if ($^O eq 'MSWin32') {
system("${cmd} 2>&1 | tee ${outfile}");
} else {
system("${cmd} 2>&1");
exit 0;
}
} else {
my $verbose = "-VV";
my $cmd = "ctest --output-on-failure ${verbose} -S \"${osdir}/runsuite.cmake${args}\"";
print "Running ${cmd}\n";
if ($^O eq 'MSWin32') {
system("${cmd} 2>&1 | tee ${outfile}");
print "Finished running ${cmd}\n";
} else {
system("${cmd} 2>&1");
print "Finished running ${cmd}\n";
exit 0;
}
}
if ($^O eq 'MSWin32') {
open my $handle, '<', "$outfile" or die "Failed to open teed ${outfile}: $!";
$res = do {
local $/; <$handle>
};
}
my @lines = split('\n', $res);
my $should_print = 0;
my $exit_code = 0;
for (my $i = 0; $i <= $#lines; ++$i) {
my $line = $lines[$i];
my $fail = 0;
my $name = '';
$should_print = 1 if ($line =~ /^RESULTS/);
if ($line =~ /^([-\w]+):.*\*\*/) {
$name = $1;
if ($line =~ /build errors/ ||
$line =~ /configure errors/ ||
$line =~ /tests failed:/) {
$fail = 1;
} elsif ($line =~ /(\d+) tests failed, of which (\d+)/) {
$fail = 1 if ($2 < $1);
}
} elsif ($line =~ /CMake Error.*runsuite/) {
$fail = 1;
$should_print = 1;
$name = "runsuite script itself";
} elsif ($line =~ /^\s*ERROR: diff contains/) {
$fail = 1;
$should_print = 1;
$name = "diff pre-commit checks";
}
if ($fail && $is_CI && $line =~ /tests failed/) {
my $is_32 = $line =~ /-32/;
my $issue_no = "";
my %ignore_failures_32 = ();
my %ignore_failures_64 = ();
if ($^O eq 'cygwin' ||
$^O eq 'MSWin32') {
%ignore_failures_32 = (
'code_api|client.drsyms-test' => 1,
'code_api|win32.earlythread' => 1,
'code_api|client.drx-test' => 1,
'code_api|client.drwrap-test' => 1,
'code_api|client.drutil-test' => 1,
'code_api|tool.histogram.offline' => 1,
'code_api|tool.drcacheoff.burst_replace' => 1,
'code_api|tool.drcacheoff.burst_traceopts' => 1,
'code_api|tool.drcacheoff.burst_replaceall' => 1,
'code_api|tool.drcacheoff.burst_static' => 1,
'code_api|api.symtest' => 1,
'code_api|client.drwrap-test-detach' => 1,
'code_api|client.cbr4' => 1,
'code_api|win32.hookerfirst' => 1,
'code_api|client.winxfer' => 1,
'code_api|security-common.retnonexisting' => 1,
'code_api|security-win32.gbop-test' => 1,
'code_api|win32.reload-newaddr' => 1,
'code_api|client.pcache-use' => 1,
'code_api|api.detach' => 1,
'code_api|api.detach_spawn' => 1,
'code_api|api.startstop' => 1,
'code_api|client.drmgr-test' => 1,
'code_api|client.nudge_test' => 1,
'code_api|client.nudge_ex' => 1,
'code_api|client.alloc-noreset' => 1,
'code_api,thread_private,tracedump_binary|common.fib' => 1,
'code_api,opt_speed|common.decode-stress' => 1,
'code_api,thread_private|common.decode-stress' => 1,
'code_api,thread_private,disable_traces|common.decode-stress' => 1,
'code_api,thread_private,tracedump_binary|common.decode-stress' => 1,
'code_api|client.file_io' => 1,
);
%ignore_failures_64 = (
'code_api|client.drsyms-test' => 1,
'code_api|client.drsyms-testgcc' => 1,
'code_api|client.cleancall' => 1,
'code_api|win32.callback' => 1,
'code_api|common.nativeexec' => 1,
'code_api|client.drx-test' => 1,
'code_api|client.drutil-test' => 1,
'code_api|client.pcache-use' => 1,
'code_api|api.startstop' => 1,
'code_api|api.detach' => 1,
'code_api|client.drwrap-test-detach' => 1,
'code_api|tool.histogram.offline' => 1,
'code_api|tool.drcacheoff.burst_static' => 1,
'code_api|tool.drcacheoff.burst_replace' => 1,
'code_api|win32.mixedmode_late' => 1,
'code_api|win32.mixedmode' => 1,
'code_api|win32.x86_to_x64' => 1,
'code_api|win32.x86_to_x64_ibl_opt' => 1,
'code_api|common.floatpc_xl8all' => 1,
'code_api|win32.reload-newaddr' => 1,
'code_api|client.loader' => 1,
'code_api|client.drmgr-test' => 1,
'code_api|client.nudge_test' => 1,
'code_api|client.nudge_ex' => 1,
'code_api|client.alloc-noreset' => 1,
'code_api|api.detach_spawn' => 1,
'code_api|api.static_noinit' => 1,
'code_api,opt_memory|common.nativeexec' => 1,
'code_api,opt_speed|common.decode-bad' => 1,
'code_api,opt_speed|common.decode-stress' => 1,
'code_api,opt_speed|common.nativeexec' => 1,
'code_api,thread_private|common.nativeexec' => 1,
'code_api,disable_traces|common.nativeexec' => 1,
'code_api,thread_private,disable_traces|common.nativeexec' => 1,
'code_api,loglevel|common.nativeexec' => 1,
'code_api,stack_size|common.nativeexec' => 1,
'enable_full_api|common.nativeexec' => 1,
'code_api,stack_size,loglevel,no_hide|common.nativeexec' => 1,
'|common.nativeexec' => 1,
'code_api,tracedump_text,tracedump_origins|common.nativeexec' => 1,
'code_api,tracedump_text,tracedump_origins,syntax_intel|common.nativeexec' => 1,
'code_api,thread_private,tracedump_binary|common.nativeexec' => 1,
'code_api,bbdump_tags|common.nativeexec' => 1,
'checklevel|common.nativeexec' => 1,
'finite_shared_bb_cache,cache_shared_bb_regen|common.nativeexec' => 1,
'finite_shared_trace_cache,cache_shared_trace_regen|common.nativeexec' => 1,
'common.floatpc_xl8all' => 1,
'code_api|client.file_io' => 1,
);
if ($is_long) {
$ignore_failures_32{'code_api|tool.drcachesim.invariants'} = 1;
$ignore_failures_32{'code_api|tool.drcachesim.threads-with-config-file'} = 1;
$ignore_failures_32{'code_api|tool.drcachesim.simple-config-file'} = 1;
$ignore_failures_64{'code_api|tool.drcachesim.invariants'} = 1;
$ignore_failures_64{'code_api|tool.drcachesim.threads-with-config-file'} = 1;
$ignore_failures_64{'code_api|tool.drcachesim.simple-config-file'} = 1;
}
$issue_no = "#2145";
} elsif ($is_aarchxx) {
%ignore_failures_32 = ('code_api|tool.histogram.offline' => 1,
'code_api|linux.eintr-noinline' => 1,
'code_api|pthreads.ptsig' => 1,
'code_api|linux.sigaction_nosignals' => 1,
'code_api|linux.signal_race' => 1,
'code_api|linux.sigsuspend' => 1,
'code_api|client.drmgr-test' => 1,
'code_api|tool.drcachesim.delay-simple' => 1,
'code_api|tool.drcachesim.invariants' => 1,
'code_api|tool.drcacheoff.simple' => 1,
'code_api|tool.histogram.gzip' => 1,
);
%ignore_failures_64 = ('code_api|linux.sigsuspend' => 1,
'code_api|pthreads.pthreads_exit' => 1,
'code_api|tool.histogram.offline' => 1,
'code_api|linux.fib-conflict' => 1,
'code_api|linux.fib-conflict-early' => 1,
'code_api|linux.mangle_asynch' => 1,
'code_api,tracedump_text,tracedump_origins,syntax_intel|common.loglevel' => 1,
'code_api|client.attach_test' => 1,
'code_api|client.attach_blocking' => 1,
'code_api|tool.drcacheoff.rseq' => 1,
'code_api|tool.drcacheoff.windows-zlib' => 1,
);
if ($is_32) {
$issue_no = "#2416";
} else {
$issue_no = "#2417";
}
} elsif ($is_x86_64 && ($ENV{'DYNAMORIO_CROSS_AARCHXX_LINUX_ONLY'} eq 'yes') && $args =~ /64_only/) {
$ignore_failures_64{'code_api|client.drx_buf-test'} = 1;
$ignore_failures_64{'code_api|sample.memval_simple'} = 1;
$ignore_failures_64{'code_api|client.drreg-test'} = 1;
$issue_no = "#6260";
} elsif ($^O eq 'darwin') {
%ignore_failures_32 = ('code_api|common.decode-bad' => 1,
'code_api|linux.signal0000' => 1,
'code_api|linux.signal0010' => 1,
'code_api|linux.signal0100' => 1,
'code_api|linux.signal0110' => 1,
'code_api|linux.sigaction' => 1,
'code_api|security-common.codemod' => 1,
'code_api|client.crashmsg' => 1,
'code_api|client.exception' => 1,
'code_api|client.timer' => 1,
'code_api|sample.signal' => 1);
} else {
%ignore_failures_32 = (
'code_api|pthreads.ptsig' => 1,
'code_api|client.drwrap-test-detach' => 1,
'code_api|linux.thread-reset' => 1,
'code_api|linux.clone-reset' => 1,
'common.decode-stress' => 1,
'code_api,opt_speed|common.fib' => 1,
'prof_pcs|common.nativeexec_exe_opt' => 1,
'prof_pcs|common.nativeexec_retakeover_opt' => 1,
'prof_pcs|common.nativeexec_bindnow_opt' => 1,
'prof_pcs,thread_private|common.nativeexec_exe_opt' => 1,
'prof_pcs,thread_private|common.nativeexec_retakeover_opt' => 1,
'prof_pcs,thread_private|common.nativeexec_bindnow_opt' => 1,
);
%ignore_failures_64 = (
'code_api|tool.drcacheoff.burst_threadfilter' => 1,
'code_api,opt_memory|common.loglevel' => 1,
'code_api,opt_speed|common.decode-stress' => 1,
'code_api,opt_memory|common.nativeexec_exe_opt' => 1,
'common.nativeexec_bindnow_opt' => 1,
'common.nativeexec_retakeover_opt' => 1,
'common.nativeexec_exe' => 1,
'common.nativeexec_bindnow' => 1,
'code_api,opt_speed|common.floatpc_xl8all' => 1,
'prof_pcs|common.nativeexec_exe_opt' => 1,
'prof_pcs|common.nativeexec_retakeover_opt' => 1,
'prof_pcs|common.nativeexec_bindnow_opt' => 1,
'prof_pcs,thread_private|common.nativeexec_exe_opt' => 1,
'prof_pcs,thread_private|common.nativeexec_retakeover_opt' => 1,
'prof_pcs,thread_private|common.nativeexec_bindnow_opt' => 1,
);
if ($is_long) {
$ignore_failures_32{'code_api|api.startstop'} = 1;
$ignore_failures_64{'code_api|api.detach_state'} = 1;
$ignore_failures_64{'code_api|client.cleancallsig'} = 1;
$ignore_failures_64{'code_api|client.drx_buf-test'} = 1;
}
$issue_no = "#2941";
}
$fail = 0;
my $num_ignore = 0;
for (my $j = $i+1; $j <= $#lines; ++$j) {
my $test;
my $test_base_name;
if ($lines[$j] =~ /^\t(\S+)\s/) {
$test = $1;
$test_base_name = (split '\|', $test)[-1];
if (($is_32 && ($ignore_failures_32{$test} ||
$ignore_failures_32{$test_base_name})) ||
(!$is_32 && ($ignore_failures_64{$test} ||
$ignore_failures_64{$test_base_name}))) {
$lines[$j] = "\t(ignore: i" . $issue_no . ") " . $lines[$j];
$num_ignore++;
} elsif ($test =~ /_FLAKY$/) {
} else {
$fail = 1;
}
} else {
last if ($lines[$j] =~ /^\S/);
}
}
$line =~ s/: \*/, but ignoring $num_ignore for i$issue_no: */;
}
if ($fail) {
$exit_code++;
print "\n====> FAILURE in $name <====\n";
}
print "$line\n" if ($should_print);
}
if (!$should_print) {
print "Error: RESULTS line not found\n";
$exit_code++;
}
exit $exit_code;