--- /dev/null
+#!/bin/sh
+# SPDX-FileCopyrightText: 2025 Lady <https://www.ladys.computer/about/#lady>
+# SPDX-License-Identifier: MPL-2.0
+
+# This Source Code Form is subject to the terms of the Mozilla Public License, v 2.0.
+# If a copy of the M·P·L was not distributed with this file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
+
+# The program name is used in rendering the output.
+PROGRAM_NAME=$0
+# The first argument specifies the test program(s) to use.
+TEST_PROGRAMS=$1
+# The second argument specifies the test(s) to run.
+TEST_FILES=$2
+
+TEST_EXIT_STATUS=0
+TEST_PROGRAM_PREFIX=cgirls-test-
+
+# If no test programs are specified, find all of them by looking for files which start with `cgirls-test-´ and end in `.c´.
+if test -z "${TEST_PROGRAMS}"
+then :
+ TEST_PROGRAMS=$(find . '(' -path '.' -o -prune ')' -a -type f -a -name "${TEST_PROGRAM_PREFIX}"'*.c' | sed 's|^\./'"${TEST_PROGRAM_PREFIX}"'||;s|\.c$||')
+fi
+
+# Iterate over the test programs and run the tests.
+# This code first gets the list of available tests (via another `find´) and saves it as the `.index´ in the test directory.
+# Tests must have names which start with two digits and a hymin.
+# If a specific test was not requested, all tests are run.
+# Otherwise, only those tests which match one of the specified tests will run.
+for test_program in ${TEST_PROGRAMS}
+do :
+ printf '\033[1;4m %-45s \033[0m\n' "${PROGRAM_NAME} ${test_program}"
+ if test '!' -x "${TEST_PROGRAM_PREFIX}${test_program}"
+ then :
+ printf '%b\n' '\0033[1;93;41;m[ERROR]\0033[0m Test program has not been compiled.\n\033[7m \033[0m (Try \0033[3mmake '"${TEST_PROGRAM_PREFIX}${test_program}"'\0033[23m.)'
+ TEST_EXIT_STATUS=$((${TEST_EXIT_STATUS} | 4))
+ else :
+ if test '!' -d "test/${test_program}/logs"
+ then :
+ mkdir -p "test/${test_program}/logs"
+ fi
+ if test '!' -d "expect/${test_program}"
+ then :
+ mkdir -p "expect/${test_program}"
+ fi
+ AVAILABLE_TEST_FILES=$(LC_ALL=POSIX find "test/${test_program}" '(' -path "test/${test_program}" -o -prune ')' -a -type f -a -name '[0-9][0-9]-*' | sed 's|^[^/]*/[^/]*/||' | sort -)
+ printf '%s\n' $AVAILABLE_TEST_FILES >|'test/'"${test_program}"'/logs/!!INDEX!!'
+ if test -z "${TEST_FILES}"
+ then :
+ SELECTED_TEST_FILES=${AVAILABLE_TEST_FILES}
+ else :
+ SELECTED_TEST_FILES=$(LC_ALL=POSIX printf '%s\n' ${TEST_FILES} | sort - | comm -1 -2 - 'test/'"${test_program}"'/logs/!!INDEX!!')
+ fi
+ for test_file in ${SELECTED_TEST_FILES}
+ do :
+ printf '\033[7m \033[0m \033[3m%-34s\033[0m ' "${PROGRAM_NAME} ${test_program} ${test_file}"
+ TEST_RESULT="$(sed '/# /d' <"test/${test_program}/${test_file}" | "./${TEST_PROGRAM_PREFIX}${test_program}" 2>|"test/${test_program}/logs/${test_file}")"
+ TEST_LOG="$(cat "test/${test_program}/logs/${test_file}")"
+ if test -n "${TEST_LOG}"
+ then :
+ printf '%27b \n' '\0033[1;93;41;m[NG]\0033[0m'
+ printf '\033[7m \033[0m \033[2m%b\033[0m \n' "${TEST_LOG}"
+ TEST_EXIT_STATUS=$((${TEST_EXIT_STATUS} | 1))
+ else :
+ if test -n "$SET_EXPECTATION"
+ then :
+ sed '/# SPDX-/!d' <"test/${test_program}/${test_file}" >|"expect/${test_program}/${test_file}"
+ printf '%s\n' "${TEST_RESULT}" >>"expect/${test_program}/${test_file}"
+ printf '%27b\n' '\0033[1;93;45;m[SAVED]\0033[0m'
+ else :
+ if test '!' -f "expect/${test_program}/${test_file}"
+ then :
+ printf '%27b\n' '\033[1;93;44;m[UNEXPECTED]\0033[0m'
+ printf '\033[7m \033[0m \033[2m%b\033[0m \n' 'Run with \0033[3mSET_EXPECTATION=1\0033[23m to set an' 'expectation.'
+ TEST_EXIT_STATUS=$((${TEST_EXIT_STATUS} | 2))
+ else :
+ TEST_EXPECTATION="$(sed '/# /d' <"expect/${test_program}/${test_file}")"
+ if test "${TEST_RESULT}" '=' "${TEST_EXPECTATION}"
+ then :
+ printf '%27b \n' '\0033[1;93;42;m[OK]\0033[0m'
+ else :
+ printf '%27b \n' '\0033[1;93;41;m[NG]\0033[0m'
+ printf '\033[7m \033[0m \033[2m%b\033[0m \n' 'Result did not match expectation.' 'Got:'
+ printf '\033[30;107m%-49s\033[0m\n' "${TEST_RESULT}"
+ printf '\033[7m \033[0m \033[2m%b\033[0m \n' 'Expected:'
+ printf '\033[30;107m%-49s\033[0m\n' "${TEST_EXPECTATION}"
+ TEST_EXIT_STATUS=$((${TEST_EXIT_STATUS} | 1))
+ fi
+ fi
+ fi
+ fi
+ done
+ fi
+ if test ${TEST_EXIT_STATUS} -eq 0
+ then :
+ printf '\033[1m%s\033[0m\n' 'All tests succeeded.'
+ fi
+ if test $((${TEST_EXIT_STATUS} & 1)) -gt 0
+ then :
+ printf '\033[1m%s\033[0m\n' 'Not all tests completed successfully.'
+ fi
+ if test $((${TEST_EXIT_STATUS} & 2)) -gt 0
+ then :
+ printf '\033[1m%s\033[0m\n' 'At least one test was unexpected.'
+ fi
+ if test $((${TEST_EXIT_STATUS} & 4)) -gt 0
+ then :
+ printf '\033[1m%s\033[0m\n' 'At least one test program needs to be built.'
+ fi
+ exit ${TEST_EXIT_STATUS}
+done