# BST-TIMEOUT: 300 # reads 508 kB across three files; the cost here is the # # 110-name API census, which runs inside ONE gawk # # jquery 3.7.1 (poky meta/recipes-devtools/jquery) -- the jQuery library shipped # as a SYSTEM JavaScript asset under /usr/share/javascript/jquery, the form # other packages' web interfaces expect to find it in rather than each bundling # its own copy. # # DATA AND NOTHING BUT DATA. The recipe compiles nothing: it inherits allarch, # fetches three files from code.jquery.com against pinned sha256sums, and copies # them to ${datadir}/javascript/${BPN}/ at mode 644. So byte-identity with an # x86-64 build is expected BY CONSTRUCTION and asserting it is not a statement # about the compiler. What it IS a statement about is the install and packaging # path, which is the part that can break on this arm: that the payload landed in # the package the image installs, that ${datadir} resolved to /usr/share, that # nothing truncated it on the way to a virtiofs root, and that the package # claims those paths and no others. # # THIS IMAGE SHIPS THIS jQUERY AND NO OTHER. BRINTOS-1684 decided between this # recipe and meta-oe's libjs-jquery 3.3.1, which owns two of the same paths with # different content -- do_rootfs cannot install both, because oe-core's deb # backend passes no --force-overwrite. The absence cases below are that decision # read back off the target rather than off the image recipe: no Debian # compatibility symlinks, and no libjs-jquery in dpkg's database. # # THE DELIVERABLE IS THE PAYLOAD, AND THERE IS NO CONSUMER ON THIS IMAGE. There # is no browser, no web server serving it and no package here that reads it -- # across the whole image no RDEPENDS names jquery -- so this suite asserts that # the library arrived complete and intact; it CANNOT assert that jQuery runs, # and it does not claim to. There is no interactive arm. # # THE ONE PLACE A NAIVE COMPLETENESS CHECK GOES WRONG, RUN AS A CONTROL BEFORE # IT WAS BUILT ON. The API census spans 110 documented jQuery 3 method names and # each must appear in BOTH javascript files. innerHeight, innerWidth, # outerHeight and outerWidth are NOT among them and must not be added: jQuery # builds those four at runtime by string concatenation ("inner" + name), so they # exist as literals only in a comment in the readable file and nowhere at all in # the minified one. The census is NOT run against jquery.min.map either, and # that is the same measurement rather than an omission: the map's names table # holds 102 of the 110, because the shorthand event methods -- keydown, # keypress, keyup, mousedown, mousemove, mouseout, mouseover, mouseup -- are # generated by jQuery.each over a string and never appear as identifiers. A # census over the map would report eight short on every image that ever built # the package. andSelf and die are carried instead as NEGATIVES: jQuery 3 # removed both, so their absence pins the major version from the content rather # than from a filename. # # ALL THREE FILES ARE PURE ASCII, and that is asserted rather than assumed. The # Debian repack this image shipped until BRINTOS-1684 carried one raw U+FFFD in # its minified file, which made LC_ALL=C load-bearing for its byte counts; # upstream's own artifacts spell the same character as the six-character # escape \uFFFD instead. # The high-byte counts below are what would notice a re-encoding on the way to # the target, and they are read under LC_ALL=C so that a non-ASCII byte would # count as one byte rather than as part of a character. # # WRITTEN TO EXEC AS LITTLE AS POSSIBLE. On this arm a process's memory is not # returned when it exits and /bin/sh is a 16 MB wasm module, so a suite's cost # is dominated by how many programs it starts. Three execs cover the whole file. . "$BST_LIB" S=jquery # THE CANARY, which asserts nothing about jquery. # # A suite's FIRST BST result line is lost between the guest's printf and the # host's read -- per-suite, deterministic, and NOT a defect in the host tool # (BRINTOS-1149 established that and filed it as linux-in-the-browser#177). # The harness reports the deficit but computes its pass count as # total-minus-failures, so THE DROPPED LINE IS COUNTED AS A PASS. A nothing-case # therefore stands in that position and the eaten line costs nothing; every real # case below is still counted. It sits ahead of the `require` guards # deliberately, because a `require` that skips would emit its skip as the first # line and that line would be eaten too. # # Remove this case when linux-in-the-browser#177 is fixed. bst_ok $S/suite-canary P=/usr/share/javascript/jquery D=$BST_DATA tmp=${TMPDIR:-/tmp} W=$tmp/bst-jquery.$$ require gawk $S/gawk-present require sha256sum $S/sha256sum-present require find $S/find-present if [ -d "$P" ]; then bst_ok $S/root; else bst_notok $S/root "$P is not a directory"; return 2>/dev/null || exit 0; fi # dpkg's own two answers, read if this image carries them and skipped if it does # not, rather than reddening on an image with no package database. LIST=/var/lib/dpkg/info/jquery.list STAT=/var/lib/dpkg/status [ -f "$LIST" ] || LIST=/dev/null [ -f "$STAT" ] || STAT=/dev/null # ------------------------------------------------------------- payload shape # One find for the whole directory; the inventory, the counts, the modes and the # byte total all come off it. -printf carries the mode, because "present at its # install path with the expected mode" is the requirement and a 0644 that became # 0600 on the way through packaging is invisible to `test -f`. find "$P" -mindepth 1 -printf '%P %y %m %s %l\n' 2>/dev/null | LC_ALL=C sort > "$W.inv" sha256sum "$P/jquery.js" "$P/jquery.min.js" "$P/jquery.min.map" > "$W.sums" 2>&1 LC_ALL=C gawk \ -v NAMES='addClass ajax animate append appendTo attr before bind blur change children clone closest contents css data delay dequeue detach each empty end eq fadeIn fadeOut fadeTo fadeToggle filter find finish first focus get has hasClass height hide html index insertAfter insertBefore is keydown keypress keyup last map mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup next nextAll nextUntil not off offset offsetParent on one parent parents parentsUntil position prepend prependTo prev prevAll prevUntil promise prop pushStack queue ready remove removeAttr removeClass removeData removeProp replaceAll replaceWith scrollLeft scrollTop serialize serializeArray show siblings slice slideDown slideToggle slideUp stop submit text toArray toggle toggleClass trigger triggerHandler unbind undelegate unwrap val width wrap wrapAll wrapInner' \ -v NEG='andSelf die' \ -v PKG=jquery \ -v PAYLOAD="$P/jquery.js $P/jquery.min.js $P/jquery.min.map" \ -v PARENTS='/usr /usr/share /usr/share/javascript /usr/share/javascript/jquery' \ -v INV="$W.inv" -v SUMS="$W.sums" \ -v JS="$P/jquery.js" -v MIN="$P/jquery.min.js" -v MAP="$P/jquery.min.map" \ -v LIST="$LIST" -v STATUS="$STAT" \ -f "$D/jquery-scan.awk" \ "$W.inv" "$W.sums" "$P/jquery.js" "$P/jquery.min.js" "$P/jquery.min.map" "$LIST" "$STAT" \ > "$W.f1" 2> "$W.err" . "$W.f1" # The scan either ran to its end or it did not, and the difference is not # otherwise visible: gawk is fatal on a payload file that is absent, which # leaves the assignments truncated and turns every case below into a comparison # against an empty string -- 38 reds for one cause. This case is emitted first # so the cause is read before its consequences. The cases still run: which of # the three files went missing is a fact only they carry. if [ "${JQ_SCAN_OK:-}" = 1 ]; then bst_ok $S/scan-complete else bst_notok $S/scan-complete \ "the payload scan did not finish; the cases below read an empty result. $(head -1 "$W.err" 2>/dev/null)" fi # The three entries do_install produces, by name, type, mode and size. A # directory that exists and holds two of them is the partial install `test -d` # cannot see; a directory that holds a fourth is a collision like the one # BRINTOS-1684 removed. check_eq $S/payload-entries 3 "$JQ_INV_N" check_eq $S/payload-files 3 "$JQ_FILES" check_eq $S/payload-links 0 "$JQ_LINKS" check_eq $S/payload-subdirs 0 "$JQ_DIRS" check_eq $S/payload-mode644 3 "$JQ_MODE644" check_eq $S/payload-bytes 507614 "$JQ_BYTES" check_eq $S/payload-inventory \ 'jquery.js:f:644 285314 jquery.min.js:f:644 87533 jquery.min.map:f:644 134767' \ "$JQ_INV" # ------------------------------------------- content, against x86-64 reference # These three sums are the recipe's own SRC_URI[*.sha256sum] values -- the # artifacts the jQuery project published at code.jquery.com, by their own route. # The oracle is therefore upstream, not a copy of what this image built, so the # comparison is not tautological. The recipe is allarch and its do_install # copies bytes it does not transform, so these are also the bytes a native # x86-64 build installs. check_eq $S/sha256-jquery-js \ 78a85aca2f0b110c29e0d2b137e09f0a1fb7a8e554b499f740d6744dc8962cfe "$JQ_SHA_JS" check_eq $S/sha256-jquery-min-js \ fc9a93dd241f6b045cbff0481cf4e1901becd0e12fb45166a8f17f95823f0b1a "$JQ_SHA_MIN" check_eq $S/sha256-jquery-min-map \ 5e7d6d9c28b7f21006535e8875eb47e9667852a14c4624eed301c6cea19ae62b "$JQ_SHA_MAP" # ------------------------------------------------ read back through the target # The requirement this suite exists for: read the installed files back with the # target's own tooling and show they are complete and not truncated. The sums # above are one way to say that; these are an INDEPENDENT way, because they come # from gawk's own reader rather than from sha256sum's, and they localise a short # read instead of merely detecting one -- a truncation shows up as a short LINE, # naming which. check_eq $S/readback-js-bytes 285314 "$JQ_JS_BYTES" check_eq $S/readback-js-lines 10716 "$JQ_JS_LINES" check_eq $S/readback-min-bytes 87533 "$JQ_MIN_BYTES" check_eq $S/readback-min-lines 2 "$JQ_MIN_LINES" check_eq $S/readback-min-line-lengths '88,87443' "$JQ_MIN_LENS" check_eq $S/readback-map-bytes 134767 "$JQ_MAP_BYTES" check_eq $S/readback-map-lines 1 "$JQ_MAP_LINES" # The map is a single line with NO trailing newline -- its last byte is the # closing brace of the JSON object. Pinned because every byte count above is # line-count plus content, and a transfer that helpfully appended a newline # would shift the map's total by one while looking like a clean copy. check_eq $S/readback-map-no-trailing-newline 0 "$JQ_MAP_RT" # The banner lines, which are the licence attribution and the version in one. # Debian's repack of 3.3.1 carried NO banner at all in its minified file; a # minified copy with the MIT attribution stripped is exactly what these two # cases refuse. check_eq $S/readback-js-head '/*!' "$JQ_JS_HEAD" check_eq $S/version-banner-jquery-js ' * jQuery JavaScript Library v3.7.1' "$JQ_JS_BANNER" check_eq $S/readback-js-tail '} );' "$JQ_JS_TAIL" check_eq $S/licence-banner-min-js \ '/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */' \ "$JQ_MIN_BANNER" check_eq $S/readback-min-head '!function(e,t){"use strict";"object"==ty' "$JQ_MIN_HEAD" check_eq $S/readback-min-tail 'ed"==typeof e&&(ie.jQuery=ie.$=ce),ce});' "$JQ_MIN_TAIL" # Pure ASCII, all three. A re-encoding or a mangled multibyte character on the # way to a virtiofs root would move these off zero while every size above could # still pass in a UTF-8 locale. check_eq $S/ascii-only-jquery-js 0 "$JQ_HI_JS" check_eq $S/ascii-only-min-js 0 "$JQ_HI_MIN" check_eq $S/ascii-only-min-map 0 "$JQ_HI_MAP" # --------------------------------------------------------- the source map # jquery.min.map is what makes this port's payload three files rather than the # two the previous jQuery shipped, so it is asserted as a source map and not # merely as 134,767 bytes that hashed correctly. Its four structural fields say # it maps THIS release: v3 format, generated from jquery-3.7.1.js, describing # jquery-3.7.1.min.js. check_eq $S/map-format-version 3 "$JQ_MAP_VER" check_eq $S/map-sources '"jquery-3.7.1.js"' "$JQ_MAP_SRC" check_eq $S/map-file 'jquery-3.7.1.min.js' "$JQ_MAP_FILE" check_eq $S/map-names-count 1227 "$JQ_MAP_NAMES" check_eq $S/map-mappings-length 120533 "$JQ_MAP_MAPLEN" # ------------------------------------------------------------- the API surface # 110 documented jQuery 3 method names, each of which must appear in BOTH # javascript files. Minification does not mangle property names, so agreeing # across the readable and the minified file is a real statement about the # payload rather than a restatement of one file -- and a file truncated anywhere # loses the names that live past the cut. check_eq $S/api-names-total 110 "$JQ_API_TOTAL" check_eq $S/api-in-jquery-js 110 "$JQ_API_JS" check_eq $S/api-in-jquery-min 110 "$JQ_API_MIN" check_eq $S/api-jquery-js-first-missing '' "$JQ_API_JS_MISS" check_eq $S/api-jquery-min-first-missing '' "$JQ_API_MIN_MISS" # The negatives, which are what make the census a version assertion: jQuery 3 # removed .andSelf() and .die(), so a 1.x file dropped in under the same name # fails here while passing every count above. check_eq $S/removed-in-jquery3-js '' "$JQ_NEG_JS" check_eq $S/removed-in-jquery3-min '' "$JQ_NEG_MIN" # ----------------------------------------------------------------- packaging # What dpkg on the target says the package owns. The recipe sets # FILES:${PN} = "${datadir}", which claims the whole of /usr/share -- broad # enough that anything else landing under it would be swept into this package # silently. So the claim is read back: the three payload paths, and nothing that # is not one of them or a parent directory of one. if [ "$LIST" = /dev/null ]; then bst_skip $S/dpkg-owns-payload "no /var/lib/dpkg/info/jquery.list on this image" bst_skip $S/dpkg-claims-nothing-else "no /var/lib/dpkg/info/jquery.list on this image" else check_eq $S/dpkg-owns-payload 3 "$JQ_LIST_PAYLOAD" check_eq $S/dpkg-claims-nothing-else '' "$JQ_LIST_EXTRA" fi # The allarch claim, read from the image's own package manager rather than from # the recipe that made the promise: pure JavaScript text packaged once for every # machine, not per-machine as the recipe this replaced did. if [ "$STAT" = /dev/null ]; then bst_skip $S/package-arch-all "no /var/lib/dpkg/status on this image" bst_skip $S/package-version "no /var/lib/dpkg/status on this image" else check_eq $S/package-arch-all all "$JQ_PKG_ARCH" check_eq $S/package-version 3.7.1-r0 "$JQ_PKG_VER" fi # ------------------------------------------------- the decision, read on target # BRINTOS-1684 removed libjs-jquery from this image because it owns two of these # three paths with different content. These cases are that removal asserted from # the target: the two Debian compatibility symlinks only libjs-jquery ships must # be absent, and dpkg must not know the package at all. Stated as absences # because the failure they catch is a re-selection of the other recipe by a # later round, which would break do_rootfs long before it reached here -- but # would be silent if it ever stopped doing so. if [ -e "$P/jquery.lite.js" ] || [ -e "$P/jquery.pack.js" ]; then bst_notok $S/no-debian-compat-symlinks \ "jquery.lite.js or jquery.pack.js present; libjs-jquery is back in this image" else bst_ok $S/no-debian-compat-symlinks fi if [ -f /var/lib/dpkg/info/libjs-jquery.list ]; then bst_notok $S/libjs-jquery-not-installed \ "dpkg knows libjs-jquery; BRINTOS-1684 removed it from this image" else bst_ok $S/libjs-jquery-not-installed fi rm -f "$W.inv" "$W.sums" "$W.f1" "$W.err"