ia64/xen-unstable

changeset 6039:9faafa21bf98

xenstored has had a testsuite for some time. This splits the test
targets into "make -s check" (the GNU standard) which is designed to run
in several seconds or less, with only "<dirname>:" and a seried of "."
for output, and "make fullcheck" which is more verbose and complete, and
runs in minutes.

I plan to submit a patch to plumb these tests in at the top level soon,
with the idea of having a "make -s check" which you can reasonable run
every checkin (time make check << time make), and a "make fullcheck"
which you can run after significant changes.

This patch speeds up testing by making tests one single "xs_test"
script, enhancing xs_test with a simple "expect" command. It also only
runs the "high value" tests under "make check", and leaves the rest for
"make fullcheck".

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
author kaf24@firebug.cl.cam.ac.uk
date Fri Aug 05 09:04:01 2005 +0000 (2005-08-05)
parents 8727c784c07d
children 5a33233a608e
files tools/xenstore/Makefile tools/xenstore/testsuite/test.sh tools/xenstore/xs_random.c tools/xenstore/xs_test.c
line diff
     1.1 --- a/tools/xenstore/Makefile	Fri Aug 05 09:02:58 2005 +0000
     1.2 +++ b/tools/xenstore/Makefile	Fri Aug 05 09:04:01 2005 +0000
     1.3 @@ -69,10 +69,21 @@ clean: testsuite-clean
     1.4  	rm -f xs_test xenstored_test xs_dom0_test
     1.5  	-$(RM) $(PROG_DEP)
     1.6  
     1.7 -check: testsuite-run randomcheck stresstest
     1.8 +print-dir:
     1.9 +	@echo -n tools/xenstore: 
    1.10 +
    1.11 +print-end:
    1.12 +	@echo
    1.13 +
    1.14 +check: print-dir testsuite-fast randomcheck-fast print-end
    1.15 +
    1.16 +fullcheck: testsuite-run randomcheck stresstest
    1.17  
    1.18  testsuite-run: xen xenstored_test xs_test
    1.19 -	$(TESTENV) testsuite/test.sh
    1.20 +	$(TESTENV) testsuite/test.sh && echo
    1.21 +
    1.22 +testsuite-fast: xen xenstored_test xs_test
    1.23 +	@$(TESTENV) testsuite/test.sh --fast
    1.24  
    1.25  testsuite-clean:
    1.26  	rm -rf $(TESTDIR)
    1.27 @@ -81,10 +92,13 @@ testsuite-clean:
    1.28  # fail.
    1.29  RANDSEED=$(shell date +%s)
    1.30  randomcheck: xs_random xenstored_test
    1.31 -	$(TESTENV) ./xs_random --simple --fast /tmp/xs_random 200000 $(RANDSEED)
    1.32 -	$(TESTENV) ./xs_random --fast /tmp/xs_random 100000 $(RANDSEED)
    1.33 +	$(TESTENV) ./xs_random --simple --fast /tmp/xs_random 200000 $(RANDSEED) && echo
    1.34 +	$(TESTENV) ./xs_random --fast /tmp/xs_random 100000 $(RANDSEED) && echo
    1.35  	$(TESTENV) ./xs_random --fail /tmp/xs_random 10000 $(RANDSEED)
    1.36  
    1.37 +randomcheck-fast: xs_random xenstored_test
    1.38 +	@$(TESTENV) ./xs_random --fast /tmp/xs_random 10000 $(RANDSEED)
    1.39 +
    1.40  stresstest: xs_stress xs_watch_stress xenstored_test
    1.41  	rm -rf $(TESTDIR)/store $(TESTDIR)/transactions
    1.42  	export $(TESTENV); PID=`./xenstored_test --output-pid --trace-file=/tmp/trace`; ./xs_stress 5000; ret=$$?; kill $$PID; exit $$ret
     2.1 --- a/tools/xenstore/testsuite/01simple.sh	Fri Aug 05 09:02:58 2005 +0000
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,4 +0,0 @@
     2.4 -#! /bin/sh
     2.5 -
     2.6 -# Create an entry, read it.
     2.7 -[ "`echo -e 'write /test create contents\nread /test' | ./xs_test 2>&1`" = "contents" ]
     3.1 --- a/tools/xenstore/testsuite/02directory.sh	Fri Aug 05 09:02:58 2005 +0000
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,32 +0,0 @@
     3.4 -#! /bin/sh
     3.5 -
     3.6 -# Root directory has only tool dir in it.
     3.7 -[ "`echo -e 'dir /' | ./xs_test 2>&1`" = "tool" ]
     3.8 -
     3.9 -# Create a file.
    3.10 -[ "`echo -e 'write /test create contents' | ./xs_test 2>&1`" = "" ]
    3.11 -
    3.12 -# Directory shows it.
    3.13 -[ "`echo -e 'dir /' | ./xs_test 2>&1 | sort`" = "test
    3.14 -tool" ]
    3.15 -
    3.16 -# Make a new directory.
    3.17 -[ "`echo -e 'mkdir /dir' | ./xs_test 2>&1`" = "" ]
    3.18 -
    3.19 -# Check it's there.
    3.20 -DIR="`echo -e 'dir /' | ./xs_test 2>&1 | sort`"
    3.21 -[ "$DIR" = "dir
    3.22 -test
    3.23 -tool" ]
    3.24 -
    3.25 -# Check it's empty.
    3.26 -[ "`echo -e 'dir /dir' | ./xs_test 2>&1`" = "" ]
    3.27 -
    3.28 -# Create a file, check it exists.
    3.29 -[ "`echo -e 'write /dir/test2 create contents2' | ./xs_test 2>&1`" = "" ]
    3.30 -[ "`echo -e 'dir /dir' | ./xs_test 2>&1`" = "test2" ]
    3.31 -[ "`echo -e 'read /dir/test2' | ./xs_test 2>&1`" = "contents2" ]
    3.32 -
    3.33 -# Creating dir over the top should fail.
    3.34 -[ "`echo -e 'mkdir /dir' | ./xs_test 2>&1`" = "FATAL: mkdir: File exists" ]
    3.35 -[ "`echo -e 'mkdir /dir/test2' | ./xs_test 2>&1`" = "FATAL: mkdir: File exists" ]
     4.1 --- a/tools/xenstore/testsuite/03write.sh	Fri Aug 05 09:02:58 2005 +0000
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,17 +0,0 @@
     4.4 -#! /bin/sh
     4.5 -
     4.6 -# Write without create fails.
     4.7 -[ "`echo -e 'write /test none contents' | ./xs_test 2>&1`" = "FATAL: write: No such file or directory" ]
     4.8 -
     4.9 -# Exclusive write succeeds
    4.10 -[ "`echo -e 'write /test excl contents' | ./xs_test 2>&1`" = "" ]
    4.11 -[ "`echo -e 'read /test' | ./xs_test 2>&1`" = "contents" ]
    4.12 -
    4.13 -# Exclusive write fails to overwrite.
    4.14 -[ "`echo -e 'write /test excl contents' | ./xs_test 2>&1`" = "FATAL: write: File exists" ]
    4.15 -
    4.16 -# Non-exclusive overwrite succeeds.
    4.17 -[ "`echo -e 'write /test none contents2' | ./xs_test 2>&1`" = "" ]
    4.18 -[ "`echo -e 'read /test' | ./xs_test 2>&1`" = "contents2" ]
    4.19 -[ "`echo -e 'write /test create contents3' | ./xs_test 2>&1`" = "" ]
    4.20 -[ "`echo -e 'read /test' | ./xs_test 2>&1`" = "contents3" ]
     5.1 --- a/tools/xenstore/testsuite/04rm.sh	Fri Aug 05 09:02:58 2005 +0000
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,18 +0,0 @@
     5.4 -#! /bin/sh
     5.5 -
     5.6 -# Remove non-existant fails.
     5.7 -[ "`echo -e 'rm /test' | ./xs_test 2>&1`" = "FATAL: rm: No such file or directory" ]
     5.8 -[ "`echo -e 'rm /dir/test' | ./xs_test 2>&1`" = "FATAL: rm: No such file or directory" ]
     5.9 -
    5.10 -# Create file and remove it
    5.11 -[ "`echo -e 'write /test excl contents' | ./xs_test 2>&1`" = "" ]
    5.12 -[ "`echo -e 'rm /test' | ./xs_test 2>&1`" = "" ]
    5.13 -
    5.14 -# Create directory and remove it.
    5.15 -[ "`echo -e 'mkdir /dir' | ./xs_test 2>&1`" = "" ]
    5.16 -[ "`echo -e 'rm /dir' | ./xs_test 2>&1`" = "" ]
    5.17 -
    5.18 -# Create directory, create file, remove all.
    5.19 -[ "`echo -e 'mkdir /dir' | ./xs_test 2>&1`" = "" ]
    5.20 -[ "`echo -e 'write /dir/test excl contents' | ./xs_test 2>&1`" = "" ]
    5.21 -[ "`echo -e 'rm /dir' | ./xs_test 2>&1`" = "" ]
     6.1 --- a/tools/xenstore/testsuite/05filepermissions.sh	Fri Aug 05 09:02:58 2005 +0000
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,49 +0,0 @@
     6.4 -#! /bin/sh
     6.5 -
     6.6 -# Fail to get perms on non-existent file.
     6.7 -[ "`echo -e 'getperm /test' | ./xs_test 2>&1`" = "FATAL: getperm: No such file or directory" ]
     6.8 -[ "`echo -e 'getperm /dir/test' | ./xs_test 2>&1`" = "FATAL: getperm: No such file or directory" ]
     6.9 -
    6.10 -# Create file: inherits from root (0 READ)
    6.11 -[ "`echo -e 'write /test excl contents' | ./xs_test 2>&1`" = "" ]
    6.12 -[ "`echo -e 'getperm /test' | ./xs_test 2>&1`" = "0 READ" ]
    6.13 -[ "`echo -e 'setid 1\ngetperm /test' | ./xs_test 2>&1`" = "0 READ" ]
    6.14 -[ "`echo -e 'setid 1\nread /test' | ./xs_test 2>&1`" = "contents" ]
    6.15 -[ "`echo -e 'setid 1\nwrite /test none contents2' | ./xs_test 2>&1`" = "FATAL: write: Permission denied" ]
    6.16 -
    6.17 -# Take away read access to file.
    6.18 -[ "`echo -e 'setperm /test 0 NONE' | ./xs_test 2>&1`" = "" ]
    6.19 -[ "`echo -e 'setid 1\ngetperm /test' | ./xs_test 2>&1`" = "FATAL: getperm: Permission denied" ]
    6.20 -[ "`echo -e 'setid 1\nread /test' | ./xs_test 2>&1`" = "FATAL: read: Permission denied" ]
    6.21 -[ "`echo -e 'setid 1\nwrite /test none contents2' | ./xs_test 2>&1`" = "FATAL: write: Permission denied" ]
    6.22 -
    6.23 -# Grant everyone write access to file.
    6.24 -[ "`echo -e 'setperm /test 0 WRITE' | ./xs_test 2>&1`" = "" ]
    6.25 -[ "`echo -e 'setid 1\ngetperm /test' | ./xs_test 2>&1`" = "FATAL: getperm: Permission denied" ]
    6.26 -[ "`echo -e 'setid 1\nread /test' | ./xs_test 2>&1`" = "FATAL: read: Permission denied" ]
    6.27 -[ "`echo -e 'setid 1\nwrite /test none contents2' | ./xs_test 2>&1`" = "" ]
    6.28 -[ "`echo -e 'read /test' | ./xs_test 2>&1`" = "contents2" ]
    6.29 -
    6.30 -# Grant everyone both read and write access.
    6.31 -[ "`echo -e 'setperm /test 0 READ/WRITE' | ./xs_test 2>&1`" = "" ]
    6.32 -[ "`echo -e 'setid 1\ngetperm /test' | ./xs_test 2>&1`" = "0 READ/WRITE" ]
    6.33 -[ "`echo -e 'setid 1\nread /test' | ./xs_test 2>&1`" = "contents2" ]
    6.34 -[ "`echo -e 'setid 1\nwrite /test none contents3' | ./xs_test 2>&1`" = "" ]
    6.35 -[ "`echo -e 'setid 1\nread /test' | ./xs_test 2>&1`" = "contents3" ]
    6.36 -
    6.37 -# Change so that user 1 owns it, noone else can do anything.
    6.38 -[ "`echo -e 'setperm /test 1 NONE' | ./xs_test 2>&1`" = "" ]
    6.39 -[ "`echo -e 'setid 1\ngetperm /test' | ./xs_test 2>&1`" = "1 NONE" ]
    6.40 -[ "`echo -e 'setid 1\nread /test' | ./xs_test 2>&1`" = "contents3" ]
    6.41 -[ "`echo -e 'setid 1\nwrite /test none contents4' | ./xs_test 2>&1`" = "" ]
    6.42 -
    6.43 -# User 2 can do nothing.
    6.44 -[ "`echo -e 'setid 2\nsetperm /test 2 NONE' | ./xs_test 2>&1`" = "FATAL: setperm: Permission denied" ]
    6.45 -[ "`echo -e 'setid 2\ngetperm /test' | ./xs_test 2>&1`" = "FATAL: getperm: Permission denied" ]
    6.46 -[ "`echo -e 'setid 2\nread /test' | ./xs_test 2>&1`" = "FATAL: read: Permission denied" ]
    6.47 -[ "`echo -e 'setid 2\nwrite /test none contents4' | ./xs_test 2>&1`" = "FATAL: write: Permission denied" ]
    6.48 -
    6.49 -# Tools can always access things.
    6.50 -[ "`echo -e 'getperm /test' | ./xs_test 2>&1`" = "1 NONE" ]
    6.51 -[ "`echo -e 'read /test' | ./xs_test 2>&1`" = "contents4" ]
    6.52 -[ "`echo -e 'write /test none contents5' | ./xs_test 2>&1`" = "" ]
     7.1 --- a/tools/xenstore/testsuite/06dirpermissions.sh	Fri Aug 05 09:02:58 2005 +0000
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,75 +0,0 @@
     7.4 -#! /bin/sh
     7.5 -
     7.6 -# Root directory: owned by tool, everyone has read access.
     7.7 -[ "`echo -e 'getperm /' | ./xs_test 2>&1`" = "0 READ" ]
     7.8 -
     7.9 -# Create directory: inherits from root.
    7.10 -[ "`echo -e 'mkdir /dir' | ./xs_test 2>&1`" = "" ]
    7.11 -[ "`echo -e 'getperm /dir' | ./xs_test 2>&1`" = "0 READ" ]
    7.12 -[ "`echo -e 'setid 1\ngetperm /dir' | ./xs_test 2>&1`" = "0 READ" ]
    7.13 -[ "`echo -e 'setid 1\ndir /dir' | ./xs_test 2>&1`" = "" ]
    7.14 -[ "`echo -e 'setid 1\nwrite /dir/test create contents2' | ./xs_test 2>&1`" = "FATAL: write: Permission denied" ]
    7.15 -
    7.16 -# Remove everyone's read access to directoy.
    7.17 -[ "`echo -e 'setperm /dir 0 NONE' | ./xs_test 2>&1`" = "" ]
    7.18 -[ "`echo -e 'setid 1\ndir /dir' | ./xs_test 2>&1`" = "FATAL: dir: Permission denied" ]
    7.19 -[ "`echo -e 'setid 1\nread /dir/test create contents2' | ./xs_test 2>&1`" = "FATAL: read: Permission denied" ]
    7.20 -[ "`echo -e 'setid 1\nwrite /dir/test create contents2' | ./xs_test 2>&1`" = "FATAL: write: Permission denied" ]
    7.21 -
    7.22 -# Grant everyone write access to directory.
    7.23 -[ "`echo -e 'setperm /dir 0 WRITE' | ./xs_test 2>&1`" = "" ]
    7.24 -[ "`echo -e 'setid 1\ngetperm /dir' | ./xs_test 2>&1`" = "FATAL: getperm: Permission denied" ]
    7.25 -[ "`echo -e 'setid 1\ndir /dir' | ./xs_test 2>&1`" = "FATAL: dir: Permission denied" ]
    7.26 -[ "`echo -e 'setid 1\nwrite /dir/test create contents' | ./xs_test 2>&1`" = "" ]
    7.27 -[ "`echo -e 'getperm /dir/test' | ./xs_test 2>&1`" = "1 WRITE" ]
    7.28 -[ "`echo -e 'setperm /dir/test 0 NONE' | ./xs_test 2>&1`" = "" ]
    7.29 -[ "`echo -e 'read /dir/test' | ./xs_test 2>&1`" = "contents" ]
    7.30 -
    7.31 -# Grant everyone both read and write access.
    7.32 -[ "`echo -e 'setperm /dir 0 READ/WRITE' | ./xs_test 2>&1`" = "" ]
    7.33 -[ "`echo -e 'setid 1\ngetperm /dir' | ./xs_test 2>&1`" = "0 READ/WRITE" ]
    7.34 -[ "`echo -e 'setid 1\ndir /dir' | ./xs_test 2>&1`" = "test" ]
    7.35 -[ "`echo -e 'setid 1\nwrite /dir/test2 create contents' | ./xs_test 2>&1`" = "" ]
    7.36 -[ "`echo -e 'setid 1\nread /dir/test2' | ./xs_test 2>&1`" = "contents" ]
    7.37 -[ "`echo -e 'setid 1\nsetperm /dir/test2 1 NONE' | ./xs_test 2>&1`" = "" ]
    7.38 -
    7.39 -# Change so that user 1 owns it, noone else can do anything.
    7.40 -[ "`echo -e 'setperm /dir 1 NONE' | ./xs_test 2>&1`" = "" ]
    7.41 -[ "`echo -e 'setid 1\ngetperm /dir' | ./xs_test 2>&1`" = "1 NONE" ]
    7.42 -[ "`echo -e 'setid 1\ndir /dir' | ./xs_test 2>&1 | sort`" = "test
    7.43 -test2" ]
    7.44 -[ "`echo -e 'setid 1\nwrite /dir/test3 create contents' | ./xs_test 2>&1`" = "" ]
    7.45 -
    7.46 -# User 2 can do nothing.  Can't even tell if file exists.
    7.47 -[ "`echo -e 'setid 2\nsetperm /dir 2 NONE' | ./xs_test 2>&1`" = "FATAL: setperm: Permission denied" ]
    7.48 -[ "`echo -e 'setid 2\ngetperm /dir' | ./xs_test 2>&1`" = "FATAL: getperm: Permission denied" ]
    7.49 -[ "`echo -e 'setid 2\ndir /dir' | ./xs_test 2>&1`" = "FATAL: dir: Permission denied" ]
    7.50 -[ "`echo -e 'setid 2\nread /dir/test' | ./xs_test 2>&1`" = "FATAL: read: Permission denied" ]
    7.51 -[ "`echo -e 'setid 2\nread /dir/test2' | ./xs_test 2>&1`" = "FATAL: read: Permission denied" ]
    7.52 -[ "`echo -e 'setid 2\nread /dir/test3' | ./xs_test 2>&1`" = "FATAL: read: Permission denied" ]
    7.53 -[ "`echo -e 'setid 2\nread /dir/test4' | ./xs_test 2>&1`" = "FATAL: read: Permission denied" ]
    7.54 -[ "`echo -e 'setid 2\nwrite /dir/test none contents' | ./xs_test 2>&1`" = "FATAL: write: Permission denied" ]
    7.55 -[ "`echo -e 'setid 2\nwrite /dir/test create contents' | ./xs_test 2>&1`" = "FATAL: write: Permission denied" ]
    7.56 -[ "`echo -e 'setid 2\nwrite /dir/test excl contents' | ./xs_test 2>&1`" = "FATAL: write: Permission denied" ]
    7.57 -[ "`echo -e 'setid 2\nwrite /dir/test4 none contents' | ./xs_test 2>&1`" = "FATAL: write: Permission denied" ]
    7.58 -[ "`echo -e 'setid 2\nwrite /dir/test4 create contents' | ./xs_test 2>&1`" = "FATAL: write: Permission denied" ]
    7.59 -[ "`echo -e 'setid 2\nwrite /dir/test4 excl contents' | ./xs_test 2>&1`" = "FATAL: write: Permission denied" ]
    7.60 -
    7.61 -# Tools can always access things.
    7.62 -[ "`echo -e 'getperm /dir' | ./xs_test 2>&1`" = "1 NONE" ]
    7.63 -[ "`echo -e 'dir /dir' | ./xs_test 2>&1 | sort`" = "test
    7.64 -test2
    7.65 -test3" ]
    7.66 -[ "`echo -e 'write /dir/test4 create contents' | ./xs_test 2>&1`" = "" ]
    7.67 -
    7.68 -# Inherited by child.
    7.69 -[ "`echo -e 'mkdir /dir/subdir' | ./xs_test 2>&1`" = "" ]
    7.70 -[ "`echo -e 'getperm /dir/subdir' | ./xs_test 2>&1`" = "1 NONE" ]
    7.71 -[ "`echo -e 'write /dir/subfile excl contents' | ./xs_test 2>&1`" = "" ]
    7.72 -[ "`echo -e 'getperm /dir/subfile' | ./xs_test 2>&1`" = "1 NONE" ]
    7.73 -
    7.74 -# But for domains, they own it.
    7.75 -[ "`echo -e 'setperm /dir/subdir 2 READ/WRITE' | ./xs_test 2>&1`" = "" ]
    7.76 -[ "`echo -e 'getperm /dir/subdir' | ./xs_test 2>&1`" = "2 READ/WRITE" ]
    7.77 -[ "`echo -e 'setid 3\nwrite /dir/subdir/subfile excl contents' | ./xs_test 2>&1`" = "" ]
    7.78 -[ "`echo -e 'getperm /dir/subdir/subfile' | ./xs_test 2>&1`" = "3 READ/WRITE" ]
     8.1 --- a/tools/xenstore/testsuite/07watch.sh	Fri Aug 05 09:02:58 2005 +0000
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,181 +0,0 @@
     8.4 -#! /bin/sh
     8.5 -
     8.6 -# Watch something, write to it, check watch has fired.
     8.7 -[ "`echo -e 'write /test create contents' | ./xs_test 2>&1`" = "" ]
     8.8 -
     8.9 -[ "`echo -e '1 watch /test token
    8.10 -2 async write /test create contents2
    8.11 -1 waitwatch
    8.12 -1 ackwatch token' | ./xs_test 2>&1`" = "1:/test:token" ]
    8.13 -
    8.14 -# Check that reads don't set it off.
    8.15 -[ "`echo -e '1 watch /test token
    8.16 -2 read /test
    8.17 -1 waitwatch' | ./xs_test 2>&1`" = "2:contents2
    8.18 -1:waitwatch timeout" ]
    8.19 -
    8.20 -# mkdir, setperm and rm should (also tests watching dirs)
    8.21 -[ "`echo -e 'mkdir /dir' | ./xs_test 2>&1`" = "" ]
    8.22 -[ "`echo -e '1 watch /dir token
    8.23 -2 async mkdir /dir/newdir
    8.24 -1 waitwatch
    8.25 -1 ackwatch token
    8.26 -asyncwait
    8.27 -2 async setperm /dir/newdir 0 READ
    8.28 -1 waitwatch
    8.29 -1 ackwatch token
    8.30 -asyncwait
    8.31 -2 async rm /dir/newdir
    8.32 -1 waitwatch
    8.33 -1 ackwatch token' | ./xs_test 2>&1`" = "1:/dir/newdir:token
    8.34 -1:/dir/newdir:token
    8.35 -1:/dir/newdir:token" ]
    8.36 -
    8.37 -# We don't get a watch from our own commands.
    8.38 -[ "`echo -e 'watch /dir token
    8.39 -mkdir /dir/newdir
    8.40 -waitwatch' | ./xs_test 2>&1`" = "waitwatch timeout" ]
    8.41 -
    8.42 -# ignore watches while doing commands, should work.
    8.43 -[ "`echo -e 'watch /dir token
    8.44 -1 async write /dir/test create contents
    8.45 -read /dir/test
    8.46 -waitwatch
    8.47 -ackwatch token' | ./xs_test 2>&1`" = "contents
    8.48 -/dir/test:token" ]
    8.49 -
    8.50 -# watch priority test: all simultaneous
    8.51 -[ "`echo -e '1 watch /dir token1
    8.52 -3 watch /dir token3
    8.53 -2 watch /dir token2
    8.54 -async write /dir/test create contents
    8.55 -3 waitwatch
    8.56 -3 ackwatch token3
    8.57 -2 waitwatch
    8.58 -2 ackwatch token2
    8.59 -1 waitwatch
    8.60 -1 ackwatch token1' | ./xs_test 2>&1`" = "3:/dir/test:token3
    8.61 -2:/dir/test:token2
    8.62 -1:/dir/test:token1" ]
    8.63 -
    8.64 -# If one dies (without acking), the other should still get ack.
    8.65 -[ "`echo -e '1 watch /dir token1
    8.66 -2 watch /dir token2
    8.67 -async write /dir/test create contents
    8.68 -2 waitwatch
    8.69 -2 close
    8.70 -1 waitwatch
    8.71 -1 ackwatch token1' | ./xs_test 2>&1`" = "2:/dir/test:token2
    8.72 -1:/dir/test:token1" ]
    8.73 -
    8.74 -# If one dies (without reading at all), the other should still get ack.
    8.75 -[ "`echo -e '1 watch /dir token1
    8.76 -2 watch /dir token2
    8.77 -async write /dir/test create contents
    8.78 -2 close
    8.79 -1 waitwatch
    8.80 -1 ackwatch token1' | ./xs_test 2>&1`" = "1:/dir/test:token1" ]
    8.81 -
    8.82 -# unwatch
    8.83 -[ "`echo -e '1 watch /dir token1
    8.84 -1 unwatch /dir token1
    8.85 -1 watch /dir token2
    8.86 -2 async write /dir/test2 create contents
    8.87 -1 waitwatch
    8.88 -1 unwatch /dir token2' | ./xs_test 2>&1`" = "1:/dir/test2:token2" ]
    8.89 -
    8.90 -# unwatch while watch pending.  Next watcher gets the event.
    8.91 -[ "`echo -e '1 watch /dir token1
    8.92 -2 watch /dir token2
    8.93 -async write /dir/test create contents
    8.94 -2 unwatch /dir token2
    8.95 -1 waitwatch
    8.96 -1 ackwatch token1' | ./xs_test 2>&1`" = "1:/dir/test:token1" ]
    8.97 -
    8.98 -# unwatch while watch pending.  Should clear this so we get next event.
    8.99 -[ "`echo -e '1 watch /dir token1
   8.100 -async write /dir/test create contents
   8.101 -1 unwatch /dir token1
   8.102 -1 watch /dir/test token2
   8.103 -asyncwait
   8.104 -async write /dir/test none contents2
   8.105 -1 waitwatch
   8.106 -1 ackwatch token2' | ./xs_test 2>&1`" = "1:/dir/test:token2" ]
   8.107 -
   8.108 -# check we only get notified once.
   8.109 -[ "`echo -e '1 watch /test token
   8.110 -2 async write /test create contents2
   8.111 -1 waitwatch
   8.112 -1 ackwatch token
   8.113 -1 waitwatch' | ./xs_test 2>&1`" = "1:/test:token
   8.114 -1:waitwatch timeout" ]
   8.115 -
   8.116 -# watches are queued in order.
   8.117 -[ "`echo -e '1 watch / token
   8.118 -async 2 write /test1 create contents
   8.119 -async 2 write /test2 create contents
   8.120 -async 2 write /test3 create contents
   8.121 -1 waitwatch
   8.122 -1 ackwatch token
   8.123 -1 waitwatch
   8.124 -1 ackwatch token
   8.125 -1 waitwatch
   8.126 -1 ackwatch token' | ./xs_test 2>&1`" = "1:/test1:token
   8.127 -1:/test2:token
   8.128 -1:/test3:token" ]
   8.129 -
   8.130 -# Creation of subpaths should be covered correctly.
   8.131 -[ "`echo -e '1 watch / token
   8.132 -2 async write /test/subnode create contents2
   8.133 -2 async write /test/subnode/subnode create contents2
   8.134 -1 waitwatch
   8.135 -1 ackwatch token
   8.136 -1 waitwatch
   8.137 -1 ackwatch token
   8.138 -1 waitwatch' | ./xs_test 2>&1`" = "1:/test/subnode:token
   8.139 -1:/test/subnode/subnode:token
   8.140 -1:waitwatch timeout" ]
   8.141 -
   8.142 -# Watch event must have happened before we registered interest.
   8.143 -[ "`echo -e '1 watch / token
   8.144 -2 async write /test/subnode create contents2
   8.145 -1 watch / token2 0
   8.146 -1 waitwatch
   8.147 -1 ackwatch token
   8.148 -1 waitwatch' | ./xs_test 2>&1`" = "1:/test/subnode:token
   8.149 -1:waitwatch timeout" ]
   8.150 -
   8.151 -# Rm fires notification on child.
   8.152 -[ "`echo -e '1 watch /test/subnode token
   8.153 -2 async rm /test
   8.154 -1 waitwatch
   8.155 -1 ackwatch token' | ./xs_test 2>&1`" = "1:/test/subnode:token" ]
   8.156 -
   8.157 -# Watch should not double-send after we ack, even if we did something in between.
   8.158 -[ "`echo -e '1 watch /test2 token
   8.159 -2 async write /test2/foo create contents2
   8.160 -1 waitwatch
   8.161 -1 read /test2/foo
   8.162 -1 ackwatch token
   8.163 -1 waitwatch' | ./xs_test 2>&1`" = "1:/test2/foo:token
   8.164 -1:contents2
   8.165 -1:waitwatch timeout" ]
   8.166 -
   8.167 -# We can watch something which doesn't exist.
   8.168 -[ "`echo '1 watch /dir/subdir token
   8.169 -2 mkdir /dir/subdir
   8.170 -1 waitwatch' | ./xs_test 2>&1`" = "1:/dir/subdir:token" ]
   8.171 -
   8.172 -# If we don't have permission, we won't see event (rm).
   8.173 -[ "`echo '1 setid 1
   8.174 -1 watch /dir/subdir token
   8.175 -setperm /dir 0 NONE
   8.176 -rm /dir/subdir
   8.177 -1 waitwatch' | ./xs_test 2>&1`" = "1:waitwatch timeout" ]
   8.178 -
   8.179 -# If we don't have permission, we won't see event (create).
   8.180 -[ "`echo '1 setid 1
   8.181 -1 watch /dir/subdir token
   8.182 -mkdir /dir/subdir
   8.183 -write /dir/subdir/entry create contents
   8.184 -1 waitwatch' | ./xs_test 2>&1`" = "1:waitwatch timeout" ]
     9.1 --- a/tools/xenstore/testsuite/08transaction.sh	Fri Aug 05 09:02:58 2005 +0000
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,93 +0,0 @@
     9.4 -#! /bin/sh
     9.5 -# Test transactions.
     9.6 -
     9.7 -echo mkdir /test | ./xs_test
     9.8 -
     9.9 -# Simple transaction: create a file inside transaction.
    9.10 -[ "`echo -e '1 start /test
    9.11 -1 write /test/entry1 create contents
    9.12 -2 dir /test
    9.13 -1 dir /test
    9.14 -1 commit
    9.15 -2 read /test/entry1' | ./xs_test`" = "1:entry1
    9.16 -2:contents" ]
    9.17 -echo rm /test/entry1 | ./xs_test
    9.18 -
    9.19 -# Create a file and abort transaction.
    9.20 -[ "`echo -e '1 start /test
    9.21 -1 write /test/entry1 create contents
    9.22 -2 dir /test
    9.23 -1 dir /test
    9.24 -1 abort
    9.25 -2 dir /test' | ./xs_test`" = "1:entry1" ]
    9.26 -
    9.27 -echo write /test/entry1 create contents | ./xs_test
    9.28 -# Delete in transaction, commit
    9.29 -[ "`echo -e '1 start /test
    9.30 -1 rm /test/entry1
    9.31 -2 dir /test
    9.32 -1 dir /test
    9.33 -1 commit
    9.34 -2 dir /test' | ./xs_test`" = "2:entry1" ]
    9.35 -
    9.36 -# Delete in transaction, abort.
    9.37 -echo write /test/entry1 create contents | ./xs_test
    9.38 -[ "`echo -e '1 start /test
    9.39 -1 rm /test/entry1
    9.40 -2 dir /test
    9.41 -1 dir /test
    9.42 -1 abort
    9.43 -2 dir /test' | ./xs_test`" = "2:entry1
    9.44 -2:entry1" ]
    9.45 -
    9.46 -# Transactions can take as long as the want...
    9.47 -[ "`echo -e 'start /test
    9.48 -sleep 1
    9.49 -rm /test/entry1
    9.50 -commit
    9.51 -dir /test' | ./xs_test --no-timeout`" = "" ]
    9.52 -
    9.53 -# ... as long as noone is waiting.
    9.54 -[ "`echo -e '1 start /test
    9.55 -2 mkdir /test/dir
    9.56 -1 mkdir /test/dir
    9.57 -1 dir /test
    9.58 -1 commit' | ./xs_test --no-timeout 2>&1`" = "1:dir
    9.59 -FATAL: 1: commit: Connection timed out" ]
    9.60 -
    9.61 -# Events inside transactions don't trigger watches until (successful) commit.
    9.62 -[ "`echo -e '1 watch /test token
    9.63 -2 start /test
    9.64 -2 mkdir /test/dir/sub
    9.65 -1 waitwatch' | ./xs_test 2>&1`" = "1:waitwatch timeout" ]
    9.66 -[ "`echo -e '1 watch /test token
    9.67 -2 start /test
    9.68 -2 mkdir /test/dir/sub
    9.69 -2 abort
    9.70 -1 waitwatch' | ./xs_test 2>&1`" = "1:waitwatch timeout" ]
    9.71 -[ "`echo -e '1 watch /test token
    9.72 -2 start /test
    9.73 -2 mkdir /test/dir/sub
    9.74 -2 async commit
    9.75 -1 waitwatch
    9.76 -1 ackwatch token' | ./xs_test 2>&1`" = "1:/test/dir/sub:token" ]
    9.77 -
    9.78 -# Rm inside transaction works like rm outside: children get notified.
    9.79 -[ "`echo -e '1 watch /test/dir/sub token
    9.80 -2 start /test
    9.81 -2 rm /test/dir
    9.82 -2 async commit
    9.83 -1 waitwatch
    9.84 -1 ackwatch token' | ./xs_test 2>&1`" = "1:/test/dir/sub:token" ]
    9.85 -
    9.86 -# Multiple events from single transaction don't trigger assert
    9.87 -[ "`echo -e '1 watch /test token
    9.88 -2 start /test
    9.89 -2 write /test/1 create contents
    9.90 -2 write /test/2 create contents
    9.91 -2 async commit
    9.92 -1 waitwatch
    9.93 -1 ackwatch token
    9.94 -1 waitwatch
    9.95 -1 ackwatch token' | ./xs_test 2>&1`" = "1:/test/1:token
    9.96 -1:/test/2:token" ]
    10.1 --- a/tools/xenstore/testsuite/09domain.sh	Fri Aug 05 09:02:58 2005 +0000
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,16 +0,0 @@
    10.4 -#! /bin/sh
    10.5 -# Test domain communication.
    10.6 -
    10.7 -# Create a domain, write an entry.
    10.8 -[ "`echo -e 'introduce 1 100 7 /my/home
    10.9 -1 write /entry1 create contents
   10.10 -dir /' | ./xs_test 2>&1 | sort`" = "entry1
   10.11 -handle is 1
   10.12 -tool" ]
   10.13 -
   10.14 -# Release that domain.
   10.15 -[ "`echo -e 'release 1' | ./xs_test`" = "" ]
   10.16 -
   10.17 -# Introduce and release by same connection.
   10.18 -[ "`echo -e 'introduce 1 100 7 /my/home
   10.19 -release 1' | ./xs_test 2>&1`" = "handle is 1" ]
    11.1 --- a/tools/xenstore/testsuite/10domain-homedir.sh	Fri Aug 05 09:02:58 2005 +0000
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,20 +0,0 @@
    11.4 -#! /bin/sh
    11.5 -# Test domain "implicit" paths.
    11.6 -
    11.7 -# Create a domain, write an entry using implicit path, read using implicit
    11.8 -[ "`echo -e 'mkdir /home
    11.9 -introduce 1 100 7 /home
   11.10 -1 write entry1 create contents
   11.11 -read /home/entry1
   11.12 -dir /home' | ./xs_test 2>&1`" = "handle is 1
   11.13 -contents
   11.14 -entry1" ]
   11.15 -
   11.16 -# Place a watch using a relative path: expect relative answer.
   11.17 -[ "`echo 'introduce 1 100 7 /home
   11.18 -1 mkdir foo
   11.19 -1 watch foo token
   11.20 -async write /home/foo/bar create contents
   11.21 -1 waitwatch
   11.22 -1 ackwatch token' | ./xs_test 2>&1`" = "handle is 1
   11.23 -1:foo/bar:token" ]
    12.1 --- a/tools/xenstore/testsuite/11domain-watch.sh	Fri Aug 05 09:02:58 2005 +0000
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,55 +0,0 @@
    12.4 -#! /bin/sh
    12.5 -# Test watching from a domain.
    12.6 -
    12.7 -# Watch something, write to it, check watch has fired.
    12.8 -[ "`echo -e 'write /test create contents' | ./xs_test 2>&1`" = "" ]
    12.9 -[ "`echo -e 'mkdir /dir' | ./xs_test 2>&1`" = "" ]
   12.10 -
   12.11 -[ "`echo -e 'introduce 1 100 7 /my/home
   12.12 -1 watch /test token
   12.13 -async write /test create contents2
   12.14 -1 waitwatch
   12.15 -1 ackwatch token
   12.16 -1 unwatch /test token
   12.17 -asyncwait
   12.18 -release 1' | ./xs_test 2>&1`" = "handle is 1
   12.19 -1:/test:token" ]
   12.20 -
   12.21 -# ignore watches while doing commands, should work.
   12.22 -[ "`echo -e 'introduce 1 100 7 /my/home
   12.23 -1 watch /dir token
   12.24 -async write /dir/test create contents
   12.25 -1 write /dir/test2 create contents2
   12.26 -1 write /dir/test3 create contents3
   12.27 -1 write /dir/test4 create contents4
   12.28 -1 waitwatch
   12.29 -1 ackwatch token
   12.30 -asyncwait
   12.31 -release 1' | ./xs_test 2>&1`" = "handle is 1
   12.32 -1:/dir/test:token" ]
   12.33 -
   12.34 -# unwatch
   12.35 -[ "`echo -e 'introduce 1 100 7 /my/home
   12.36 -1 watch /dir token1
   12.37 -1 unwatch /dir token1
   12.38 -1 watch /dir token2
   12.39 -async 2 write /dir/test2 create contents
   12.40 -1 waitwatch
   12.41 -1 unwatch /dir token2
   12.42 -asyncwait
   12.43 -release 1' | ./xs_test 2>&1`" = "handle is 1
   12.44 -1:/dir/test2:token2" ]
   12.45 -
   12.46 -# unwatch while watch pending.
   12.47 -[ "`echo -e 'introduce 1 100 7 /my/home
   12.48 -introduce 2 101 8 /my/secondhome
   12.49 -1 watch /dir token1
   12.50 -2 watch /dir token2
   12.51 -3 async write /dir/test create contents
   12.52 -2 unwatch /dir token2
   12.53 -1 waitwatch
   12.54 -1 ackwatch token1
   12.55 -release 1
   12.56 -release 2' | ./xs_test 2>&1`" = "handle is 1
   12.57 -handle is 2
   12.58 -1:/dir/test:token1" ]
    13.1 --- a/tools/xenstore/testsuite/12readonly.sh	Fri Aug 05 09:02:58 2005 +0000
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,38 +0,0 @@
    13.4 -#! /bin/sh
    13.5 -# Test that read only connection can't alter store.
    13.6 -
    13.7 -[ "`echo 'write /test create contents' | ./xs_test 2>&1`" = "" ]
    13.8 -
    13.9 -# These are all valid.
   13.10 -[ "`echo dir / | ./xs_test --readonly 2>&1 | sort`" = "test
   13.11 -tool" ]
   13.12 -
   13.13 -[ "`echo 'read /test
   13.14 -getperm /test
   13.15 -watch /test token
   13.16 -unwatch /test token 
   13.17 -start /
   13.18 -commit
   13.19 -start /
   13.20 -abort' | ./xs_test --readonly 2>&1`" = "contents
   13.21 -0 READ" ]
   13.22 -
   13.23 -# These don't work
   13.24 -[ "`echo 'write /test2 create contents' | ./xs_test --readonly 2>&1`" = "FATAL: write: Read-only file system" ]
   13.25 -[ "`echo 'write /test create contents' | ./xs_test --readonly 2>&1`" = "FATAL: write: Read-only file system" ]
   13.26 -[ "`echo 'setperm /test 100 NONE' | ./xs_test --readonly 2>&1`" = "FATAL: setperm: Read-only file system" ]
   13.27 -[ "`echo 'setperm /test 100 NONE' | ./xs_test --readonly 2>&1`" = "FATAL: setperm: Read-only file system" ]
   13.28 -[ "`echo 'shutdown' | ./xs_test --readonly 2>&1`" = "FATAL: shutdown: Read-only file system" ]
   13.29 -[ "`echo 'introduce 1 100 7 /home' | ./xs_test --readonly 2>&1`" = "FATAL: introduce: Read-only file system" ]
   13.30 -
   13.31 -# Check that watches work like normal.
   13.32 -set -m
   13.33 -[ "`echo 'watch / token
   13.34 -waitwatch
   13.35 -ackwatch token' | ./xs_test --readonly 2>&1`" = "/test:token" ] &
   13.36 -
   13.37 -[ "`echo 'write /test create contents' | ./xs_test 2>&1`" = "" ]
   13.38 -if wait; then :; else
   13.39 -    echo Readonly wait test failed: $?
   13.40 -    exit 1
   13.41 -fi
    14.1 --- a/tools/xenstore/testsuite/13watch-ack.sh	Fri Aug 05 09:02:58 2005 +0000
    14.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.3 @@ -1,23 +0,0 @@
    14.4 -#! /bin/sh
    14.5 -
    14.6 -# This demonstrates a bug where an xs_acknowledge_watch returns
    14.7 -# EINVAL, because the daemon doesn't track what watch event it sent
    14.8 -# and relies on it being the "first" watch which has an event.
    14.9 -# Watches firing after the first event is sent out will change this.
   14.10 -
   14.11 -# Create three things to watch.
   14.12 -echo mkdir /test | ./xs_test
   14.13 -echo mkdir /test/1 | ./xs_test
   14.14 -echo mkdir /test/2 | ./xs_test
   14.15 -echo mkdir /test/3 | ./xs_test
   14.16 -
   14.17 -# Watch all three, fire event on 2, read watch, fire event on 1 and 3, ack 2.
   14.18 -[ "`echo '1 watch /test/1 token1 0
   14.19 -1 watch /test/2 token2 0
   14.20 -1 watch /test/3 token3 0
   14.21 -2 async write /test/2 create contents2
   14.22 -3 async write /test/1 create contents1
   14.23 -4 async write /test/3 create contents3
   14.24 -1 waitwatch
   14.25 -1 ackwatch token2
   14.26 -1 close' | ./xs_test 2>&1`" = "1:/test/2:token2" ]
    15.1 --- a/tools/xenstore/testsuite/test.sh	Fri Aug 05 09:02:58 2005 +0000
    15.2 +++ b/tools/xenstore/testsuite/test.sh	Fri Aug 05 09:04:01 2005 +0000
    15.3 @@ -7,19 +7,16 @@ run_test()
    15.4  {
    15.5      rm -rf $XENSTORED_ROOTDIR
    15.6      mkdir $XENSTORED_ROOTDIR
    15.7 -# Weird failures with this.
    15.8 -    if type valgrind >/dev/null 2>&1; then
    15.9 +    if [ $VALGRIND -eq 1 ]; then
   15.10  	valgrind -q --logfile-fd=3 ./xenstored_test --output-pid --trace-file=testsuite/tmp/trace --no-fork 3>testsuite/tmp/vgout > /tmp/pid 2> testsuite/tmp/xenstored_errors &
   15.11  	while [ ! -s /tmp/pid ]; do sleep 0; done
   15.12  	PID=`cat /tmp/pid`
   15.13  	rm /tmp/pid
   15.14      else
   15.15 -	./xenstored_test --output-pid --trace-file=testsuite/tmp/trace --no-fork > /tmp/pid 2> testsuite/tmp/xenstored_errors &
   15.16 -	while [ ! -s /tmp/pid ]; do sleep 0; done
   15.17 -	PID=`cat /tmp/pid`
   15.18 -	rm /tmp/pid
   15.19 +	# We don't get error messages from this, though. 
   15.20 +	PID=`./xenstored_test --output-pid --trace-file=testsuite/tmp/trace`
   15.21      fi
   15.22 -    if sh -e $2 $1; then
   15.23 +    if ./xs_test $2 $1; then
   15.24  	if [ -s testsuite/tmp/vgout ]; then
   15.25  	    kill $PID
   15.26  	    echo VALGRIND errors:
   15.27 @@ -36,12 +33,27 @@ run_test()
   15.28      fi
   15.29  }
   15.30  
   15.31 +if [ x$1 = x--fast ]; then
   15.32 +    VALGRIND=0
   15.33 +    SLOWTESTS=""
   15.34 +    shift
   15.35 +else
   15.36 +    if type valgrind >/dev/null 2>&1; then
   15.37 +	VALGRIND=1
   15.38 +    else
   15.39 +	echo "WARNING: valgrind not available" >&2
   15.40 +	VALGRIND=0
   15.41 +    fi
   15.42 +    SLOWTESTS=testsuite/[0-9]*.slowtest
   15.43 +fi
   15.44 +
   15.45  MATCH=${1:-"*"}
   15.46 -for f in testsuite/[0-9]*.sh; do
   15.47 +for f in testsuite/[0-9]*.test $SLOWTESTS; do
   15.48      case `basename $f` in $MATCH) RUN=1;; esac
   15.49      [ -n "$RUN" ] || continue
   15.50 -    if run_test $f; then
   15.51 -	echo Test $f passed...
   15.52 +
   15.53 +    if run_test $f > /dev/null; then
   15.54 +	echo -n .
   15.55      else
   15.56  	echo Test $f failed, running verbosely...
   15.57  	run_test $f -x || true
    16.1 --- a/tools/xenstore/xs_random.c	Fri Aug 05 09:02:58 2005 +0000
    16.2 +++ b/tools/xenstore/xs_random.c	Fri Aug 05 09:04:01 2005 +0000
    16.3 @@ -1112,9 +1112,6 @@ static unsigned int try_simple(const boo
    16.4  			data->ops->close(pre);
    16.5  		}
    16.6  	}
    16.7 -	if (data->print_progress)
    16.8 -		printf("\n");
    16.9 -
   16.10  out:
   16.11  	data->ops->close(h);	
   16.12  	return i;
   16.13 @@ -1192,10 +1189,9 @@ static void simple_test(const char *dir,
   16.14  	try = try_simple(NULL, iters, verbose, &data);
   16.15  	if (try == iters) {
   16.16  		cleanup_xs_ops();
   16.17 -		printf("Succeeded\n");
   16.18  		exit(0);
   16.19  	}
   16.20 -	printf("Failed on iteration %u\n", try + 1);
   16.21 +	printf("Failed on iteration %u of seed %u\n", try + 1, seed);
   16.22  	data.print_progress = false;
   16.23  	reduce_problem(try + 1, try_simple, &data);
   16.24  }
   16.25 @@ -1406,8 +1402,6 @@ static unsigned int try_diff(const bool 
   16.26  			talloc_free(fileh_pre);
   16.27  		}
   16.28  	}
   16.29 -	if (data->print_progress)
   16.30 -		printf("\n");
   16.31  
   16.32  	fail = NULL;
   16.33  	if (data->fast)
   16.34 @@ -1435,10 +1429,9 @@ static void diff_test(const char *dir,
   16.35  	try = try_diff(NULL, iters, verbose, &data);
   16.36  	if (try == iters) {
   16.37  		cleanup_xs_ops();
   16.38 -		printf("Succeeded\n");
   16.39  		exit(0);
   16.40  	}
   16.41 -	printf("Failed on iteration %u\n", try + 1);
   16.42 +	printf("Failed on iteration %u of seed %u\n", try + 1, seed);
   16.43  	data.print_progress = false;
   16.44  	reduce_problem(try + 1, try_diff, &data);
   16.45  }
   16.46 @@ -1593,8 +1586,6 @@ static unsigned int try_fail(const bool 
   16.47  		xs_close(tmpxsh);
   16.48  		file_close(tmpfileh);
   16.49  	}
   16.50 -
   16.51 -	printf("Total %u of %u not aborted\n", tried - aborted, tried);
   16.52  out:
   16.53  	if (xsh)
   16.54  		xs_close(xsh);
   16.55 @@ -1615,10 +1606,9 @@ static void fail_test(const char *dir,
   16.56  	try = try_fail(NULL, iters, verbose, &data);
   16.57  	if (try == iters) {
   16.58  		cleanup_xs_ops();
   16.59 -		printf("Succeeded\n");
   16.60  		exit(0);
   16.61  	}
   16.62 -	printf("Failed on iteration %u\n", try + 1);
   16.63 +	printf("Failed on iteration %u of seed %u\n", try + 1, seed);
   16.64  	fflush(stdout);
   16.65  	data.print_progress = false;
   16.66  	reduce_problem(try + 1, try_fail, &data);
    17.1 --- a/tools/xenstore/xs_test.c	Fri Aug 05 09:02:58 2005 +0000
    17.2 +++ b/tools/xenstore/xs_test.c	Fri Aug 05 09:04:01 2005 +0000
    17.3 @@ -17,6 +17,7 @@
    17.4      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17.5  */
    17.6  
    17.7 +#define _GNU_SOURCE
    17.8  #include <stdio.h>
    17.9  #include <stdlib.h>
   17.10  #include <sys/types.h>
   17.11 @@ -27,17 +28,26 @@
   17.12  #include <stdint.h>
   17.13  #include <stdbool.h>
   17.14  #include <stdlib.h>
   17.15 +#include <fnmatch.h>
   17.16 +#include <stdarg.h>
   17.17 +#include <string.h>
   17.18 +#include <getopt.h>
   17.19 +#include <ctype.h>
   17.20 +#include <sys/time.h>
   17.21  #include <sys/mman.h>
   17.22  #include "utils.h"
   17.23  #include "xs_lib.h"
   17.24 +#include "list.h"
   17.25  
   17.26  #define XSTEST
   17.27  
   17.28  static struct xs_handle *handles[10] = { NULL };
   17.29 -static unsigned int children;
   17.30  
   17.31 -static bool timeout = true;
   17.32 +static unsigned int timeout_ms = 50;
   17.33 +static bool timeout_suppressed = true;
   17.34  static bool readonly = false;
   17.35 +static bool print_input = false;
   17.36 +static unsigned int linenum = 0;
   17.37  
   17.38  struct ringbuf_head
   17.39  {
   17.40 @@ -178,7 +188,7 @@ static bool write_all_choice(int fd, con
   17.41  static void __attribute__((noreturn)) usage(void)
   17.42  {
   17.43  	barf("Usage:\n"
   17.44 -	     "       xs_test [--readonly] [--notimeout]\n"
   17.45 +	     "       xs_test [--readonly] [--no-timeout] [-x]\n"
   17.46  	     "Reads commands from stdin, one per line:"
   17.47  	     "  dir <path>\n"
   17.48  	     "  read <path>\n"
   17.49 @@ -190,8 +200,6 @@ static void __attribute__((noreturn)) us
   17.50  	     "  setperm <path> <id> <flags> ...\n"
   17.51  	     "  shutdown\n"
   17.52  	     "  watch <path> <token>\n"
   17.53 -	     "  async <command>...\n"
   17.54 -	     "  asyncwait\n"
   17.55  	     "  waitwatch\n"
   17.56  	     "  ackwatch <token>\n"
   17.57  	     "  unwatch <path> <token>\n"
   17.58 @@ -200,7 +208,11 @@ static void __attribute__((noreturn)) us
   17.59  	     "  abort\n"
   17.60  	     "  introduce <domid> <mfn> <eventchn> <path>\n"
   17.61  	     "  commit\n"
   17.62 -	     "  sleep <seconds>\n"
   17.63 +	     "  sleep <milliseconds>\n"
   17.64 +	     "  expect <pattern>\n"
   17.65 +	     "  notimeout\n"
   17.66 +	     "  readonly\n"
   17.67 +	     "  readwrite\n"
   17.68  	     "  dump\n");
   17.69  }
   17.70  
   17.71 @@ -218,7 +230,7 @@ static int argpos(const char *line, unsi
   17.72  	return off;
   17.73  }
   17.74  
   17.75 -static char *arg(char *line, unsigned int num)
   17.76 +static char *arg(const char *line, unsigned int num)
   17.77  {
   17.78  	static char *args[10];
   17.79  	unsigned int off, len;
   17.80 @@ -236,12 +248,64 @@ static char *arg(char *line, unsigned in
   17.81  	return args[num];
   17.82  }
   17.83  
   17.84 +struct expect
   17.85 +{
   17.86 +	struct list_head list;
   17.87 +	char *pattern;
   17.88 +};
   17.89 +static LIST_HEAD(expects);
   17.90 +
   17.91  static char *command;
   17.92 -static void __attribute__((noreturn)) failed(int handle)
   17.93 +
   17.94 +/* Trim leading and trailing whitespace */
   17.95 +static void trim(char *str)
   17.96 +{
   17.97 +	while (isspace(str[0]))
   17.98 +		memmove(str, str+1, strlen(str));
   17.99 +
  17.100 +	while (strlen(str) && isspace(str[strlen(str)-1]))
  17.101 +		str[strlen(str)-1] = '\0';
  17.102 +}
  17.103 +
  17.104 +static void output(const char *fmt, ...)
  17.105 +{
  17.106 +	char *str;
  17.107 +	struct expect *i;
  17.108 +	va_list arglist;
  17.109 +
  17.110 +	va_start(arglist, fmt);
  17.111 +	vasprintf(&str, fmt, arglist);
  17.112 +	va_end(arglist);
  17.113 +
  17.114 +	printf("%s", str);
  17.115 +	fflush(stdout);
  17.116 +	trim(str);
  17.117 +	list_for_each_entry(i, &expects, list) {
  17.118 +		if (fnmatch(i->pattern, str, 0) == 0) {
  17.119 +			list_del(&i->list);
  17.120 +			free(i);
  17.121 +			return;
  17.122 +		}
  17.123 +	}
  17.124 +	barf("Unexpected output %s\n", str);
  17.125 +}
  17.126 +
  17.127 +static void failed(int handle)
  17.128  {
  17.129  	if (handle)
  17.130 -		barf_perror("%i: %s", handle, command);
  17.131 -	barf_perror("%s", command);
  17.132 +		output("%i: %s failed: %s\n",
  17.133 +		       handle, command, strerror(errno));
  17.134 +	else
  17.135 +		output("%s failed: %s\n", command, strerror(errno));
  17.136 +}
  17.137 +
  17.138 +static void expect(const char *line)
  17.139 +{
  17.140 +	struct expect *e = malloc(sizeof(*e));
  17.141 +
  17.142 +	e->pattern = strdup(line + argpos(line, 1));
  17.143 +	trim(e->pattern);
  17.144 +	list_add(&e->list, &expects);
  17.145  }
  17.146  
  17.147  static void do_dir(unsigned int handle, char *path)
  17.148 @@ -250,14 +314,16 @@ static void do_dir(unsigned int handle, 
  17.149  	unsigned int i, num;
  17.150  
  17.151  	entries = xs_directory(handles[handle], path, &num);
  17.152 -	if (!entries)
  17.153 +	if (!entries) {
  17.154  		failed(handle);
  17.155 +		return;
  17.156 +	}
  17.157  
  17.158  	for (i = 0; i < num; i++)
  17.159  		if (handle)
  17.160 -			printf("%i:%s\n", handle, entries[i]);
  17.161 +			output("%i:%s\n", handle, entries[i]);
  17.162  		else
  17.163 -			printf("%s\n", entries[i]);
  17.164 +			output("%s\n", entries[i]);
  17.165  	free(entries);
  17.166  }
  17.167  
  17.168 @@ -267,15 +333,17 @@ static void do_read(unsigned int handle,
  17.169  	unsigned int len;
  17.170  
  17.171  	value = xs_read(handles[handle], path, &len);
  17.172 -	if (!value)
  17.173 +	if (!value) {
  17.174  		failed(handle);
  17.175 +		return;
  17.176 +	}
  17.177  
  17.178  	/* It's supposed to nul terminate for us. */
  17.179  	assert(value[len] == '\0');
  17.180  	if (handle)
  17.181 -		printf("%i:%.*s\n", handle, len, value);
  17.182 +		output("%i:%.*s\n", handle, len, value);
  17.183  	else
  17.184 -		printf("%.*s\n", len, value);
  17.185 +		output("%.*s\n", len, value);
  17.186  }
  17.187  
  17.188  static void do_write(unsigned int handle, char *path, char *flags, char *data)
  17.189 @@ -322,8 +390,10 @@ static void do_getperm(unsigned int hand
  17.190  	struct xs_permissions *perms;
  17.191  
  17.192  	perms = xs_get_permissions(handles[handle], path, &num);
  17.193 -	if (!perms)
  17.194 +	if (!perms) {
  17.195  		failed(handle);
  17.196 +		return;
  17.197 +	}
  17.198  
  17.199  	for (i = 0; i < num; i++) {
  17.200  		char *permstring;
  17.201 @@ -346,9 +416,9 @@ static void do_getperm(unsigned int hand
  17.202  		}
  17.203  
  17.204  		if (handle)
  17.205 -			printf("%i:%i %s\n", handle, perms[i].id, permstring);
  17.206 +			output("%i:%i %s\n", handle, perms[i].id, permstring);
  17.207  		else
  17.208 -			printf("%i %s\n", perms[i].id, permstring);
  17.209 +			output("%i %s\n", perms[i].id, permstring);
  17.210  	}
  17.211  	free(perms);
  17.212  }
  17.213 @@ -399,15 +469,31 @@ static void do_watch(unsigned int handle
  17.214  static void do_waitwatch(unsigned int handle)
  17.215  {
  17.216  	char **vec;
  17.217 +	struct timeval tv = {.tv_sec = timeout_ms/1000,
  17.218 +			     .tv_usec = (timeout_ms*1000)%1000000 };
  17.219 +	fd_set set;
  17.220 +
  17.221 +	if (xs_fileno(handles[handle]) != -2) {
  17.222 +		FD_ZERO(&set);
  17.223 +		FD_SET(xs_fileno(handles[handle]), &set);
  17.224 +		if (select(xs_fileno(handles[handle])+1, &set,
  17.225 +			   NULL, NULL, &tv) == 0) {
  17.226 +			errno = ETIMEDOUT;
  17.227 +			failed(handle);
  17.228 +			return;
  17.229 +		}
  17.230 +	}
  17.231  
  17.232  	vec = xs_read_watch(handles[handle]);
  17.233 -	if (!vec)
  17.234 +	if (!vec) {
  17.235  		failed(handle);
  17.236 +		return;
  17.237 +	}
  17.238  
  17.239  	if (handle)
  17.240 -		printf("%i:%s:%s\n", handle, vec[0], vec[1]);
  17.241 +		output("%i:%s:%s\n", handle, vec[0], vec[1]);
  17.242  	else
  17.243 -		printf("%s:%s\n", vec[0], vec[1]);
  17.244 +		output("%s:%s\n", vec[0], vec[1]);
  17.245  	free(vec);
  17.246  }
  17.247  
  17.248 @@ -417,82 +503,6 @@ static void do_ackwatch(unsigned int han
  17.249  		failed(handle);
  17.250  }
  17.251  
  17.252 -static bool wait_for_input(unsigned int handle)
  17.253 -{
  17.254 -	unsigned int i;
  17.255 -	for (i = 0; i < ARRAY_SIZE(handles); i++) {
  17.256 -		int fd;
  17.257 -
  17.258 -		if (!handles[i] || i == handle)
  17.259 -			continue;
  17.260 -
  17.261 -		fd = xs_fileno(handles[i]);
  17.262 -		if (fd == -2) {
  17.263 -			unsigned int avail;
  17.264 -			get_input_chunk(in, in->buf, &avail);
  17.265 -			if (avail != 0)
  17.266 -				return true;
  17.267 -		} else {
  17.268 -			struct timeval tv = {.tv_sec = 0, .tv_usec = 0 };
  17.269 -			fd_set set;
  17.270 -
  17.271 -			FD_ZERO(&set);
  17.272 -			FD_SET(fd, &set);
  17.273 -			if (select(fd+1, &set, NULL, NULL,&tv))
  17.274 -				return true;
  17.275 -		}
  17.276 -	}
  17.277 -	return false;
  17.278 -}
  17.279 -
  17.280 -
  17.281 -/* Async wait for watch on handle */
  17.282 -static void do_command(unsigned int default_handle, char *line);
  17.283 -static void do_async(unsigned int handle, char *line)
  17.284 -{
  17.285 -	int child;
  17.286 -	unsigned int i;
  17.287 -	children++;
  17.288 -	if ((child = fork()) != 0) {
  17.289 -		/* Wait until *something* happens, which indicates
  17.290 -		 * child has created an event.  V. sloppy, but we can't
  17.291 -		 * select on fake domain connections.
  17.292 -		 */
  17.293 -		while (!wait_for_input(handle));
  17.294 -		return;
  17.295 -	}
  17.296 -
  17.297 -	/* Don't keep other handles open in parent. */
  17.298 -	for (i = 0; i < ARRAY_SIZE(handles); i++) {
  17.299 -		if (handles[i] && i != handle) {
  17.300 -			xs_daemon_close(handles[i]);
  17.301 -			handles[i] = NULL;
  17.302 -		}
  17.303 -	}
  17.304 -
  17.305 -	do_command(handle, line + argpos(line, 1));
  17.306 -	exit(0);
  17.307 -}
  17.308 -
  17.309 -static void do_asyncwait(unsigned int handle)
  17.310 -{
  17.311 -	int status;
  17.312 -
  17.313 -	if (handle)
  17.314 -		barf("handle has no meaning with asyncwait");
  17.315 -
  17.316 -	if (children == 0)
  17.317 -		barf("No children to wait for!");
  17.318 -
  17.319 -	if (waitpid(0, &status, 0) > 0) {
  17.320 -		if (!WIFEXITED(status))
  17.321 -			barf("async died");
  17.322 -		if (WEXITSTATUS(status))
  17.323 -			exit(WEXITSTATUS(status));
  17.324 -	}
  17.325 -	children--;
  17.326 -}
  17.327 -
  17.328  static void do_unwatch(unsigned int handle, const char *node, const char *token)
  17.329  {
  17.330  	if (!xs_unwatch(handles[handle], node, token))
  17.331 @@ -538,15 +548,18 @@ static void do_introduce(unsigned int ha
  17.332  	*(int *)((void *)out + 32) = getpid();
  17.333  	*(u16 *)((void *)out + 36) = atoi(eventchn);
  17.334  
  17.335 +	if (!xs_introduce_domain(handles[handle], atoi(domid),
  17.336 +				 atol(mfn), atoi(eventchn), path)) {
  17.337 +		failed(handle);
  17.338 +		munmap(out, getpagesize());
  17.339 +		return;
  17.340 +	}
  17.341 +	output("handle is %i\n", i);
  17.342 +
  17.343  	/* Create new handle. */
  17.344  	handles[i] = new(struct xs_handle);
  17.345  	handles[i]->fd = -2;
  17.346  
  17.347 -	if (!xs_introduce_domain(handles[handle], atoi(domid),
  17.348 -				 atol(mfn), atoi(eventchn), path))
  17.349 -		failed(handle);
  17.350 -	printf("handle is %i\n", i);
  17.351 -
  17.352  	/* Read in daemon pid. */
  17.353  	daemon_pid = *(int *)((void *)out + 32);
  17.354  }
  17.355 @@ -593,18 +606,20 @@ static void dump_dir(unsigned int handle
  17.356  		sprintf(subnode, "%s/%s", node, dir[i]);
  17.357  
  17.358  		perms = xs_get_permissions(handles[handle], subnode,&numperms);
  17.359 -		if (!perms)
  17.360 +		if (!perms) {
  17.361  			failed(handle);
  17.362 +			return;
  17.363 +		}
  17.364  
  17.365 -		printf("%s%s: ", spacing, dir[i]);
  17.366 +		output("%s%s: ", spacing, dir[i]);
  17.367  		for (j = 0; j < numperms; j++) {
  17.368  			char buffer[100];
  17.369  			if (!xs_perm_to_string(&perms[j], buffer))
  17.370  				barf("perm to string");
  17.371 -			printf("%s ", buffer);
  17.372 +			output("%s ", buffer);
  17.373  		}
  17.374  		free(perms);
  17.375 -		printf("\n");
  17.376 +		output("\n");
  17.377  
  17.378  		/* Even directories can have contents. */
  17.379  		contents = xs_read(handles[handle], subnode, &len);
  17.380 @@ -612,14 +627,16 @@ static void dump_dir(unsigned int handle
  17.381  			if (errno != EISDIR)
  17.382  				failed(handle);
  17.383  		} else {
  17.384 -			printf(" %s(%.*s)\n", spacing, len, contents);
  17.385 +			output(" %s(%.*s)\n", spacing, len, contents);
  17.386  			free(contents);
  17.387  		}			
  17.388  
  17.389  		/* Every node is a directory. */
  17.390  		subdirs = xs_directory(handles[handle], subnode, &subnum);
  17.391 -		if (!subdirs)
  17.392 +		if (!subdirs) {
  17.393  			failed(handle);
  17.394 +			return;
  17.395 +		}
  17.396  		dump_dir(handle, subnode, subdirs, subnum, depth+1);
  17.397  		free(subdirs);
  17.398  	}
  17.399 @@ -631,8 +648,10 @@ static void dump(int handle)
  17.400  	unsigned int subnum;
  17.401  
  17.402  	subdirs = xs_directory(handles[handle], "/", &subnum);
  17.403 -	if (!subdirs)
  17.404 +	if (!subdirs) {
  17.405  		failed(handle);
  17.406 +		return;
  17.407 +	}
  17.408  
  17.409  	dump_dir(handle, "", subdirs, subnum, 0);
  17.410  	free(subdirs);
  17.411 @@ -652,10 +671,31 @@ static void alarmed(int sig __attribute_
  17.412  	exit(1);
  17.413  }
  17.414  
  17.415 +static void set_timeout(void)
  17.416 +{
  17.417 +	struct itimerval timeout;
  17.418 +
  17.419 +	timeout.it_interval.tv_sec = timeout_ms / 1000;
  17.420 +	timeout.it_interval.tv_usec = (timeout_ms * 1000) % 1000000;
  17.421 +	setitimer(ITIMER_REAL, &timeout, NULL);
  17.422 +}
  17.423 +
  17.424 +static void disarm_timeout(void)
  17.425 +{
  17.426 +	struct itimerval timeout;
  17.427 +
  17.428 +	timeout.it_interval.tv_sec = 0;
  17.429 +	timeout.it_interval.tv_usec = 0;
  17.430 +	setitimer(ITIMER_REAL, &timeout, NULL);
  17.431 +}
  17.432 +
  17.433  static void do_command(unsigned int default_handle, char *line)
  17.434  {
  17.435  	char *endp;
  17.436  
  17.437 +	if (print_input)
  17.438 +		printf("%i> %s", ++linenum, line);
  17.439 +
  17.440  	if (strspn(line, " \n") == strlen(line))
  17.441  		return;
  17.442  	if (strstarts(line, "#"))
  17.443 @@ -667,6 +707,7 @@ static void do_command(unsigned int defa
  17.444  	else
  17.445  		handle = default_handle;
  17.446  
  17.447 +	command = arg(line, 0);
  17.448  	if (!handles[handle]) {
  17.449  		if (readonly)
  17.450  			handles[handle] = xs_daemon_open_readonly();
  17.451 @@ -675,10 +716,10 @@ static void do_command(unsigned int defa
  17.452  		if (!handles[handle])
  17.453  			barf_perror("Opening connection to daemon");
  17.454  	}
  17.455 -	command = arg(line, 0);
  17.456  
  17.457 -	if (timeout)
  17.458 -		alarm(1);
  17.459 +	if (!timeout_suppressed)
  17.460 +		set_timeout();
  17.461 +	timeout_suppressed = false;
  17.462  
  17.463  	if (streq(command, "dir"))
  17.464  		do_dir(handle, arg(line, 1));
  17.465 @@ -703,10 +744,6 @@ static void do_command(unsigned int defa
  17.466  		do_watch(handle, arg(line, 1), arg(line, 2));
  17.467  	else if (streq(command, "waitwatch"))
  17.468  		do_waitwatch(handle);
  17.469 -	else if (streq(command, "async"))
  17.470 -		do_async(handle, line);
  17.471 -	else if (streq(command, "asyncwait"))
  17.472 -		do_asyncwait(handle);
  17.473  	else if (streq(command, "ackwatch"))
  17.474  		do_ackwatch(handle, arg(line, 1));
  17.475  	else if (streq(command, "unwatch"))
  17.476 @@ -727,32 +764,66 @@ static void do_command(unsigned int defa
  17.477  		do_release(handle, arg(line, 1));
  17.478  	else if (streq(command, "dump"))
  17.479  		dump(handle);
  17.480 -	else if (streq(command, "sleep"))
  17.481 -		sleep(atoi(arg(line, 1)));
  17.482 -	else
  17.483 +	else if (streq(command, "sleep")) {
  17.484 +		disarm_timeout();
  17.485 +		usleep(atoi(arg(line, 1)) * 1000);
  17.486 +	} else if (streq(command, "expect"))
  17.487 +		expect(line);
  17.488 +	else if (streq(command, "notimeout"))
  17.489 +		timeout_suppressed = true;
  17.490 +	else if (streq(command, "readonly")) {
  17.491 +		readonly = true;
  17.492 +		xs_daemon_close(handles[handle]);
  17.493 +		handles[handle] = NULL;
  17.494 +	} else if (streq(command, "readwrite")) {
  17.495 +		readonly = false;
  17.496 +		xs_daemon_close(handles[handle]);
  17.497 +		handles[handle] = NULL;
  17.498 +	} else
  17.499  		barf("Unknown command %s", command);
  17.500  	fflush(stdout);
  17.501 -	alarm(0);
  17.502 +	disarm_timeout();
  17.503 +
  17.504 +	/* Check expectations. */
  17.505 +	if (!streq(command, "expect")) {
  17.506 +		struct expect *i = list_top(&expects, struct expect, list);
  17.507 +
  17.508 +		if (i)
  17.509 +			barf("Expected '%s', didn't happen\n", i->pattern);
  17.510 +	}
  17.511  }
  17.512  
  17.513 +static struct option options[] = { { "readonly", 0, NULL, 'r' },
  17.514 +				   { "no-timeout", 0, NULL, 't' },
  17.515 +				   { NULL, 0, NULL, 0 } };
  17.516 +
  17.517  int main(int argc, char *argv[])
  17.518  {
  17.519 +	int opt;
  17.520  	char line[1024];
  17.521  
  17.522 -	if (argc > 1 && streq(argv[1], "--readonly")) {
  17.523 -		readonly = true;
  17.524 -		argc--;
  17.525 -		argv++;
  17.526 +	while ((opt = getopt_long(argc, argv, "xrt", options, NULL)) != -1) {
  17.527 +		switch (opt) {
  17.528 +		case 'r':
  17.529 +			readonly = true;
  17.530 +			break;
  17.531 +		case 't':
  17.532 +			timeout_ms = 0;
  17.533 +			break;
  17.534 +		case 'x':
  17.535 +			print_input = true;
  17.536 +			break;
  17.537 +		}
  17.538  	}
  17.539  
  17.540 -	if (argc > 1 && streq(argv[1], "--no-timeout")) {
  17.541 -		timeout = false;
  17.542 -		argc--;
  17.543 -		argv++;
  17.544 -	}
  17.545 -
  17.546 -	if (argc != 1)
  17.547 +	if (optind + 1 == argc) {
  17.548 +		int fd = open(argv[optind], O_RDONLY);
  17.549 +		if (!fd)
  17.550 +			barf_perror("Opening %s", argv[optind]);
  17.551 +		dup2(fd, STDIN_FILENO);
  17.552 +	} else if (optind != argc)
  17.553  		usage();
  17.554 +	
  17.555  
  17.556  	/* The size of the ringbuffer: half a page minus head structure. */
  17.557  	ringbuf_datasize = getpagesize() / 2 - sizeof(struct ringbuf_head);
  17.558 @@ -761,7 +832,5 @@ int main(int argc, char *argv[])
  17.559  	while (fgets(line, sizeof(line), stdin))
  17.560  		do_command(0, line);
  17.561  
  17.562 -	while (children)
  17.563 -		do_asyncwait(0);
  17.564  	return 0;
  17.565  }