#!/bin/sh # libcoap ptest driver — REPLACES meta-networking's, which cannot be shipped. # # meta-networking's run-ptest is three lines: # # if /usr/lib/libcoap/ptest/testdriver; then echo "PASS: libcoap"; else echo "FAIL: libcoap"; fi # # and it is a FALSE GREEN GENERATOR. testdriver returns CU_basic_run_tests(), # which is CUnit's CU_ErrorCode — a FRAMEWORK error, not a test verdict. A failing # assertion is recorded in the run summary and leaves CU_get_error() at # CUE_SUCCESS, so the driver exits 0 no matter how many cases failed. MEASURED on # a native x86_64 control of this exact SRCREV: injecting one CU_FAIL into # t_parse_uri1 gave "tests 167 167 166 1" in the summary, exit status 0, and # upstream's run-ptest duly printed "PASS: libcoap". Every test failure on this # image would have been invisible to the acceptance gate. # # So this driver reads the OUTPUT, not the exit status, and it emits one # PASS:/FAIL: line per CUnit case so ptest-runner can attribute a red to the case # that produced it instead of to the package. # # Four ways it refuses to report a silent green, in increasing subtlety: # 1. no "Run Summary" block at all -> the run died mid-way # 2. Ran == 0 -> the registry was empty # 3. Total != Ran -> cases registered but not executed # 4. cases parsed != Ran -> output truncated under our feet # (3) and (4) are the ones a summary that only counts green lines cannot see. set -u PTEST_DIR=${PTEST_DIR:-/usr/lib/libcoap/ptest} DRIVER=${DRIVER:-$PTEST_DIR/testdriver} # Lower bound only, never an equality: 167 cases is what libcoap 4.3.4 registers # with this port's configure options (measured on the native control). Pinning the # exact number would go false the day upstream adds a case, which is how a guard # stops being read; a floor still catches a suite that collapsed. MIN_TESTS=${MIN_TESTS:-150} if [ ! -x "$DRIVER" ]; then echo "FAIL: libcoap.testdriver-missing" echo "ERROR: no executable testdriver at $DRIVER" exit 1 fi out=$("$DRIVER" 2>&1) drv_rc=$? # One PASS:/FAIL: per case, keyed .. CUnit prints # Suite: # Test: ...passed # but the verdict word is NOT reliably on the Test: line: libcoap logs to the same # stream, so a case that warns emits " Test: t_parse_uri5 ..." and the # bare word "passed" lands on a later line. Hence the verdict is matched wherever # it next appears rather than anchored to the Test: line. cases=$(printf '%s\n' "$out" | awk ' /^Suite: / { s = $0; sub(/^Suite: /, "", s); gsub(/[^A-Za-z0-9]+/, "-", s); sub(/-+$/, "", s); suite = s; next } /^[ \t]*Test: / { t = $0; sub(/^[ \t]*Test: /, "", t); sub(/ \.\.\..*$/, "", t); name = t } /passed[ \t]*$/ { if (name != "") { printf "PASS: libcoap.%s.%s\n", suite, name; name = "" } next } /FAILED[ \t]*$/ { if (name != "") { printf "FAIL: libcoap.%s.%s\n", suite, name; name = "" } next } ') printf '%s\n' "$cases" n_cases=$(printf '%s\n' "$cases" | grep -c '^\(PASS\|FAIL\): ' || true) # The summary row: " tests 167 167 167 0 0" # = Total Ran Passed Failed Inactive. Scoped to the Run Summary block so a test # name containing the word "tests" cannot be read as the tally. summary=$(printf '%s\n' "$out" | awk ' /^Run Summary:/ { in_rs = 1; next } in_rs && $1 == "tests" && NF >= 5 { print $2, $3, $4, $5; exit } ') if [ -z "$summary" ]; then echo "FAIL: libcoap.run-summary" echo "ERROR: testdriver printed no 'Run Summary' block (exit $drv_rc); the run did not complete" exit 1 fi set -- $summary total=$1; ran=$2; passed=$3; failed=$4 echo "INFO: libcoap testdriver: total=$total ran=$ran passed=$passed failed=$failed exit=$drv_rc parsed=$n_cases" rc=0 if [ "$ran" -eq 0 ]; then echo "FAIL: libcoap.no-cases" echo "ERROR: the CUnit registry ran 0 tests — a green with nothing asserted" rc=1 fi if [ "$total" -ne "$ran" ]; then echo "FAIL: libcoap.cases-not-run" echo "ERROR: $total cases registered but only $ran ran" rc=1 fi if [ "$ran" -lt "$MIN_TESTS" ]; then echo "FAIL: libcoap.case-count" echo "ERROR: $ran cases ran, fewer than the $MIN_TESTS floor this suite is known to register" rc=1 fi if [ "$n_cases" -ne "$ran" ]; then echo "FAIL: libcoap.case-parse" echo "ERROR: parsed $n_cases case verdicts but the summary reports $ran ran" rc=1 fi if [ "$failed" -ne 0 ]; then echo "ERROR: $failed of $ran cases failed; the FAIL: lines above name them" rc=1 fi exit $rc