From: Michal Sojka Date: Fri, 25 Feb 2011 22:22:01 +0000 (+0100) Subject: Add optional WvTest protocol output for build-all X-Git-Url: https://rtime.felk.cvut.cz/gitweb/sysless.git/commitdiff_plain/8c4613a7fe31875dada70ae023a54fe26dec30c4?ds=sidebyside Add optional WvTest protocol output for build-all Running make test in build-all directory colorizes the results and produces summary numbers of successful and failed builds. --- diff --git a/build-all/Makefile b/build-all/Makefile index 80a87db..a171dc7 100644 --- a/build-all/Makefile +++ b/build-all/Makefile @@ -1,6 +1,6 @@ include Makefile.dirs -all $(MAKECMDGOALS): rm-Makefile.dirs $(BUILD_DIRS) +all $(filter-out test,$(MAKECMDGOALS)): rm-Makefile.dirs $(BUILD_DIRS) Makefile.dirs: ./create-build-tree.sh @@ -9,10 +9,22 @@ Makefile.dirs: rm-Makefile.dirs: rm Makefile.dirs + +ifdef WVTEST +WVSTART = @echo 'Testing "Board $1" in Makefile:' +WVPASS = $1 && echo "! $1 ok" || ( RC=$$$$?; echo "! $1 FAILED"; exit $$$$RC ) +else +WVPASS = $1 +endif + define subdir .PHONY: $1 $1: - $$(MAKE) -C $1 $(MAKECMDGOALS) + $(WVSTART) + $(call WVPASS,$$(MAKE) -C $1 $(MAKECMDGOALS)) endef $(foreach d,$(BUILD_DIRS),$(eval $(call subdir,$d))) + +test: + ./wvtestrun make WVTEST=1 diff --git a/build-all/README b/build-all/README new file mode 100644 index 0000000..6d611a3 --- /dev/null +++ b/build-all/README @@ -0,0 +1,6 @@ +The Makefile in this directory allows you to compile sysless for all supported +boards. This can be used to test whether some change does not break compilation +of some board. + +To start the compilation, simply run `make' (or `make -k test' for colored +output with summary). diff --git a/build-all/wvtestrun b/build-all/wvtestrun new file mode 100755 index 0000000..4499840 --- /dev/null +++ b/build-all/wvtestrun @@ -0,0 +1,186 @@ +#!/usr/bin/perl -w +# +# WvTest: +# Copyright (C)2007-2009 Versabanq Innovations Inc. and contributors. +# Licensed under the GNU Library General Public License, version 2. +# See the included file named LICENSE for license information. +# +use strict; +use Time::HiRes qw(time); + +# always flush +$| = 1; + +if (@ARGV < 1) { + print STDERR "Usage: $0 \n"; + exit 127; +} + +print STDERR "Testing \"all\" in @ARGV:\n"; + +my $pid = open(my $fh, "-|"); +if (!$pid) { + # child + setpgrp(); + open STDERR, '>&STDOUT' or die("Can't dup stdout: $!\n"); + exec(@ARGV); + exit 126; # just in case +} + +my $istty = -t STDOUT && $ENV{'TERM'} ne "dumb"; +my @log = (); +my ($gpasses, $gfails) = (0,0); + +sub bigkill($) +{ + my $pid = shift; + + if (@log) { + print "\n" . join("\n", @log) . "\n"; + } + + print STDERR "\n! Killed by signal FAILED\n"; + + ($pid > 0) || die("pid is '$pid'?!\n"); + + local $SIG{CHLD} = sub { }; # this will wake us from sleep() faster + kill 15, $pid; + sleep(2); + + if ($pid > 1) { + kill 9, -$pid; + } + kill 9, $pid; + + exit(125); +} + +# parent +local $SIG{INT} = sub { bigkill($pid); }; +local $SIG{TERM} = sub { bigkill($pid); }; +local $SIG{ALRM} = sub { + print STDERR "Alarm timed out! No test results for too long.\n"; + bigkill($pid); +}; + +sub colourize($) +{ + my $result = shift; + my $pass = ($result eq "ok"); + + if ($istty) { + my $colour = $pass ? "\e[32;1m" : "\e[31;1m"; + return "$colour$result\e[0m"; + } else { + return $result; + } +} + +sub mstime($$$) +{ + my ($floatsec, $warntime, $badtime) = @_; + my $ms = int($floatsec * 1000); + my $str = sprintf("%d.%03ds", $ms/1000, $ms % 1000); + + if ($istty && $ms > $badtime) { + return "\e[31;1m$str\e[0m"; + } elsif ($istty && $ms > $warntime) { + return "\e[33;1m$str\e[0m"; + } else { + return "$str"; + } +} + +sub resultline($$) +{ + my ($name, $result) = @_; + return sprintf("! %-65s %s", $name, colourize($result)); +} + +my $allstart = time(); +my ($start, $stop); + +sub endsect() +{ + $stop = time(); + if ($start) { + printf " %s %s\n", mstime($stop - $start, 15000, 30000), colourize("ok"); + } +} + +while (<$fh>) +{ + chomp; + s/\r//g; + + if (/^\s*Testing "(.*)" in (.*):\s*$/) + { + alarm(120); + my ($sect, $file) = ($1, $2); + + endsect(); + + printf("! %s %s: ", $file, $sect); + @log = (); + $start = $stop; + } + elsif (/^!\s*(.*?)\s+(\S+)\s*$/) + { + alarm(120); + + my ($name, $result) = ($1, $2); + my $pass = ($result eq "ok"); + + if (!$start) { + printf("\n! Startup: "); + $start = time(); + } + + push @log, resultline($name, $result); + + if (!$pass) { + $gfails++; + if (@log) { + print "\n" . join("\n", @log) . "\n"; + @log = (); + } + } else { + $gpasses++; + print "."; + } + } + else + { + push @log, $_; + } +} + +endsect(); + +my $newpid = waitpid($pid, 0); +if ($newpid != $pid) { + die("waitpid returned '$newpid', expected '$pid'\n"); +} + +my $code = $?; +my $ret = ($code >> 8); + +# return death-from-signal exits as >128. This is what bash does if you ran +# the program directly. +if ($code && !$ret) { $ret = $code | 128; } + +if ($ret && @log) { + print "\n" . join("\n", @log) . "\n"; +} + +if ($code != 0) { + print resultline("Program returned non-zero exit code ($ret)", "FAILED"); +} + +my $gtotal = $gpasses+$gfails; +printf("\nWvTest: %d test%s, %d failure%s, total time %s.\n", + $gtotal, $gtotal==1 ? "" : "s", + $gfails, $gfails==1 ? "" : "s", + mstime(time() - $allstart, 200000, 500000)); +print STDERR "\nWvTest result code: $ret\n"; +exit( $ret ? $ret : ($gfails ? 125 : 0) );