test-many-klibcs: Test shared library build in a chroot
diff --git a/test-many-klibcs b/test-many-klibcs
index 2eb72ba..07d22f5 100755
--- a/test-many-klibcs
+++ b/test-many-klibcs
@@ -12,6 +12,43 @@
     || return
 }
 
+do_install() {
+    # Set up a tmpfs in case the current filesystem is mounted nodev
+    mkdir -p install
+    if mountpoint install >/dev/null; then
+	find install -xdev -mindepth 1 -delete || return
+    else
+	sudo mount -t tmpfs tmpfs install || return
+    fi
+
+    # Install klibc itself
+    make -C ../klibc install "ARCH=$arch" "CROSS_COMPILE=$gnuarch-" \
+	 $makeflags INSTALLROOT="$PWD/install" \
+    || return
+
+    # Install shared-library tests
+    mkdir install/tests
+    cp ../klibc/usr/klibc/tests/*.shared install/tests/ || return
+
+    # Some tests need these
+    mkdir -p install/dev
+    sudo mknod -m 666 install/dev/null c 1 3
+    sudo mknod -m 666 install/dev/zero c 1 5
+    mkdir -p install/etc
+    head -1 /etc/passwd > install/etc/passwd
+
+    # Install statically-linked QEMU inside
+    case "$arch" in
+	i386 | x86_64)
+	    ;;
+	*)
+	    mkdir -p install/bin
+	    install "$(command -v "qemu-$qemuarch-static")" install/bin/ \
+	    || return
+	    ;;
+    esac
+}
+
 clean() {
     echo "I: Cleaning"
     make -C ../klibc clean "ARCH=$arch"
@@ -29,13 +66,42 @@
     esac
 }
 
-run_test_program() {
-    local progname="$1"
-    shift
-    local logname="test-$gnuarch-$progname.log"
+run_installed() {
+    local useropt
 
-    if run_built ../klibc/usr/klibc/tests/"$progname" \
-	 > "$logname"; then
+    useropt="--userspec=$(id -un):$(id -gn)"
+
+    # XXX We assume build architecture is x86_64
+    case "$arch" in
+	i386 | x86_64)
+	    sudo chroot "$useropt" -- install "$@"
+	    ;;
+	*)
+	    sudo chroot "$useropt" -- install "/bin/qemu-$qemuarch-static" -- \
+		 "$@"
+	    ;;
+    esac
+}
+
+run_test_program() {
+    local flavour="$1"
+    local progname="$2"
+    shift 2
+    local logname="test-$gnuarch-$progname.log"
+    local err=0
+
+    case "$flavour" in
+	static)
+	    run_built ../klibc/usr/klibc/tests/"$progname" > "$logname" \
+	    || err=$?
+	    ;;
+	shared)
+	    run_installed /tests/"$progname".shared > "$logname" \
+	    || err=$?
+	    ;;
+    esac
+
+    if [ "$err" -eq 0 ]; then
 	if grep -qw ERROR "$logname"; then
 	    echo "E: $progname: Error found in output"
 	    return 1
@@ -54,7 +120,7 @@
     fi
 }
 
-run_shell() {
+run_shell_static() {
     local command="$1"
 
     if run_built ../klibc/usr/dash/static/sh -c "$command"; then
@@ -65,31 +131,56 @@
     fi
 }
 
+run_shell_shared() {
+    local command="$1"
+
+    if run_installed /usr/lib/klibc/bin/sh -c "$command"; then
+	echo "I: shell '$command': pass"
+    else
+	echo "E: shell '$command': fail"
+	return 1
+    fi
+}
+
+run_tests_flavour() {
+    local flavour="$1"
+    local err=0
+
+    run_test_program "$flavour" microhello || err=1
+    run_test_program "$flavour" minihello || err=1
+    run_test_program "$flavour" hello || err=1
+    run_test_program "$flavour" environ 'Verifying envp == environ... ok' \
+	|| err=1
+    run_test_program "$flavour" fcntl || err=1
+    run_test_program "$flavour" malloctest || err=1
+    run_test_program "$flavour" malloctest2 || err=1
+    run_test_program "$flavour" opentest "Line 1 = $(head -1 /etc/passwd)" \
+	|| err=1
+    run_test_program "$flavour" pipetest || err=1
+    run_test_program "$flavour" select || err=1
+    run_test_program "$flavour" setjmptest \
+	"calling longjmp with 256... setjmp returned 256" || err=1
+    run_test_program "$flavour" sigint "Signal received OK" || err=1
+    run_test_program "$flavour" socket || err=1
+    run_test_program "$flavour" sscanf || err=1
+    run_test_program "$flavour" stdio "Hello, World!" \
+        "Hello again - and some more - and some more" || err=1
+    run_test_program "$flavour" strlcpycat || err=1
+    run_test_program "$flavour" vfork || err=1
+
+    return $err
+}
+
 run_tests() {
     local err=0
 
-    run_test_program microhello || err=1
-    run_test_program minihello || err=1
-    run_test_program hello || err=1
-    run_test_program environ 'Verifying envp == environ... ok' || err=1
-    run_test_program fcntl || err=1
-    run_test_program malloctest || err=1
-    run_test_program malloctest2 || err=1
-    run_test_program opentest "Line 1 = $(head -1 /etc/passwd)" || err=1
-    run_test_program pipetest || err=1
-    run_test_program select || err=1
-    run_test_program setjmptest \
-	"calling longjmp with 256... setjmp returned 256" || err=1
-    run_test_program sigint "Signal received OK" || err=1
-    run_test_program socket || err=1
-    run_test_program sscanf || err=1
-    run_test_program stdio "Hello, World!" \
-        "Hello again - and some more - and some more" || err=1
-    run_test_program strlcpycat || err=1
-    run_test_program vfork || err=1
+    run_tests_flavour static || err=1
+    run_shell_static "exit" || err=1
+    run_shell_static "../klibc/usr/utils/static/true; exit" || err=1
 
-    run_shell "exit" || err=1
-    run_shell "../klibc/usr/utils/static/true; exit" || err=1
+    run_tests_flavour shared || err=1
+    run_shell_shared "exit" || err=1
+    run_shell_shared "/usr/lib/klibc/bin/true; exit" || err=1
 
     return $err
 }
@@ -102,7 +193,7 @@
     makeflags="${5:-}"
 
     echo "I: Architecture $arch/$gnuarch: begin"
-    if clean && build && run_tests; then
+    if clean && build && do_install && run_tests; then
 	echo "I: Architecture $arch/$gnuarch: pass"
     else
 	echo "E: Architecture $arch/$gnuarch: fail"