#!/bin/bash

# vim: ft=bash

set -u
#set -o pipefail

# A script that runs the test_system program against known inputs. This is to
# make sure I understand the behaviour of the libC's system(3) call.

declare -r PFX=TEST_SYSTEM
declare -r TEST_PROG=./test_system
declare -i NUM_TESTS=0
declare -i NUM_FAILURES=0


# Case 1: we can run $TEST_PROG

((NUM_TESTS++))
printf "Checking we can run $TEST_PROG... "
if "$TEST_PROG" >/dev/null; then
	echo ok
else
	((NUM_FAILURES++))
	echo Failure!
fi

# Case 2: a shell is available

((NUM_TESTS++))
printf "Checking that a shell is available... "
if "$TEST_PROG" | grep "$PFX.*shell available" >/dev/null; then
	echo ok
else
	((NUM_FAILURES++))
	echo Failure!
fi

# Case 3: we can create children processes

((NUM_TESTS++))
printf "Checking we can create children processes... "
if "$TEST_PROG" 'ls' | grep "$PFX.*child process created" >/dev/null; then
	echo ok
else
	((NUM_FAILURES++))
	echo Failure!
fi

# Case 4: a child process terminates normally

((NUM_TESTS++))
printf "Checking that a child process terminates normally... "
if "$TEST_PROG" 'ls' | grep "$PFX.*child terminated normally" >/dev/null; then
	echo ok
else
	((NUM_FAILURES++))
	echo Failure!
fi

# Case 5: a child process can launch a shell

((NUM_TESTS++))
printf "Checking that a child process can launch a shell... "
if "$TEST_PROG" 'ls' | grep "$PFX.*child process could launch a shell" >/dev/null; then
	echo ok
else
	((NUM_FAILURES++))
	echo Failure!
fi

# Case 6: a command runs successfully

((NUM_TESTS++))
printf "Checking that we can tell when a command runs successfully... "
if "$TEST_PROG" 'ls' | grep "$PFX.*command ran successfully" >/dev/null; then
	echo ok
else
	((NUM_FAILURES++))
	echo Failure!
fi

# Case 7: a command is not found (indistinguishable from shell not runnable, or
# a command having exit status 127)

((NUM_TESTS++))
printf "Checking that the exit status is 127 if the command isn't found... "
if "$TEST_PROG" 'no-such-cmd' 2>/dev/null | grep "$PFX.*command not found" >/dev/null; then
	echo ok
else
	((NUM_FAILURES++))
	echo Failure!
fi

# Case 8: user command exits with 127 (indistinguishable from shell not runnable, or
# command not found)

((NUM_TESTS++))
printf "Checking that the system()'s return value is 127 if the user command's exit is 127... "
if "$TEST_PROG" 'exit 127' 2>/dev/null | grep "$PFX.*exit status 127" >/dev/null; then
	echo ok
else
	((NUM_FAILURES++))
	echo Failure!
fi

# Case 9: user command fails, but with an error code other than 127

((NUM_TESTS++))
printf "Checking that the system()'s return value is indicates failure other than 127... "
if "$TEST_PROG" 'exit 1' 2>/dev/null | grep "$PFX.*did NOT run successfully" >/dev/null; then
	echo ok
else
	((NUM_FAILURES++))
	echo Failure!
fi

# Case 10: a less contribed example: permission denied (note that system() and
# waitpid() treat this differently from e.g. command not found)

((NUM_TESTS++))
printf "Checking that permission denied is reported as a failure... "
# test_system.c should not be executable
if "$TEST_PROG" './test_system.c' 2>/dev/null | grep "$PFX.*did NOT run successfully" >/dev/null; then
	echo ok
else
	((NUM_FAILURES++))
	echo Failure!
fi

# Case 11: ls fails on a nonexistent file

((NUM_TESTS++))
printf "Checking that ls fails on a nonexistent file... "
if "$TEST_PROG" 'ls nosuch' 2>/dev/null | grep "$PFX.*did NOT run successfully" >/dev/null; then
	echo ok
else
	((NUM_FAILURES++))
	echo Failure!
fi
