2017-07-07 11:54:15 +02:00
|
|
|
#!/usr/bin/perl
|
|
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
|
use warnings;
|
|
|
|
|
use Getopt::Long;
|
|
|
|
|
use IO::Handle;
|
|
|
|
|
use IPC::Open2 qw( open2 );
|
|
|
|
|
use POSIX qw( WIFEXITED WEXITSTATUS WIFSIGNALED WTERMSIG );
|
|
|
|
|
|
|
|
|
|
my $VALGRIND = 0;
|
2020-05-17 16:04:44 +02:00
|
|
|
my $EXECUTABLE = "t/.libs/harness";
|
2017-07-07 11:54:15 +02:00
|
|
|
GetOptions(
|
|
|
|
|
'valgrind|v+' => \$VALGRIND,
|
2020-05-17 16:04:44 +02:00
|
|
|
'executable|e=s' => \$EXECUTABLE
|
2017-07-07 11:54:15 +02:00
|
|
|
) or exit 1;
|
|
|
|
|
|
|
|
|
|
my ( $hin, $hout, $hpid );
|
|
|
|
|
{
|
|
|
|
|
local $ENV{LD_LIBRARY_PATH} = ".libs";
|
2020-05-17 16:04:44 +02:00
|
|
|
my @command = $EXECUTABLE;
|
2018-12-15 14:49:34 +01:00
|
|
|
unshift @command, "valgrind", "--tool=memcheck", "--leak-check=yes", "--num-callers=25", "--log-file=valgrind.out", "--error-exitcode=126" if $VALGRIND;
|
2017-07-07 11:54:15 +02:00
|
|
|
|
|
|
|
|
$hpid = open2 $hout, $hin, @command or die "Cannot open2 harness - $!";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
my $exitcode = 0;
|
|
|
|
|
|
|
|
|
|
my $command;
|
|
|
|
|
my @expect;
|
|
|
|
|
|
|
|
|
|
sub do_onetest
|
|
|
|
|
{
|
|
|
|
|
$hin->print( "$command\n" );
|
|
|
|
|
undef $command;
|
|
|
|
|
|
|
|
|
|
my $fail_printed = 0;
|
|
|
|
|
|
|
|
|
|
while( my $outline = <$hout> ) {
|
|
|
|
|
last if $outline eq "DONE\n" or $outline eq "?\n";
|
|
|
|
|
|
|
|
|
|
chomp $outline;
|
|
|
|
|
|
|
|
|
|
if( !@expect ) {
|
|
|
|
|
print "# Test failed\n" unless $fail_printed++;
|
|
|
|
|
print "# expected nothing more\n" .
|
|
|
|
|
"# Actual: $outline\n";
|
|
|
|
|
next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
my $expectation = shift @expect;
|
|
|
|
|
|
|
|
|
|
next if $expectation eq $outline;
|
|
|
|
|
|
|
|
|
|
print "# Test failed\n" unless $fail_printed++;
|
|
|
|
|
print "# Expected: $expectation\n" .
|
|
|
|
|
"# Actual: $outline\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( @expect ) {
|
|
|
|
|
print "# Test failed\n" unless $fail_printed++;
|
|
|
|
|
print "# Expected: $_\n" .
|
|
|
|
|
"# didn't happen\n" for @expect;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$exitcode = 1 if $fail_printed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub do_line
|
|
|
|
|
{
|
|
|
|
|
my ( $line ) = @_;
|
|
|
|
|
|
|
|
|
|
if( $line =~ m/^!(.*)/ ) {
|
|
|
|
|
do_onetest if defined $command;
|
|
|
|
|
print "> $1\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Commands have capitals
|
|
|
|
|
elsif( $line =~ m/^([A-Z]+)/ ) {
|
|
|
|
|
# Some convenience formatting
|
|
|
|
|
if( $line =~ m/^(PUSH|ENCIN) (.*)$/ ) {
|
|
|
|
|
# we're evil
|
|
|
|
|
my $string = eval($2);
|
|
|
|
|
$line = "$1 " . unpack "H*", $string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
do_onetest if defined $command;
|
|
|
|
|
|
|
|
|
|
$command = $line;
|
|
|
|
|
undef @expect;
|
|
|
|
|
}
|
|
|
|
|
# Expectations have lowercase
|
|
|
|
|
elsif( $line =~ m/^([a-z]+)/ ) {
|
|
|
|
|
# Convenience formatting
|
|
|
|
|
if( $line =~ m/^(text|encout) (.*)$/ ) {
|
|
|
|
|
$line = "$1 " . join ",", map sprintf("%x", $_), eval($2);
|
|
|
|
|
}
|
|
|
|
|
elsif( $line =~ m/^(output) (.*)$/ ) {
|
|
|
|
|
$line = "$1 " . join ",", map sprintf("%x", $_), unpack "C*", eval($2);
|
|
|
|
|
}
|
|
|
|
|
elsif( $line =~ m/^control (.*)$/ ) {
|
|
|
|
|
$line = sprintf "control %02x", eval($1);
|
|
|
|
|
}
|
|
|
|
|
elsif( $line =~ m/^csi (\S+) (.*)$/ ) {
|
|
|
|
|
$line = sprintf "csi %02x %s", eval($1), $2; # TODO
|
|
|
|
|
}
|
|
|
|
|
elsif( $line =~ m/^(escape|osc|dcs) (.*)$/ ) {
|
|
|
|
|
$line = "$1 " . join "", map sprintf("%02x", $_), unpack "C*", eval($2);
|
|
|
|
|
}
|
|
|
|
|
elsif( $line =~ m/^putglyph (\S+) (.*)$/ ) {
|
|
|
|
|
$line = "putglyph " . join( ",", map sprintf("%x", $_), eval($1) ) . " $2";
|
|
|
|
|
}
|
|
|
|
|
elsif( $line =~ m/^(?:movecursor|scrollrect|moverect|erase|damage|sb_pushline|sb_popline|settermprop|setmousefunc) / ) {
|
|
|
|
|
# no conversion
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
warn "Unrecognised test expectation '$line'\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
push @expect, $line;
|
|
|
|
|
}
|
|
|
|
|
# ?screen_row assertion is emulated here
|
|
|
|
|
elsif( $line =~ s/^\?screen_row\s+(\d+)\s*=\s*// ) {
|
|
|
|
|
my $row = $1;
|
|
|
|
|
my $row1 = $row + 1;
|
|
|
|
|
my $want = eval($line);
|
|
|
|
|
|
|
|
|
|
do_onetest if defined $command;
|
|
|
|
|
|
|
|
|
|
# TODO: may not be 80
|
|
|
|
|
$hin->print( "\?screen_chars $row,0,$row1,80\n" );
|
|
|
|
|
my $response = <$hout>;
|
|
|
|
|
chomp $response;
|
|
|
|
|
|
|
|
|
|
$response = pack "C*", map hex, split m/,/, $response;
|
|
|
|
|
if( $response ne $want ) {
|
|
|
|
|
print "# Assert ?screen_row $row failed:\n" .
|
|
|
|
|
"# Expected: $want\n" .
|
|
|
|
|
"# Actual: $response\n";
|
|
|
|
|
$exitcode = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
# Assertions start with '?'
|
|
|
|
|
elsif( $line =~ s/^\?([a-z]+.*?=)\s+// ) {
|
|
|
|
|
do_onetest if defined $command;
|
|
|
|
|
|
|
|
|
|
my ( $assertion ) = $1 =~ m/^(.*)\s+=/;
|
|
|
|
|
|
|
|
|
|
$hin->print( "\?$assertion\n" );
|
|
|
|
|
my $response = <$hout>; defined $response or wait, die "Test harness failed - $?\n";
|
|
|
|
|
chomp $response;
|
|
|
|
|
|
|
|
|
|
if( $response ne $line ) {
|
|
|
|
|
print "# Assert $assertion failed:\n" .
|
|
|
|
|
"# Expected: $line\n" .
|
|
|
|
|
"# Actual: $response\n";
|
|
|
|
|
$exitcode = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
# Test controls start with '$'
|
|
|
|
|
elsif( $line =~ s/\$SEQ\s+(\d+)\s+(\d+):\s*// ) {
|
|
|
|
|
my ( $low, $high ) = ( $1, $2 );
|
|
|
|
|
foreach my $val ( $low .. $high ) {
|
|
|
|
|
( my $inner = $line ) =~ s/\\#/$val/g;
|
|
|
|
|
do_line( $inner );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
elsif( $line =~ s/\$REP\s+(\d+):\s*// ) {
|
|
|
|
|
my $count = $1;
|
|
|
|
|
do_line( $line ) for 1 .. $count;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
die "Unrecognised TEST line $line\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
open my $test, "<", $ARGV[0] or die "Cannot open test script $ARGV[0] - $!";
|
|
|
|
|
|
|
|
|
|
while( my $line = <$test> ) {
|
|
|
|
|
$line =~ s/^\s+//;
|
|
|
|
|
next if $line =~ m/^(?:#|$)/;
|
|
|
|
|
|
|
|
|
|
chomp $line;
|
|
|
|
|
do_line( $line );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
do_onetest if defined $command;
|
|
|
|
|
|
|
|
|
|
close $hin;
|
|
|
|
|
close $hout;
|
|
|
|
|
|
|
|
|
|
waitpid $hpid, 0;
|
|
|
|
|
if( $? ) {
|
|
|
|
|
printf STDERR "Harness exited %d\n", WEXITSTATUS($?) if WIFEXITED($?);
|
|
|
|
|
printf STDERR "Harness exit signal %d\n", WTERMSIG($?) if WIFSIGNALED($?);
|
|
|
|
|
$exitcode = WIFEXITED($?) ? WEXITSTATUS($?) : 125;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
exit $exitcode;
|