. "$BST_LIB" # BST-TIMEOUT: 600 # MEASURED: see the Self-Test Record in the BRINTOS-1581 # # design doc. Four wasm modules are staged and run here -- # # the 2.9 MB probe and the three shipped tools at 2.6-3.2 # # MB each -- and staging dominates the run. # # libraw1394 2.1.2 (meta-oe recipes-support/libraw1394, the kernel.org tarball) # -- the base library for low-level IEEE-1394 access. What ships is # /usr/lib/libraw1394.a, the three headers under /usr/include/libraw1394/, # /usr/lib/pkgconfig/libraw1394.pc, the three tools /usr/bin/{testlibraw, # dumpiso,sendiso}, and the probe this port adds at # /usr/libexec/libraw1394-tests/raw1394-probe (built in the recipe against the # very archive that ships -- see libraw1394_%.bbappend). # # --------------------------------------------------------------------------- # THERE IS NO IEEE-1394 HOST ON THIS MACHINE, AND THAT IS THE DESIGN PROBLEM. # # libraw1394 talks to a FireWire host controller the kernel enumerated. Nothing # behind this machine's virtio surface is one, so there is no /dev/fw0 and no # /dev/raw1394. Call raw1394_new_handle(), get NULL, report one green, ship -- # and a libraw1394.a miscompiled into rubble would produce THE SAME NULL. So # this file drives everything that does NOT need a controller, for real, and # PROBES the rest: # # ARTIFACT the shipped files, and a header-to-archive completeness check # over every entry point raw1394.h declares. # ABI the word sizes and struct widths. raw1394_private.h selects its # int<->pointer conversion on SIZEOF_VOID_P == 4, so ILP32 is # load-bearing rather than incidental, and the recipe carries a # build-time guard on the same fact. # ERRCODE raw1394_errcode_to_errno() -- a pure state machine over a 32-bit # code, swept across every ack, every rcode and all twelve # internal errors. # NULL the documented failure of all 64 handle-taking entry points # against a NULL handle (of 68 declared; the other four take no # handle and are driven in their own sections). Every one of them guards, so the whole API surface # is genuinely executed rather than inspected -- this is the group # that would catch a partial compile or a header/library skew. # SYSCALL epoll_create/inotify_init/pipe, MEASURED. # HANDLE raw1394_new_handle() -- probed, and asserted to its DOCUMENTED # failure rather than skipped. # OVERRIDE the RAW1394DEV path, driven for real against an ordinary file. # TOOLS testlibraw, dumpiso and sendiso actually run. # # --------------------------------------------------------------------------- # THE NULL HANDLE HERE IS OWNED BY brintos/linux#53, NOT BY THE ABSENT DEVICE. # # This is the finding that a bare "no device, so NULL" would have hidden. # raw1394_new_handle() tries the legacy backend (open /dev/raw1394) and then # the fw backend. fw_new_handle() calls epoll_create(16), pipe(), and # inotify_init()/inotify_add_watch("/dev") BEFORE it ever looks for a device, # and it does NOT check what scan_devices() found -- so on a host with epoll # and no FireWire hardware it returns a PERFECTLY VALID handle with zero # ports. Measured: the same probe, same source, on x86-64 returns a non-NULL # handle and `testlibraw` prints "0 cards found" and exits 0. # # On wasm32-hwjs the whole epoll family is ENOSYS (brintos/linux#53, open), so # fw_new_handle() dies on its first statement and the handle is NULL for a # reason that has nothing to do with FireWire. Both facts are asserted here, # each conditioned on its own probe, so if #53 closes this suite reports the # handle becoming valid instead of going red at it. # # --------------------------------------------------------------------------- # THE ORACLE IS A NATIVE x86-64 RUN OF THE SAME PROBE AGAINST THE SAME SOURCE. # # Every value pinned below was read off a native build of raw1394_probe.c # against libraw1394 2.1.2 -- the recipe's own tarball, sha256 ddc4e327... -- # before this guest ever booted. Four answers differ by word size and are # asserted as wasm32 facts rather than copied from the oracle: sz-void and # sz-long are 8 there and 4 here, and the three structs carrying a pointer # (raw1394_arm_request 40->32, raw1394_arm_response 16->12, # raw1394_arm_request_response 16->8) shrink with it. # # Text assertions are `case` globs against files read once into shell # variables -- no fork per case, the same reason 99-libsoc.test gives. # --------------------------------------------------------------------------- tmp=${TMPDIR:-/tmp} lib=/usr/lib/libraw1394.a incd=/usr/include/libraw1394 pc=/usr/lib/pkgconfig/libraw1394.pc probe_src=/usr/libexec/libraw1394-tests/raw1394-probe _NL=' ' # hasfile -- ok iff is a non-empty regular file. hasfile() { if [ -f "$2" ] && [ -s "$2" ]; then bst_ok "$1" else bst_notok "$1" "missing or empty: $2"; fi } # hasline -- ok iff is a whole line of it. hasline() { case "$_NL$3$_NL" in *"$_NL$2$_NL"*) bst_ok "$1" ;; *) bst_notok "$1" "not found: $2" ;; esac; } # =========================================================================== # ARTIFACT # =========================================================================== hasfile libraw1394/archive "$lib" hasfile libraw1394/hdr-raw1394 "$incd/raw1394.h" hasfile libraw1394/hdr-csr "$incd/csr.h" hasfile libraw1394/hdr-ieee1394 "$incd/ieee1394.h" hasfile libraw1394/pkgconfig "$pc" hasfile libraw1394/testlibraw /usr/bin/testlibraw hasfile libraw1394/dumpiso /usr/bin/dumpiso hasfile libraw1394/sendiso /usr/bin/sendiso hasfile libraw1394/probe-shipped "$probe_src" check_eq libraw1394/archive-format '!' "$(head -c 7 "$lib" 2>/dev/null)" # Shape, not absence: this arm converts to shared libraries per recipe # (BRINTOS-1740), so a .so here is a conversion, not a policy breach. bst_lib_shape libraw1394/static-only "/usr/lib/libraw1394.so" "/usr/lib/libraw1394.la" # The headers install into a SUBDIRECTORY (pkginclude_HEADERS) while the .pc # offers a bare -I${includedir}, so a consumer writes # `#include `. Pinned because that asymmetry is what a # consumer's build actually depends on. if [ -e /usr/include/raw1394.h ]; then bst_notok libraw1394/hdr-subdir "raw1394.h is also at /usr/include, so the pkginclude layout moved" else bst_ok libraw1394/hdr-subdir fi pctext=$(cat "$pc" 2>/dev/null) hasline libraw1394/pc-name 'Name: libraw1394' "$pctext" hasline libraw1394/pc-libs 'Libs: -L${libdir} -lraw1394' "$pctext" hasline libraw1394/pc-cflags 'Cflags: -I${includedir}' "$pctext" hasline libraw1394/pc-libdir 'libdir=/usr/lib' "$pctext" hasline libraw1394/pc-incdir 'includedir=/usr/include' "$pctext" # The .pc version is upstream's configure.ac version and equals the recipe's # PV here; pinned because a consumer's PKG_CHECK_MODULES version test reads it. hasline libraw1394/pc-version 'Version: 2.1.2' "$pctext" hdr=$(cat "$incd/raw1394.h" 2>/dev/null) hasline libraw1394/hdr-guard '#define _LIBRAW1394_RAW1394_H' "$hdr" case "$hdr" in *"#define RAW1394_LONG_RESET 0"*) bst_ok libraw1394/hdr-reset-verbs ;; *) bst_notok libraw1394/hdr-reset-verbs "RAW1394_LONG_RESET is not 0" ;; esac case "$hdr" in *"#define raw1394_make_errcode(ack, rcode) (((ack) << 16) | rcode)"*) bst_ok libraw1394/hdr-errcode-macro ;; *) bst_notok libraw1394/hdr-errcode-macro "the errcode packing macro moved" ;; esac csrh=$(cat "$incd/csr.h" 2>/dev/null) case "$csrh" in *"0xfffff0000000ULL"*) bst_ok libraw1394/hdr-csr-base ;; *) bst_notok libraw1394/hdr-csr-base "CSR_REGISTER_BASE is not 0xfffff0000000ULL" ;; esac # --- completeness: every entry point the header declares is DEFINED --- # # READ THE SYMBOL INDEX, NOT THE WHOLE ARCHIVE. An ar archive opens with a # member named `/` holding a symbol index that lists only DEFINED, exported # symbols. The member data after it also carries every UNDEFINED name a member # references, so a scan of the whole file counts a call to an entry point as # evidence that it exists. # # Measured, by deleting one member at a time from the native archive and # scoring both forms against the header's 68 names (`defs lost` read from the # rebuilt index): # # member defs lost whole-archive sees index sees # 0 68 68 # dispatch.o 57 17 11 # main.o 5 63 63 # eventloop.o 4 64 64 # errors.o 1 67 67 # version.o 1 67 67 # fw.o / readwrite.o 0 68 68 # # Both forms red on every real loss, so the whole-archive form is not wrong on # THIS archive -- it is right by luck of the call graph, because every public # entry point is defined in dispatch.o and the library does not call its own # wrappers. Where it does differ it OVER-counts (17 against 11: six names # surviving only as undefined references), and that is the direction that reads # as coverage. The index form cannot over-count by construction, so it is the # one kept; the table is here so a later reader does not have to re-derive # which of the two they are looking at. # # THE DEFINITIVE COMPLETENESS PROOF IS THE PROBE'S LINK, and it is upstream of # this file: raw1394-probe references all 68 entry points and is linked against # ${B}/src/.libs/libraw1394.a in do_compile, so a missing definition is an # undefined-reference link failure and no image is produced at all. What pins # that the probe still references all 68 is nul-total-count below (64 # handle-taking) plus the four handle-free ones asserted by name. This check is # the runtime half, against the archive that actually shipped. # # The header's byte offsets: 8 bytes of magic, then a 60-byte member header # whose size field is 10 ASCII bytes at offset 56; the index data begins at 68. flat=$tmp/bst-raw1394-flat.$$ namef=$tmp/bst-raw1394-names.$$ foundf=$tmp/bst-raw1394-found.$$ : > "$flat" if [ "$(head -c 24 "$lib" 2>/dev/null | tail -c 16 | cut -c1)" = "/" ]; then bst_ok libraw1394/archive-has-index idxsz=$(head -c 66 "$lib" 2>/dev/null | tail -c 10 | tr -d ' ') case "$idxsz" in ''|*[!0-9]*) idxsz=0 ;; esac [ "$idxsz" -gt 0 ] && head -c $((68 + idxsz)) "$lib" 2>/dev/null | tail -c "$idxsz" \ | tr -c '[:print:]' '\n' > "$flat" 2>/dev/null else bst_notok libraw1394/archive-has-index "the first member is not the symbol index -- the archive format moved and the completeness check below cannot see definitions" fi # Declarations start at column 0; the doc comments do not. `typedef` lines are # dropped first: `typedef enum raw1394_iso_disposition (*raw1394_iso_xmit_handler_t)(` # otherwise yields raw1394_iso_disposition, which is an ENUM TAG and not an # entry point -- it would then be reported missing from the archive forever. grep -v '^typedef' "$incd/raw1394.h" 2>/dev/null \ | grep -hoE '^[a-zA-Z_][a-zA-Z_0-9 *]*\**raw1394_[a-z_0-9]+[[:space:]]*\(' \ | sed 's/(.*//' | awk '{print $NF}' | sed 's/^\**//' \ | sort -u > "$namef" # -x: the WHOLE LINE must equal the name. The index's names are NUL-separated, # so flattening leaves one per line, and a substring match would still count a # longer name that merely contains a shorter one. grep -xFf "$namef" "$flat" 2>/dev/null | sort -u > "$foundf" ndecl=$(grep -c . "$namef"); nfound=$(grep -c . "$foundf") # The floor guards the check itself: a header that lost its declarations, or an # extraction that silently matched nothing, would otherwise pass vacuously with # zero names to look up. This tree declares and defines 68. if [ "$ndecl" -ge 60 ] && [ "$nfound" -eq "$ndecl" ]; then bst_ok libraw1394/sym-complete else bst_notok libraw1394/sym-complete "declared=$ndecl found=$nfound"; fi if [ "$ndecl" -eq 68 ]; then bst_ok libraw1394/sym-declared-count else bst_notok libraw1394/sym-declared-count "raw1394.h declares $ndecl entry points, expected 68"; fi # A spot check that the extraction is finding real symbols and not its own # input: three entry points from three different declaration groups. for s in raw1394_new_handle raw1394_errcode_to_errno raw1394_iso_xmit_write; do if grep -qxF "$s" "$foundf"; then bst_ok "libraw1394/sym-$s" else bst_notok "libraw1394/sym-$s" "not present in the archive"; fi done rm -f "$flat" "$namef" "$foundf" # =========================================================================== # THE PROBE # =========================================================================== # # A probe is not run in place: do_install ships it 0755 but the rootfs is # read-only at browser runtime, so it is copied to tmpfs first. Never assert # `test -x` on the shipped path -- see the packager README. probe=$tmp/bst-raw1394-probe.$$ if cp "$probe_src" "$probe" 2>/dev/null && chmod +x "$probe" 2>/dev/null; then out=$("$probe" 2>&1); prc=$? else out=; prc=127 fi pget() { printf '%s\n' "$out" | sed -n "s/^$1=//p" | head -n 1; } case "$out" in *raw1394-probe-start*) bst_ok libraw1394/probe-started ;; *) if bst_execfail "$out"; then bst_unrun libraw1394/probe-started "$out" else bst_notok libraw1394/probe-started "probe produced no start marker: '$(_bst_1line "$out")'"; fi ;; esac case "$out" in *raw1394-probe-end*) bst_ok libraw1394/probe-complete ;; *) bst_notok libraw1394/probe-complete "probe did not reach its end marker -- it died mid-run" ;; esac check_eq libraw1394/probe-rc 0 "$prc" check_eq libraw1394/libversion 2.1.2 "$(pget libversion)" # --- ABI: wasm32 is ILP32, and that is load-bearing here -------------------- # # raw1394_private.h picks int2ptr/ptr2int on SIZEOF_VOID_P == 4. configure.ac # writes autoconf's cross-compile default into the call itself # (AC_CHECK_SIZEOF(void *, 8)), which is exactly the shape that silently # selects the wrong arm; the recipe carries a build-time grep of config.h for # the same reason, and this is its runtime half. check_eq libraw1394/abi-sizeof-void 4 "$(pget sz-void)" check_eq libraw1394/abi-sizeof-int 4 "$(pget sz-int)" check_eq libraw1394/abi-sizeof-long 4 "$(pget sz-long)" # The public typedefs are fixed-width and must not move with the word size. check_eq libraw1394/abi-byte 1 "$(pget sz-byte)" check_eq libraw1394/abi-quadlet 4 "$(pget sz-quadlet)" check_eq libraw1394/abi-octlet 8 "$(pget sz-octlet)" check_eq libraw1394/abi-nodeaddr 8 "$(pget sz-nodeaddr)" check_eq libraw1394/abi-nodeid 2 "$(pget sz-nodeid)" check_eq libraw1394/abi-errcode 4 "$(pget sz-errcode)" # struct raw1394_portinfo is { int; char[32] } -- 36 on both word sizes. check_eq libraw1394/abi-portinfo 36 "$(pget sz-portinfo)" # The three arm structs each carry a pointer, so they DO shrink: 40/16/16 on # the LP64 oracle against 32/12/8 here. check_eq libraw1394/abi-armreq 32 "$(pget sz-armreq)" check_eq libraw1394/abi-armresp 12 "$(pget sz-armresp)" check_eq libraw1394/abi-armrr 8 "$(pget sz-armrr)" # errno numbers are the asm-generic set on both arms; pinned because every # assertion below compares against them. check_eq libraw1394/eno-einval 22 "$(pget eno-EINVAL)" check_eq libraw1394/eno-enosys 38 "$(pget eno-ENOSYS)" check_eq libraw1394/eno-enoent 2 "$(pget eno-ENOENT)" # Header constants as the compiler saw them, not as the header reads. check_eq libraw1394/csr-base-lo 4026531840 "$(pget csr-base-lo)" check_eq libraw1394/csr-config-rom 1024 "$(pget csr-config-rom)" check_eq libraw1394/ack-complete 1 "$(pget ack-complete)" check_eq libraw1394/ack-pending 2 "$(pget ack-pending)" # --- ERRCODE: the pure state machine --------------------------------------- # # 0xdead (57005) is upstream's own "invalid ack/rcode" filler and is a real # return value, not a sentinel this suite invented: ack2errno[] and # rcode2errno[] carry it in every slot the 1394 spec leaves undefined. Pinning # it is what makes the sweep a table check rather than a spot check. # # The sweep stops at ack 15. ack2errno[] has sixteen entries and the library # indexes it unguarded, so ack 17 would be an out-of-bounds read UPSTREAM; # driving it would measure undefined behaviour rather than the library. check_eq libraw1394/e2e-ack0-invalid 57005 "$(pget e2e-ack0)" check_eq libraw1394/e2e-ack1-complete 0 "$(pget e2e-ack1)" check_eq libraw1394/e2e-ack3-busyx 11 "$(pget e2e-ack3)" check_eq libraw1394/e2e-ack4-busya 11 "$(pget e2e-ack4)" check_eq libraw1394/e2e-ack5-busyb 11 "$(pget e2e-ack5)" check_eq libraw1394/e2e-ack13-dataerr 121 "$(pget e2e-ack13)" check_eq libraw1394/e2e-ack14-typeerr 1 "$(pget e2e-ack14)" check_eq libraw1394/e2e-ack15-invalid 57005 "$(pget e2e-ack15)" # Every ack the spec leaves undefined maps to 0xdead: 0, 6..12 and 15. bad=0 for a in 0 6 7 8 9 10 11 12 15; do [ "$(pget "e2e-ack$a")" = 57005 ] || bad="$bad $a" done if [ "$bad" = 0 ]; then bst_ok libraw1394/e2e-ack-invalid-all else bst_notok libraw1394/e2e-ack-invalid-all "acks not mapping to 0xdead:$bad"; fi # ack 0x10 and ack 2 (ACK_PENDING) are both scored on the RCODE instead, and # must agree with each other for every rcode -- two entries into one table. check_eq libraw1394/e2e-x10r0-complete 0 "$(pget e2e-x10r0)" check_eq libraw1394/e2e-x10r4-conflict 11 "$(pget e2e-x10r4)" check_eq libraw1394/e2e-x10r5-dataerr 121 "$(pget e2e-x10r5)" check_eq libraw1394/e2e-x10r6-typeerr 1 "$(pget e2e-x10r6)" check_eq libraw1394/e2e-x10r7-addrerr 22 "$(pget e2e-x10r7)" diff=0 for r in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do [ "$(pget "e2e-x10r$r")" = "$(pget "e2e-pendr$r")" ] || diff="$diff $r" done if [ "$diff" = 0 ]; then bst_ok libraw1394/e2e-pending-matches-x10 else bst_notok libraw1394/e2e-pending-matches-x10 "ack 0x10 and ACK_PENDING disagree at rcode:$diff"; fi # The twelve internal codes and the switch default. check_eq libraw1394/e2e-int-compat 22 "$(pget e2e-int-compat)" check_eq libraw1394/e2e-int-stateorder 22 "$(pget e2e-int-stateorder)" check_eq libraw1394/e2e-int-generation 11 "$(pget e2e-int-generation)" check_eq libraw1394/e2e-int-invalidarg 22 "$(pget e2e-int-invalidarg)" check_eq libraw1394/e2e-int-memfault 14 "$(pget e2e-int-memfault)" check_eq libraw1394/e2e-int-already 22 "$(pget e2e-int-already)" check_eq libraw1394/e2e-int-excessive 22 "$(pget e2e-int-excessive)" check_eq libraw1394/e2e-int-untidylen 22 "$(pget e2e-int-untidylen)" check_eq libraw1394/e2e-int-senderror 11 "$(pget e2e-int-senderror)" check_eq libraw1394/e2e-int-aborted 11 "$(pget e2e-int-aborted)" check_eq libraw1394/e2e-int-timeout 11 "$(pget e2e-int-timeout)" check_eq libraw1394/e2e-int-default 22 "$(pget e2e-int-default)" # --- NULL: the documented failure of all 68 public entry points ------------- # # Every entry point guards its handle, so this is the whole API surface really # executed. The bulk contract is `errno = EINVAL; return -1`; the exceptions # below return a type-specific sentinel instead, and each is asserted by name # because the sentinel is what a caller actually tests against. check_eq libraw1394/nul-get_errcode -1004:0 "$(pget nul-get_errcode)" check_eq libraw1394/nul-get_generation 4294967295:22 "$(pget nul-get_generation)" check_eq libraw1394/nul-get_local_id 65535:22 "$(pget nul-get_local_id)" check_eq libraw1394/nul-get_irm_id 65535:22 "$(pget nul-get_irm_id)" check_eq libraw1394/nul-get_userdata 0:22 "$(pget nul-get_userdata)" # The four handler setters return the PREVIOUS handler, so NULL is their # failure value too -- and unlike get_userdata they are declared to set errno. for f in set_bus_reset_handler set_tag_handler set_arm_tag_handler set_fcp_handler; do check_eq "libraw1394/nul-$f" 0:22 "$(pget "nul-$f")" done # The five void entry points cannot report anything; that they returned at all # is the assertion, and errno must be untouched. for f in destroy_handle set_userdata update_generation iso_stop iso_shutdown; do check_eq "libraw1394/nul-$f" 0:0 "$(pget "nul-$f")" done # Everything else: -1 with errno EINVAL, counted rather than listed. The counts # are asserted EXACTLY, so a probe that silently stopped emitting lines cannot # pass by shrinking the population. # # THE ACCOUNTING, because two different totals appear in this file and a reader # is entitled to know they agree: raw1394.h declares 68 entry points # (sym-declared-count), of which 64 take a handle and are swept here. The other # four take none -- raw1394_errcode_to_errno, raw1394_get_libversion, # raw1394_new_handle and raw1394_new_handle_on_port -- and each is driven in its # own section above and below. 64 = 50 at -1:EINVAL + 5 returning NULL with # EINVAL (get_userdata and the four handler setters) + 5 void + 4 with a # type-specific sentinel (get_errcode, get_generation, get_local_id, # get_irm_id), every one of which is asserted by name. n_eiv=$(printf '%s\n' "$out" | grep -c '^nul-[a-z_0-9]*=-1:22$') if [ "$n_eiv" -eq 50 ]; then bst_ok libraw1394/nul-einval-count else bst_notok libraw1394/nul-einval-count "expected 50 entry points at -1:EINVAL, got $n_eiv"; fi n_nul=$(printf '%s\n' "$out" | grep -c '^nul-') if [ "$n_nul" -eq 64 ]; then bst_ok libraw1394/nul-total-count else bst_notok libraw1394/nul-total-count "expected 64 handle-taking entry points driven, got $n_nul"; fi # No entry point may report a DIFFERENT errno: anything not in the three # documented shapes is a real divergence. odd=$(printf '%s\n' "$out" | grep '^nul-' | grep -v ':22$' | grep -v ':0$' | head -n 3) if [ -z "$odd" ]; then bst_ok libraw1394/nul-no-stray-errno else bst_notok libraw1394/nul-no-stray-errno "unexpected errno: $(_bst_1line "$odd")"; fi # --- SYSCALL: what fw_new_handle() needs BEFORE it sees a device ------------ # # Measured, not assumed. These three decide whether the NULL handle below is # owned by brintos/linux#53 or by the absent controller, and they are the # reason this suite can tell those apart at all. epoll=$(pget sys-epoll); epoll_e=$(pget sys-epoll-errno) inot=$(pget sys-inotify); inot_e=$(pget sys-inotify-errno) check_eq libraw1394/sys-pipe 0 "$(pget sys-pipe)" if [ "$epoll" = "-1" ]; then if [ "$epoll_e" = 38 ]; then bst_ok libraw1394/sys-epoll-enosys else bst_notok libraw1394/sys-epoll-enosys "epoll_create failed with errno=$epoll_e, not ENOSYS -- a new failure mode, not brintos/linux#53" fi else bst_skip libraw1394/sys-epoll-enosys "epoll_create returned $epoll -- brintos/linux#53 has closed; re-read this suite's header, the handle cases below now take their other arm" fi if [ "$inot" = "-1" ]; then bst_ok libraw1394/sys-inotify-absent else bst_skip libraw1394/sys-inotify-absent "inotify_init returned $inot (errno=$inot_e) -- brintos/linux#33 has closed" fi # --- HANDLE: probed, and asserted to its documented failure ------------------ # # The ticket asks for the absence to be MEASURED and the documented failure # asserted, not skipped. So the device nodes are read first and the assertion # is chosen from what the probe found -- three arms, and the one that fires # here is the third. devraw=$(pget dev-raw1394); nfw=$(pget dev-fw-count) check_eq libraw1394/dev-raw1394-absent 0 "$devraw" check_eq libraw1394/dev-fw-absent 0 "$nfw" if [ "$devraw" != 0 ] || [ "$nfw" != 0 ]; then bst_skip libraw1394/nh-null "an IEEE-1394 device node is present: this suite's against-a-bus half was never written, because no machine had one -- extend it" bst_skip libraw1394/nh-errno "an IEEE-1394 device node is present" elif [ "$epoll" != "-1" ]; then # No controller but epoll works: fw_new_handle() succeeds anyway, because it # does not check what scan_devices() found. This is the oracle's behaviour. check_eq libraw1394/nh-null 0 "$(pget nh-null)" bst_skip libraw1394/nh-errno "the handle was created (epoll works and fw_new_handle ignores an empty scan), so there is no failure errno to assert" else # The arm this machine takes. NULL, and the errno is epoll's ENOSYS carried # out of fw_new_handle() -- not a FireWire error, which is the whole point of # measuring the syscall. check_eq libraw1394/nh-null 1 "$(pget nh-null)" check_eq libraw1394/nh-errno 38 "$(pget nh-errno)" fi # _on_port() returns NULL on EVERY arm, including the oracle's -- no port # exists to select -- so the null is asserted unconditionally. Its ERRNO is # not: the two arms reach the null by different routes and leave different # errnos, which the first target run caught (this case wanted EINVAL and got # ENOSYS). With epoll working, fw_new_handle() succeeds and selecting port 0 # then fails EINVAL; with epoll ENOSYS, fw_new_handle() never gets that far and # ENOSYS is what survives. Same null, different cause -- and the errno is the # only thing that distinguishes them, so it is worth asserting rather than # dropping. check_eq libraw1394/nhp-null 1 "$(pget nhp-null)" if [ "$epoll" = "-1" ]; then check_eq libraw1394/nhp-errno 38 "$(pget nhp-errno)" else check_eq libraw1394/nhp-errno 22 "$(pget nhp-errno)" fi # --- OVERRIDE: the RAW1394DEV path, driven for real ------------------------- # # This is the half of the library an absent controller does NOT cost us. # ieee1394_new_handle() opens $RAW1394DEV O_RDWR and, on failure, "fails over # to the default in an attempt to idiot proof". Pointed at an ordinary file the # open SUCCEEDS, so init_rawdevice() write()s a 56-byte raw1394_request and # read()s back EOF; the zeroed struct reports generation 0 rather than -1, the # handle is built, and raw1394_new_handle() then asks # ieee1394_get_port_info(), which writes a second request and returns misc==0 # -- fewer than the one port required -- so the handle is destroyed. # # 112 bytes in the file is the evidence that both calls ran for real. It is the # same on the oracle, because struct raw1394_request is all fixed-width types # and is 56 bytes on either word size. check_eq libraw1394/ov-setup 0 "$(pget ov-setup)" check_eq libraw1394/ov-bytes 112 "$(pget ov-bytes)" if [ "$epoll" = "-1" ]; then check_eq libraw1394/ov-nh-null 1 "$(pget ov-nh-null)" else bst_skip libraw1394/ov-nh-null "epoll works, so the fw backend still supplies a handle after the legacy path declines" fi # A RAW1394DEV that cannot be opened at all: the override is ignored and the # absent default is tried, so this arm reaches the same place with no bytes # written anywhere. if [ "$epoll" = "-1" ]; then check_eq libraw1394/ovmiss-nh-null 1 "$(pget ovmiss-nh-null)" else bst_skip libraw1394/ovmiss-nh-null "epoll works, so the fw backend still supplies a handle" fi rm -f "$probe" # =========================================================================== # TOOLS # =========================================================================== # # The three upstream tools, staged to tmpfs for the same read-only-rootfs # reason as the probe. for t in testlibraw dumpiso sendiso; do c=$tmp/bst-raw1394-$t.$$ if cp "/usr/bin/$t" "$c" 2>/dev/null && chmod +x "$c" 2>/dev/null; then eval "bin_$t=\$c" else eval "bin_$t=" bst_notok "libraw1394/$t-staged" "could not copy /usr/bin/$t to tmpfs" fi done # dumpiso/sendiso: -h prints usage and exits 0. This needs no bus on any arm. if [ -n "$bin_dumpiso" ]; then o=$("$bin_dumpiso" -h 2>&1); r=$? case "$o" in *"Usage: dumpiso"*) bst_ok libraw1394/dumpiso-usage ;; *) if bst_execfail "$o"; then bst_unrun libraw1394/dumpiso-usage "$o" else bst_notok libraw1394/dumpiso-usage "no usage banner: '$(_bst_1line "$o")'"; fi ;; esac check_eq libraw1394/dumpiso-usage-rc 0 "$r" case "$o" in *"--channels"*) bst_ok libraw1394/dumpiso-usage-opts ;; *) bst_notok libraw1394/dumpiso-usage-opts "the option list is missing from the banner" ;; esac fi if [ -n "$bin_sendiso" ]; then o=$("$bin_sendiso" -h 2>&1); r=$? case "$o" in *"Usage: sendiso"*) bst_ok libraw1394/sendiso-usage ;; *) if bst_execfail "$o"; then bst_unrun libraw1394/sendiso-usage "$o" else bst_notok libraw1394/sendiso-usage "no usage banner: '$(_bst_1line "$o")'"; fi ;; esac check_eq libraw1394/sendiso-usage-rc 0 "$r" fi # With no arguments both open a handle and then need port 0. They exit 1 on # every arm -- on this one because the handle is NULL, on a host with epoll # because the port does not exist -- so the exit code is asserted # unconditionally and only the DIAGNOSTIC is conditioned on the probe. if [ -n "$bin_dumpiso" ]; then o=$("$bin_dumpiso" 2>&1); r=$? check_eq libraw1394/dumpiso-nobus-rc 1 "$r" if [ "$epoll" = "-1" ]; then case "$o" in *raw1394_get_handle*) bst_ok libraw1394/dumpiso-nobus-out ;; *) if bst_execfail "$o"; then bst_unrun libraw1394/dumpiso-nobus-out "$o" else bst_notok libraw1394/dumpiso-nobus-out "expected the perror('raw1394_get_handle') path: '$(_bst_1line "$o")'"; fi ;; esac else bst_skip libraw1394/dumpiso-nobus-out "epoll works, so dumpiso gets a handle and fails later at 'Port 0 does not exist'" fi fi if [ -n "$bin_sendiso" ]; then check_rc libraw1394/sendiso-nobus-rc 1 "$bin_sendiso" fi # testlibraw is the tool whose EXIT CODE discriminates the two worlds: it # returns 1 only when raw1394_new_handle() gave NULL, and 0 when a handle was # created and reported zero cards. Both are asserted, each on its own probe. if [ -n "$bin_testlibraw" ]; then o=$("$bin_testlibraw" 2>&1); r=$? if [ "$epoll" = "-1" ]; then check_eq libraw1394/testlibraw-rc 1 "$r" case "$o" in *"couldn't get handle"*) bst_ok libraw1394/testlibraw-out ;; *) if bst_execfail "$o"; then bst_unrun libraw1394/testlibraw-out "$o" else bst_notok libraw1394/testlibraw-out "expected the no-handle diagnostic: '$(_bst_1line "$o")'"; fi ;; esac case "$o" in *"you haven't loaded the raw1394 module"*) bst_ok libraw1394/testlibraw-hint ;; *) bst_notok libraw1394/testlibraw-hint "the not_loaded hint is missing: '$(_bst_1line "$o")'" ;; esac else check_eq libraw1394/testlibraw-rc 0 "$r" case "$o" in *"0 cards found"*) bst_ok libraw1394/testlibraw-out ;; *) bst_notok libraw1394/testlibraw-out "expected '0 cards found': '$(_bst_1line "$o")'" ;; esac bst_skip libraw1394/testlibraw-hint "epoll works, so the no-handle hint is not on this arm's path" fi fi rm -f "$tmp"/bst-raw1394-*.$$