# BST-TIMEOUT: 1800 # one full run of upstream's 42-test driver + ~10 pins # # libtommath 1.3.0 -- "a portable number theoretic multiple-precision integer # library": mp_int arithmetic, the Karatsuba and Toom-Cook fast paths, # Montgomery and Barrett reduction, primality testing, and the radix and binary # conversions. # # THE EVIDENCE HERE IS UPSTREAM'S OWN TEST DRIVER, RUN ON TARGET, AND IT IS # UNUSUALLY GOOD EVIDENCE FOR A PORT. # # demo/test.c is a 70 kB driver holding 42 test functions with their vectors # built in. Unlike the check(1) suites next to it on this image, NONE OF ITS # TESTS ARE STUBS -- every one of the 42 asserts something, and a large part of # what they assert is exactly what a 32-bit arm gets wrong: mp_word overflow at # the digit boundary, the sign handling in mp_get_*/mp_set_*, the carry # propagation in the Karatsuba/Toom split points, and the radix conversions. # The driver reports its own pass/fail and exits non-zero if any test failed, # so this suite is that driver plus the pins the driver cannot make about # itself. # # WHY THE 42 CASES COME FROM ONE INVOCATION. The driver takes test-name # substrings as arguments, so each test COULD be its own process. It is not, # for two reasons: 42 process spawns on this runtime cost more than the tests # do, and the driver seeds its deterministic generator once per process # (`s_mp_rand_jenkins_init(time(NULL))`), so 42 invocations would test 42 # different vector sets and none of them the set the summary line describes. # One run, parsed into 42 named cases, keeps the attribution without either # cost. # # THE DIGIT PIN IS THE ARM ASSERTION. tommath.h picks its digit size at compile # time: a 64-bit target with an __int128 gets MP_DIGIT_BIT 60 and an 8-byte # mp_digit, everything else falls back to MP_DIGIT_BIT 28 and a 4-byte digit. # This arm must land on the 32-bit path -- if it ever silently picked the # 64-bit one, mp_word would need a 128-bit integer type that wasm32 does not # have. The header the driver prints is where that shows, so it is pinned # rather than skipped past. It is also why the x86_64 reference figures below # are quoted as test names and counts and NOT as digit values: those two # numbers are the one part of the output that is SUPPOSED to differ by arm. # # CROSS-ARM REFERENCE (x86_64, same SRCREV 95d80fd, measured 2026-08-11): # 42 tests, 42 OK, 0 NOP, 0 FAIL, 10.8 s wall, 2.1 MB peak RSS. The per-test # cost is concentrated in three: mp_prime_is_prime 4.7 s, mp_root_n 3.8 s and # mp_montgomery_reduce 2.0 s account for 10.5 s of the 10.8, and the other 39 # together take under half a second. Those three are therefore what sets this # suite's bound, and a 32-bit digit makes each of them do roughly four times # the digit-level work for the same operand sizes. # # WHAT IS NOT COVERED, DELIBERATELY: the mtest comparison harness. Upstream's # other driver, demo/mtest_opponent.c, checks libtommath against a second # bignum implementation by reading its output over a pipe -- it needs mtest(1) # built and running as a peer process. It is real coverage and it is out of # scope here for the reason the ticket names: the gate is non-interactive and # has no second implementation to run against. Stated as a gap rather than # papered over. . "$BST_LIB" # Locate the driver rather than hardcoding libexecdir: a layer that moves # libexecdir should make this fail loudly, not vanish. Absent is `not ok`, not # `skip` -- the driver IS this ticket's acceptance gate, so a missing one means # the package did not ship, which is a failure and not a legitimate absence. LTM= for d in /usr/libexec/libtommath-tests /usr/lib/libtommath-tests; do [ -x "$d/ltm-test" ] && { LTM="$d/ltm-test"; break; } done # The 42 tests upstream's table declares, in the order the driver runs them. # Pinned as a list rather than read back from the output, so a driver that # stops declaring one reports a red instead of quietly shrinking the suite. TESTS="feature_detection trivial_stuff mp_get_set_i32 mp_get_set_i64 mp_and \ mp_cnt_lsb mp_complement mp_decr s_mp_div_3 mp_dr_reduce mp_pack_unpack \ mp_fread_fwrite mp_get_u32 mp_get_u64 mp_get_ul mp_log_n mp_incr mp_invmod \ mp_is_square mp_kronecker mp_montgomery_reduce mp_root_n mp_or \ mp_prime_is_prime mp_prime_next_prime mp_prime_rand mp_rand mp_read_radix \ mp_read_write_ubin mp_read_write_sbin mp_reduce_2k mp_reduce_2k_l \ mp_set_double mp_signed_rsh mp_sqrt mp_sqrtmod_prime mp_xor s_mp_balance_mul \ s_mp_karatsuba_mul s_mp_karatsuba_sqr s_mp_toom_mul s_mp_toom_sqr" if [ -z "$LTM" ]; then bst_notok libtommath/present "ltm-test not installed (libtommath-tests missing from the image?)" for t in $TESTS; do bst_notok "libtommath/$t" "driver absent, so this test never ran" done exit 0 fi bst_ok libtommath/present # --------------------------------------------------------------------------- # 1. Packaging -- the halves this image actually installs. # libtommath ships no shared library and no program on this arm, so ${PN} is # empty and the image installs -dev, -staticdev and -tests. Assert the three # files those carry, because a port whose driver passes while its library did # not ship is not a port. [ -f /usr/lib/libtommath.a ] && bst_ok libtommath/staticlib \ || bst_notok libtommath/staticlib "/usr/lib/libtommath.a absent (libtommath-staticdev not installed?)" [ -f /usr/include/tommath.h ] && bst_ok libtommath/header \ || bst_notok libtommath/header "/usr/include/tommath.h absent (libtommath-dev not installed?)" # The .pc is generated by the bbappend rather than by the makefile this arm # uses; if that generation ever silently stops, the next recipe to pkg-config # libtommath is where it would surface. Pin it here instead. if [ -f /usr/lib/pkgconfig/libtommath.pc ]; then check_out libtommath/pkgconfig "-ltommath" cat /usr/lib/pkgconfig/libtommath.pc else bst_notok libtommath/pkgconfig "/usr/lib/pkgconfig/libtommath.pc absent" fi # --------------------------------------------------------------------------- # 2. The full driver, once. OUT=${TMPDIR:-/tmp}/bst-libtommath.$$ "$LTM" > "$OUT" 2>&1 LTMRC=$? HEAD=$(head -6 "$OUT" 2>/dev/null) if bst_execfail "$HEAD"; then bst_unrun libtommath/driver-ran "$HEAD" for t in $TESTS; do bst_unrun "libtommath/$t" "$HEAD"; done rm -f "$OUT" exit 0 fi bst_ok libtommath/driver-ran # The arm assertion. wasm32 has no 128-bit integer, so tommath.h must take the # MP_32BIT branch: 4-byte mp_digit, 8-byte mp_word, MP_DIGIT_BIT 28. The # x86_64 reference prints 8 / 16 / 60 here, and that difference is correct. check_out libtommath/digit-size-32 "Size of mp_digit: 4" head -6 "$OUT" check_out libtommath/word-size-32 "Size of mp_word: 8" head -6 "$OUT" check_out libtommath/digit-bit-28 "MP_DIGIT_BIT: 28" head -6 "$OUT" # The driver's own verdict. It prints the summary line last and returns # EXIT_FAILURE iff any test failed, so these two are the upstream gate itself. SUMMARY=$(grep '^Tests OK/NOP/FAIL:' "$OUT" 2>/dev/null | tail -1) if [ -n "$SUMMARY" ]; then bst_ok libtommath/driver-complete else bst_notok libtommath/driver-complete "no 'Tests OK/NOP/FAIL:' line -- the driver did not reach the end (rc=$LTMRC)" fi check_eq libtommath/driver-rc "0" "$LTMRC" # --------------------------------------------------------------------------- # 3. One case per upstream test, read out of that single run. # # Three states are distinguished on purpose, because they are three different # findings and a bare count cannot carry the difference: # # FAIL the test ran and the assertion failed -> not ok # NOP MP_HAS said the feature is compiled out -> skip # TEST started, and (see below) finished -> ok # no TEST line the test never started. If the driver reached its summary # line, that means upstream dropped the test from its table # (a red -- the suite shrank without anyone noticing). If it # did not, the driver died partway and every later test is # simply unknown, which is reported as such rather than as a # failed assertion. # # A `TEST ` LINE ALONE IS NOT A PASS WHEN THE DRIVER DIED. The driver # announces a test before running it, so on an abort the LAST announced test is # the one that was executing when the process went down -- and reading it as a # green would report a crash site as the one thing that worked. When there is # no summary line, that last name is therefore a red in its own right, with the # exit status as its detail. LASTTEST= if [ -z "$SUMMARY" ]; then LASTTEST=$(grep '^TEST ' "$OUT" 2>/dev/null | tail -1 | sed 's/^TEST //') fi for t in $TESTS; do if grep -q "^FAIL $t\$" "$OUT" 2>/dev/null; then bst_notok "libtommath/$t" "upstream driver reported FAIL" elif grep -q "^NOP $t\$" "$OUT" 2>/dev/null; then bst_skip "libtommath/$t" "compiled out on this build (MP_HAS false)" elif [ -n "$LASTTEST" ] && [ "$t" = "$LASTTEST" ]; then bst_notok "libtommath/$t" "driver died inside this test (rc=$LTMRC, no summary line followed)" elif grep -q "^TEST $t\$" "$OUT" 2>/dev/null; then bst_ok "libtommath/$t" elif [ -n "$SUMMARY" ]; then bst_notok "libtommath/$t" "not in this driver's test table (upstream dropped it?)" else bst_notok "libtommath/$t" "driver stopped before this test (rc=$LTMRC, died in ${LASTTEST:-?})" fi done # The count the summary line reports, bounded from below rather than pinned # exactly: a driver that grows a test should not turn this red, but one that # quietly loses half its table should. NTEST=$(grep -c '^TEST ' "$OUT" 2>/dev/null) [ -n "$NTEST" ] || NTEST=0 if [ "$NTEST" -ge 41 ]; then bst_ok libtommath/test-count else bst_notok libtommath/test-count "only $NTEST 'TEST' lines, want >= 41 (summary: ${SUMMARY:-none})" fi rm -f "$OUT"