#!/bin/sh
# Run libsolv's upstream test suite -- the 104 cases under test/testcases/ -- and
# report one PASS:/FAIL:/SKIP: line each, which is the protocol ptest-runner reads.
#
# THIS IS SEMANTICALLY upstream's own test/runtestcases.sh, which is what
# test/CMakeLists.txt drives from ctest. That script loops over `find
-name
# \*.t | sort` and runs `testsolv `, treating exit 0 as pass, 77 as skip and
# anything else as failure -- exactly the loop below. Two deliberate differences,
# neither of which changes a verdict:
#
# - It is not the upstream script itself, because that script is #!/bin/bash and
# the image ships no bash (busybox ash is the login shell). Nothing in it needs
# bash; it is POSIX sh with a bash shebang.
#
# - ctest declares one test per testcases/ SUBDIRECTORY (27 of them) and hands
# the whole directory to one runtestcases.sh. This reports per CASE (104), the
# granularity at which the cases are actually independent and the granularity
# the driver is actually invoked at -- so a red names the solver behaviour that
# broke instead of the folder it lives in. The totals are the same run.
#
# THE DRIVER IS THE SHIPPED BINARY, NOT A STAGED COPY. `testsolv` is installed to
# /usr/bin by the ordinary recipe (tools/CMakeLists.txt puts it in tools_list), so
# the ptest package RDEPENDs on libsolv-tools and runs what the image ships. A
# defect confined to the packaged tool is therefore visible here, which it would
# not be if this carried its own build of the driver.
#
# NO WRITABLE WORKING DIRECTORY IS NEEDED, and none is created. testsolv's only
# writes are in testcase_write(), reachable solely via its -T option, which nothing
# here passes; the cases are read through fopen(..., "r") and their external
# repository files likewise. Verified by running the whole corpus with the ptest
# directory read-only, which is the deployed rootfs's condition at browser runtime.
# (libmpc's run-ptest does create a scratch dir -- its tio_str writes ./mpc_test
# through a relative path. libsolv has no equivalent, so adding one here would be
# ceremony that implies a constraint that does not exist.)
set -u
pdir=$(cd "$(dirname "$0")" && pwd)
tdir=$pdir/testcases
# Overridable so the identical script can be dry-run against a native build on the
# build host before an image build is spent on it.
testsolv=${TESTSOLV:-/usr/bin/testsolv}
[ -x "$testsolv" ] || { echo "FAIL: libsolv-ptest-setup"; echo "ERROR: no testsolv driver at $testsolv"; exit 1; }
[ -d "$tdir" ] || { echo "FAIL: libsolv-ptest-setup"; echo "ERROR: no test corpus at $tdir"; exit 1; }
# Sorted so the report order is stable between runs and between arms, which is what
# makes two captures diffable.
for tc in $(find "$tdir" -name '*.t' | sort); do
# -, built with parameter expansion only: this loop runs 104 times
# and every fork here is a fresh wasm module instantiation, so a `tr`, `sed` or
# `basename` per case would cost more than the test it names. The two-level
# corpus shape this relies on is enforced at package time by the bbappend.
rel=${tc#"$tdir"/}
dir=${rel%%/*}
base=${rel##*/}
name=$dir-${base%.t}
"$testsolv" "$tc" >/dev/null 2>&1
rc=$?
# 77 is testsolv's skip: testcase_read() returns it when a case asks for a
# solver feature this build does not have (ext/testcase.c:2639). It is a
# legitimate outcome of the suite, not a failure, and upstream's own script
# treats it the same way.
if [ $rc -eq 0 ]; then
echo "PASS: $name"
elif [ $rc -eq 77 ]; then
echo "SKIP: $name"
else
echo "FAIL: $name"
fi
done
# The per-case verdicts above are the report; ptest-runner tallies them itself and
# a non-zero exit here would be counted a second time as a harness failure.
exit 0