blob: 405082d15b3cc0e0cac8500689307d548990c4c8 [file] [log] [blame]
#!/usr/bin/perl
# **********************************************************
# Copyright (c) 2016-2017 Google, Inc. All rights reserved.
# **********************************************************
# Dr. Memory: the memory debugger
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation;
# version 2.1 of the License, and no later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# XXX: we should share this w/ DR.
# Build-and-test driver for Travis CI.
# Travis uses the exit code to check success, so we need a layer outside of
# ctest on runsuite.
# We stick with runsuite rather than creating a parallel scheme using
# a Travis matrix of builds.
# Travis only supports Linux and Mac, so we're ok relying on perl.
use strict;
use Cwd 'abs_path';
use File::Basename;
my $mydir = dirname(abs_path($0));
my $is_CI = 0;
# Forward args to runsuite.cmake:
my $args = '';
for (my $i = 0; $i <= $#ARGV; $i++) {
$is_CI = 1 if ($ARGV[$i] eq 'travis');
if ($i == 0) {
$args .= ",$ARGV[$i]";
} else {
# We don't use a backslash to escape ; b/c we'll quote below, and
# the backslash is problematically converted to / by Cygwin perl.
$args .= ";$ARGV[$i]";
}
}
# We have no way to access the log files, so we use -VV to ensure
# we can diagnose failures.
# We tee to stdout to provide incremental output and avoid the 10-min
# no-output timeout on Travis.
my $res = '';
my $child = open(CHILD, '-|');
die "Failed to fork: $!" if (!defined($child));
if ($child) {
# Parent
my $output;
while (<CHILD>) {
print STDOUT $_;
$res .= $_;
}
close(CHILD);
} else {
if ($^O eq 'cygwin') {
# CMake is native Windows so pass it a Windows path.
# We use the full path to cygpath as git's cygpath is earlier on
# the PATH for AppVeyor and it fails.
$mydir = `/usr/bin/cygpath -wi \"$mydir\"`;
chomp $mydir;
}
# To shrink the log sizes and make Travis and Appveyor error pages easier
# to work with we omit a second V and instead use --output-on-failure.
# We rely on runsuite_common_post.cmake extracting configure and build error
# details from the xml files, as they don't show up with one V.
system("ctest --output-on-failure -V -S \"${mydir}/runsuite.cmake${args}\" 2>&1");
exit 0;
}
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 =~ /^\s*ERROR: diff contains/) {
$fail = 1;
$should_print = 1;
$name = "diff pre-commit checks";
}
if ($fail && $is_CI && $^O eq 'cygwin' && $line =~ /tests failed/) {
# FIXME i#1938: ignoring certain AppVeyor test failures until
# we get all tests passing.
my $is_32 = $line =~ /-32/;
my %ignore_failures_32 = ('procterm' => 1,
'winthreads' => 1,
'malloc_callstacks' => 1,
'wrap_wincrt' => 1, # i#1741: flaky.
'app_suite.pattern' => 1,
'app_suite' => 1,
'drstrace_unit_tests' => 1);
my %ignore_failures_64 = ('handle' => 1,
'app_suite' => 1,
'app_suite.pattern' => 1,
'drstrace_unit_tests' => 1);
# Read ahead to examine the test failures:
$fail = 0;
my $num_ignore = 0;
for (my $j = $i+1; $j < $#lines; ++$j) {
my $test;
if ($lines[$j] =~ /^\t(\S+)\s/) {
$test = $1;
if (($is_32 && $ignore_failures_32{$test}) ||
(!$is_32 && $ignore_failures_64{$test})) {
$lines[$j] = "\t(ignore: i#1938) " . $lines[$j];
$num_ignore++;
} elsif ($test =~ /_FLAKY$/) {
# Don't count toward failure.
} else {
$fail = 1;
}
} else {
last if ($lines[$j] =~ /^\S/);
}
}
$line =~ s/: \*/, but ignoring $num_ignore for i1938: */;
}
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;