summaryrefslogtreecommitdiff
path: root/libdde-linux26/mk/ptest
diff options
context:
space:
mode:
Diffstat (limited to 'libdde-linux26/mk/ptest')
-rwxr-xr-xlibdde-linux26/mk/ptest444
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";