1*7c356e86SAndroid Build Coastguard Worker# $MirOS: src/bin/mksh/check.pl,v 1.51 2020/06/22 17:10:59 tg Exp $ 2*7c356e86SAndroid Build Coastguard Worker# $OpenBSD: th,v 1.1 2013/12/02 20:39:44 millert Exp $ 3*7c356e86SAndroid Build Coastguard Worker#- 4*7c356e86SAndroid Build Coastguard Worker# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 5*7c356e86SAndroid Build Coastguard Worker# 2012, 2013, 2014, 2015, 2017 6*7c356e86SAndroid Build Coastguard Worker# mirabilos <[email protected]> 7*7c356e86SAndroid Build Coastguard Worker# 8*7c356e86SAndroid Build Coastguard Worker# Provided that these terms and disclaimer and all copyright notices 9*7c356e86SAndroid Build Coastguard Worker# are retained or reproduced in an accompanying document, permission 10*7c356e86SAndroid Build Coastguard Worker# is granted to deal in this work without restriction, including un- 11*7c356e86SAndroid Build Coastguard Worker# limited rights to use, publicly perform, distribute, sell, modify, 12*7c356e86SAndroid Build Coastguard Worker# merge, give away, or sublicence. 13*7c356e86SAndroid Build Coastguard Worker# 14*7c356e86SAndroid Build Coastguard Worker# This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to 15*7c356e86SAndroid Build Coastguard Worker# the utmost extent permitted by applicable law, neither express nor 16*7c356e86SAndroid Build Coastguard Worker# implied; without malicious intent or gross negligence. In no event 17*7c356e86SAndroid Build Coastguard Worker# may a licensor, author or contributor be held liable for indirect, 18*7c356e86SAndroid Build Coastguard Worker# direct, other damage, loss, or other issues arising in any way out 19*7c356e86SAndroid Build Coastguard Worker# of dealing in the work, even if advised of the possibility of such 20*7c356e86SAndroid Build Coastguard Worker# damage or existence of a defect, except proven that it results out 21*7c356e86SAndroid Build Coastguard Worker# of said person's immediate fault when using the work as intended. 22*7c356e86SAndroid Build Coastguard Worker#- 23*7c356e86SAndroid Build Coastguard Worker# Example test: 24*7c356e86SAndroid Build Coastguard Worker# name: a-test 25*7c356e86SAndroid Build Coastguard Worker# description: 26*7c356e86SAndroid Build Coastguard Worker# a test to show how tests are done 27*7c356e86SAndroid Build Coastguard Worker# arguments: !-x!-f! 28*7c356e86SAndroid Build Coastguard Worker# stdin: 29*7c356e86SAndroid Build Coastguard Worker# echo -n * 30*7c356e86SAndroid Build Coastguard Worker# false 31*7c356e86SAndroid Build Coastguard Worker# expected-stdout: ! 32*7c356e86SAndroid Build Coastguard Worker# * 33*7c356e86SAndroid Build Coastguard Worker# expected-stderr: 34*7c356e86SAndroid Build Coastguard Worker# + echo -n * 35*7c356e86SAndroid Build Coastguard Worker# + false 36*7c356e86SAndroid Build Coastguard Worker# expected-exit: 1 37*7c356e86SAndroid Build Coastguard Worker# --- 38*7c356e86SAndroid Build Coastguard Worker# This runs the test-program (eg, mksh) with the arguments -x and -f, 39*7c356e86SAndroid Build Coastguard Worker# standard input is a file containing "echo hi*\nfalse\n". The program 40*7c356e86SAndroid Build Coastguard Worker# is expected to produce "hi*" (no trailing newline) on standard output, 41*7c356e86SAndroid Build Coastguard Worker# "+ echo hi*\n+false\n" on standard error, and an exit code of 1. 42*7c356e86SAndroid Build Coastguard Worker# 43*7c356e86SAndroid Build Coastguard Worker# 44*7c356e86SAndroid Build Coastguard Worker# Format of test files: 45*7c356e86SAndroid Build Coastguard Worker# - blank lines and lines starting with # are ignored 46*7c356e86SAndroid Build Coastguard Worker# - a test file contains a series of tests 47*7c356e86SAndroid Build Coastguard Worker# - a test is a series of tag:value pairs ended with a "---" line 48*7c356e86SAndroid Build Coastguard Worker# (leading/trailing spaces are stripped from the first line of value) 49*7c356e86SAndroid Build Coastguard Worker# - test tags are: 50*7c356e86SAndroid Build Coastguard Worker# Tag Flag Description 51*7c356e86SAndroid Build Coastguard Worker# ----- ---- ----------- 52*7c356e86SAndroid Build Coastguard Worker# name r The name of the test; should be unique 53*7c356e86SAndroid Build Coastguard Worker# description m What test does 54*7c356e86SAndroid Build Coastguard Worker# arguments M Arguments to pass to the program; 55*7c356e86SAndroid Build Coastguard Worker# default is no arguments. 56*7c356e86SAndroid Build Coastguard Worker# script m Value is written to a file which 57*7c356e86SAndroid Build Coastguard Worker# is passed as an argument to the program 58*7c356e86SAndroid Build Coastguard Worker# (after the arguments from arguments) 59*7c356e86SAndroid Build Coastguard Worker# stdin m Value is written to a file which is 60*7c356e86SAndroid Build Coastguard Worker# used as standard-input for the program; 61*7c356e86SAndroid Build Coastguard Worker# default is to use /dev/null. 62*7c356e86SAndroid Build Coastguard Worker# perl-setup m Value is a perl script which is executed 63*7c356e86SAndroid Build Coastguard Worker# just before the test is run. Try to 64*7c356e86SAndroid Build Coastguard Worker# avoid using this... 65*7c356e86SAndroid Build Coastguard Worker# perl-cleanup m Value is a perl script which is executed 66*7c356e86SAndroid Build Coastguard Worker# just after the test is run. Try to 67*7c356e86SAndroid Build Coastguard Worker# avoid using this... 68*7c356e86SAndroid Build Coastguard Worker# env-setup M Value is a list of NAME=VALUE elements 69*7c356e86SAndroid Build Coastguard Worker# which are put in the environment before 70*7c356e86SAndroid Build Coastguard Worker# the test is run. If the =VALUE is 71*7c356e86SAndroid Build Coastguard Worker# missing, NAME is removed from the 72*7c356e86SAndroid Build Coastguard Worker# environment. Programs are run with 73*7c356e86SAndroid Build Coastguard Worker# the following minimal environment: 74*7c356e86SAndroid Build Coastguard Worker# HOME, LD_LIBRARY_PATH, LOCPATH, 75*7c356e86SAndroid Build Coastguard Worker# LOGNAME, PATH, SHELL, UNIXMODE, 76*7c356e86SAndroid Build Coastguard Worker# UNIXROOT, USER 77*7c356e86SAndroid Build Coastguard Worker# (values taken from the environment of 78*7c356e86SAndroid Build Coastguard Worker# the test harness). 79*7c356e86SAndroid Build Coastguard Worker# CYGWIN is set to nodosfilewarning. 80*7c356e86SAndroid Build Coastguard Worker# ENV is set to /nonexistant. 81*7c356e86SAndroid Build Coastguard Worker# __progname is set to the -p argument. 82*7c356e86SAndroid Build Coastguard Worker# __perlname is set to $^X (perlexe). 83*7c356e86SAndroid Build Coastguard Worker# @utflocale@ is substituted from -U. 84*7c356e86SAndroid Build Coastguard Worker# file-setup mps Used to create files, directories 85*7c356e86SAndroid Build Coastguard Worker# and symlinks. First word is either 86*7c356e86SAndroid Build Coastguard Worker# file, dir or symlink; second word is 87*7c356e86SAndroid Build Coastguard Worker# permissions; this is followed by a 88*7c356e86SAndroid Build Coastguard Worker# quoted word that is the name of the 89*7c356e86SAndroid Build Coastguard Worker# file; the end-quote should be followed 90*7c356e86SAndroid Build Coastguard Worker# by a newline, then the file data 91*7c356e86SAndroid Build Coastguard Worker# (if any). The first word may be 92*7c356e86SAndroid Build Coastguard Worker# preceded by a ! to strip the trailing 93*7c356e86SAndroid Build Coastguard Worker# newline in a symlink. 94*7c356e86SAndroid Build Coastguard Worker# file-result mps Used to verify a file, symlink or 95*7c356e86SAndroid Build Coastguard Worker# directory is created correctly. 96*7c356e86SAndroid Build Coastguard Worker# The first word is either 97*7c356e86SAndroid Build Coastguard Worker# file, dir or symlink; second word is 98*7c356e86SAndroid Build Coastguard Worker# expected permissions; third word 99*7c356e86SAndroid Build Coastguard Worker# is user-id; fourth is group-id; 100*7c356e86SAndroid Build Coastguard Worker# fifth is "exact" or "pattern" 101*7c356e86SAndroid Build Coastguard Worker# indicating whether the file contents 102*7c356e86SAndroid Build Coastguard Worker# which follow is to be matched exactly 103*7c356e86SAndroid Build Coastguard Worker# or if it is a regular expression. 104*7c356e86SAndroid Build Coastguard Worker# The fifth argument is the quoted name 105*7c356e86SAndroid Build Coastguard Worker# of the file that should be created. 106*7c356e86SAndroid Build Coastguard Worker# The end-quote should be followed 107*7c356e86SAndroid Build Coastguard Worker# by a newline, then the file data 108*7c356e86SAndroid Build Coastguard Worker# (if any). The first word may be 109*7c356e86SAndroid Build Coastguard Worker# preceded by a ! to strip the trailing 110*7c356e86SAndroid Build Coastguard Worker# newline in the file contents. 111*7c356e86SAndroid Build Coastguard Worker# The permissions, user and group fields 112*7c356e86SAndroid Build Coastguard Worker# may be * meaning accept any value. 113*7c356e86SAndroid Build Coastguard Worker# time-limit Time limit - the program is sent a 114*7c356e86SAndroid Build Coastguard Worker# SIGKILL N seconds. Default is no 115*7c356e86SAndroid Build Coastguard Worker# limit. 116*7c356e86SAndroid Build Coastguard Worker# expected-fail 'yes' if the test is expected to fail. 117*7c356e86SAndroid Build Coastguard Worker# expected-exit expected exit code. Can be a number, 118*7c356e86SAndroid Build Coastguard Worker# or a C expression using the variables 119*7c356e86SAndroid Build Coastguard Worker# e, s and w (exit code, termination 120*7c356e86SAndroid Build Coastguard Worker# signal, and status code). 121*7c356e86SAndroid Build Coastguard Worker# expected-stdout m What the test should generate on stdout; 122*7c356e86SAndroid Build Coastguard Worker# default is to expect no output. 123*7c356e86SAndroid Build Coastguard Worker# expected-stdout-pattern m A perl pattern which matches the 124*7c356e86SAndroid Build Coastguard Worker# expected output. 125*7c356e86SAndroid Build Coastguard Worker# expected-stderr m What the test should generate on stderr; 126*7c356e86SAndroid Build Coastguard Worker# default is to expect no output. 127*7c356e86SAndroid Build Coastguard Worker# expected-stderr-pattern m A perl pattern which matches the 128*7c356e86SAndroid Build Coastguard Worker# expected standard error. 129*7c356e86SAndroid Build Coastguard Worker# category m Specify a comma separated list of 130*7c356e86SAndroid Build Coastguard Worker# 'categories' of program that the test 131*7c356e86SAndroid Build Coastguard Worker# is to be run for. A category can be 132*7c356e86SAndroid Build Coastguard Worker# negated by prefixing the name with a !. 133*7c356e86SAndroid Build Coastguard Worker# The idea is that some tests in a 134*7c356e86SAndroid Build Coastguard Worker# test suite may apply to a particular 135*7c356e86SAndroid Build Coastguard Worker# program version and shouldn't be run 136*7c356e86SAndroid Build Coastguard Worker# on other versions. The category(s) of 137*7c356e86SAndroid Build Coastguard Worker# the program being tested can be 138*7c356e86SAndroid Build Coastguard Worker# specified on the command line. 139*7c356e86SAndroid Build Coastguard Worker# One category os:XXX is predefined 140*7c356e86SAndroid Build Coastguard Worker# (XXX is the operating system name, 141*7c356e86SAndroid Build Coastguard Worker# eg, linux, dec_osf). 142*7c356e86SAndroid Build Coastguard Worker# need-ctty 'yes' if the test needs a ctty, run 143*7c356e86SAndroid Build Coastguard Worker# with -C regress:no-ctty to disable. 144*7c356e86SAndroid Build Coastguard Worker# Flag meanings: 145*7c356e86SAndroid Build Coastguard Worker# r tag is required (eg, a test must have a name tag). 146*7c356e86SAndroid Build Coastguard Worker# m value can be multiple lines. Lines must be prefixed with 147*7c356e86SAndroid Build Coastguard Worker# a tab. If the value part of the initial tag:value line is 148*7c356e86SAndroid Build Coastguard Worker# - empty: the initial blank line is stripped. 149*7c356e86SAndroid Build Coastguard Worker# - a lone !: the last newline in the value is stripped; 150*7c356e86SAndroid Build Coastguard Worker# M value can be multiple lines (prefixed by a tab) and consists 151*7c356e86SAndroid Build Coastguard Worker# of multiple fields, delimited by a field separator character. 152*7c356e86SAndroid Build Coastguard Worker# The value must start and end with the f-s-c. 153*7c356e86SAndroid Build Coastguard Worker# p tag takes parameters (used with m). 154*7c356e86SAndroid Build Coastguard Worker# s tag can be used several times. 155*7c356e86SAndroid Build Coastguard Worker 156*7c356e86SAndroid Build Coastguard Worker# require Config only if it exists 157*7c356e86SAndroid Build Coastguard Worker# pull EINTR from POSIX.pm or Errno.pm if they exist 158*7c356e86SAndroid Build Coastguard Worker# otherwise just skip it 159*7c356e86SAndroid Build Coastguard WorkerBEGIN { 160*7c356e86SAndroid Build Coastguard Worker eval { 161*7c356e86SAndroid Build Coastguard Worker require Config; 162*7c356e86SAndroid Build Coastguard Worker import Config; 163*7c356e86SAndroid Build Coastguard Worker 1; 164*7c356e86SAndroid Build Coastguard Worker }; 165*7c356e86SAndroid Build Coastguard Worker $EINTR = 0; 166*7c356e86SAndroid Build Coastguard Worker eval { 167*7c356e86SAndroid Build Coastguard Worker require POSIX; 168*7c356e86SAndroid Build Coastguard Worker $EINTR = POSIX::EINTR(); 169*7c356e86SAndroid Build Coastguard Worker }; 170*7c356e86SAndroid Build Coastguard Worker if ($@) { 171*7c356e86SAndroid Build Coastguard Worker eval { 172*7c356e86SAndroid Build Coastguard Worker require Errno; 173*7c356e86SAndroid Build Coastguard Worker $EINTR = Errno::EINTR(); 174*7c356e86SAndroid Build Coastguard Worker } or do { 175*7c356e86SAndroid Build Coastguard Worker $EINTR = 0; 176*7c356e86SAndroid Build Coastguard Worker }; 177*7c356e86SAndroid Build Coastguard Worker } 178*7c356e86SAndroid Build Coastguard Worker}; 179*7c356e86SAndroid Build Coastguard Worker 180*7c356e86SAndroid Build Coastguard Workeruse Getopt::Std; 181*7c356e86SAndroid Build Coastguard Worker 182*7c356e86SAndroid Build Coastguard Worker$os = defined $^O ? $^O : 'unknown'; 183*7c356e86SAndroid Build Coastguard Worker 184*7c356e86SAndroid Build Coastguard Worker($prog = $0) =~ s#.*/##; 185*7c356e86SAndroid Build Coastguard Worker 186*7c356e86SAndroid Build Coastguard Worker$Usage = <<EOF ; 187*7c356e86SAndroid Build Coastguard WorkerUsage: $prog [-Pv] [-C cat] [-e e=v] [-p prog] [-s fn] [-T dir] \ 188*7c356e86SAndroid Build Coastguard Worker [-t tmo] [-U lcl] name ... 189*7c356e86SAndroid Build Coastguard Worker -C c Specify the comma separated list of categories the program 190*7c356e86SAndroid Build Coastguard Worker belongs to (see category field). 191*7c356e86SAndroid Build Coastguard Worker -e e=v Set the environment variable e to v for all tests 192*7c356e86SAndroid Build Coastguard Worker (if no =v is given, the current value is used) 193*7c356e86SAndroid Build Coastguard Worker Only one -e option can be given at the moment, sadly. 194*7c356e86SAndroid Build Coastguard Worker -P program (-p) string has multiple words, and the program is in 195*7c356e86SAndroid Build Coastguard Worker the path (kludge option) 196*7c356e86SAndroid Build Coastguard Worker -p p Use p as the program to test 197*7c356e86SAndroid Build Coastguard Worker -s s Read tests from file s; if s is a directory, it is recursively 198*7c356e86SAndroid Build Coastguard Worker scanned for test files (which end in .t). 199*7c356e86SAndroid Build Coastguard Worker -T dir Use dir instead of /tmp to hold temporary files 200*7c356e86SAndroid Build Coastguard Worker -t t Use t as default time limit for tests (default is unlimited) 201*7c356e86SAndroid Build Coastguard Worker -U lcl Use lcl as UTF-8 locale (e.g. C.UTF-8) instead of the default 202*7c356e86SAndroid Build Coastguard Worker -v Verbose mode: print reason test failed. 203*7c356e86SAndroid Build Coastguard Worker name specifies the name of the test(s) to run; if none are 204*7c356e86SAndroid Build Coastguard Worker specified, all tests are run. 205*7c356e86SAndroid Build Coastguard WorkerEOF 206*7c356e86SAndroid Build Coastguard Worker 207*7c356e86SAndroid Build Coastguard Worker# See comment above for flag meanings 208*7c356e86SAndroid Build Coastguard Worker%test_fields = ( 209*7c356e86SAndroid Build Coastguard Worker 'name', 'r', 210*7c356e86SAndroid Build Coastguard Worker 'description', 'm', 211*7c356e86SAndroid Build Coastguard Worker 'arguments', 'M', 212*7c356e86SAndroid Build Coastguard Worker 'script', 'm', 213*7c356e86SAndroid Build Coastguard Worker 'stdin', 'm', 214*7c356e86SAndroid Build Coastguard Worker 'perl-setup', 'm', 215*7c356e86SAndroid Build Coastguard Worker 'perl-cleanup', 'm', 216*7c356e86SAndroid Build Coastguard Worker 'env-setup', 'M', 217*7c356e86SAndroid Build Coastguard Worker 'file-setup', 'mps', 218*7c356e86SAndroid Build Coastguard Worker 'file-result', 'mps', 219*7c356e86SAndroid Build Coastguard Worker 'time-limit', '', 220*7c356e86SAndroid Build Coastguard Worker 'expected-fail', '', 221*7c356e86SAndroid Build Coastguard Worker 'expected-exit', '', 222*7c356e86SAndroid Build Coastguard Worker 'expected-stdout', 'm', 223*7c356e86SAndroid Build Coastguard Worker 'expected-stdout-pattern', 'm', 224*7c356e86SAndroid Build Coastguard Worker 'expected-stderr', 'm', 225*7c356e86SAndroid Build Coastguard Worker 'expected-stderr-pattern', 'm', 226*7c356e86SAndroid Build Coastguard Worker 'category', 'm', 227*7c356e86SAndroid Build Coastguard Worker 'need-ctty', '', 228*7c356e86SAndroid Build Coastguard Worker 'need-pass', '', 229*7c356e86SAndroid Build Coastguard Worker ); 230*7c356e86SAndroid Build Coastguard Worker# Filled in by read_test() 231*7c356e86SAndroid Build Coastguard Worker%internal_test_fields = ( 232*7c356e86SAndroid Build Coastguard Worker ':full-name', 1, # file:name 233*7c356e86SAndroid Build Coastguard Worker ':long-name', 1, # dir/file:lineno:name 234*7c356e86SAndroid Build Coastguard Worker ); 235*7c356e86SAndroid Build Coastguard Worker 236*7c356e86SAndroid Build Coastguard Worker# Categories of the program under test. Provide the current 237*7c356e86SAndroid Build Coastguard Worker# os by default. 238*7c356e86SAndroid Build Coastguard Worker%categories = ( 239*7c356e86SAndroid Build Coastguard Worker "os:$os", '1' 240*7c356e86SAndroid Build Coastguard Worker ); 241*7c356e86SAndroid Build Coastguard Worker 242*7c356e86SAndroid Build Coastguard Worker$nfailed = 0; 243*7c356e86SAndroid Build Coastguard Worker$nifailed = 0; 244*7c356e86SAndroid Build Coastguard Worker$nxfailed = 0; 245*7c356e86SAndroid Build Coastguard Worker$npassed = 0; 246*7c356e86SAndroid Build Coastguard Worker$nxpassed = 0; 247*7c356e86SAndroid Build Coastguard Worker 248*7c356e86SAndroid Build Coastguard Worker%known_tests = (); 249*7c356e86SAndroid Build Coastguard Worker 250*7c356e86SAndroid Build Coastguard Workerif (!getopts('C:Ee:Pp:s:T:t:U:v')) { 251*7c356e86SAndroid Build Coastguard Worker print STDERR $Usage; 252*7c356e86SAndroid Build Coastguard Worker exit 1; 253*7c356e86SAndroid Build Coastguard Worker} 254*7c356e86SAndroid Build Coastguard Worker 255*7c356e86SAndroid Build Coastguard Workerdie "$prog: no program specified (use -p)\n" if !defined $opt_p; 256*7c356e86SAndroid Build Coastguard Workerdie "$prog: no test set specified (use -s)\n" if !defined $opt_s; 257*7c356e86SAndroid Build Coastguard Worker$test_prog = $opt_p; 258*7c356e86SAndroid Build Coastguard Worker$verbose = defined $opt_v && $opt_v; 259*7c356e86SAndroid Build Coastguard Worker$is_ebcdic = defined $opt_E && $opt_E; 260*7c356e86SAndroid Build Coastguard Worker$test_set = $opt_s; 261*7c356e86SAndroid Build Coastguard Worker$temp_base = $opt_T || "/tmp"; 262*7c356e86SAndroid Build Coastguard Worker$utflocale = $opt_U || (($os eq "hpux") ? "en_US.utf8" : "en_US.UTF-8"); 263*7c356e86SAndroid Build Coastguard Workerif (defined $opt_t) { 264*7c356e86SAndroid Build Coastguard Worker die "$prog: bad -t argument (should be number > 0): $opt_t\n" 265*7c356e86SAndroid Build Coastguard Worker if $opt_t !~ /^\d+$/ || $opt_t <= 0; 266*7c356e86SAndroid Build Coastguard Worker $default_time_limit = $opt_t; 267*7c356e86SAndroid Build Coastguard Worker} 268*7c356e86SAndroid Build Coastguard Worker$program_kludge = defined $opt_P ? $opt_P : 0; 269*7c356e86SAndroid Build Coastguard Worker 270*7c356e86SAndroid Build Coastguard Workerif ($is_ebcdic) { 271*7c356e86SAndroid Build Coastguard Worker $categories{'shell:ebcdic-yes'} = 1; 272*7c356e86SAndroid Build Coastguard Worker $categories{'shell:ascii-no'} = 1; 273*7c356e86SAndroid Build Coastguard Worker} else { 274*7c356e86SAndroid Build Coastguard Worker $categories{'shell:ebcdic-no'} = 1; 275*7c356e86SAndroid Build Coastguard Worker $categories{'shell:ascii-yes'} = 1; 276*7c356e86SAndroid Build Coastguard Worker} 277*7c356e86SAndroid Build Coastguard Worker 278*7c356e86SAndroid Build Coastguard Workerif (defined $opt_C) { 279*7c356e86SAndroid Build Coastguard Worker foreach $c (split(',', $opt_C)) { 280*7c356e86SAndroid Build Coastguard Worker $c =~ s/\s+//; 281*7c356e86SAndroid Build Coastguard Worker die "$prog: categories can't be negated on the command line\n" 282*7c356e86SAndroid Build Coastguard Worker if ($c =~ /^!/); 283*7c356e86SAndroid Build Coastguard Worker $categories{$c} = 1; 284*7c356e86SAndroid Build Coastguard Worker } 285*7c356e86SAndroid Build Coastguard Worker} 286*7c356e86SAndroid Build Coastguard Worker 287*7c356e86SAndroid Build Coastguard Worker# Note which tests are to be run. 288*7c356e86SAndroid Build Coastguard Worker%do_test = (); 289*7c356e86SAndroid Build Coastguard Workergrep($do_test{$_} = 1, @ARGV); 290*7c356e86SAndroid Build Coastguard Worker$all_tests = @ARGV == 0; 291*7c356e86SAndroid Build Coastguard Worker 292*7c356e86SAndroid Build Coastguard Worker# Set up a very minimal environment 293*7c356e86SAndroid Build Coastguard Worker%new_env = (); 294*7c356e86SAndroid Build Coastguard Workerforeach $env (('HOME', 'LD_LIBRARY_PATH', 'LOCPATH', 'LOGNAME', 295*7c356e86SAndroid Build Coastguard Worker 'PATH', 'PERLIO', 'SHELL', 'UNIXMODE', 'UNIXROOT', 'USER')) { 296*7c356e86SAndroid Build Coastguard Worker $new_env{$env} = $ENV{$env} if defined $ENV{$env}; 297*7c356e86SAndroid Build Coastguard Worker} 298*7c356e86SAndroid Build Coastguard Worker$new_env{'CYGWIN'} = 'nodosfilewarning'; 299*7c356e86SAndroid Build Coastguard Worker$new_env{'ENV'} = '/nonexistant'; 300*7c356e86SAndroid Build Coastguard Worker 301*7c356e86SAndroid Build Coastguard Workerif (($os eq 'VMS') || ($Config{perlpath} =~ m/$Config{_exe}$/i)) { 302*7c356e86SAndroid Build Coastguard Worker $new_env{'__perlname'} = $Config{perlpath}; 303*7c356e86SAndroid Build Coastguard Worker} else { 304*7c356e86SAndroid Build Coastguard Worker $new_env{'__perlname'} = $Config{perlpath} . $Config{_exe}; 305*7c356e86SAndroid Build Coastguard Worker} 306*7c356e86SAndroid Build Coastguard Worker$new_env{'__perlname'} = $^X if ($new_env{'__perlname'} eq '') and -f $^X and -x $^X; 307*7c356e86SAndroid Build Coastguard Workerif ($new_env{'__perlname'} eq '') { 308*7c356e86SAndroid Build Coastguard Worker foreach $pathelt (split /:/,$ENV{'PATH'}) { 309*7c356e86SAndroid Build Coastguard Worker chomp($pathelt = `pwd`) if $pathelt eq ''; 310*7c356e86SAndroid Build Coastguard Worker my $x = $pathelt . '/' . $^X; 311*7c356e86SAndroid Build Coastguard Worker next unless -f $x and -x $x; 312*7c356e86SAndroid Build Coastguard Worker $new_env{'__perlname'} = $x; 313*7c356e86SAndroid Build Coastguard Worker last; 314*7c356e86SAndroid Build Coastguard Worker } 315*7c356e86SAndroid Build Coastguard Worker} 316*7c356e86SAndroid Build Coastguard Worker$new_env{'__perlname'} = $^X if ($new_env{'__perlname'} eq ''); 317*7c356e86SAndroid Build Coastguard Worker 318*7c356e86SAndroid Build Coastguard Workerif (defined $opt_e) { 319*7c356e86SAndroid Build Coastguard Worker # XXX need a way to allow many -e arguments... 320*7c356e86SAndroid Build Coastguard Worker if ($opt_e =~ /^([a-zA-Z_]\w*)(|=(.*))$/) { 321*7c356e86SAndroid Build Coastguard Worker $new_env{$1} = $2 eq '' ? $ENV{$1} : $3; 322*7c356e86SAndroid Build Coastguard Worker } else { 323*7c356e86SAndroid Build Coastguard Worker die "$0: bad -e argument: $opt_e\n"; 324*7c356e86SAndroid Build Coastguard Worker } 325*7c356e86SAndroid Build Coastguard Worker} 326*7c356e86SAndroid Build Coastguard Worker%old_env = %ENV; 327*7c356e86SAndroid Build Coastguard Worker 328*7c356e86SAndroid Build Coastguard Workerchop($pwd = `pwd 2>/dev/null`); 329*7c356e86SAndroid Build Coastguard Workerdie "$prog: couldn't get current working directory\n" if $pwd eq ''; 330*7c356e86SAndroid Build Coastguard Workerdie "$prog: couldn't cd to $pwd - $!\n" if !chdir($pwd); 331*7c356e86SAndroid Build Coastguard Worker 332*7c356e86SAndroid Build Coastguard Workerdie "$prog: couldn't cd to $temp_base - $!\n" if !chdir($temp_base); 333*7c356e86SAndroid Build Coastguard Workerdie "$prog: couldn't get temporary directory base\n" unless -d '.'; 334*7c356e86SAndroid Build Coastguard Worker$temps = sprintf("chk%d-%d.", $$, time()); 335*7c356e86SAndroid Build Coastguard Worker$tempi = 0; 336*7c356e86SAndroid Build Coastguard Workeruntil (mkdir(($tempdir = sprintf("%s%03d", $temps, $tempi)), 0700)) { 337*7c356e86SAndroid Build Coastguard Worker die "$prog: couldn't get temporary directory\n" if $tempi++ >= 999; 338*7c356e86SAndroid Build Coastguard Worker} 339*7c356e86SAndroid Build Coastguard Workerdie "$prog: couldn't cd to $tempdir - $!\n" if !chdir($tempdir); 340*7c356e86SAndroid Build Coastguard Workerchop($temp_dir = `pwd 2>/dev/null`); 341*7c356e86SAndroid Build Coastguard Workerdie "$prog: couldn't get temporary directory\n" if $temp_dir eq ''; 342*7c356e86SAndroid Build Coastguard Workerdie "$prog: couldn't cd to $pwd - $!\n" if !chdir($pwd); 343*7c356e86SAndroid Build Coastguard Worker 344*7c356e86SAndroid Build Coastguard Workerif (!$program_kludge) { 345*7c356e86SAndroid Build Coastguard Worker $test_prog = "$pwd/$test_prog" if (substr($test_prog, 0, 1) ne '/') && 346*7c356e86SAndroid Build Coastguard Worker ($os ne 'os2' || substr($test_prog, 1, 1) ne ':'); 347*7c356e86SAndroid Build Coastguard Worker die "$prog: $test_prog is not executable - bye\n" 348*7c356e86SAndroid Build Coastguard Worker if (! -x $test_prog && $os ne 'os2'); 349*7c356e86SAndroid Build Coastguard Worker} 350*7c356e86SAndroid Build Coastguard Worker 351*7c356e86SAndroid Build Coastguard Worker@trap_sigs = ('TERM', 'QUIT', 'INT', 'PIPE', 'HUP'); 352*7c356e86SAndroid Build Coastguard Worker@SIG{@trap_sigs} = ('cleanup_exit') x @trap_sigs; 353*7c356e86SAndroid Build Coastguard Worker$child_kill_ok = 0; 354*7c356e86SAndroid Build Coastguard Worker$SIG{'ALRM'} = 'catch_sigalrm'; 355*7c356e86SAndroid Build Coastguard Worker 356*7c356e86SAndroid Build Coastguard Worker$| = 1; 357*7c356e86SAndroid Build Coastguard Worker 358*7c356e86SAndroid Build Coastguard Worker# Create temp files 359*7c356e86SAndroid Build Coastguard Worker$temps = "${temp_dir}/rts"; 360*7c356e86SAndroid Build Coastguard Worker$tempi = "${temp_dir}/rti"; 361*7c356e86SAndroid Build Coastguard Worker$tempo = "${temp_dir}/rto"; 362*7c356e86SAndroid Build Coastguard Worker$tempe = "${temp_dir}/rte"; 363*7c356e86SAndroid Build Coastguard Worker$tempdir = "${temp_dir}/rtd"; 364*7c356e86SAndroid Build Coastguard Workermkdir($tempdir, 0700) or die "$prog: couldn't mkdir $tempdir - $!\n"; 365*7c356e86SAndroid Build Coastguard Worker 366*7c356e86SAndroid Build Coastguard Workerif (-d $test_set) { 367*7c356e86SAndroid Build Coastguard Worker $file_prefix_skip = length($test_set) + 1; 368*7c356e86SAndroid Build Coastguard Worker $ret = &process_test_dir($test_set); 369*7c356e86SAndroid Build Coastguard Worker} else { 370*7c356e86SAndroid Build Coastguard Worker $file_prefix_skip = 0; 371*7c356e86SAndroid Build Coastguard Worker $ret = &process_test_file($test_set); 372*7c356e86SAndroid Build Coastguard Worker} 373*7c356e86SAndroid Build Coastguard Worker&cleanup_exit() if !defined $ret; 374*7c356e86SAndroid Build Coastguard Worker 375*7c356e86SAndroid Build Coastguard Worker$tot_failed = $nfailed + $nifailed + $nxfailed; 376*7c356e86SAndroid Build Coastguard Worker$tot_passed = $npassed + $nxpassed; 377*7c356e86SAndroid Build Coastguard Workerif ($tot_failed || $tot_passed) { 378*7c356e86SAndroid Build Coastguard Worker print "Total failed: $tot_failed"; 379*7c356e86SAndroid Build Coastguard Worker print " ($nifailed ignored)" if $nifailed; 380*7c356e86SAndroid Build Coastguard Worker print " ($nxfailed unexpected)" if $nxfailed; 381*7c356e86SAndroid Build Coastguard Worker print " (as expected)" if $nfailed && !$nxfailed && !$nifailed; 382*7c356e86SAndroid Build Coastguard Worker print " ($nfailed expected)" if $nfailed && ($nxfailed || $nifailed); 383*7c356e86SAndroid Build Coastguard Worker print "\nTotal passed: $tot_passed"; 384*7c356e86SAndroid Build Coastguard Worker print " ($nxpassed unexpected)" if $nxpassed; 385*7c356e86SAndroid Build Coastguard Worker print "\n"; 386*7c356e86SAndroid Build Coastguard Worker} 387*7c356e86SAndroid Build Coastguard Worker 388*7c356e86SAndroid Build Coastguard Worker&cleanup_exit('ok'); 389*7c356e86SAndroid Build Coastguard Worker 390*7c356e86SAndroid Build Coastguard Workersub 391*7c356e86SAndroid Build Coastguard Workercleanup_exit 392*7c356e86SAndroid Build Coastguard Worker{ 393*7c356e86SAndroid Build Coastguard Worker local($sig, $exitcode) = ('', 1); 394*7c356e86SAndroid Build Coastguard Worker 395*7c356e86SAndroid Build Coastguard Worker if ($_[0] eq 'ok') { 396*7c356e86SAndroid Build Coastguard Worker unless ($nxfailed) { 397*7c356e86SAndroid Build Coastguard Worker $exitcode = 0; 398*7c356e86SAndroid Build Coastguard Worker } else { 399*7c356e86SAndroid Build Coastguard Worker $exitcode = 1; 400*7c356e86SAndroid Build Coastguard Worker } 401*7c356e86SAndroid Build Coastguard Worker } elsif ($_[0] ne '') { 402*7c356e86SAndroid Build Coastguard Worker $sig = $_[0]; 403*7c356e86SAndroid Build Coastguard Worker } 404*7c356e86SAndroid Build Coastguard Worker 405*7c356e86SAndroid Build Coastguard Worker unlink($tempi, $tempo, $tempe, $temps); 406*7c356e86SAndroid Build Coastguard Worker &scrub_dir($tempdir) if defined $tempdir; 407*7c356e86SAndroid Build Coastguard Worker rmdir($tempdir) if defined $tempdir; 408*7c356e86SAndroid Build Coastguard Worker rmdir($temp_dir) if defined $temp_dir; 409*7c356e86SAndroid Build Coastguard Worker 410*7c356e86SAndroid Build Coastguard Worker if ($sig) { 411*7c356e86SAndroid Build Coastguard Worker $SIG{$sig} = 'DEFAULT'; 412*7c356e86SAndroid Build Coastguard Worker kill $sig, $$; 413*7c356e86SAndroid Build Coastguard Worker return; 414*7c356e86SAndroid Build Coastguard Worker } 415*7c356e86SAndroid Build Coastguard Worker exit $exitcode; 416*7c356e86SAndroid Build Coastguard Worker} 417*7c356e86SAndroid Build Coastguard Worker 418*7c356e86SAndroid Build Coastguard Workersub 419*7c356e86SAndroid Build Coastguard Workercatch_sigalrm 420*7c356e86SAndroid Build Coastguard Worker{ 421*7c356e86SAndroid Build Coastguard Worker $SIG{'ALRM'} = 'catch_sigalrm'; 422*7c356e86SAndroid Build Coastguard Worker kill(9, $child_pid) if $child_kill_ok; 423*7c356e86SAndroid Build Coastguard Worker $child_killed = 1; 424*7c356e86SAndroid Build Coastguard Worker} 425*7c356e86SAndroid Build Coastguard Worker 426*7c356e86SAndroid Build Coastguard Workersub 427*7c356e86SAndroid Build Coastguard Workerprocess_test_dir 428*7c356e86SAndroid Build Coastguard Worker{ 429*7c356e86SAndroid Build Coastguard Worker local($dir) = @_; 430*7c356e86SAndroid Build Coastguard Worker local($ret, $file); 431*7c356e86SAndroid Build Coastguard Worker local(@todo) = (); 432*7c356e86SAndroid Build Coastguard Worker 433*7c356e86SAndroid Build Coastguard Worker if (!opendir(DIR, $dir)) { 434*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog: can't open directory $dir - $!\n"; 435*7c356e86SAndroid Build Coastguard Worker return undef; 436*7c356e86SAndroid Build Coastguard Worker } 437*7c356e86SAndroid Build Coastguard Worker while (defined ($file = readdir(DIR))) { 438*7c356e86SAndroid Build Coastguard Worker push(@todo, $file) if $file =~ /^[^.].*\.t$/; 439*7c356e86SAndroid Build Coastguard Worker } 440*7c356e86SAndroid Build Coastguard Worker closedir(DIR); 441*7c356e86SAndroid Build Coastguard Worker 442*7c356e86SAndroid Build Coastguard Worker foreach $file (@todo) { 443*7c356e86SAndroid Build Coastguard Worker $file = "$dir/$file"; 444*7c356e86SAndroid Build Coastguard Worker if (-d $file) { 445*7c356e86SAndroid Build Coastguard Worker $ret = &process_test_dir($file); 446*7c356e86SAndroid Build Coastguard Worker } elsif (-f _) { 447*7c356e86SAndroid Build Coastguard Worker $ret = &process_test_file($file); 448*7c356e86SAndroid Build Coastguard Worker } 449*7c356e86SAndroid Build Coastguard Worker last if !defined $ret; 450*7c356e86SAndroid Build Coastguard Worker } 451*7c356e86SAndroid Build Coastguard Worker 452*7c356e86SAndroid Build Coastguard Worker return $ret; 453*7c356e86SAndroid Build Coastguard Worker} 454*7c356e86SAndroid Build Coastguard Worker 455*7c356e86SAndroid Build Coastguard Workersub 456*7c356e86SAndroid Build Coastguard Workerprocess_test_file 457*7c356e86SAndroid Build Coastguard Worker{ 458*7c356e86SAndroid Build Coastguard Worker local($file) = @_; 459*7c356e86SAndroid Build Coastguard Worker local($ret); 460*7c356e86SAndroid Build Coastguard Worker 461*7c356e86SAndroid Build Coastguard Worker if (!open(IN, $file)) { 462*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog: can't open $file - $!\n"; 463*7c356e86SAndroid Build Coastguard Worker return undef; 464*7c356e86SAndroid Build Coastguard Worker } 465*7c356e86SAndroid Build Coastguard Worker binmode(IN); 466*7c356e86SAndroid Build Coastguard Worker while (1) { 467*7c356e86SAndroid Build Coastguard Worker $ret = &read_test($file, IN, *test); 468*7c356e86SAndroid Build Coastguard Worker last if !defined $ret || !$ret; 469*7c356e86SAndroid Build Coastguard Worker next if !$all_tests && !$do_test{$test{'name'}}; 470*7c356e86SAndroid Build Coastguard Worker next if !&category_check(*test); 471*7c356e86SAndroid Build Coastguard Worker $ret = &run_test(*test); 472*7c356e86SAndroid Build Coastguard Worker last if !defined $ret; 473*7c356e86SAndroid Build Coastguard Worker } 474*7c356e86SAndroid Build Coastguard Worker close(IN); 475*7c356e86SAndroid Build Coastguard Worker 476*7c356e86SAndroid Build Coastguard Worker return $ret; 477*7c356e86SAndroid Build Coastguard Worker} 478*7c356e86SAndroid Build Coastguard Worker 479*7c356e86SAndroid Build Coastguard Workersub 480*7c356e86SAndroid Build Coastguard Workerrun_test 481*7c356e86SAndroid Build Coastguard Worker{ 482*7c356e86SAndroid Build Coastguard Worker local(*test) = @_; 483*7c356e86SAndroid Build Coastguard Worker local($name) = $test{':full-name'}; 484*7c356e86SAndroid Build Coastguard Worker 485*7c356e86SAndroid Build Coastguard Worker return undef if !&scrub_dir($tempdir); 486*7c356e86SAndroid Build Coastguard Worker 487*7c356e86SAndroid Build Coastguard Worker if (defined $test{'stdin'}) { 488*7c356e86SAndroid Build Coastguard Worker return undef if !&write_file($tempi, $test{'stdin'}); 489*7c356e86SAndroid Build Coastguard Worker $ifile = $tempi; 490*7c356e86SAndroid Build Coastguard Worker } else { 491*7c356e86SAndroid Build Coastguard Worker $ifile = '/dev/null'; 492*7c356e86SAndroid Build Coastguard Worker } 493*7c356e86SAndroid Build Coastguard Worker 494*7c356e86SAndroid Build Coastguard Worker if (defined $test{'script'}) { 495*7c356e86SAndroid Build Coastguard Worker return undef if !&write_file($temps, $test{'script'}); 496*7c356e86SAndroid Build Coastguard Worker } 497*7c356e86SAndroid Build Coastguard Worker 498*7c356e86SAndroid Build Coastguard Worker if (!chdir($tempdir)) { 499*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog: couldn't cd to $tempdir - $!\n"; 500*7c356e86SAndroid Build Coastguard Worker return undef; 501*7c356e86SAndroid Build Coastguard Worker } 502*7c356e86SAndroid Build Coastguard Worker 503*7c356e86SAndroid Build Coastguard Worker if (defined $test{'file-setup'}) { 504*7c356e86SAndroid Build Coastguard Worker local($i); 505*7c356e86SAndroid Build Coastguard Worker local($type, $perm, $rest, $c, $len, $name); 506*7c356e86SAndroid Build Coastguard Worker 507*7c356e86SAndroid Build Coastguard Worker for ($i = 0; $i < $test{'file-setup'}; $i++) { 508*7c356e86SAndroid Build Coastguard Worker $val = $test{"file-setup:$i"}; 509*7c356e86SAndroid Build Coastguard Worker 510*7c356e86SAndroid Build Coastguard Worker # format is: type perm "name" 511*7c356e86SAndroid Build Coastguard Worker ($type, $perm, $rest) = 512*7c356e86SAndroid Build Coastguard Worker split(' ', $val, 3); 513*7c356e86SAndroid Build Coastguard Worker $c = substr($rest, 0, 1); 514*7c356e86SAndroid Build Coastguard Worker $len = index($rest, $c, 1) - 1; 515*7c356e86SAndroid Build Coastguard Worker $name = substr($rest, 1, $len); 516*7c356e86SAndroid Build Coastguard Worker $rest = substr($rest, 2 + $len); 517*7c356e86SAndroid Build Coastguard Worker $perm = oct($perm) if $perm =~ /^\d+$/; 518*7c356e86SAndroid Build Coastguard Worker if ($type eq 'file') { 519*7c356e86SAndroid Build Coastguard Worker return undef if !&write_file($name, $rest); 520*7c356e86SAndroid Build Coastguard Worker if (!chmod($perm, $name)) { 521*7c356e86SAndroid Build Coastguard Worker print STDERR 522*7c356e86SAndroid Build Coastguard Worker "$prog:$test{':long-name'}: can't chmod $perm $name - $!\n"; 523*7c356e86SAndroid Build Coastguard Worker return undef; 524*7c356e86SAndroid Build Coastguard Worker } 525*7c356e86SAndroid Build Coastguard Worker } elsif ($type eq 'dir') { 526*7c356e86SAndroid Build Coastguard Worker if (!mkdir($name, $perm)) { 527*7c356e86SAndroid Build Coastguard Worker print STDERR 528*7c356e86SAndroid Build Coastguard Worker "$prog:$test{':long-name'}: can't mkdir $perm $name - $!\n"; 529*7c356e86SAndroid Build Coastguard Worker return undef; 530*7c356e86SAndroid Build Coastguard Worker } 531*7c356e86SAndroid Build Coastguard Worker } elsif ($type eq 'symlink') { 532*7c356e86SAndroid Build Coastguard Worker local($oumask) = umask($perm); 533*7c356e86SAndroid Build Coastguard Worker local($ret) = symlink($rest, $name); 534*7c356e86SAndroid Build Coastguard Worker umask($oumask); 535*7c356e86SAndroid Build Coastguard Worker if (!$ret) { 536*7c356e86SAndroid Build Coastguard Worker print STDERR 537*7c356e86SAndroid Build Coastguard Worker "$prog:$test{':long-name'}: couldn't create symlink $name - $!\n"; 538*7c356e86SAndroid Build Coastguard Worker return undef; 539*7c356e86SAndroid Build Coastguard Worker } 540*7c356e86SAndroid Build Coastguard Worker } 541*7c356e86SAndroid Build Coastguard Worker } 542*7c356e86SAndroid Build Coastguard Worker } 543*7c356e86SAndroid Build Coastguard Worker 544*7c356e86SAndroid Build Coastguard Worker if (defined $test{'perl-setup'}) { 545*7c356e86SAndroid Build Coastguard Worker eval $test{'perl-setup'}; 546*7c356e86SAndroid Build Coastguard Worker if ($@ ne '') { 547*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog:$test{':long-name'}: error running perl-setup - $@\n"; 548*7c356e86SAndroid Build Coastguard Worker return undef; 549*7c356e86SAndroid Build Coastguard Worker } 550*7c356e86SAndroid Build Coastguard Worker } 551*7c356e86SAndroid Build Coastguard Worker 552*7c356e86SAndroid Build Coastguard Worker $pid = fork; 553*7c356e86SAndroid Build Coastguard Worker if (!defined $pid) { 554*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog: can't fork - $!\n"; 555*7c356e86SAndroid Build Coastguard Worker return undef; 556*7c356e86SAndroid Build Coastguard Worker } 557*7c356e86SAndroid Build Coastguard Worker if (!$pid) { 558*7c356e86SAndroid Build Coastguard Worker @SIG{@trap_sigs} = ('DEFAULT') x @trap_sigs; 559*7c356e86SAndroid Build Coastguard Worker $SIG{'ALRM'} = 'DEFAULT'; 560*7c356e86SAndroid Build Coastguard Worker if (defined $test{'env-setup'}) { 561*7c356e86SAndroid Build Coastguard Worker local($var, $val, $i); 562*7c356e86SAndroid Build Coastguard Worker 563*7c356e86SAndroid Build Coastguard Worker foreach $var (split(substr($test{'env-setup'}, 0, 1), 564*7c356e86SAndroid Build Coastguard Worker $test{'env-setup'})) 565*7c356e86SAndroid Build Coastguard Worker { 566*7c356e86SAndroid Build Coastguard Worker $i = index($var, '='); 567*7c356e86SAndroid Build Coastguard Worker next if $i == 0 || $var eq ''; 568*7c356e86SAndroid Build Coastguard Worker if ($i < 0) { 569*7c356e86SAndroid Build Coastguard Worker delete $new_env{$var}; 570*7c356e86SAndroid Build Coastguard Worker } else { 571*7c356e86SAndroid Build Coastguard Worker $new_env{substr($var, 0, $i)} = substr($var, $i + 1); 572*7c356e86SAndroid Build Coastguard Worker } 573*7c356e86SAndroid Build Coastguard Worker } 574*7c356e86SAndroid Build Coastguard Worker } 575*7c356e86SAndroid Build Coastguard Worker if (!open(STDIN, "< $ifile")) { 576*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog: couldn't open $ifile in child - $!\n"; 577*7c356e86SAndroid Build Coastguard Worker kill('TERM', $$); 578*7c356e86SAndroid Build Coastguard Worker } 579*7c356e86SAndroid Build Coastguard Worker binmode(STDIN); 580*7c356e86SAndroid Build Coastguard Worker if (!open(STDOUT, "> $tempo")) { 581*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog: couldn't open $tempo in child - $!\n"; 582*7c356e86SAndroid Build Coastguard Worker kill('TERM', $$); 583*7c356e86SAndroid Build Coastguard Worker } 584*7c356e86SAndroid Build Coastguard Worker binmode(STDOUT); 585*7c356e86SAndroid Build Coastguard Worker if (!open(STDERR, "> $tempe")) { 586*7c356e86SAndroid Build Coastguard Worker print STDOUT "$prog: couldn't open $tempe in child - $!\n"; 587*7c356e86SAndroid Build Coastguard Worker kill('TERM', $$); 588*7c356e86SAndroid Build Coastguard Worker } 589*7c356e86SAndroid Build Coastguard Worker binmode(STDERR); 590*7c356e86SAndroid Build Coastguard Worker if ($program_kludge) { 591*7c356e86SAndroid Build Coastguard Worker @argv = split(' ', $test_prog); 592*7c356e86SAndroid Build Coastguard Worker } else { 593*7c356e86SAndroid Build Coastguard Worker @argv = ($test_prog); 594*7c356e86SAndroid Build Coastguard Worker } 595*7c356e86SAndroid Build Coastguard Worker if (defined $test{'arguments'}) { 596*7c356e86SAndroid Build Coastguard Worker push(@argv, 597*7c356e86SAndroid Build Coastguard Worker split(substr($test{'arguments'}, 0, 1), 598*7c356e86SAndroid Build Coastguard Worker substr($test{'arguments'}, 1))); 599*7c356e86SAndroid Build Coastguard Worker } 600*7c356e86SAndroid Build Coastguard Worker push(@argv, $temps) if defined $test{'script'}; 601*7c356e86SAndroid Build Coastguard Worker 602*7c356e86SAndroid Build Coastguard Worker #XXX realpathise, use command -v/whence -p/which, or sth. like that 603*7c356e86SAndroid Build Coastguard Worker #XXX if !$program_kludge, we get by with not doing it for now tho 604*7c356e86SAndroid Build Coastguard Worker $new_env{'__progname'} = $argv[0]; 605*7c356e86SAndroid Build Coastguard Worker 606*7c356e86SAndroid Build Coastguard Worker # The following doesn't work with perl5... Need to do it explicitly - yuck. 607*7c356e86SAndroid Build Coastguard Worker #%ENV = %new_env; 608*7c356e86SAndroid Build Coastguard Worker foreach $k (keys(%ENV)) { 609*7c356e86SAndroid Build Coastguard Worker delete $ENV{$k}; 610*7c356e86SAndroid Build Coastguard Worker } 611*7c356e86SAndroid Build Coastguard Worker $ENV{$k} = $v while ($k,$v) = each %new_env; 612*7c356e86SAndroid Build Coastguard Worker 613*7c356e86SAndroid Build Coastguard Worker exec { $argv[0] } @argv; 614*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog: couldn't execute $test_prog - $!\n"; 615*7c356e86SAndroid Build Coastguard Worker kill('TERM', $$); 616*7c356e86SAndroid Build Coastguard Worker exit(95); 617*7c356e86SAndroid Build Coastguard Worker } 618*7c356e86SAndroid Build Coastguard Worker $child_pid = $pid; 619*7c356e86SAndroid Build Coastguard Worker $child_killed = 0; 620*7c356e86SAndroid Build Coastguard Worker $child_kill_ok = 1; 621*7c356e86SAndroid Build Coastguard Worker alarm($test{'time-limit'}) if defined $test{'time-limit'}; 622*7c356e86SAndroid Build Coastguard Worker while (1) { 623*7c356e86SAndroid Build Coastguard Worker $xpid = waitpid($pid, 0); 624*7c356e86SAndroid Build Coastguard Worker $child_kill_ok = 0; 625*7c356e86SAndroid Build Coastguard Worker if ($xpid < 0) { 626*7c356e86SAndroid Build Coastguard Worker if ($EINTR) { 627*7c356e86SAndroid Build Coastguard Worker next if $! == $EINTR; 628*7c356e86SAndroid Build Coastguard Worker } 629*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog: error waiting for child - $!\n"; 630*7c356e86SAndroid Build Coastguard Worker return undef; 631*7c356e86SAndroid Build Coastguard Worker } 632*7c356e86SAndroid Build Coastguard Worker last; 633*7c356e86SAndroid Build Coastguard Worker } 634*7c356e86SAndroid Build Coastguard Worker $status = $?; 635*7c356e86SAndroid Build Coastguard Worker alarm(0) if defined $test{'time-limit'}; 636*7c356e86SAndroid Build Coastguard Worker 637*7c356e86SAndroid Build Coastguard Worker $failed = 0; 638*7c356e86SAndroid Build Coastguard Worker $why = ''; 639*7c356e86SAndroid Build Coastguard Worker 640*7c356e86SAndroid Build Coastguard Worker if ($child_killed) { 641*7c356e86SAndroid Build Coastguard Worker $failed = 1; 642*7c356e86SAndroid Build Coastguard Worker $why .= "\ttest timed out (limit of $test{'time-limit'} seconds)\n"; 643*7c356e86SAndroid Build Coastguard Worker } 644*7c356e86SAndroid Build Coastguard Worker 645*7c356e86SAndroid Build Coastguard Worker $ret = &eval_exit($test{'long-name'}, $status, $test{'expected-exit'}); 646*7c356e86SAndroid Build Coastguard Worker return undef if !defined $ret; 647*7c356e86SAndroid Build Coastguard Worker if (!$ret) { 648*7c356e86SAndroid Build Coastguard Worker local($expl); 649*7c356e86SAndroid Build Coastguard Worker 650*7c356e86SAndroid Build Coastguard Worker $failed = 1; 651*7c356e86SAndroid Build Coastguard Worker if (($status & 0xff) == 0x7f) { 652*7c356e86SAndroid Build Coastguard Worker $expl = "stopped"; 653*7c356e86SAndroid Build Coastguard Worker } elsif (($status & 0xff)) { 654*7c356e86SAndroid Build Coastguard Worker $expl = "signal " . ($status & 0x7f); 655*7c356e86SAndroid Build Coastguard Worker } else { 656*7c356e86SAndroid Build Coastguard Worker $expl = "exit-code " . (($status >> 8) & 0xff); 657*7c356e86SAndroid Build Coastguard Worker } 658*7c356e86SAndroid Build Coastguard Worker $why .= 659*7c356e86SAndroid Build Coastguard Worker "\tunexpected exit status $status ($expl), expected $test{'expected-exit'}\n"; 660*7c356e86SAndroid Build Coastguard Worker } 661*7c356e86SAndroid Build Coastguard Worker 662*7c356e86SAndroid Build Coastguard Worker $tmp = &check_output($test{'long-name'}, $tempo, 'stdout', 663*7c356e86SAndroid Build Coastguard Worker $test{'expected-stdout'}, $test{'expected-stdout-pattern'}); 664*7c356e86SAndroid Build Coastguard Worker return undef if !defined $tmp; 665*7c356e86SAndroid Build Coastguard Worker if ($tmp ne '') { 666*7c356e86SAndroid Build Coastguard Worker $failed = 1; 667*7c356e86SAndroid Build Coastguard Worker $why .= $tmp; 668*7c356e86SAndroid Build Coastguard Worker } 669*7c356e86SAndroid Build Coastguard Worker 670*7c356e86SAndroid Build Coastguard Worker $tmp = &check_output($test{'long-name'}, $tempe, 'stderr', 671*7c356e86SAndroid Build Coastguard Worker $test{'expected-stderr'}, $test{'expected-stderr-pattern'}); 672*7c356e86SAndroid Build Coastguard Worker return undef if !defined $tmp; 673*7c356e86SAndroid Build Coastguard Worker if ($tmp ne '') { 674*7c356e86SAndroid Build Coastguard Worker $failed = 1; 675*7c356e86SAndroid Build Coastguard Worker $why .= $tmp; 676*7c356e86SAndroid Build Coastguard Worker } 677*7c356e86SAndroid Build Coastguard Worker 678*7c356e86SAndroid Build Coastguard Worker $tmp = &check_file_result(*test); 679*7c356e86SAndroid Build Coastguard Worker return undef if !defined $tmp; 680*7c356e86SAndroid Build Coastguard Worker if ($tmp ne '') { 681*7c356e86SAndroid Build Coastguard Worker $failed = 1; 682*7c356e86SAndroid Build Coastguard Worker $why .= $tmp; 683*7c356e86SAndroid Build Coastguard Worker } 684*7c356e86SAndroid Build Coastguard Worker 685*7c356e86SAndroid Build Coastguard Worker if (defined $test{'perl-cleanup'}) { 686*7c356e86SAndroid Build Coastguard Worker eval $test{'perl-cleanup'}; 687*7c356e86SAndroid Build Coastguard Worker if ($@ ne '') { 688*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog:$test{':long-name'}: error running perl-cleanup - $@\n"; 689*7c356e86SAndroid Build Coastguard Worker return undef; 690*7c356e86SAndroid Build Coastguard Worker } 691*7c356e86SAndroid Build Coastguard Worker } 692*7c356e86SAndroid Build Coastguard Worker 693*7c356e86SAndroid Build Coastguard Worker if (!chdir($pwd)) { 694*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog: couldn't cd to $pwd - $!\n"; 695*7c356e86SAndroid Build Coastguard Worker return undef; 696*7c356e86SAndroid Build Coastguard Worker } 697*7c356e86SAndroid Build Coastguard Worker 698*7c356e86SAndroid Build Coastguard Worker if ($failed) { 699*7c356e86SAndroid Build Coastguard Worker if (!$test{'expected-fail'}) { 700*7c356e86SAndroid Build Coastguard Worker if ($test{'need-pass'}) { 701*7c356e86SAndroid Build Coastguard Worker print "FAIL $name\n"; 702*7c356e86SAndroid Build Coastguard Worker $nxfailed++; 703*7c356e86SAndroid Build Coastguard Worker } else { 704*7c356e86SAndroid Build Coastguard Worker print "FAIL $name (ignored)\n"; 705*7c356e86SAndroid Build Coastguard Worker $nifailed++; 706*7c356e86SAndroid Build Coastguard Worker } 707*7c356e86SAndroid Build Coastguard Worker } else { 708*7c356e86SAndroid Build Coastguard Worker print "fail $name (as expected)\n"; 709*7c356e86SAndroid Build Coastguard Worker $nfailed++; 710*7c356e86SAndroid Build Coastguard Worker } 711*7c356e86SAndroid Build Coastguard Worker $why = "\tDescription" 712*7c356e86SAndroid Build Coastguard Worker . &wrap_lines($test{'description'}, " (missing)\n") 713*7c356e86SAndroid Build Coastguard Worker . $why; 714*7c356e86SAndroid Build Coastguard Worker } elsif ($test{'expected-fail'}) { 715*7c356e86SAndroid Build Coastguard Worker print "PASS $name (unexpectedly)\n"; 716*7c356e86SAndroid Build Coastguard Worker $nxpassed++; 717*7c356e86SAndroid Build Coastguard Worker } else { 718*7c356e86SAndroid Build Coastguard Worker print "pass $name\n"; 719*7c356e86SAndroid Build Coastguard Worker $npassed++; 720*7c356e86SAndroid Build Coastguard Worker } 721*7c356e86SAndroid Build Coastguard Worker print $why if $verbose; 722*7c356e86SAndroid Build Coastguard Worker return 0; 723*7c356e86SAndroid Build Coastguard Worker} 724*7c356e86SAndroid Build Coastguard Worker 725*7c356e86SAndroid Build Coastguard Workersub 726*7c356e86SAndroid Build Coastguard Workercategory_check 727*7c356e86SAndroid Build Coastguard Worker{ 728*7c356e86SAndroid Build Coastguard Worker local(*test) = @_; 729*7c356e86SAndroid Build Coastguard Worker local($c); 730*7c356e86SAndroid Build Coastguard Worker 731*7c356e86SAndroid Build Coastguard Worker return 0 if ($test{'need-ctty'} && defined $categories{'regress:no-ctty'}); 732*7c356e86SAndroid Build Coastguard Worker return 1 if (!defined $test{'category'}); 733*7c356e86SAndroid Build Coastguard Worker local($ok) = 0; 734*7c356e86SAndroid Build Coastguard Worker foreach $c (split(',', $test{'category'})) { 735*7c356e86SAndroid Build Coastguard Worker $c =~ s/\s+//; 736*7c356e86SAndroid Build Coastguard Worker if ($c =~ /^!/) { 737*7c356e86SAndroid Build Coastguard Worker $c = $'; 738*7c356e86SAndroid Build Coastguard Worker return 0 if (defined $categories{$c}); 739*7c356e86SAndroid Build Coastguard Worker $ok = 1; 740*7c356e86SAndroid Build Coastguard Worker } else { 741*7c356e86SAndroid Build Coastguard Worker $ok = 1 if (defined $categories{$c}); 742*7c356e86SAndroid Build Coastguard Worker } 743*7c356e86SAndroid Build Coastguard Worker } 744*7c356e86SAndroid Build Coastguard Worker return $ok; 745*7c356e86SAndroid Build Coastguard Worker} 746*7c356e86SAndroid Build Coastguard Worker 747*7c356e86SAndroid Build Coastguard Workersub 748*7c356e86SAndroid Build Coastguard Workerscrub_dir 749*7c356e86SAndroid Build Coastguard Worker{ 750*7c356e86SAndroid Build Coastguard Worker local($dir) = @_; 751*7c356e86SAndroid Build Coastguard Worker local(@todo) = (); 752*7c356e86SAndroid Build Coastguard Worker local($file); 753*7c356e86SAndroid Build Coastguard Worker 754*7c356e86SAndroid Build Coastguard Worker if (!opendir(DIR, $dir)) { 755*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog: couldn't open directory $dir - $!\n"; 756*7c356e86SAndroid Build Coastguard Worker return undef; 757*7c356e86SAndroid Build Coastguard Worker } 758*7c356e86SAndroid Build Coastguard Worker while (defined ($file = readdir(DIR))) { 759*7c356e86SAndroid Build Coastguard Worker push(@todo, $file) if $file ne '.' && $file ne '..'; 760*7c356e86SAndroid Build Coastguard Worker } 761*7c356e86SAndroid Build Coastguard Worker closedir(DIR); 762*7c356e86SAndroid Build Coastguard Worker foreach $file (@todo) { 763*7c356e86SAndroid Build Coastguard Worker $file = "$dir/$file"; 764*7c356e86SAndroid Build Coastguard Worker if (-d $file) { 765*7c356e86SAndroid Build Coastguard Worker return undef if !&scrub_dir($file); 766*7c356e86SAndroid Build Coastguard Worker if (!rmdir($file)) { 767*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog: couldn't rmdir $file - $!\n"; 768*7c356e86SAndroid Build Coastguard Worker return undef; 769*7c356e86SAndroid Build Coastguard Worker } 770*7c356e86SAndroid Build Coastguard Worker } else { 771*7c356e86SAndroid Build Coastguard Worker if (!unlink($file)) { 772*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog: couldn't unlink $file - $!\n"; 773*7c356e86SAndroid Build Coastguard Worker return undef; 774*7c356e86SAndroid Build Coastguard Worker } 775*7c356e86SAndroid Build Coastguard Worker } 776*7c356e86SAndroid Build Coastguard Worker } 777*7c356e86SAndroid Build Coastguard Worker return 1; 778*7c356e86SAndroid Build Coastguard Worker} 779*7c356e86SAndroid Build Coastguard Worker 780*7c356e86SAndroid Build Coastguard Workersub 781*7c356e86SAndroid Build Coastguard Workerwrite_file 782*7c356e86SAndroid Build Coastguard Worker{ 783*7c356e86SAndroid Build Coastguard Worker local($file, $str) = @_; 784*7c356e86SAndroid Build Coastguard Worker 785*7c356e86SAndroid Build Coastguard Worker if (!open(TEMP, "> $file")) { 786*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog: can't open $file - $!\n"; 787*7c356e86SAndroid Build Coastguard Worker return undef; 788*7c356e86SAndroid Build Coastguard Worker } 789*7c356e86SAndroid Build Coastguard Worker binmode(TEMP); 790*7c356e86SAndroid Build Coastguard Worker print TEMP $str; 791*7c356e86SAndroid Build Coastguard Worker if (!close(TEMP)) { 792*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog: error writing $file - $!\n"; 793*7c356e86SAndroid Build Coastguard Worker return undef; 794*7c356e86SAndroid Build Coastguard Worker } 795*7c356e86SAndroid Build Coastguard Worker return 1; 796*7c356e86SAndroid Build Coastguard Worker} 797*7c356e86SAndroid Build Coastguard Worker 798*7c356e86SAndroid Build Coastguard Workersub 799*7c356e86SAndroid Build Coastguard Workercheck_output 800*7c356e86SAndroid Build Coastguard Worker{ 801*7c356e86SAndroid Build Coastguard Worker local($name, $file, $what, $expect, $expect_pat) = @_; 802*7c356e86SAndroid Build Coastguard Worker local($got) = ''; 803*7c356e86SAndroid Build Coastguard Worker local($why) = ''; 804*7c356e86SAndroid Build Coastguard Worker local($ret); 805*7c356e86SAndroid Build Coastguard Worker 806*7c356e86SAndroid Build Coastguard Worker if (!open(TEMP, "< $file")) { 807*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog:$name($what): couldn't open $file after running program - $!\n"; 808*7c356e86SAndroid Build Coastguard Worker return undef; 809*7c356e86SAndroid Build Coastguard Worker } 810*7c356e86SAndroid Build Coastguard Worker binmode(TEMP); 811*7c356e86SAndroid Build Coastguard Worker while (<TEMP>) { 812*7c356e86SAndroid Build Coastguard Worker $got .= $_; 813*7c356e86SAndroid Build Coastguard Worker } 814*7c356e86SAndroid Build Coastguard Worker close(TEMP); 815*7c356e86SAndroid Build Coastguard Worker return compare_output($name, $what, $expect, $expect_pat, $got); 816*7c356e86SAndroid Build Coastguard Worker} 817*7c356e86SAndroid Build Coastguard Worker 818*7c356e86SAndroid Build Coastguard Workersub 819*7c356e86SAndroid Build Coastguard Workercompare_output 820*7c356e86SAndroid Build Coastguard Worker{ 821*7c356e86SAndroid Build Coastguard Worker local($name, $what, $expect, $expect_pat, $got) = @_; 822*7c356e86SAndroid Build Coastguard Worker local($why) = ''; 823*7c356e86SAndroid Build Coastguard Worker 824*7c356e86SAndroid Build Coastguard Worker if (defined $expect_pat) { 825*7c356e86SAndroid Build Coastguard Worker $_ = $got; 826*7c356e86SAndroid Build Coastguard Worker $ret = eval "$expect_pat"; 827*7c356e86SAndroid Build Coastguard Worker if ($@ ne '') { 828*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog:$name($what): error evaluating $what pattern: $expect_pat - $@\n"; 829*7c356e86SAndroid Build Coastguard Worker return undef; 830*7c356e86SAndroid Build Coastguard Worker } 831*7c356e86SAndroid Build Coastguard Worker if (!$ret) { 832*7c356e86SAndroid Build Coastguard Worker $why = "\tunexpected $what - wanted pattern"; 833*7c356e86SAndroid Build Coastguard Worker $why .= &wrap_lines($expect_pat); 834*7c356e86SAndroid Build Coastguard Worker $why .= "\tgot"; 835*7c356e86SAndroid Build Coastguard Worker $why .= &wrap_lines($got); 836*7c356e86SAndroid Build Coastguard Worker } 837*7c356e86SAndroid Build Coastguard Worker } else { 838*7c356e86SAndroid Build Coastguard Worker $expect = '' if !defined $expect; 839*7c356e86SAndroid Build Coastguard Worker if ($got ne $expect) { 840*7c356e86SAndroid Build Coastguard Worker $why .= "\tunexpected $what - " . &first_diff($expect, $got) . "\n"; 841*7c356e86SAndroid Build Coastguard Worker $why .= "\twanted"; 842*7c356e86SAndroid Build Coastguard Worker $why .= &wrap_lines($expect); 843*7c356e86SAndroid Build Coastguard Worker $why .= "\tgot"; 844*7c356e86SAndroid Build Coastguard Worker $why .= &wrap_lines($got); 845*7c356e86SAndroid Build Coastguard Worker } 846*7c356e86SAndroid Build Coastguard Worker } 847*7c356e86SAndroid Build Coastguard Worker return $why; 848*7c356e86SAndroid Build Coastguard Worker} 849*7c356e86SAndroid Build Coastguard Worker 850*7c356e86SAndroid Build Coastguard Workersub 851*7c356e86SAndroid Build Coastguard Workerwrap_lines 852*7c356e86SAndroid Build Coastguard Worker{ 853*7c356e86SAndroid Build Coastguard Worker local($str, $empty) = @_; 854*7c356e86SAndroid Build Coastguard Worker local($nonl) = substr($str, -1, 1) ne "\n"; 855*7c356e86SAndroid Build Coastguard Worker 856*7c356e86SAndroid Build Coastguard Worker return (defined $empty ? $empty : " nothing\n") if $str eq ''; 857*7c356e86SAndroid Build Coastguard Worker substr($str, 0, 0) = ":\n"; 858*7c356e86SAndroid Build Coastguard Worker $str =~ s/\n/\n\t\t/g; 859*7c356e86SAndroid Build Coastguard Worker if ($nonl) { 860*7c356e86SAndroid Build Coastguard Worker $str .= "\n\t[incomplete last line]\n"; 861*7c356e86SAndroid Build Coastguard Worker } else { 862*7c356e86SAndroid Build Coastguard Worker chop($str); 863*7c356e86SAndroid Build Coastguard Worker chop($str); 864*7c356e86SAndroid Build Coastguard Worker } 865*7c356e86SAndroid Build Coastguard Worker return $str; 866*7c356e86SAndroid Build Coastguard Worker} 867*7c356e86SAndroid Build Coastguard Worker 868*7c356e86SAndroid Build Coastguard Workersub 869*7c356e86SAndroid Build Coastguard Workerfirst_diff 870*7c356e86SAndroid Build Coastguard Worker{ 871*7c356e86SAndroid Build Coastguard Worker local($exp, $got) = @_; 872*7c356e86SAndroid Build Coastguard Worker local($lineno, $char) = (1, 1); 873*7c356e86SAndroid Build Coastguard Worker local($i, $exp_len, $got_len); 874*7c356e86SAndroid Build Coastguard Worker local($ce, $cg); 875*7c356e86SAndroid Build Coastguard Worker 876*7c356e86SAndroid Build Coastguard Worker $exp_len = length($exp); 877*7c356e86SAndroid Build Coastguard Worker $got_len = length($got); 878*7c356e86SAndroid Build Coastguard Worker if ($exp_len != $got_len) { 879*7c356e86SAndroid Build Coastguard Worker if ($exp_len < $got_len) { 880*7c356e86SAndroid Build Coastguard Worker if (substr($got, 0, $exp_len) eq $exp) { 881*7c356e86SAndroid Build Coastguard Worker return "got too much output"; 882*7c356e86SAndroid Build Coastguard Worker } 883*7c356e86SAndroid Build Coastguard Worker } elsif (substr($exp, 0, $got_len) eq $got) { 884*7c356e86SAndroid Build Coastguard Worker return "got too little output"; 885*7c356e86SAndroid Build Coastguard Worker } 886*7c356e86SAndroid Build Coastguard Worker } 887*7c356e86SAndroid Build Coastguard Worker for ($i = 0; $i < $exp_len; $i++) { 888*7c356e86SAndroid Build Coastguard Worker $ce = substr($exp, $i, 1); 889*7c356e86SAndroid Build Coastguard Worker $cg = substr($got, $i, 1); 890*7c356e86SAndroid Build Coastguard Worker last if $ce ne $cg; 891*7c356e86SAndroid Build Coastguard Worker $char++; 892*7c356e86SAndroid Build Coastguard Worker if ($ce eq "\n") { 893*7c356e86SAndroid Build Coastguard Worker $lineno++; 894*7c356e86SAndroid Build Coastguard Worker $char = 1; 895*7c356e86SAndroid Build Coastguard Worker } 896*7c356e86SAndroid Build Coastguard Worker } 897*7c356e86SAndroid Build Coastguard Worker return "first difference: line $lineno, char $char (wanted " . 898*7c356e86SAndroid Build Coastguard Worker &format_char($ce) . ", got " . &format_char($cg); 899*7c356e86SAndroid Build Coastguard Worker} 900*7c356e86SAndroid Build Coastguard Worker 901*7c356e86SAndroid Build Coastguard Workersub 902*7c356e86SAndroid Build Coastguard Workerformat_char 903*7c356e86SAndroid Build Coastguard Worker{ 904*7c356e86SAndroid Build Coastguard Worker local($ch, $s, $q); 905*7c356e86SAndroid Build Coastguard Worker 906*7c356e86SAndroid Build Coastguard Worker $ch = ord($_[0]); 907*7c356e86SAndroid Build Coastguard Worker $q = "'"; 908*7c356e86SAndroid Build Coastguard Worker 909*7c356e86SAndroid Build Coastguard Worker if ($is_ebcdic) { 910*7c356e86SAndroid Build Coastguard Worker if ($ch == 0x15) { 911*7c356e86SAndroid Build Coastguard Worker return $q . '\n' . $q; 912*7c356e86SAndroid Build Coastguard Worker } elsif ($ch == 0x16) { 913*7c356e86SAndroid Build Coastguard Worker return $q . '\b' . $q; 914*7c356e86SAndroid Build Coastguard Worker } elsif ($ch == 0x05) { 915*7c356e86SAndroid Build Coastguard Worker return $q . '\t' . $q; 916*7c356e86SAndroid Build Coastguard Worker } elsif ($ch < 64 || $ch == 255) { 917*7c356e86SAndroid Build Coastguard Worker return sprintf("X'%02X'", $ch); 918*7c356e86SAndroid Build Coastguard Worker } 919*7c356e86SAndroid Build Coastguard Worker return sprintf("'%c' (X'%02X')", $ch, $ch); 920*7c356e86SAndroid Build Coastguard Worker } 921*7c356e86SAndroid Build Coastguard Worker 922*7c356e86SAndroid Build Coastguard Worker $s = sprintf("0x%02X (", $ch); 923*7c356e86SAndroid Build Coastguard Worker if ($ch == 10) { 924*7c356e86SAndroid Build Coastguard Worker return $s . $q . '\n' . $q . ')'; 925*7c356e86SAndroid Build Coastguard Worker } elsif ($ch == 13) { 926*7c356e86SAndroid Build Coastguard Worker return $s . $q . '\r' . $q . ')'; 927*7c356e86SAndroid Build Coastguard Worker } elsif ($ch == 8) { 928*7c356e86SAndroid Build Coastguard Worker return $s . $q . '\b' . $q . ')'; 929*7c356e86SAndroid Build Coastguard Worker } elsif ($ch == 9) { 930*7c356e86SAndroid Build Coastguard Worker return $s . $q . '\t' . $q . ')'; 931*7c356e86SAndroid Build Coastguard Worker } elsif ($ch > 127) { 932*7c356e86SAndroid Build Coastguard Worker $ch -= 128; 933*7c356e86SAndroid Build Coastguard Worker $s .= "M-"; 934*7c356e86SAndroid Build Coastguard Worker } 935*7c356e86SAndroid Build Coastguard Worker if ($ch < 32) { 936*7c356e86SAndroid Build Coastguard Worker return sprintf("%s^%c)", $s, $ch + ord('@')); 937*7c356e86SAndroid Build Coastguard Worker } elsif ($ch == 127) { 938*7c356e86SAndroid Build Coastguard Worker return $s . "^?)"; 939*7c356e86SAndroid Build Coastguard Worker } 940*7c356e86SAndroid Build Coastguard Worker return sprintf("%s'%c')", $s, $ch); 941*7c356e86SAndroid Build Coastguard Worker} 942*7c356e86SAndroid Build Coastguard Worker 943*7c356e86SAndroid Build Coastguard Workersub 944*7c356e86SAndroid Build Coastguard Workereval_exit 945*7c356e86SAndroid Build Coastguard Worker{ 946*7c356e86SAndroid Build Coastguard Worker local($name, $status, $expect) = @_; 947*7c356e86SAndroid Build Coastguard Worker local($expr); 948*7c356e86SAndroid Build Coastguard Worker local($w, $e, $s) = ($status, ($status >> 8) & 0xff, $status & 0x7f); 949*7c356e86SAndroid Build Coastguard Worker 950*7c356e86SAndroid Build Coastguard Worker $e = -1000 if $status & 0xff; 951*7c356e86SAndroid Build Coastguard Worker $s = -1000 if $s == 0x7f; 952*7c356e86SAndroid Build Coastguard Worker if (!defined $expect) { 953*7c356e86SAndroid Build Coastguard Worker $expr = '$w == 0'; 954*7c356e86SAndroid Build Coastguard Worker } elsif ($expect =~ /^(|-)\d+$/) { 955*7c356e86SAndroid Build Coastguard Worker $expr = "\$e == $expect"; 956*7c356e86SAndroid Build Coastguard Worker } else { 957*7c356e86SAndroid Build Coastguard Worker $expr = $expect; 958*7c356e86SAndroid Build Coastguard Worker $expr =~ s/\b([wse])\b/\$$1/g; 959*7c356e86SAndroid Build Coastguard Worker $expr =~ s/\b(SIG[A-Z][A-Z0-9]*)\b/&$1/g; 960*7c356e86SAndroid Build Coastguard Worker } 961*7c356e86SAndroid Build Coastguard Worker $w = eval $expr; 962*7c356e86SAndroid Build Coastguard Worker if ($@ ne '') { 963*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog:$test{':long-name'}: bad expected-exit expression: $expect ($@)\n"; 964*7c356e86SAndroid Build Coastguard Worker return undef; 965*7c356e86SAndroid Build Coastguard Worker } 966*7c356e86SAndroid Build Coastguard Worker return $w; 967*7c356e86SAndroid Build Coastguard Worker} 968*7c356e86SAndroid Build Coastguard Worker 969*7c356e86SAndroid Build Coastguard Workersub 970*7c356e86SAndroid Build Coastguard Workerread_test 971*7c356e86SAndroid Build Coastguard Worker{ 972*7c356e86SAndroid Build Coastguard Worker local($file, $in, *test) = @_; 973*7c356e86SAndroid Build Coastguard Worker local($field, $val, $flags, $do_chop, $need_redo, $start_lineno); 974*7c356e86SAndroid Build Coastguard Worker local(%cnt, $sfield); 975*7c356e86SAndroid Build Coastguard Worker 976*7c356e86SAndroid Build Coastguard Worker %test = (); 977*7c356e86SAndroid Build Coastguard Worker %cnt = (); 978*7c356e86SAndroid Build Coastguard Worker while (<$in>) { 979*7c356e86SAndroid Build Coastguard Worker chop; 980*7c356e86SAndroid Build Coastguard Worker next if /^\s*$/; 981*7c356e86SAndroid Build Coastguard Worker next if /^ *#/; 982*7c356e86SAndroid Build Coastguard Worker last if /^\s*---\s*$/; 983*7c356e86SAndroid Build Coastguard Worker $start_lineno = $. if !defined $start_lineno; 984*7c356e86SAndroid Build Coastguard Worker if (!/^([-\w]+):\s*(|\S|\S.*\S)\s*$/) { 985*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog:$file:$.: unrecognised line \"$_\"\n"; 986*7c356e86SAndroid Build Coastguard Worker return undef; 987*7c356e86SAndroid Build Coastguard Worker } 988*7c356e86SAndroid Build Coastguard Worker ($field, $val) = ($1, $2); 989*7c356e86SAndroid Build Coastguard Worker $sfield = $field; 990*7c356e86SAndroid Build Coastguard Worker $flags = $test_fields{$field}; 991*7c356e86SAndroid Build Coastguard Worker if (!defined $flags) { 992*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog:$file:$.: unrecognised field \"$field\"\n"; 993*7c356e86SAndroid Build Coastguard Worker return undef; 994*7c356e86SAndroid Build Coastguard Worker } 995*7c356e86SAndroid Build Coastguard Worker if ($flags =~ /s/) { 996*7c356e86SAndroid Build Coastguard Worker local($cnt) = $cnt{$field}++; 997*7c356e86SAndroid Build Coastguard Worker $test{$field} = $cnt{$field}; 998*7c356e86SAndroid Build Coastguard Worker $cnt = 0 if $cnt eq ''; 999*7c356e86SAndroid Build Coastguard Worker $sfield .= ":$cnt"; 1000*7c356e86SAndroid Build Coastguard Worker } elsif (defined $test{$field}) { 1001*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog:$file:$.: multiple \"$field\" fields\n"; 1002*7c356e86SAndroid Build Coastguard Worker return undef; 1003*7c356e86SAndroid Build Coastguard Worker } 1004*7c356e86SAndroid Build Coastguard Worker $do_chop = $flags !~ /m/; 1005*7c356e86SAndroid Build Coastguard Worker $need_redo = 0; 1006*7c356e86SAndroid Build Coastguard Worker if ($val eq '' || $val eq '!' || $flags =~ /p/) { 1007*7c356e86SAndroid Build Coastguard Worker if ($flags =~ /[Mm]/) { 1008*7c356e86SAndroid Build Coastguard Worker if ($flags =~ /p/) { 1009*7c356e86SAndroid Build Coastguard Worker if ($val =~ /^!/) { 1010*7c356e86SAndroid Build Coastguard Worker $do_chop = 1; 1011*7c356e86SAndroid Build Coastguard Worker $val = $'; 1012*7c356e86SAndroid Build Coastguard Worker } else { 1013*7c356e86SAndroid Build Coastguard Worker $do_chop = 0; 1014*7c356e86SAndroid Build Coastguard Worker } 1015*7c356e86SAndroid Build Coastguard Worker if ($val eq '') { 1016*7c356e86SAndroid Build Coastguard Worker print STDERR 1017*7c356e86SAndroid Build Coastguard Worker "$prog:$file:$.: no parameters given for field \"$field\"\n"; 1018*7c356e86SAndroid Build Coastguard Worker return undef; 1019*7c356e86SAndroid Build Coastguard Worker } 1020*7c356e86SAndroid Build Coastguard Worker } else { 1021*7c356e86SAndroid Build Coastguard Worker if ($val eq '!') { 1022*7c356e86SAndroid Build Coastguard Worker $do_chop = 1; 1023*7c356e86SAndroid Build Coastguard Worker } 1024*7c356e86SAndroid Build Coastguard Worker $val = ''; 1025*7c356e86SAndroid Build Coastguard Worker } 1026*7c356e86SAndroid Build Coastguard Worker while (<$in>) { 1027*7c356e86SAndroid Build Coastguard Worker last if !/^\t/; 1028*7c356e86SAndroid Build Coastguard Worker $val .= $'; 1029*7c356e86SAndroid Build Coastguard Worker } 1030*7c356e86SAndroid Build Coastguard Worker chop $val if $do_chop; 1031*7c356e86SAndroid Build Coastguard Worker $do_chop = 1; 1032*7c356e86SAndroid Build Coastguard Worker $need_redo = 1; 1033*7c356e86SAndroid Build Coastguard Worker 1034*7c356e86SAndroid Build Coastguard Worker # Syntax check on fields that can several instances 1035*7c356e86SAndroid Build Coastguard Worker # (can give useful line numbers this way) 1036*7c356e86SAndroid Build Coastguard Worker 1037*7c356e86SAndroid Build Coastguard Worker if ($field eq 'file-setup') { 1038*7c356e86SAndroid Build Coastguard Worker local($type, $perm, $rest, $c, $len, $name); 1039*7c356e86SAndroid Build Coastguard Worker 1040*7c356e86SAndroid Build Coastguard Worker # format is: type perm "name" 1041*7c356e86SAndroid Build Coastguard Worker if ($val !~ /^[ \t]*(\S+)[ \t]+(\S+)[ \t]+([^ \t].*)/) { 1042*7c356e86SAndroid Build Coastguard Worker print STDERR 1043*7c356e86SAndroid Build Coastguard Worker "$prog:$file:$.: bad parameter line for file-setup field\n"; 1044*7c356e86SAndroid Build Coastguard Worker return undef; 1045*7c356e86SAndroid Build Coastguard Worker } 1046*7c356e86SAndroid Build Coastguard Worker ($type, $perm, $rest) = ($1, $2, $3); 1047*7c356e86SAndroid Build Coastguard Worker if ($type !~ /^(file|dir|symlink)$/) { 1048*7c356e86SAndroid Build Coastguard Worker print STDERR 1049*7c356e86SAndroid Build Coastguard Worker "$prog:$file:$.: bad file type for file-setup: $type\n"; 1050*7c356e86SAndroid Build Coastguard Worker return undef; 1051*7c356e86SAndroid Build Coastguard Worker } 1052*7c356e86SAndroid Build Coastguard Worker if ($perm !~ /^\d+$/) { 1053*7c356e86SAndroid Build Coastguard Worker print STDERR 1054*7c356e86SAndroid Build Coastguard Worker "$prog:$file:$.: bad permissions for file-setup: $type\n"; 1055*7c356e86SAndroid Build Coastguard Worker return undef; 1056*7c356e86SAndroid Build Coastguard Worker } 1057*7c356e86SAndroid Build Coastguard Worker $c = substr($rest, 0, 1); 1058*7c356e86SAndroid Build Coastguard Worker if (($len = index($rest, $c, 1) - 1) <= 0) { 1059*7c356e86SAndroid Build Coastguard Worker print STDERR 1060*7c356e86SAndroid Build Coastguard Worker "$prog:$file:$.: missing end quote for file name in file-setup: $rest\n"; 1061*7c356e86SAndroid Build Coastguard Worker return undef; 1062*7c356e86SAndroid Build Coastguard Worker } 1063*7c356e86SAndroid Build Coastguard Worker $name = substr($rest, 1, $len); 1064*7c356e86SAndroid Build Coastguard Worker if ($name =~ /^\// || $name =~ /(^|\/)\.\.(\/|$)/) { 1065*7c356e86SAndroid Build Coastguard Worker # Note: this is not a security thing - just a sanity 1066*7c356e86SAndroid Build Coastguard Worker # check - a test can still use symlinks to get at files 1067*7c356e86SAndroid Build Coastguard Worker # outside the test directory. 1068*7c356e86SAndroid Build Coastguard Worker print STDERR 1069*7c356e86SAndroid Build Coastguard Worker"$prog:$file:$.: file name in file-setup is absolute or contains ..: $name\n"; 1070*7c356e86SAndroid Build Coastguard Worker return undef; 1071*7c356e86SAndroid Build Coastguard Worker } 1072*7c356e86SAndroid Build Coastguard Worker } 1073*7c356e86SAndroid Build Coastguard Worker if ($field eq 'file-result') { 1074*7c356e86SAndroid Build Coastguard Worker local($type, $perm, $uid, $gid, $matchType, 1075*7c356e86SAndroid Build Coastguard Worker $rest, $c, $len, $name); 1076*7c356e86SAndroid Build Coastguard Worker 1077*7c356e86SAndroid Build Coastguard Worker # format is: type perm uid gid matchType "name" 1078*7c356e86SAndroid Build Coastguard Worker if ($val !~ /^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S.*)/) { 1079*7c356e86SAndroid Build Coastguard Worker print STDERR 1080*7c356e86SAndroid Build Coastguard Worker "$prog:$file:$.: bad parameter line for file-result field\n"; 1081*7c356e86SAndroid Build Coastguard Worker return undef; 1082*7c356e86SAndroid Build Coastguard Worker } 1083*7c356e86SAndroid Build Coastguard Worker ($type, $perm, $uid, $gid, $matchType, $rest) 1084*7c356e86SAndroid Build Coastguard Worker = ($1, $2, $3, $4, $5, $6); 1085*7c356e86SAndroid Build Coastguard Worker if ($type !~ /^(file|dir|symlink)$/) { 1086*7c356e86SAndroid Build Coastguard Worker print STDERR 1087*7c356e86SAndroid Build Coastguard Worker "$prog:$file:$.: bad file type for file-result: $type\n"; 1088*7c356e86SAndroid Build Coastguard Worker return undef; 1089*7c356e86SAndroid Build Coastguard Worker } 1090*7c356e86SAndroid Build Coastguard Worker if ($perm !~ /^\d+$/ && $perm ne '*') { 1091*7c356e86SAndroid Build Coastguard Worker print STDERR 1092*7c356e86SAndroid Build Coastguard Worker "$prog:$file:$.: bad permissions for file-result: $perm\n"; 1093*7c356e86SAndroid Build Coastguard Worker return undef; 1094*7c356e86SAndroid Build Coastguard Worker } 1095*7c356e86SAndroid Build Coastguard Worker if ($uid !~ /^\d+$/ && $uid ne '*') { 1096*7c356e86SAndroid Build Coastguard Worker print STDERR 1097*7c356e86SAndroid Build Coastguard Worker "$prog:$file:$.: bad user-id for file-result: $uid\n"; 1098*7c356e86SAndroid Build Coastguard Worker return undef; 1099*7c356e86SAndroid Build Coastguard Worker } 1100*7c356e86SAndroid Build Coastguard Worker if ($gid !~ /^\d+$/ && $gid ne '*') { 1101*7c356e86SAndroid Build Coastguard Worker print STDERR 1102*7c356e86SAndroid Build Coastguard Worker "$prog:$file:$.: bad group-id for file-result: $gid\n"; 1103*7c356e86SAndroid Build Coastguard Worker return undef; 1104*7c356e86SAndroid Build Coastguard Worker } 1105*7c356e86SAndroid Build Coastguard Worker if ($matchType !~ /^(exact|pattern)$/) { 1106*7c356e86SAndroid Build Coastguard Worker print STDERR 1107*7c356e86SAndroid Build Coastguard Worker "$prog:$file:$.: bad match type for file-result: $matchType\n"; 1108*7c356e86SAndroid Build Coastguard Worker return undef; 1109*7c356e86SAndroid Build Coastguard Worker } 1110*7c356e86SAndroid Build Coastguard Worker $c = substr($rest, 0, 1); 1111*7c356e86SAndroid Build Coastguard Worker if (($len = index($rest, $c, 1) - 1) <= 0) { 1112*7c356e86SAndroid Build Coastguard Worker print STDERR 1113*7c356e86SAndroid Build Coastguard Worker "$prog:$file:$.: missing end quote for file name in file-result: $rest\n"; 1114*7c356e86SAndroid Build Coastguard Worker return undef; 1115*7c356e86SAndroid Build Coastguard Worker } 1116*7c356e86SAndroid Build Coastguard Worker $name = substr($rest, 1, $len); 1117*7c356e86SAndroid Build Coastguard Worker if ($name =~ /^\// || $name =~ /(^|\/)\.\.(\/|$)/) { 1118*7c356e86SAndroid Build Coastguard Worker # Note: this is not a security thing - just a sanity 1119*7c356e86SAndroid Build Coastguard Worker # check - a test can still use symlinks to get at files 1120*7c356e86SAndroid Build Coastguard Worker # outside the test directory. 1121*7c356e86SAndroid Build Coastguard Worker print STDERR 1122*7c356e86SAndroid Build Coastguard Worker"$prog:$file:$.: file name in file-result is absolute or contains ..: $name\n"; 1123*7c356e86SAndroid Build Coastguard Worker return undef; 1124*7c356e86SAndroid Build Coastguard Worker } 1125*7c356e86SAndroid Build Coastguard Worker } 1126*7c356e86SAndroid Build Coastguard Worker } elsif ($val eq '') { 1127*7c356e86SAndroid Build Coastguard Worker print STDERR 1128*7c356e86SAndroid Build Coastguard Worker "$prog:$file:$.: no value given for field \"$field\"\n"; 1129*7c356e86SAndroid Build Coastguard Worker return undef; 1130*7c356e86SAndroid Build Coastguard Worker } 1131*7c356e86SAndroid Build Coastguard Worker } 1132*7c356e86SAndroid Build Coastguard Worker $val .= "\n" if !$do_chop; 1133*7c356e86SAndroid Build Coastguard Worker $test{$sfield} = $val; 1134*7c356e86SAndroid Build Coastguard Worker redo if $need_redo; 1135*7c356e86SAndroid Build Coastguard Worker } 1136*7c356e86SAndroid Build Coastguard Worker if ($_ eq '') { 1137*7c356e86SAndroid Build Coastguard Worker if (%test) { 1138*7c356e86SAndroid Build Coastguard Worker print STDERR 1139*7c356e86SAndroid Build Coastguard Worker "$prog:$file:$start_lineno: end-of-file while reading test\n"; 1140*7c356e86SAndroid Build Coastguard Worker return undef; 1141*7c356e86SAndroid Build Coastguard Worker } 1142*7c356e86SAndroid Build Coastguard Worker return 0; 1143*7c356e86SAndroid Build Coastguard Worker } 1144*7c356e86SAndroid Build Coastguard Worker 1145*7c356e86SAndroid Build Coastguard Worker while (($field, $val) = each %test_fields) { 1146*7c356e86SAndroid Build Coastguard Worker if ($val =~ /r/ && !defined $test{$field}) { 1147*7c356e86SAndroid Build Coastguard Worker print STDERR 1148*7c356e86SAndroid Build Coastguard Worker "$prog:$file:$start_lineno: required field \"$field\" missing\n"; 1149*7c356e86SAndroid Build Coastguard Worker return undef; 1150*7c356e86SAndroid Build Coastguard Worker } 1151*7c356e86SAndroid Build Coastguard Worker } 1152*7c356e86SAndroid Build Coastguard Worker 1153*7c356e86SAndroid Build Coastguard Worker $test{':full-name'} = substr($file, $file_prefix_skip) . ":$test{'name'}"; 1154*7c356e86SAndroid Build Coastguard Worker $test{':long-name'} = "$file:$start_lineno:$test{'name'}"; 1155*7c356e86SAndroid Build Coastguard Worker 1156*7c356e86SAndroid Build Coastguard Worker # Syntax check on specific fields 1157*7c356e86SAndroid Build Coastguard Worker if (defined $test{'expected-fail'}) { 1158*7c356e86SAndroid Build Coastguard Worker if ($test{'expected-fail'} !~ /^(yes|no)$/) { 1159*7c356e86SAndroid Build Coastguard Worker print STDERR 1160*7c356e86SAndroid Build Coastguard Worker "$prog:$test{':long-name'}: bad value for expected-fail field\n"; 1161*7c356e86SAndroid Build Coastguard Worker return undef; 1162*7c356e86SAndroid Build Coastguard Worker } 1163*7c356e86SAndroid Build Coastguard Worker $test{'expected-fail'} = $1 eq 'yes'; 1164*7c356e86SAndroid Build Coastguard Worker } else { 1165*7c356e86SAndroid Build Coastguard Worker $test{'expected-fail'} = 0; 1166*7c356e86SAndroid Build Coastguard Worker } 1167*7c356e86SAndroid Build Coastguard Worker if (defined $test{'need-ctty'}) { 1168*7c356e86SAndroid Build Coastguard Worker if ($test{'need-ctty'} !~ /^(yes|no)$/) { 1169*7c356e86SAndroid Build Coastguard Worker print STDERR 1170*7c356e86SAndroid Build Coastguard Worker "$prog:$test{':long-name'}: bad value for need-ctty field\n"; 1171*7c356e86SAndroid Build Coastguard Worker return undef; 1172*7c356e86SAndroid Build Coastguard Worker } 1173*7c356e86SAndroid Build Coastguard Worker $test{'need-ctty'} = $1 eq 'yes'; 1174*7c356e86SAndroid Build Coastguard Worker } else { 1175*7c356e86SAndroid Build Coastguard Worker $test{'need-ctty'} = 0; 1176*7c356e86SAndroid Build Coastguard Worker } 1177*7c356e86SAndroid Build Coastguard Worker if (defined $test{'need-pass'}) { 1178*7c356e86SAndroid Build Coastguard Worker if ($test{'need-pass'} !~ /^(yes|no)$/) { 1179*7c356e86SAndroid Build Coastguard Worker print STDERR 1180*7c356e86SAndroid Build Coastguard Worker "$prog:$test{':long-name'}: bad value for need-pass field\n"; 1181*7c356e86SAndroid Build Coastguard Worker return undef; 1182*7c356e86SAndroid Build Coastguard Worker } 1183*7c356e86SAndroid Build Coastguard Worker $test{'need-pass'} = $1 eq 'yes'; 1184*7c356e86SAndroid Build Coastguard Worker } else { 1185*7c356e86SAndroid Build Coastguard Worker $test{'need-pass'} = 1; 1186*7c356e86SAndroid Build Coastguard Worker } 1187*7c356e86SAndroid Build Coastguard Worker if (defined $test{'arguments'}) { 1188*7c356e86SAndroid Build Coastguard Worker local($firstc) = substr($test{'arguments'}, 0, 1); 1189*7c356e86SAndroid Build Coastguard Worker 1190*7c356e86SAndroid Build Coastguard Worker if (substr($test{'arguments'}, -1, 1) ne $firstc) { 1191*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog:$test{':long-name'}: arguments field doesn't start and end with the same character\n"; 1192*7c356e86SAndroid Build Coastguard Worker return undef; 1193*7c356e86SAndroid Build Coastguard Worker } 1194*7c356e86SAndroid Build Coastguard Worker } 1195*7c356e86SAndroid Build Coastguard Worker if (defined $test{'env-setup'}) { 1196*7c356e86SAndroid Build Coastguard Worker local($firstc) = substr($test{'env-setup'}, 0, 1); 1197*7c356e86SAndroid Build Coastguard Worker 1198*7c356e86SAndroid Build Coastguard Worker if (substr($test{'env-setup'}, -1, 1) ne $firstc) { 1199*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog:$test{':long-name'}: env-setup field doesn't start and end with the same character\n"; 1200*7c356e86SAndroid Build Coastguard Worker return undef; 1201*7c356e86SAndroid Build Coastguard Worker } 1202*7c356e86SAndroid Build Coastguard Worker 1203*7c356e86SAndroid Build Coastguard Worker $test{'env-setup'} =~ s/\@utflocale\@/$utflocale/g; 1204*7c356e86SAndroid Build Coastguard Worker } 1205*7c356e86SAndroid Build Coastguard Worker if (defined $test{'expected-exit'}) { 1206*7c356e86SAndroid Build Coastguard Worker local($val) = $test{'expected-exit'}; 1207*7c356e86SAndroid Build Coastguard Worker 1208*7c356e86SAndroid Build Coastguard Worker if ($val =~ /^(|-)\d+$/) { 1209*7c356e86SAndroid Build Coastguard Worker if ($val < 0 || $val > 255) { 1210*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog:$test{':long-name'}: expected-exit value $val not in 0..255\n"; 1211*7c356e86SAndroid Build Coastguard Worker return undef; 1212*7c356e86SAndroid Build Coastguard Worker } 1213*7c356e86SAndroid Build Coastguard Worker } elsif ($val !~ /^([\s\d<>+=*%\/&|!()-]|\b[wse]\b|\bSIG[A-Z][A-Z0-9]*\b)+$/) { 1214*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog:$test{':long-name'}: bad expected-exit expression: $val\n"; 1215*7c356e86SAndroid Build Coastguard Worker return undef; 1216*7c356e86SAndroid Build Coastguard Worker } 1217*7c356e86SAndroid Build Coastguard Worker } else { 1218*7c356e86SAndroid Build Coastguard Worker $test{'expected-exit'} = 0; 1219*7c356e86SAndroid Build Coastguard Worker } 1220*7c356e86SAndroid Build Coastguard Worker if (defined $test{'expected-stdout'} 1221*7c356e86SAndroid Build Coastguard Worker && defined $test{'expected-stdout-pattern'}) 1222*7c356e86SAndroid Build Coastguard Worker { 1223*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog:$test{':long-name'}: can't use both expected-stdout and expected-stdout-pattern\n"; 1224*7c356e86SAndroid Build Coastguard Worker return undef; 1225*7c356e86SAndroid Build Coastguard Worker } 1226*7c356e86SAndroid Build Coastguard Worker if (defined $test{'expected-stderr'} 1227*7c356e86SAndroid Build Coastguard Worker && defined $test{'expected-stderr-pattern'}) 1228*7c356e86SAndroid Build Coastguard Worker { 1229*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog:$test{':long-name'}: can't use both expected-stderr and expected-stderr-pattern\n"; 1230*7c356e86SAndroid Build Coastguard Worker return undef; 1231*7c356e86SAndroid Build Coastguard Worker } 1232*7c356e86SAndroid Build Coastguard Worker if (defined $test{'time-limit'}) { 1233*7c356e86SAndroid Build Coastguard Worker if ($test{'time-limit'} !~ /^\d+$/ || $test{'time-limit'} == 0) { 1234*7c356e86SAndroid Build Coastguard Worker print STDERR 1235*7c356e86SAndroid Build Coastguard Worker "$prog:$test{':long-name'}: bad value for time-limit field\n"; 1236*7c356e86SAndroid Build Coastguard Worker return undef; 1237*7c356e86SAndroid Build Coastguard Worker } 1238*7c356e86SAndroid Build Coastguard Worker } elsif (defined $default_time_limit) { 1239*7c356e86SAndroid Build Coastguard Worker $test{'time-limit'} = $default_time_limit; 1240*7c356e86SAndroid Build Coastguard Worker } 1241*7c356e86SAndroid Build Coastguard Worker 1242*7c356e86SAndroid Build Coastguard Worker if (defined $known_tests{$test{'name'}}) { 1243*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog:$test{':long-name'}: warning: duplicate test name ${test{'name'}}\n"; 1244*7c356e86SAndroid Build Coastguard Worker } 1245*7c356e86SAndroid Build Coastguard Worker $known_tests{$test{'name'}} = 1; 1246*7c356e86SAndroid Build Coastguard Worker 1247*7c356e86SAndroid Build Coastguard Worker return 1; 1248*7c356e86SAndroid Build Coastguard Worker} 1249*7c356e86SAndroid Build Coastguard Worker 1250*7c356e86SAndroid Build Coastguard Workersub 1251*7c356e86SAndroid Build Coastguard Workertty_msg 1252*7c356e86SAndroid Build Coastguard Worker{ 1253*7c356e86SAndroid Build Coastguard Worker local($msg) = @_; 1254*7c356e86SAndroid Build Coastguard Worker 1255*7c356e86SAndroid Build Coastguard Worker open(TTY, "> /dev/tty") || return 0; 1256*7c356e86SAndroid Build Coastguard Worker print TTY $msg; 1257*7c356e86SAndroid Build Coastguard Worker close(TTY); 1258*7c356e86SAndroid Build Coastguard Worker return 1; 1259*7c356e86SAndroid Build Coastguard Worker} 1260*7c356e86SAndroid Build Coastguard Worker 1261*7c356e86SAndroid Build Coastguard Workersub 1262*7c356e86SAndroid Build Coastguard Workernever_called_funcs 1263*7c356e86SAndroid Build Coastguard Worker{ 1264*7c356e86SAndroid Build Coastguard Worker return 0; 1265*7c356e86SAndroid Build Coastguard Worker &tty_msg("hi\n"); 1266*7c356e86SAndroid Build Coastguard Worker &never_called_funcs(); 1267*7c356e86SAndroid Build Coastguard Worker &catch_sigalrm(); 1268*7c356e86SAndroid Build Coastguard Worker $old_env{'foo'} = 'bar'; 1269*7c356e86SAndroid Build Coastguard Worker $internal_test_fields{'foo'} = 'bar'; 1270*7c356e86SAndroid Build Coastguard Worker} 1271*7c356e86SAndroid Build Coastguard Worker 1272*7c356e86SAndroid Build Coastguard Workersub 1273*7c356e86SAndroid Build Coastguard Workercheck_file_result 1274*7c356e86SAndroid Build Coastguard Worker{ 1275*7c356e86SAndroid Build Coastguard Worker local(*test) = @_; 1276*7c356e86SAndroid Build Coastguard Worker 1277*7c356e86SAndroid Build Coastguard Worker return '' if (!defined $test{'file-result'}); 1278*7c356e86SAndroid Build Coastguard Worker 1279*7c356e86SAndroid Build Coastguard Worker local($why) = ''; 1280*7c356e86SAndroid Build Coastguard Worker local($i); 1281*7c356e86SAndroid Build Coastguard Worker local($type, $perm, $uid, $gid, $rest, $c, $len, $name); 1282*7c356e86SAndroid Build Coastguard Worker local(@stbuf); 1283*7c356e86SAndroid Build Coastguard Worker 1284*7c356e86SAndroid Build Coastguard Worker for ($i = 0; $i < $test{'file-result'}; $i++) { 1285*7c356e86SAndroid Build Coastguard Worker $val = $test{"file-result:$i"}; 1286*7c356e86SAndroid Build Coastguard Worker 1287*7c356e86SAndroid Build Coastguard Worker # format is: type perm "name" 1288*7c356e86SAndroid Build Coastguard Worker ($type, $perm, $uid, $gid, $matchType, $rest) = 1289*7c356e86SAndroid Build Coastguard Worker split(' ', $val, 6); 1290*7c356e86SAndroid Build Coastguard Worker $c = substr($rest, 0, 1); 1291*7c356e86SAndroid Build Coastguard Worker $len = index($rest, $c, 1) - 1; 1292*7c356e86SAndroid Build Coastguard Worker $name = substr($rest, 1, $len); 1293*7c356e86SAndroid Build Coastguard Worker $rest = substr($rest, 2 + $len); 1294*7c356e86SAndroid Build Coastguard Worker $perm = oct($perm) if $perm =~ /^\d+$/; 1295*7c356e86SAndroid Build Coastguard Worker 1296*7c356e86SAndroid Build Coastguard Worker @stbuf = lstat($name); 1297*7c356e86SAndroid Build Coastguard Worker if (!@stbuf) { 1298*7c356e86SAndroid Build Coastguard Worker $why .= "\texpected $type \"$name\" not created\n"; 1299*7c356e86SAndroid Build Coastguard Worker next; 1300*7c356e86SAndroid Build Coastguard Worker } 1301*7c356e86SAndroid Build Coastguard Worker if ($perm ne '*' && ($stbuf[2] & 07777) != $perm) { 1302*7c356e86SAndroid Build Coastguard Worker $why .= "\t$type \"$name\" has unexpected permissions\n"; 1303*7c356e86SAndroid Build Coastguard Worker $why .= sprintf("\t\texpected 0%o, found 0%o\n", 1304*7c356e86SAndroid Build Coastguard Worker $perm, $stbuf[2] & 07777); 1305*7c356e86SAndroid Build Coastguard Worker } 1306*7c356e86SAndroid Build Coastguard Worker if ($uid ne '*' && $stbuf[4] != $uid) { 1307*7c356e86SAndroid Build Coastguard Worker $why .= "\t$type \"$name\" has unexpected user-id\n"; 1308*7c356e86SAndroid Build Coastguard Worker $why .= sprintf("\t\texpected %d, found %d\n", 1309*7c356e86SAndroid Build Coastguard Worker $uid, $stbuf[4]); 1310*7c356e86SAndroid Build Coastguard Worker } 1311*7c356e86SAndroid Build Coastguard Worker if ($gid ne '*' && $stbuf[5] != $gid) { 1312*7c356e86SAndroid Build Coastguard Worker $why .= "\t$type \"$name\" has unexpected group-id\n"; 1313*7c356e86SAndroid Build Coastguard Worker $why .= sprintf("\t\texpected %d, found %d\n", 1314*7c356e86SAndroid Build Coastguard Worker $gid, $stbuf[5]); 1315*7c356e86SAndroid Build Coastguard Worker } 1316*7c356e86SAndroid Build Coastguard Worker 1317*7c356e86SAndroid Build Coastguard Worker if ($type eq 'file') { 1318*7c356e86SAndroid Build Coastguard Worker if (-l _ || ! -f _) { 1319*7c356e86SAndroid Build Coastguard Worker $why .= "\t$type \"$name\" is not a regular file\n"; 1320*7c356e86SAndroid Build Coastguard Worker } else { 1321*7c356e86SAndroid Build Coastguard Worker local $tmp = &check_output($test{'long-name'}, $name, 1322*7c356e86SAndroid Build Coastguard Worker "$type contents in \"$name\"", 1323*7c356e86SAndroid Build Coastguard Worker $matchType eq 'exact' ? $rest : undef 1324*7c356e86SAndroid Build Coastguard Worker $matchType eq 'pattern' ? $rest : undef); 1325*7c356e86SAndroid Build Coastguard Worker return undef if (!defined $tmp); 1326*7c356e86SAndroid Build Coastguard Worker $why .= $tmp; 1327*7c356e86SAndroid Build Coastguard Worker } 1328*7c356e86SAndroid Build Coastguard Worker } elsif ($type eq 'dir') { 1329*7c356e86SAndroid Build Coastguard Worker if ($rest !~ /^\s*$/) { 1330*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog:$test{':long-name'}: file-result test for directory $name should not have content specified\n"; 1331*7c356e86SAndroid Build Coastguard Worker return undef; 1332*7c356e86SAndroid Build Coastguard Worker } 1333*7c356e86SAndroid Build Coastguard Worker if (-l _ || ! -d _) { 1334*7c356e86SAndroid Build Coastguard Worker $why .= "\t$type \"$name\" is not a directory\n"; 1335*7c356e86SAndroid Build Coastguard Worker } 1336*7c356e86SAndroid Build Coastguard Worker } elsif ($type eq 'symlink') { 1337*7c356e86SAndroid Build Coastguard Worker if (!-l _) { 1338*7c356e86SAndroid Build Coastguard Worker $why .= "\t$type \"$name\" is not a symlink\n"; 1339*7c356e86SAndroid Build Coastguard Worker } else { 1340*7c356e86SAndroid Build Coastguard Worker local $content = readlink($name); 1341*7c356e86SAndroid Build Coastguard Worker if (!defined $content) { 1342*7c356e86SAndroid Build Coastguard Worker print STDERR "$prog:$test{':long-name'}: file-result test for $type $name failed - could not readlink - $!\n"; 1343*7c356e86SAndroid Build Coastguard Worker return undef; 1344*7c356e86SAndroid Build Coastguard Worker } 1345*7c356e86SAndroid Build Coastguard Worker local $tmp = &compare_output($test{'long-name'}, 1346*7c356e86SAndroid Build Coastguard Worker "$type contents in \"$name\"", 1347*7c356e86SAndroid Build Coastguard Worker $matchType eq 'exact' ? $rest : undef 1348*7c356e86SAndroid Build Coastguard Worker $matchType eq 'pattern' ? $rest : undef); 1349*7c356e86SAndroid Build Coastguard Worker return undef if (!defined $tmp); 1350*7c356e86SAndroid Build Coastguard Worker $why .= $tmp; 1351*7c356e86SAndroid Build Coastguard Worker } 1352*7c356e86SAndroid Build Coastguard Worker } 1353*7c356e86SAndroid Build Coastguard Worker } 1354*7c356e86SAndroid Build Coastguard Worker 1355*7c356e86SAndroid Build Coastguard Worker return $why; 1356*7c356e86SAndroid Build Coastguard Worker} 1357*7c356e86SAndroid Build Coastguard Worker 1358*7c356e86SAndroid Build Coastguard Workersub 1359*7c356e86SAndroid Build Coastguard WorkerHELP_MESSAGE 1360*7c356e86SAndroid Build Coastguard Worker{ 1361*7c356e86SAndroid Build Coastguard Worker print STDERR $Usage; 1362*7c356e86SAndroid Build Coastguard Worker exit 0; 1363*7c356e86SAndroid Build Coastguard Worker} 1364