Commit a5ddfe8

kravantokh <kravantokh@noreply.codeberg.org>
2026-08-16 16:13:36
Improve testing (parallel builds, debugger).
1 parent 3186141
Changed files (1)
testing
testing/test.sh
@@ -1,82 +1,100 @@
 #!/bin/bash
 
-FAILED=0
-
 rm -rf ./build/tests/*
 mkdir -p ./build/tests
 
-if [[ ! -v CC ]]; then
-	CC=cc
-fi
+CFLAGS=(-nostdlib -ffreestanding -I. -DNOTLIBC_IMPLEMENT -DNOTLIBC_SILENCE -fno-builtin -g -Wall -Wextra -Wpedantic -Werror)
 
-# Debug test builds on Og, O2, O3 and release test builds on O2 and O3
-TESTDIRS="o0d ogd o2d o3d o2r o3r"
+ensure () {
+	if ! command -v "$1" >/dev/null 2>&1 ; then
+		echo "Error: '$1' is not a known command on the current system." >&2
+		exit 1;
+	fi
+}
 
-for DIR in $TESTDIRS; do
-	mkdir -p "./build/tests/$DIR"
-done
+build () {
+	local flags=("${CFLAGS[@]}")
 
-echo
-echo Compiling tests.
-echo
+	if [ "$2" == "tcc" ]; then
+		flags+=("-gdwarf")
+	fi
 
-CFLAGS="-nostdlib -ffreestanding -I. -DNOTLIBC_IMPLEMENT -DNOTLIBC_SILENCE -fno-builtin -g -Wall -Wextra -Wpedantic -Werror"
+	case "$3" in
+		dbg) flags+=(-DBUILD_TYPE=1) ;;
+		rel) flags+=(-DBUILD_TYPE=2) ;;
+		*)   echo "Invalid build type flag passed to build()." >&2
+		exit 1 ;;
+	esac
 
-for SRC in ./testing/tests/*.c; do
+	case "$4" in
+		o0) flags+=(-O0) ;;
+		o1) flags+=(-O1) ;;
+		o2) flags+=(-O2) ;;
+		o3) flags+=(-O3) ;;
+		*)   echo "Invalid optimization flag passed to build()." >&2
+		exit 1 ;;
+	esac
 
-	if ! $CC $CFLAGS -O0 -DBUILD_TYPE=1 $SRC -o ./build/tests/o0d/$(basename "$SRC" .c); then
-		echo
-		echo "Compilation failure for $SRC - O0D."
-		FAILURE=1
-	fi
+	local filename=$(basename "$1" .c)-$2-$3-$4
+	local out="./build/tests/$filename"
 
-	if ! $CC $CFLAGS -Og -DBUILD_TYPE=1 $SRC -o ./build/tests/ogd/$(basename "$SRC" .c); then
-		echo
-		echo "Compilation failure for $SRC - OgD."
-		FAILURE=1
-	fi
 
-	if ! $CC $CFLAGS -O2 -DBUILD_TYPE=1 $SRC -o ./build/tests/o2d/$(basename "$SRC" .c); then
-		echo
-		echo "Compilation failure for $SRC - O2D."
-		FAILURE=1
-	fi
+	echo "Building $filename."
 
-	if ! $CC $CFLAGS -O3 -DBUILD_TYPE=1 $SRC -o ./build/tests/o3d/$(basename "$SRC" .c); then
-		echo
-		echo "Compilation failure for $SRC - O3D."
-		FAILURE=1
+	if ! $2 ${flags[@]} $1 -o "$out"; then
+		echo "Build failed for "
 	fi
+}
 
-	if ! $CC $CFLAGS -O2 -DBUILD_TYPE=2 $SRC -o ./build/tests/o2r/$(basename "$SRC" .c); then
-		echo
-		echo "Compilation failure for $SRC - O2R."
-		FAILURE=1
-	fi
+debug () {
+	echo "Running $1"
+	gdb -q --return-child-result -ex "set debuginfod enabled on" -ex 'python gdb.events.exited.connect(lambda e: gdb.execute("quit"))' -ex "file $1" -ex run
+}
 
-	if ! $CC $CFLAGS -O3 -DBUILD_TYPE=2 $SRC -o ./build/tests/o3r/$(basename "$SRC" .c); then
-		echo
-		echo "Compilation failure for $SRC - O3R."
-		FAILURE=1
+ensure gcc
+ensure clang
+ensure tcc
+ensure gdb
+
+i=0
+pids=()
+
+for SRC in ./testing/tests/*.c; do
+
+	build $SRC gcc dbg o0 & pids+=($!)
+	build $SRC gcc dbg o2 & pids+=($!)
+	build $SRC gcc rel o2 & pids+=($!)
+
+	build $SRC clang dbg o0 & pids+=($!)
+	build $SRC clang dbg o2 & pids+=($!)
+	build $SRC clang rel o2 & pids+=($!)
+
+	# tcc doesn't do optimization, so it just ignores it
+	build $SRC tcc dbg o2 & pids+=($!)
+	build $SRC tcc rel o2 & pids+=($!)
+
+	# Parallelize the builds across 4 tests (aka a *very* primitive way to limit parallelism)
+	if (( i % 4 == 1 )); then
+		for pid in "${pids[@]}"; do
+			if ! wait "$pid"; then
+				echo "Some compilation failed. Check the other messages, since this is parallelized."
+			fi
+		done
+		pids=()
 	fi
-done
 
-echo
-echo Running tests.
-echo
+	((i++))
+done
 
-for DIR in $TESTDIRS; do
-	for TEST in "./build/tests/$DIR/"*; do
-		"$TEST"
-		RET=$?
+for pid in "${pids[@]}"; do
+	wait "$pid"
+done
 
-		if [ "$RET" -ne 0 ]; then
-			echo "FAILURE: $(basename $TEST)@$(basename $DIR):$RET (./testing/tests/$(basename $TEST).c)"
-			FAILURE=1
-		fi
-	done
+for BIN in ./build/tests/*; do
+	if ! debug $BIN; then
+		exit 1
+	fi
 done
 
-exit $FAILURE