diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2013-07-27 22:15:01 +0000 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2013-07-27 22:15:01 +0000 |
commit | 7996a3d79d55b7f879dfd62e202bbfe2963718d3 (patch) | |
tree | 8d9f6759fec4099b9be503c11c7ed174f7204980 /libdde-linux26/mk/ptest | |
parent | 4fbe7358c7747a9165f776eb19addbb9baf7def2 (diff) |
really properly move files
Diffstat (limited to 'libdde-linux26/mk/ptest')
-rwxr-xr-x | libdde-linux26/mk/ptest | 444 |
1 files changed, 444 insertions, 0 deletions
diff --git a/libdde-linux26/mk/ptest b/libdde-linux26/mk/ptest new file mode 100755 index 00000000..e85d53b6 --- /dev/null +++ b/libdde-linux26/mk/ptest @@ -0,0 +1,444 @@ +#! /usr/bin/perl -W +# +# Run package tests using Fiasco-UX +# +# +# Adam Lackorzynski <adam@os.inf.tu-dresden.de> +# Ronald Aigner <ra3@os.inf.tu-dresden.de> +# +# This script is derived from the autocheck script which can be found in +# kernel/fiasco/tools. It has been slightly modified to suit the demands of +# the package tests. +# + +# make it pass for now +#exit 0; + +use strict; +use Getopt::Long; + +my $FIASCOUX; +my $FIASCOUX_PARAM; +my $L4DIR; +my $OBJ_BASE; +my $OBJDIR = 'OBJ-x86_586-l4v2'; +my $EXPECTED_OUT = 'expected.txt'; +my $TMP_OUT = 'tmp_out.txt'; +my $PKGNAME; +my $COMPARE_CMD = 'diff -u $EXPECTED_OUT $TMP_OUT'; + +my $ALARM_TIMEOUT = 60; # in seconds + +my %templs = ( + roottask => '%s/pkg/roottask/server/src/%s/roottask', + sigma0 => '%s/pkg/sigma0/server/src/%s/sigma0', +); + +my $Verbose = 0; +my $Quiet = 0; +my $Generate = 0; +my $Memory = 32; +my $Plainrun = 0; +my $No_fb = 0; +my $Use_Symbols = 0; +my $Use_Lines = 0; + +my %progs; +my %results; +my %output; +my @Baseservers; +my $Client; +my $Server; +my $Fiasco_Dir; + +# filehandle for fiasco output +my $Input; +my $Output; + +my $Exit_code = 0; +my $pid = 0; + +my $FILTER_LEVEL_FIASCO = 0; +my $FILTER_LEVEL_ROOTTASK = 1; +my $FILTER_LEVEL_USER = 2; +my $Filter_state = $FILTER_LEVEL_FIASCO; +my $Filter_level = $FILTER_LEVEL_USER; + +sub usage() { + print <<EOU; +$0 [options] -c <client> -s <server> + + --l4dir, -l path Path to an L4 directory + --fiascoux, -f file Path to the Fiasco-UX binary + --fiascoux_param, -p params Parameters for Fiasco-UX + --memory, -m megabyte Number of Megabytes used by Fiasco. (default: 32) + --objdir, -O objdir Object dir, currently: $OBJDIR + --verbose, -v Be verbose (e.g. show output of L4 apps) + --quiet, -q Tell nothing, just set the exit code + --generate Generate the output file instead of comparing to it + --server, -s file The server to be tested + --client, -c file The file to run as test-application + --base, -b file Additional base servers required by the application + Can be a comma seperated list. (Only specify the + binary names!) (default: log, names, dm_phys) + --timeout, -t timeout Time in seconds to wait before shooting down a + runaway fiasco. (default: 60) + --expectfail Expect failure. Return 0 on failure, 1 on success. + + Environment variables: + L4DIR Path to an L4 directory + OBJ_BASE Path to build directory + FIASCOUX Path to the Fiasco-UX binary + EXPECTED_OUT Filename of the file containing the expected output + TMP_OUT Filename of the tempfile containing Fiasco's output + COMPARE_CMD Command to compare output and expected output + + Notes: + Environment variables override options! +EOU +} + +## +# Check if L4DIR looks like an L4 directory +sub check_for_l4dir() { + unless (-d "$L4DIR/pkg/l4sys/include" || + -d "$L4DIR/../kernel/fiasco/src/kern/ux") { + die "$L4DIR doesn't look like an L4 directory!"; + } +} + +## +# Just check if the supplied binary in $FIASCOUX is really +# a Fiasco UX version. Native versions will just segfault. +sub check_for_fiasco_ux() { + + unless ((-x $FIASCOUX && -f $FIASCOUX) || + (-l $FIASCOUX && -x readlink $FIASCOUX && -f readlink $FIASCOUX)) { + die "$FIASCOUX: Does not exist or isn't an executable file"; + } + + system("$FIASCOUX -h >/dev/null 2>&1"); + die "$FIASCOUX doesn't seem to be a UX version." if $?; + + $FIASCOUX =~ /(.*)\/([^\/]*)$/; + $Fiasco_Dir = $1; +} + +# check for user app in binary path of L4 +sub check_user_app($) +{ + my $app_with_args = shift; + + # extract arch and api from OBJ-dir + $OBJDIR =~ /OBJ-([^-]*)-(.*)/; + my $arch = $1; + my $api = $2; + + my @check = split(/\s+/, $app_with_args); + my $app = shift @check; + + my $p = sprintf "%s/bin/%s/%s/%s", $OBJ_BASE, $arch, $api, $app; + die "There's no $p!" unless -f $p; + + return $p.'\\ '.join('\\ ', @check) if @check; + $p; +} + +## +# Check for userland (roottask, sigma0, ...) +sub check_for_userland() { + foreach my $t (keys %templs) { + my $p = sprintf $templs{$t}, $OBJ_BASE, $OBJDIR; + die "There's no $p!" unless -f $p; + $progs{$t} = $p; + } + + # check for base-servers + my @servers = @Baseservers; + @Baseservers = {}; + if (scalar(@servers) eq 0) { + @servers = ( "log", "names", "dm_phys" ); + } + + # iterate over servers and test if they exist in the bin dir + foreach my $s (@servers) { + push @Baseservers, check_user_app($s); + } + + # test client and server + push @Baseservers, check_user_app($Client) if defined($Client); + push @Baseservers, check_user_app($Server); +} + +## +# Does the comparison of the output +sub run_diff { + print STDERR "Running compare command \"$COMPARE_CMD\".\n" if $Verbose; + open(TMP, "$COMPARE_CMD |") or die "Cannot run diff: $!"; + my @diff = <TMP>; + close TMP; + + # reset console in interactive mode + system "if tty -s; then stty echo icrnl icanon; fi"; + + # check if there are differences between expected and generated output + if (@diff == 0) { + print STDERR "Output of test in $PKGNAME ok.\n"; + return $Exit_code; + } + + print STDERR "Test in $PKGNAME generated unexpected output:\n"; + @diff = splice @diff, 1000 if @diff > 1000; + print STDERR @diff, "\n"; + return 1 - $Exit_code; +} + +## +# Called if second alarm signal received +# +# Now all the output of Fiasco-UX should be through and we can savely kill +# Fiasco-UX. We then check the generated output and terminate ourselves. +sub got_sig_alarm_second { + print STDERR "Timeout for flushing Fiasco-UX output\n" if $Verbose; + print STDERR "Sending SIGKILL to $pid and diff output\n" if $Verbose; + + kill KILL => $pid; + alarm 0; + + # some sanity checks + if ( $Filter_state < $FILTER_LEVEL_USER ) { + print $Output "\n"; + print $Output "User tasks did not start. Maybe overlapping modules?\n"; + print $Output "Run \"" . fiascoux_cmdline() . "\" manually to check.\n"; + } + close $Output; + + # in generate mode, simply return + if ($Generate) { + system "stty echo"; + exit 0; + } + + exit run_diff(); +} + +## +# Called if first alarm signal received +# +# To flush Fiasco Output we send it a SIGINT (^C). Then we set up a second +# timeout and return, so the filter can process the output which we forced to +# be flushed. +sub got_sig_alarm_first { + print STDERR "Timeout for Fiasco-UX hit!\n" if $Verbose; + print STDERR "Sending SIGINT to $pid\n" if $Verbose; + + kill INT => $pid; + $SIG{ALRM} = \&got_sig_alarm_second; + alarm 2; # time to flush output + + # return to keep on filtering the output of Fiasco +} + +## +# Runs the timer and kills fiasco if runaway +# +# - sets the signal handler +# - initializes the timeout +sub set_alarm { + $SIG{ALRM} = \&got_sig_alarm_first; + alarm $ALARM_TIMEOUT; + print STDERR "Set alarm to $ALARM_TIMEOUT seconds\n" if $Verbose; +} + +## +# Build the fiasco command line +# +# Adds the binaries with the appropriate parameters. +sub fiascoux_cmdline() { + (my $p = $FIASCOUX) =~ s/\/[^\/]+$//; + my $cmdline = "$FIASCOUX"; + $cmdline .= " $FIASCOUX_PARAM" if defined $FIASCOUX_PARAM; + $cmdline .= " -symbols $Fiasco_Dir/Symbols" if $Use_Symbols; + $cmdline .= " -lines $Fiasco_Dir/Lines" if $Use_Lines; + $cmdline .= " -m $Memory"; + $cmdline .= " -R $progs{roottask}"; # -quiet"; + $cmdline .= "\"" if $Use_Symbols || $Use_Lines; + $cmdline .= " -symbols" if $Use_Symbols; + $cmdline .= " -lines" if $Use_Lines; + $cmdline .= "\"" if $Use_Symbols || $Use_Lines; + $cmdline .= " -S $progs{sigma0}"; # --quiet"; + # when we change this to not cd into Fiasco dir, then + # prepend $p to $irq0 + $cmdline .= " -I ".$p."/irq0"; + if ($No_fb eq 1) { + $cmdline .= " -F /bin/true"; + } else { + $cmdline .= " -F ".$p."/con_ux"; + } + # add -l to base-servers, which already contains client and server + for my $s (@Baseservers) { + if (ref($s) ne "HASH") { # just checking for Hashes that smuggled in + $cmdline .= " -l ".$s; + } + } + $cmdline; +} + +## +# filters the output of fiasco +# +# We want to see everything once roottask are finished loading. +# Therefore, we need some state machine to skip everything before and while +# roottask is running. +sub filter_fiasco_out +{ + $_ = shift; + + # filter escape sequences + s/[[:cntrl:]]\[(\d;)?\d{0,2}m//g; + s/
//g; + s/[[:cntrl:]]\[K//g; + s/[[:cntrl:]]\[\d+;\d+[Hfr]//g; + + # check if we have to change state + if (/^Roottask: Loading \d+ modules\./ && + $Filter_state eq $FILTER_LEVEL_FIASCO) { + $Filter_state = $FILTER_LEVEL_ROOTTASK; + print STDERR "Changed state to Roottask-Output\n" if $Verbose; + } + if ( /^$/ && $Filter_state eq $FILTER_LEVEL_ROOTTASK) { + $Filter_state = $FILTER_LEVEL_USER; + print STDERR "Changed state to Userland-Output\n" if $Verbose; + } + + # skip everything before and from roottask + return undef if $Filter_state < $Filter_level; + + # if we are not supposed to filter anything, then return the line + return $_ if $Filter_level eq $FILTER_LEVEL_FIASCO; + + # filter empty lines + return undef if /^$/; + + # filter JDB warning and prompt + return undef if /^Terminal probably too small, should be at least/; + return undef if /^\([a-f0-9]\.\d\d\) jdb:/; + return undef if /^--.*ESP:.*EIP:.*/; + + # filter memory dump + return undef if /^([a-f0-9]){8}:/; + + $_; +} + +## +# call_test +sub run_fiasco { + my $cmdline = fiascoux_cmdline(); + print "Calling: $cmdline\n" if $Verbose; + + $pid = open($Input, "$cmdline|"); + die "Can't start Fiasco: $!" unless defined $pid; + print "Run Fiasco-UX in $pid\n" if $Verbose; + + # if in generate mode, we redirect output to EXPECTED_OUT + # otherwise we redirect stdout to the TMP_OUT file + my $filename = $Generate ? $EXPECTED_OUT : $TMP_OUT; + open($Output, ">$filename") || die "Cannot open output file $filename"; + my $oldfh = select($Output); $| = 1; select($oldfh); + print STDERR "Opened $filename, now setting timer\n" if $Verbose; + + # the parent sets up the timer (it will eventually call the run_diff sub) + set_alarm(); + + my $o; + while (<$Input>) { + # we have to strip some lines + $o = filter_fiasco_out($_); + next unless defined $o; + print $Output $o; + } + print STDERR "Fiasco terminated.\n" if $Verbose; + close $Input; + close $Output; + # when we drop out of this loop fiasco terminated + alarm 0; + + # in generate mode, simply return + exit 0 if $Generate; + + exit run_diff(); +} + +## +# Plain run of Fiasco UX +# +# Not timer, no filter, simply run UX +sub run_plain_fiasco { + my $cmdline = fiascoux_cmdline(); + print "Running UX: \"$cmdline\"\n"; + exec($cmdline) or die "Can't start Fiasco: $!"; + exit 1; +} + + +# ------------------------------------------------------------- + +unless (GetOptions("help|h", sub { usage(); exit(0); }, + "l4dir|l=s", \$L4DIR, + "builddir=s", \$OBJ_BASE, + "fiascoux|f=s", \$FIASCOUX, + "fiascoux_param|p=s", \$FIASCOUX_PARAM, + "memory|m=s", \$Memory, + "objdir|O=s", \$OBJDIR, + "verbose|v!", \$Verbose, + "quiet|q!", \$Quiet, + "generate!", \$Generate, + "expectfail!", \$Exit_code, + "client|c=s", \$Client, + "server|s=s", \$Server, + "base|b=s", \@Baseservers, + "timeout|t=s", \$ALARM_TIMEOUT, + "plainrun!", \$Plainrun, + "filterlevel=i", \$Filter_level, + "nofb!", \$No_fb, + "symbols!", \$Use_Symbols, + "lines!", \$Use_Lines, + )) { + usage(); + exit(1); +} + +@Baseservers = split(/,/,join(',',@Baseservers)); + +$L4DIR = $ENV{L4DIR} || die "Need an L4DIR set!" unless $L4DIR; +$OBJ_BASE = $ENV{OBJ_BASE} || die "Need an builddir (OBJ_BASE) set!" unless $OBJ_BASE; +$FIASCOUX = $ENV{FIASCOUX} || die "Need a Fiasco-UX path!" unless $FIASCOUX; +if ($ENV{EXPECTED_OUT}) { $EXPECTED_OUT = $ENV{EXPECTED_OUT}; } +die "Need filename of expected output!" unless $EXPECTED_OUT; +if ($ENV{TMP_OUT}) { $TMP_OUT = $ENV{TMP_OUT}; } +die "No valid temporary file set!" unless $TMP_OUT; +$PKGNAME = $ENV{PKGNAME} || $Server + || die "No package-name set!" unless $PKGNAME; +if ($ENV{COMPARE_CMD}) { $COMPARE_CMD = $ENV{COMPARE_CMD}; } +die "No compare command set!" unless $COMPARE_CMD; + +check_for_l4dir(); +check_for_fiasco_ux(); +check_for_userland(); + +## +# The package test script: +# This script forks off Fiasco and sets up a timeout. When the timeout +# strikes, it sends a SIGINT to Fiasco to force a flush of the output buffer. +# Then it sends a SIGKILL to terminate Fiasco. +print "Main called by $$.\n" if $Verbose; + +# if plainrun, start run_plain_fiasco (it never returns) +run_plain_fiasco() if $Plainrun; + +# this function forks off fiasco +run_fiasco(); + +# when we reach this point, something terribly went wrong +die "Oops, error in script!\n"; |