. "$BST_LIB" # BST-TIMEOUT: 1200 # THREE python3 starts, and they are the whole cost. Every # # assertion below either reads the filesystem/dpkg with # # shell builtins or greps the output of one of those three. # # # # They are the package-level `import pyroute2', a second # # start for `import ctypes', and the probe -- which takes # # ONE start for ninety-one measurements, including the # # whole netlink conversation. # # # # The netlink work itself is microseconds: roughly a dozen # # AF_NETLINK sockets opened and closed, each carrying one # # dump or one request. Nothing here sleeps and nothing here # # waits on a timer. # # # # 1200 is 400s per start, the same budget 99-python3-jdcal # # and 99-python3-async-timeout set for their three, and # # roughly six times the ~60s a python3 start has measured # # at here. # # # # NOT MEASURED ON TARGET YET: this port's first on-target # # run is the batch verify, and the measured elapsed replaces # # this note in the test plan rather than in this comment, # # which would cost an image build to keep the shipped suite # # byte-identical. # # python3-pyroute2 0.7.10 (meta-openembedded/meta-python # recipes-devtools/python/python3-pyroute2_0.7.10.bb, `inherit setuptools3 pypi # ptest', PyPI sdist) on the wasm32-hwjs glibc image. NO bbappend and NO patch: # the stock recipe builds and packages correctly as it stands -- `bitbake # python3-pyroute2' completed 1622 of 1622 tasks with zero ERROR lines against a # warm sstate, 2026-09-08, producing exactly python3-pyroute2, -dev and -dbg. # # ============================================================================ # THE HEADLINE: `import pyroute2' DOES NOT WORK ON THIS IMAGE -- AND THE NETLINK # CORE UNDERNEATH IT WORKS COMPLETELY. # ============================================================================ # # Both halves are findings, and reporting either one alone misdescribes the # port. # # THE BLOCK, BEFORE BRINTOS-2269. python3 was built with _ctypes configured # out, and pyroute2/__init__.py line 16 (`from pyroute2.cli.console import # Console') reaches pyroute2/ndb/main.py, whose line 282 is `import ctypes'. The # package import died with `ModuleNotFoundError: No module named '_ctypes''. # # THE BLOCK SINCE BRINTOS-2269. _ctypes is built in and `import ctypes' works, # so the package import runs PAST ndb.main -- and the interpreter now dies with # `hwjs-user-rt VIOLATION[lane 0]: set-over-set: parked slot not empty at a new # park', rc=132 (measured, HardwareJS 389ac7e). That is a platform lane fault, # not ctypes: nothing pyroute2 runs at import makes an FFI call (every CDLL in # the package is inside a function), and the same violation reproduces in # curses `setupterm' with _ctypes configured out (BRINTOS-2269 design doc, # Issues Found 5). The next import console.py reaches is `readline', whose init # runs rl_initialize over the same terminfo library, so that is the likeliest # site -- INFERRED, not measured; `python3 -u -X importtime -c "import # pyroute2"' names it. # # THE BLOCK IS INDEPENDENT OF THE CORE. Not one module under pyroute2/netlink/ imports # ctypes at module scope, and neither does pyroute2/iproute/linux.py. The ctypes # users are ndb.main, netns, inotify, ethtool, ext.rawsocket and # iproute/windows -- none of which the rtnetlink path touches. EVERY submodule # nevertheless fails to import, because importing `pyroute2.anything' runs the # parent package's __init__ first. That is why the honest package-level failure # HIDES a working core, and why this suite does not stop at it. # # THE BYPASS, AND WHY IT IS AN INSTRUMENT RATHER THAN A WORKAROUND. The probe # stubs the parent package (a module object carrying only __path__) and imports # `pyroute2.iproute' underneath it. Nothing installs that stub, nothing ships # it, and a caller on this image really does have to wait for the platform: the # suite asserts the package import separately, as an attributed red, so the gap # cannot go quiet. The probe does NOT attempt `import pyroute2' itself -- the # crash above killed it before its first buffered line reached the file, and # took every core case with it. 99-python3-periphery uses the same instrument for the same # reason -- three of its seven interfaces are sound and hidden behind one # ctypes-reaching sibling. # # WHAT THE BYPASS BUYS is the whole subject of the port: `IPRoute()' opens # AF_NETLINK, and every rtnetlink case below runs for real against this arm's # kernel. # # ============================================================================ # THE POINT OF THIS PORT: THERE IS NO C LIBRARY BETWEEN THE TEST AND AF_NETLINK. # ============================================================================ # # pyroute2 builds and parses the netlink messages ITSELF, in Python, byte for # byte -- 442 packaged files and not one `.so' (asserted below off the package's # own file list). So a red in the rtnetlink cases is the KERNEL's or the SOCKET # LAYER's, and cannot be a binding's. That is a stronger instrument than any # `ip'/`ifconfig' suite on this image: busybox `ip' is rtnetlink-based too, but # a failure there could always be busybox's. # # THE ARM SUPPORTS THIS. arch/wasm32/configs/wasm32_defconfig carries # CONFIG_NET=y, and its own comment states the other side of it -- "rtnetlink # core (busybox `ip` is rtnetlink-based; rtnetlink is unconditional core under # NET)". The syscall table (arch/wasm32/kernel/syscall_table.c) registers every # member this needs: socket [41], connect [42], sendto [44], recvfrom [45], # sendmsg [46], recvmsg [47], bind [49], getsockname [51], setsockopt [54], # getsockopt [55], plus poll [7] and select [23]. None of them is the epoll # family, which is unwired here (brintos/linux#53) and which this port does not # reach. # # ============================================================================ # NetNS IS BLOCKED TWICE OVER, AND THE TWO ARE ASSERTED SEPARATELY. # ============================================================================ # # GAP 1 -- pyroute2/netns/__init__.py line 82 is `import ctypes', so NetNS was # unreachable for the SAME reason the package import was. Since BRINTOS-2269 # the import succeeds (`netns-gap1-import'), and the first libc call moves the # failure: `_get_libc()' is `ctypes.CDLL(find_library("c"))', and the host # refuses a second libc.so instance with an OSError naming `side module owns # TLS' (brintos/hardwarejs#42; refused for TLS per hwjs-cc#106) -- `netns-gap1-libc-refused', a red witness. # # GAP 2 -- even with ctypes working, this arm's defconfig carries # `# CONFIG_NET_NS is not set', naming the same class of arch work PID_NS and # USER_NS wait on. `netns.create()' would call `libc.unshare(CLONE_NEWNET)'; # unshare IS wired ([272], GR-402), so the refusal would come from the kernel's # own check_unshare_flags rather than from an unregistered syscall. # # THEY ARE ASSERTED SEPARATELY ON PURPOSE, exactly as 99-python3-file-magic # separates its two: a reader who saw only the ctypes failure would conclude # that FFI is the whole of what NetNS waits on, and would be wrong by one gap. # Closing hwjs-cc#106 alone moves the failure from the CDLL to the unshare and # changes the message rather than making NetNS work. # # `proc-ns-net-absent' is the kernel's own side of gap 2, READ rather than # inferred: with CONFIG_NET_NS unset the net namespace type is not registered # and /proc/self/ns/net does not exist. # # NOT YET MEASURED ON TARGET. This port's first on-target run is the batch # verify. Gap 2's two cases -- `netns-gap2-proc-ns-net' and the CONFIG_NET_NS # reasoning behind it -- are PREDICTIONS derived from the defconfig, not # results: the x86-64 control has CONFIG_NET_NS=y and could not measure them. # Gap 1 IS measured (see the control note below). # # ============================================================================ # WHERE THE EXPECTED VALUES CAME FROM. # ============================================================================ # # MEASURED BEFOREHAND ON AN x86-64 CONTROL, run against THIS BUILD's own .deb # payload -- the bytes that ship, extracted from # python3-pyroute2_0.7.10-r0_wasm32.deb -- with `_ctypes' forced to raise # ModuleNotFoundError through a sys.meta_path hook, which is this image's # condition exactly. That control established, as RESULTS rather than guesses: # the package import failure and its precise chain; the netlink core importing # and working with ctypes blocked; NetNS blocked at gap 1; version 0.7.10; # NetlinkError carrying code 19 for a bad index AND for a bad ifname; OSError # for a malformed address; and the sysfs/rtnetlink cross-check agreeing across # eight interfaces. # # THE WRITE PATH WAS MEASURED IN A PRIVATE user+net NAMESPACE (`unshare -Urn'), # which is root over a FRESH `lo' and touches nothing on the shared build host. # Add, independent read-back, delete, independent re-read, and link down/up all # ran green there. # # TWO VALUES THE CONTROL COULD NOT SUPPLY, and neither is guessed: # - `lo' carrying 127.0.0.1/8. A fresh namespace's `lo' is unconfigured, so # the control could not show it. It is not an assumption either: # 99-net-tools.test on THIS image already asserts `ifconfig lo' reporting # 127.0.0.1, so the fact is measured -- just by a different suite. # - The interface set. The target has `lo' and the virtio-net `eth0' # (CONFIG_VIRTIO_NET=y; 41 suites on this image assert eth0). The suite # asserts those two by name and cross-checks the whole set against sysfs, # rather than pinning a count that a future netdev would red. # # ============================================================================ # WHAT THIS SUITE CHANGES ON THE GUEST. # ============================================================================ # # It runs on an image SHARED with the rest of its batch, so the write cases are # constrained twice over. They touch `lo' and NOTHING ELSE -- never eth0, which # carries the guest's connectivity and the verify's own transport. Every # mutation is wrapped in try/finally in the probe, so the address is removed and # `lo' is brought back UP whatever raises. `restore-ok' is emitted last from # those finally blocks and is asserted below, so a probe that died mid-mutation # SAYS so rather than leaving a quiet mess for the next suite to trip over. # # The link-state cases are written to be correct whichever way `lo' starts: # after `set down' it must not be UP, and after `set up' it must be. That pair # is the observed flag change, and it does not depend on the guest's boot state # the way a raw before/after flag comparison would. # # ============================================================================ # PACKAGING. # ============================================================================ # # The recipe declares `RDEPENDS:${PN} += ' -- an APPEND, so the `python3-core' # that setuptools3-base contributes survives; measured on the built .deb, the # control stanza carries it alongside the eleven declared names, and all twelve # are asserted below. python3-ctypes is among them; it ships the pure-Python # half, and the C module is built into the interpreter since BRINTOS-2269. # # The recipe DOES `inherit ptest', but DISTRO_FEATURES on this distro is # `ipv4 x11 wayland' (conf/distro/brintos.conf) with no `ptest', so no -ptest # package is produced: the build emitted exactly three .debs. Asserted below # rather than assumed. # # TWO top-level packages ship, not one: `pyroute2' and `pr2modules' (the legacy # compatibility shim), which is what dist-info's top_level.txt declares. And # FOUR CLI entry points land in /usr/bin -- pyroute2-cli, pyroute2-dhcp-client, # pyroute2-test-platform and ss2. Every one of them imports the package at # startup, so all four are dead on this image for the reason the package import # is; the suite asserts they were INSTALLED (the packaging is correct) without # claiming they run. P=python3-pyroute2 # The canary is what tells a reader the suite STARTED, as distinct from a suite # that produced nothing because the interpreter never came up. bst_ok $P/suite-canary require python3 $P/python3-present SITE=/usr/lib/python3.12/site-packages PKGDIR=$SITE/pyroute2 DI=$SITE/pyroute2-0.7.10.dist-info PKGLIST=/var/lib/dpkg/info/python3-pyroute2.list PROBE=$BST_DATA/python3-pyroute2-probe.py tmp=${TMPDIR:-/tmp} W=$tmp/bst-pyroute2.$$ mkdir -p "$W" || { bst_notok $P/workdir "cannot create $W"; exit 0; } # ------------------------------------------------------------- on the disk --- check $P/site-packages-dir test -d "$SITE" check $P/package-dir test -d "$PKGDIR" check $P/init-file test -s "$PKGDIR/__init__.py" check $P/no-flat-module test ! -e "$SITE/pyroute2.py" # The netlink core, which is what this port is actually for. check $P/core-netlink-dir test -d "$PKGDIR/netlink" check $P/core-rtnl-dir test -d "$PKGDIR/netlink/rtnl" check $P/core-iproute-dir test -d "$PKGDIR/iproute" check $P/core-iproute-linux test -s "$PKGDIR/iproute/linux.py" # The legacy compatibility shim -- the SECOND top-level package, which a suite # looking only for `pyroute2' would miss entirely. check $P/pr2modules-dir test -d "$SITE/pr2modules" check $P/pycache test -s "$PKGDIR/__pycache__/__init__.cpython-312.pyc" # The four CLI entry points. They are asserted as INSTALLED, not as working: # each imports the package at startup and so is dead here with it. for _c in pyroute2-cli pyroute2-dhcp-client pyroute2-test-platform ss2; do check $P/cli-installed-$_c test -x /usr/bin/$_c done # ------------------------------------------------------- what dpkg shipped --- cat "$PKGLIST" > "$W/pkgf" 2>/dev/null || : > "$W/pkgf" check $P/pkg-list-present test -s "$W/pkgf" # PURE PYTHON, ASSERTED FROM THE PACKAGE'S OWN FILE LIST. This is the claim the # whole port rests on: no C library stands between the test and AF_NETLINK. # This image's python3 has an empty lib-dynload and no dynamic loader # (BRINTOS-1476), so a release that grew a compiled extension could not be # imported whatever it built to -- it would land here first. check_eq $P/pkg-no-so "" \ "$(grep -E '\.so($|\.)' "$W/pkgf" 2>/dev/null)" # Every packaged file is Python, a bytecode cache, dist-info metadata, or one of # the four CLI scripts -- named explicitly, because a blanket rule would stop # catching anything. _bad= while IFS= read -r _p; do [ -d "$_p" ] && continue case "$_p" in *.py|*.pyc) continue ;; *.dist-info/*) continue ;; /usr/bin/pyroute2-cli|/usr/bin/pyroute2-dhcp-client) continue ;; /usr/bin/pyroute2-test-platform|/usr/bin/ss2) continue ;; esac _bad="$_bad $_p" done < "$W/pkgf" check_eq $P/pkg-only-python "" "$_bad" # ------------------------------------------------------------- dist-info ---- check $P/dist-info-dir test -d "$DI" check_out $P/dist-info-name "Name: pyroute2" cat "$DI/METADATA" check_out $P/dist-info-version "Version: 0.7.10" cat "$DI/METADATA" check_out $P/dist-info-summary "Summary: Python Netlink library" cat "$DI/METADATA" # The wheel metadata's own statement that there is nothing arch-specific here -- # the packaging side of "pure Python". check_out $P/dist-info-purelib "Root-Is-Purelib: true" cat "$DI/WHEEL" check_out $P/dist-info-tag "Tag: py3-none-any" cat "$DI/WHEEL" # BOTH top-level packages, which is the fact a one-package assumption would miss. check_out $P/dist-info-top-level-pyroute2 "pyroute2" cat "$DI/top_level.txt" check_out $P/dist-info-top-level-pr2modules "pr2modules" cat "$DI/top_level.txt" # Dual-licensed, and both files ship. check $P/license-gpl test -s "$DI/LICENSE.GPL-2.0-or-later" check $P/license-apache test -s "$DI/LICENSE.Apache-2.0" # --------------------------------------------------------- what dpkg says ---- dpkg -s python3-pyroute2 > "$W/st" 2>/dev/null || : > "$W/st" check_out $P/pkg-installed "Status: install ok installed" cat "$W/st" grep '^Depends:' "$W/st" > "$W/dep" 2>/dev/null || : > "$W/dep" # The eleven the recipe declares... for _d in python3-ctypes python3-io python3-json python3-fcntl python3-logging \ python3-multiprocessing python3-pickle python3-pkgutil python3-pprint \ python3-shell python3-unixadmin; do check_out $P/pkg-depends-$_d "$_d" cat "$W/dep" done # ...and the one it does NOT, which arrives from `setuptools3-base'. The recipe # uses `+=' rather than `=', so this survives; asserted because nothing in the # recipe text says it should be there. check_out $P/pkg-depends-core "python3-core" cat "$W/dep" # THE WHOLE STANZA, in dpkg's own order, so a dependency APPEARING is caught as # well as one going missing. check_eq $P/pkg-depends-exact \ "Depends: python3-core, python3-ctypes, python3-fcntl, python3-io, python3-json, python3-logging, python3-multiprocessing, python3-pickle, python3-pkgutil, python3-pprint, python3-shell, python3-unixadmin" \ "$(cat "$W/dep")" # The recipe DOES `inherit ptest', but this distro's DISTRO_FEATURES is # "ipv4 x11 wayland" with no `ptest', so the split does not exist here. check_eq $P/no-ptest-package "" \ "$(dpkg -s python3-pyroute2-ptest 2>/dev/null | grep '^Status: install ok installed')" # ------------------------------------------------------------- the probe ----- check $P/probe-present test -s "$PROBE" bst_probe $P/probe-run "$W/probe" 900 python3 "$PROBE" OUT="$W/probe" pv() { grep "^$1=" "$OUT" 2>/dev/null | head -n 1 | cut -d= -f2-; } if ! test -s "$OUT"; then bst_notok $P/probe-output "the probe emitted nothing -- python3 did not start, or died before its first line; every CASE below is unscorable" else bst_ok $P/probe-output fi check_eq $P/probe-complete "yes" "$(pv probe_done)" # 91 = the 79 the x86-64 control emitted with eth0 ABSENT, plus the eleven eth0 # adds here: three sysfs_eth0_* and the nine-key link_eth0_* block that replaces # the single `link_eth0_present=no'; minus `pkg_import', which the probe no # longer attempts, plus the two `netns_libc_*' keys. On a guest with no eth0 it # reads 80 -- measured on the local-verify rig, which has no virtio-net. _exp_count=91 [ "$(pv link_eth0_present)" = "no" ] && _exp_count=80 check_eq $P/probe-count "$_exp_count" "$(pv emitted_count)" # ------------------------------------------------ ctypes, from the probe ----- # Red witnesses for the missing _ctypes until BRINTOS-2269, inverted to what the # image now measures: `import ctypes' works and _ctypes is a builtin -- on this # arm every extension module is linked into the interpreter. check_eq $P/probe-ctypes-import "ok" "$(pv ctypes_import)" check_eq $P/probe-ctypes-builtin "present" "$(pv ctypes_builtin)" # The stdlib the core needs. If one of these were missing the port would be # blocked by MORE than ctypes, and this suite would be reporting a smaller gap # than the image really has. for _m in socket struct os errno select threading json io logging pickle \ pprint fcntl multiprocessing pkgutil time; do check_eq $P/stdlib-$_m "ok" "$(pv stdlib_$_m)" done # ------------------------------------------------------ the netlink floor ---- # The address family this entire port stands on: DEFINED in the interpreter... check_eq $P/af-netlink-defined "yes" "$(pv af_netlink_defined)" check_eq $P/af-netlink-value "16" "$(pv af_netlink_value)" # ...and ACCEPTED by the kernel. Two cases, because a constant the header # defines proves nothing about a socket the kernel will open -- and on this arm # that distinction is the difference between a wired syscall and an unwired one. check_eq $P/af-netlink-socket "ok" "$(pv af_netlink_socket)" # --------------------------------------- the core, with the package blocked -- # THE SECOND HALF OF THE HEADLINE. The package import above is dead; these say # the netlink core underneath it is not. check_eq $P/core-import-iproute "ok" "$(pv core_iproute_import)" check_eq $P/core-import-exceptions "ok" "$(pv core_exceptions_import)" check_eq $P/core-version "0.7.10" "$(pv core_version)" check_eq $P/core-iproute-class "IPRoute" "$(pv iproute_class)" # ------------------------------------------------------- NetNS: two gaps ----- # GAP 1. The module's own `import ctypes' (line 82) now succeeds -- a red # witness for the missing _ctypes until BRINTOS-2269... check_eq $P/netns-gap1-import "ok" "$(pv netns_import)" # ...and the gap moves to its libc handle: CDLL on the libc path, which the host # refuses as a second libc.so (brintos/hardwarejs#42; refused for TLS per hwjs-cc#106). A RED WITNESS -- it reds on # the day #106 closes. The message is the one measured for the same CDLL call in # BRINTOS-2269; not yet measured through this probe. check_eq $P/netns-gap1-libc-refused "OSError" "$(pv netns_libc_class)" check_eq $P/netns-gap1-libc-tls "yes" "$(pv netns_libc_tls)" # GAP 2, PREDICTED, NOT YET MEASURED: `# CONFIG_NET_NS is not set' in this arm's # defconfig means the net namespace type is not registered, so this link does # not exist. The x86-64 control has CONFIG_NET_NS=y and could not measure it. # If this reds, the defconfig has changed and gap 2 has closed -- re-read the # header rather than "fixing" the case. check_eq $P/netns-gap2-proc-ns-net "absent" "$(pv proc_ns_net)" # ------------------------------------------------------- the link dump ------- # rtnetlink's idea of which interfaces exist must be sysfs's. Two independent # windows onto the same kernel state: a cached or synthesised netlink answer # would agree with neither. check_eq $P/links-match-sysfs "yes" "$(pv links_match_sysfs)" check_eq $P/link-lo-present "yes" "$(pv link_lo_present)" check_eq $P/link-lo-index "1" "$(pv link_lo_index)" check_eq $P/link-lo-mtu "65536" "$(pv link_lo_mtu)" check_eq $P/link-lo-address "00:00:00:00:00:00" "$(pv link_lo_address)" # Each field against sysfs individually, so a mismatch names the FIELD rather # than only the interface. check_eq $P/link-lo-index-matches "yes" "$(pv link_lo_index_matches)" check_eq $P/link-lo-mtu-matches "yes" "$(pv link_lo_mtu_matches)" check_eq $P/link-lo-address-matches "yes" "$(pv link_lo_address_matches)" # The virtio-net interface (CONFIG_VIRTIO_NET=y). Its MTU and MAC are the # guest's own and are NOT pinned -- the cross-check against sysfs is what says # they are right, without inventing a value a future rig would red on. check_eq $P/link-eth0-present "yes" "$(pv link_eth0_present)" check_eq $P/link-eth0-index-matches "yes" "$(pv link_eth0_index_matches)" check_eq $P/link-eth0-mtu-matches "yes" "$(pv link_eth0_mtu_matches)" check_eq $P/link-eth0-address-matches "yes" "$(pv link_eth0_address_matches)" # link_lookup is the API most callers use to turn a name into an index... check_eq $P/lookup-lo "1" "$(pv lookup_lo)" # ...and it must answer EMPTY for a name that is not there, rather than raising # or inventing an index. check_eq $P/lookup-absent "" "$(pv lookup_absent)" # --------------------------------------------------------------- addresses --- # 127.0.0.1/8 on lo. 99-net-tools.test asserts the same fact through `ifconfig'; # this reads it from rtnetlink, which is a different path to the same kernel. check_eq $P/addr-lo-loopback "yes" "$(pv addr_lo_has_loopback)" # ----------------------------------------------------------- the write path --- # THE CASE A CACHED OR SYNTHESISED ANSWER CANNOT FAKE: written through one # netlink socket, read back through a DIFFERENT one, removed, and confirmed gone # through a third. Every read is a fresh IPRoute() for exactly that reason. check_eq $P/addr-add "ok" "$(pv addr_add)" check_eq $P/addr-add-readback "yes" "$(pv addr_after_add_present)" # An "add" that REPLACED rather than added would pass a naive presence check. check_eq $P/addr-add-keeps-loopback "yes" "$(pv addr_after_add_keeps_loopback)" check_eq $P/addr-del "ok" "$(pv addr_del)" check_eq $P/addr-del-readback "no" "$(pv addr_after_del_present)" # ...and the interface is back exactly where it started. check_eq $P/addr-restored "yes" "$(pv addr_restored)" # ------------------------------------------------------------ link up/down --- # Written to be correct whichever way `lo' starts on this guest: after `set # down' it must not be UP, and after `set up' it must be. That PAIR is the # observed flag change, and unlike a raw before/after comparison it does not # depend on the boot state. check_eq $P/link-set-down "ok" "$(pv link_set_down)" check_eq $P/link-down-observed "no" "$(pv lo_up_after_down)" check_eq $P/link-set-up "ok" "$(pv link_set_up)" check_eq $P/link-up-observed "yes" "$(pv lo_up_after_up)" # THE GUEST IS SHARED WITH THE REST OF THE BATCH. This is emitted last, from the # probe's finally blocks, and says every mutation above was undone. A red here # is a mess the NEXT suite will trip over, so it is worth its own case. check_eq $P/restore-ok "yes" "$(pv restore_ok)" # ------------------------------------------------------------------ routes --- check_eq $P/routes-have-loopback "yes" "$(pv routes_have_loopback)" # The loopback route lives in the `local' table (255). Asserting the TABLE, not # just the prefix, is what distinguishes a real routing table from a list that # merely mentions 127. check_eq $P/routes-local-table "yes" "$(pv routes_local_table)" # ------------------------------------------------------------------ errors --- # THE KERNEL'S OWN ERRNO, carried up as NetlinkError. This is the case that says # the request really reached the kernel: pyroute2 did not invent 19. check_eq $P/err-bad-index-class "NetlinkError" "$(pv err_bad_index)" check_eq $P/err-bad-index-errno "19" "$(pv err_bad_index_code)" check_eq $P/err-bad-ifname-class "NetlinkError" "$(pv err_bad_ifname)" check_eq $P/err-bad-ifname-errno "19" "$(pv err_bad_ifname_code)" # A MALFORMED REQUEST IS REFUSED BEFORE IT IS SENT -- a different and WEAKER # claim than the two above: pyroute2's own encoder rejects it and the kernel # never sees it. Both are worth having; one says the library validates, the # other says the kernel does. check_eq $P/err-bad-address-class "OSError" "$(pv err_bad_address)" # ------------------------------------------------------------- the import --- # ctypes itself imports: _ctypes is built in, and says nothing (measured by the # same command in 99-python3-inotify and -libevdev). First, # because the package import below can take the interpreter down. check_eq $P/ctypes-import "" "$(python3 -c 'import ctypes' 2>&1 | tail -1)" # THE HONEST ANSWER. Until BRINTOS-2269 this was a red witness for the missing # _ctypes. It now asserts the documented contract, and reds as rc=132 on the # set-over-set lane fault (see the header; BRINTOS-2269 Issues Found 5, same # class as hwjs-cc#69). Its own process, and LAST, so neither the crash nor the # memory it leaves behind (brintos/linux#44) can reach the probe. check $P/pkg-import python3 -c 'import pyroute2'