Public Access
Make a failing test run say what went wrong
Two suites fail on the runner and pass everywhere else, and every attempt to work out why has been an inference from a filename. The runner prints the path of a log written to a disk nobody has a shell on, and the log is where the exception type, the message and the stack all live — so a red build has been a guess, and the last guess was wrong: 69 layout failures looked like missing fonts and were a missing shared library instead. This prints the log, and three facts about the machine that no log will ever carry: which distribution it is and who the job runs as, whether docker answers, and — the one that matters for the layout suite — ldd against the libSkiaSharp.so the test project carries, filtered to its unresolved rows. A managed TypeInitializationException on SKImageInfo is a symptom several missing libraries share; ldd names the library. The fontconfig step ahead of this exits early when ldconfig already reports one, so if that is present and Skia still will not load, the answer is a different dependency and this is what says which. head rather than tail on the log, which is the whole trick. A suite that fails wholesale writes one stack per test and they are the same stack; the first explains it and the last two hundred lines are that sentence repeated. if: failure() and exit 0, so it runs only on a red build and reports without becoming a second failure on top of the first. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -152,6 +152,44 @@ jobs:
|
||||
# Docker daemon and gets one here. That is why the tests run on ubuntu rather than
|
||||
# macOS, whose runners have no daemon at all. Expect the Keycloak image pull to
|
||||
# dominate a cold run.
|
||||
|
||||
# A failing run says only that tests failed and names a log file on a machine nobody
|
||||
# has a shell on. Every diagnostic thing — exception type, message, stack — is inside
|
||||
# that file, so a red build was a filename and a guess. This prints it.
|
||||
#
|
||||
# head rather than tail, and that is the whole trick: when a suite fails wholesale it
|
||||
# writes one stack per test and they are all the same stack. The first is the one that
|
||||
# explains it, and the last two hundred lines are the same sentence repeated.
|
||||
- name: what actually failed
|
||||
if: failure()
|
||||
run: |
|
||||
set +e
|
||||
echo "=== distro ==="
|
||||
cat /etc/os-release 2>/dev/null | head -3
|
||||
id
|
||||
|
||||
echo "=== what Skia needs, and whether it is here ==="
|
||||
# ldd against the copy the test project carries. Its unresolved rows are the
|
||||
# answer whenever the layout suite dies in HeadlessUnitTestSession, and asking
|
||||
# here beats inferring it from a managed TypeInitializationException.
|
||||
skia="$(find tests -name 'libSkiaSharp.so' 2>/dev/null | head -1)"
|
||||
if [ -n "$skia" ]; then
|
||||
echo "$skia"
|
||||
ldd "$skia" 2>&1 | grep -Ei 'not found|fontconfig|freetype' || echo " all resolved"
|
||||
else
|
||||
echo " libSkiaSharp.so was not in the test output at all"
|
||||
fi
|
||||
ldconfig -p 2>/dev/null | grep -ci fontconfig | sed 's/^/fontconfig entries in ldconfig: /'
|
||||
|
||||
echo "=== docker, for the Testcontainers suites ==="
|
||||
docker version --format '{{.Server.Version}}' 2>&1 | head -2
|
||||
|
||||
echo "=== test logs ==="
|
||||
find tests -path '*/TestResults/*.log' 2>/dev/null | while read -r log; do
|
||||
echo "----- $log"
|
||||
head -n 120 "$log"
|
||||
done
|
||||
exit 0
|
||||
android:
|
||||
name: android head
|
||||
runs-on: [linux]
|
||||
|
||||
Reference in New Issue
Block a user