Stabilize the docker smoke testing scripts and HTML 3.2 webview
Some checks failed
Build & Upload tux-dock / build (push) Has been cancelled

This commit is contained in:
mrkmntal 2026-08-14 17:16:46 -04:00
commit 47c6d988cc
4 changed files with 215 additions and 9 deletions

View file

@ -92,4 +92,7 @@ if(BUILD_TESTING)
target_include_directories(tux-dock-stop-sequence-tests PRIVATE src)
target_compile_options(tux-dock-stop-sequence-tests PRIVATE -Wall -Wextra -Wpedantic)
add_test(NAME tux-dock-stop-sequence-tests COMMAND tux-dock-stop-sequence-tests)
add_test(NAME tux-dock-docker-integration-tests
COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_docker_integration.sh)
endif()

View file

@ -47,10 +47,15 @@ sudo ./build/tux-dock
# Build without running tests
./compile.sh --no-test
# Run tests and serve an HTML 3.2 report on port 8095
./compile.sh --web-test-view
# Override the report server port
./compile.sh --web-test-view 9000
```
Prefer a prebuilt binary? CI artifacts are published at:
https://mentalnet.xyz/forgejo/markmental/tuxdock/actions
The web report is generated under `/tmp` and includes exact CTest output, test summaries, Docker integration output, and a text rendition of the TUI flow. It requires `nc` or `netcat`; press `Ctrl-C` to stop the server. The default port is `8095`; pass a port after `--web-test-view` to override it. `--web-test-view --no-test` is invalid. Normal test runs include a Docker integration test using `debian:forky`, so Docker must be available.
---
@ -161,7 +166,7 @@ ctest --test-dir build --output-on-failure
- Version: `0.1-beta`
- Created by: `markmental`
- GitHub: https://github.com/MARKMENTAL/tuxdock
- Forgejo: https://mentalnet.xyz/forgejo/markmental/tuxdock
- Forgejo: https://mentalnet.xyz/forgejo-v2/markmental/tuxdock
---

View file

@ -2,14 +2,37 @@
set -eu
if [ "$#" -gt 1 ] || { [ "$#" -eq 1 ] && [ "$1" != "--no-test" ]; }; then
printf '%s\n' "Usage: $0 [--no-test]" >&2
run_tests=1
web_view=0
web_port=8095
while [ "$#" -gt 0 ]; do
argument=$1
shift
case "$argument" in
--no-test) run_tests=0 ;;
--web-test-view)
web_view=1
if [ "$#" -gt 0 ] && printf '%s' "$1" | grep -Eq '^[0-9]+$'; then
web_port=$1
shift
fi
;;
*)
printf '%s\n' "Usage: $0 [--no-test] [--web-test-view [port]]" >&2
exit 2
;;
esac
done
if [ "$web_port" -lt 1 ] || [ "$web_port" -gt 65535 ]; then
printf '%s\n' "Web test view port must be between 1 and 65535" >&2
exit 2
fi
run_tests=1
if [ "$#" -eq 1 ]; then
run_tests=0
if [ "$web_view" -eq 1 ] && [ "$run_tests" -eq 0 ]; then
printf '%s\n' "--web-test-view cannot be combined with --no-test" >&2
exit 2
fi
if [ "$run_tests" -eq 1 ]; then
@ -21,7 +44,106 @@ fi
cmake --build build -j
if [ "$run_tests" -eq 1 ]; then
ctest --test-dir build --output-on-failure
report_dir=$(mktemp -d /tmp/tux-dock-test.XXXXXX)
test_output="$report_dir/ctest-output.txt"
test_status=0
ctest --test-dir build --output-on-failure >"$test_output" 2>&1 || test_status=$?
if [ "$web_view" -eq 1 ]; then
report="$report_dir/report.html"
escaped_output=$(mktemp "$report_dir/output.XXXXXX")
sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g' "$test_output" >"$escaped_output"
total=$(awk '/tests passed, [0-9]+ tests failed out of [0-9]+/ { print $(NF); exit }' "$test_output" 2>/dev/null || true)
failed=$(awk '/tests passed, [0-9]+ tests failed out of [0-9]+/ { print $4; exit }' "$test_output" 2>/dev/null || true)
total=${total:-unknown}
passed=${passed:-0}
failed=${failed:-0}
if [ "$total" != unknown ]; then
passed=$((total - failed))
fi
duration=$(awk '/Total Test time/ { print $(NF - 1); exit }' "$test_output" 2>/dev/null || true)
duration=${duration:-unknown}
command_line='ctest --test-dir build --output-on-failure'
test_rows=$(mktemp "$report_dir/test-rows.XXXXXX")
awk '
match($0, /^[[:space:]]*([0-9]+)\/([0-9]+) Test #[0-9]+: ([^ ]+)[[:space:]]+\.+[[:space:]]+(Passed|Failed|Skipped)[[:space:]]+([0-9.]+) sec/, m) {
printf "<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD><TD>%s sec</TD></TR>\n", m[1], m[3], m[4], m[5]
}
' "$test_output" >"$test_rows"
integration_output=$(mktemp "$report_dir/integration-output.XXXXXX")
test_log="build/Testing/Temporary/LastTest.log"
if [ -f "$test_log" ]; then
awk '
/^[0-9]+\/[0-9]+ Testing: tux-dock-docker-integration-tests$/ { capture=1 }
capture { print }
/^Test Passed\.$/ && capture { end=1 }
end && /time elapsed:/ { print; exit }
' "$test_log" >"$integration_output"
else
printf '%s\n' 'Docker integration transcript unavailable: LastTest.log was not found.' >"$integration_output"
fi
escaped_integration=$(mktemp "$report_dir/integration-escaped.XXXXXX")
sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g' "$integration_output" >"$escaped_integration"
raw_output=$(mktemp "$report_dir/raw-output.XXXXXX")
awk '/\[TEST OUTPUT BEGIN\]/{capture=1} capture{print} /\[TEST RESULT\]/{capture=0}' "$integration_output" >"$raw_output"
escaped_raw=$(mktemp "$report_dir/raw-escaped.XXXXXX")
sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g' "$raw_output" >"$escaped_raw"
tui_output=$(mktemp "$report_dir/tui-output.XXXXXX")
awk '!/\[TEST OUTPUT BEGIN\]/ && !/\[TEST OUTPUT END\]/ && !/\[TEST RESULT\]/ { print }' "$integration_output" >"$tui_output"
escaped_tui=$(mktemp "$report_dir/tui-escaped.XXXXXX")
sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g' "$tui_output" >"$escaped_tui"
{
printf '%s\n' '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">'
printf '%s\n' '<HTML><HEAD><TITLE>Tux-Dock Test Report</TITLE></HEAD><BODY>'
printf '%s\n' '<H1>Tux-Dock Test Report</H1>'
printf '<P>Generated: %s</P>\n' "$(date)"
printf '%s\n' '<H2>Summary</H2><TABLE BORDER="1"><TR><TH>Metric</TH><TH>Value</TH><TH>Graph</TH></TR>'
printf '<TR><TD>Total tests</TD><TD>%s</TD><TD><TABLE BORDER="0"><TR><TD BGCOLOR="blue" WIDTH="160">&nbsp;</TD></TR></TABLE></TD></TR>\n' "$total"
printf '<TR><TD>Passed</TD><TD>%s</TD><TD><TABLE BORDER="0"><TR><TD BGCOLOR="green" WIDTH="160">&nbsp;</TD></TR></TABLE></TD></TR>\n' "$passed"
printf '<TR><TD>Failed</TD><TD>%s</TD><TD><TABLE BORDER="0"><TR><TD BGCOLOR="red" WIDTH="%s">&nbsp;</TD></TR></TABLE></TD></TR>\n' "$failed" "$([ "$failed" -gt 0 ] 2>/dev/null && printf 160 || printf 1)"
printf '<TR><TD>Duration</TD><TD>%s seconds</TD><TD>&nbsp;</TD></TR></TABLE>\n' "$duration"
printf '%s\n' '<H2>Individual Tests</H2><TABLE BORDER="1"><TR><TH>#</TH><TH>Test</TH><TH>Status</TH><TH>Duration</TH></TR>'
cat "$test_rows"
printf '%s\n' '</TABLE>'
printf '%s\n' '<H2>Exact Test Run</H2><PRE>'
printf '%s\n' "$command_line"
printf '%s\n' '</PRE><H2>Test Output</H2><PRE>'
cat "$escaped_output"
printf '%s\n' '</PRE><H2>Docker Integration Raw Output</H2><PRE>'
cat "$escaped_raw"
printf '%s\n' '</PRE><H2>TUI Transcript</H2><PRE>'
cat "$escaped_tui"
printf '%s\n' '</PRE></BODY></HTML>'
} >"$report"
response="$report_dir/http-response.txt"
report_size=$(wc -c <"$report" | tr -d ' ')
{
printf 'HTTP/1.1 200 OK\r\n'
printf 'Content-Type: text/html; charset=utf-8\r\n'
printf 'Content-Length: %s\r\n' "$report_size"
printf 'Connection: close\r\n'
printf '\r\n'
cat "$report"
} >"$response"
if command -v nc >/dev/null 2>&1; then
nc_command=nc
elif command -v netcat >/dev/null 2>&1; then
nc_command=netcat
else
printf '%s\n' "Web report generated at $report, but nc/netcat is unavailable." >&2
exit "$test_status"
fi
printf '%s\n' "Test report: http://0.0.0.0:$web_port/"
printf '%s\n' "Report file: $report"
printf '%s\n' "Press Ctrl-C to stop the server."
while :; do
"$nc_command" -l -N -s 0.0.0.0 -p "$web_port" <"$response"
done
fi
exit "$test_status"
fi
printf '%s\n' "tux-dock successfully compiled!"

View file

@ -0,0 +1,76 @@
#!/bin/sh
set -eu
image=${TUX_DOCK_TEST_IMAGE:-debian:forky}
name="tux-dock-test-$$-$(date +%s)"
cleanup_status=0
run_raw() {
command_name=$1
shift
started=$(date +%s)
printf '%s\n' "[TEST OUTPUT BEGIN] $command_name"
set +e
"$@" 2>&1
command_status=$?
set -e
elapsed=$(( $(date +%s) - started ))
printf '%s\n' "[TEST OUTPUT END] $command_name"
printf '%s\n' "[TEST RESULT] command=$command_name status=$command_status elapsed=${elapsed}s"
return "$command_status"
}
cleanup() {
if docker container inspect "$name" >/dev/null 2>&1; then
printf '%s\n' "[TUI] Cleanup: Remove Container"
printf '%s\n' "[TUI] Busy |"
if ! docker rm -f "$name"; then
cleanup_status=1
fi
printf '%s\n' "[TUI] Complete: Container removed"
fi
}
trap cleanup EXIT INT TERM
printf '%s\n' "[TUI] Actions > Run/Create Interactive Container"
printf '%s\n' "[TUI] Busy |"
printf '%s\n' "[TUI] docker run --name $name $image sh -c '<tests>'"
if ! docker image inspect "$image" >/dev/null 2>&1; then
printf '%s\n' "[TUI] Pull Docker Image: $image"
run_raw "docker pull $image" docker pull "$image"
else
printf '%s\n' "[TUI] Image available: $image"
fi
run_in_container() {
command_name=$1
shift
printf '%s\n' "[TUI] Run command: $command_name"
printf '%s\n' "[TUI] Busy |"
run_raw "$command_name" docker exec "$name" "$@"
printf '%s\n' "[TUI] Complete: $command_name succeeded"
}
run_raw "docker run -d --name $name $image sleep 300" docker run -d --name "$name" "$image" sleep 300
printf '%s\n' "[TUI] Complete: Container created"
run_in_container "ls /" ls /
run_in_container "cat /etc/os-release" cat /etc/os-release
run_in_container "apt-get update" apt-get update
run_in_container "bash --version" bash --version
printf '%s\n' "[TUI] Remove Container: $name"
run_raw "docker rm -f $name" docker rm -f "$name"
printf '%s\n' "[TUI] Complete: Container removed"
printf '%s\n' "[TUI] Verify removal: docker container inspect $name"
if run_raw "docker container inspect $name" docker container inspect "$name"; then
printf '%s\n' "Container still exists after removal" >&2
exit 1
else
printf '%s\n' "[TUI] Complete: Removal verified"
fi
trap - EXIT INT TERM
exit "$cleanup_status"