#!/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