# BST-TIMEOUT: 300 # measured 55 s and 30 s on two local-verify boots # # (2026-08-22, idle host): 320 kB across 115 files, 150 kB of # # it through one gawk, 115 sha256sums, 115 cksums, one # # 66-file pngcheck, and two duk runs that each load a 5.8 MB # # interpreter. The default 60 s is NOT safe -- the worse of # # those two runs is already 55 s on an idle box. 300 is ~5x # # the measurement rather than the ~3x the heavier suites # # declare, because the two duk loads dominate and they are # # the part that stretches most on a host under memory # # pressure. # # libjs-jquery-icheck 1.0.3 (iCheck) -- the jQuery/Zepto plugin that replaces # checkbox and radio controls with skinned equivalents, shipped as a system # JavaScript asset under /usr/share/javascript/jquery-icheck: two script files # and six skins, 47 stylesheets and 66 PNG sprites. # # DATA AND NOTHING BUT DATA. The recipe has no do_compile, no DEPENDS and no # configure: it clones fronteed/icheck at SRCREV c8c1af84 -- which is the 1.0.3 # tag AND the head of the branch named 1.0.3, both checked with rev-parse -- and # copies icheck.js, icheck.min.js and skins/ out of the checkout. So byte # identity with x86-64 is expected BY CONSTRUCTION and asserting it says nothing # about the compiler. What it IS a statement about is the install and packaging # path: that the payload landed in the package the image installs rather than in # a -doc or -dev package it does not, that ${datadir} resolved to /usr/share, # that nothing truncated it on the way to a virtiofs root, and that no other # recipe claims the same paths. # # TWO THIRDS OF THIS PAYLOAD IS BINARY, WHICH IS WHY THE SUMS ARE THE POINT. 66 # of the 115 files are PNG sprites. A corrupted sprite has no textual symptom at # all -- no short line, no missing name, nothing a grep would find -- so the # per-file sha256 against the x86-64 reference is the only check that would # catch it, and pngcheck below is the independent second opinion that reads them # as images rather than as bytes. # # THE RECIPE PRESERVES THE SKIN SUBDIRECTORIES, AND THAT IS WHAT MAKES THE # STYLESHEETS WORK. This is the opposite finding to its libjs-jquery-globalize # sibling, where do_install flattened two directories into one and broke the # package's own module graph. Here every skin keeps its own directory, so each # stylesheet's `url(flat.png)` and each `@import url("flat/_all.css")` resolves # against the directory it was written for: 170 active references, all 170 # resolve, and all 66 sprites are reached by one. That is asserted rather than # assumed precisely because a recipe that started globbing skins/*/* into one # directory would keep every sha256 below green while breaking every skin. # # THE PAYLOAD IS PURE ASCII AND ALMOST NONE OF IT ENDS IN A NEWLINE. Zero bytes # above 0x7f across all 49 text files, which is what keeps the LC_ALL=C byte # read-back exact; and 48 of those 49 files have no final newline (icheck.js is # the one that does). Both are upstream's shape, both are asserted as exact # counts, and both are what a transfer that re-encoded or normalised the tree on # the way to the virtiofs root would move. # # THE JAVASCRIPT IS RUN, NOT ONLY WEIGHED. duktape is on this image, so both # script files are fed to a real engine under a four-global stub and asked to # register their plugin entry point. That is a statement no byte comparison can # make -- a truncation landing on a statement boundary passes a line count and # fails here -- and it is the closest this image can get to exercising iCheck, # which past registration wants a DOM there is no browser to provide. # # WRITTEN TO EXEC AS LITTLE AS POSSIBLE -- two finds, one sha256sum, one cksum, # one pngcheck, one gawk, two duk. . "$BST_LIB" S=libjs-jquery-icheck # THE CANARY, which asserts nothing about libjs-jquery-icheck. # # 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. Same idiom and reason as 99-mailcap. # # Remove this case when linux-in-the-browser#177 is fixed. bst_ok $S/suite-canary P=/usr/share/javascript/jquery-icheck D=$BST_DATA tmp=${TMPDIR:-/tmp} W=$tmp/bst-libjs-jquery-icheck.$$ require gawk $S/gawk-present require sha256sum $S/sha256sum-present require cksum $S/cksum-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 # ------------------------------------------------------------- payload shape # One find for the whole subtree -- the inventory, the counts, the byte total, # the directory list and the per-directory census all come off it. %P keeps the # path relative to $P, so a nested directory shows up as a path with a slash in # it and the skins/ structure is CHECKED rather than assumed. That check is what # makes the reference-resolution section below a statement about the real # layout. find "$P" -mindepth 1 -printf '%P %y %s %m %l\n' 2>/dev/null | LC_ALL=C sort > "$W.inv" # One list, reused by both digest passes so they cannot disagree about WHICH # files they read. LC_ALL=C sort is what makes the reference comparison and the # first-mismatch report deterministic. find "$P" -type f 2>/dev/null | LC_ALL=C sort > "$W.list" xargs -a "$W.list" sha256sum > "$W.sums" 2>&1 xargs -a "$W.list" cksum > "$W.ck" 2>&1 find "$P" \( -name '*.css' -o -name '*.js' \) 2>/dev/null | LC_ALL=C sort > "$W.txt" LC_ALL=C gawk \ -v INV="$W.inv" -v SUMS="$W.sums" -v REF="$D/libjs-jquery-icheck.sha256" \ -v CK="$W.ck" -v PREFIX="$P" \ -f "$D/libjs-jquery-icheck-scan.awk" \ "$W.inv" "$W.sums" "$D/libjs-jquery-icheck.sha256" "$W.ck" $(cat "$W.txt") > "$W.f1" . "$W.f1" # THE SCAN RAN AT ALL. gawk is fatal on a payload file that is not there, so a # missing file kills the scanner before END and every IC_* below comes back # empty. This suite is written so that no case can be satisfied by that -- every # assertion is a count, an n/total or an exact string, and the three # empty-asserting cases (sha256-first-mismatch, readback-first-short and # css-refs-first-bad) sit behind this marker. Asserted first regardless: the failure was found by # mutation on the libjs-jquery-cookie suite (BRINTOS-1330), where three cases # went green off a scanner that never printed a line. check_eq $S/scan-ran 'ok' "$IC_SCAN" # The 122 entries the recipe's do_install produces -- 115 regular files in 7 # directories. A directory that exists and holds 114 of them is the partial # install `test -d` cannot see. There are no symlinks in this package, unlike # its libjs-jquery sibling, so a link appearing here is a recipe change. check_eq $S/payload-entries 122 "$IC_INV_N" check_eq $S/payload-files 115 "$IC_FILES" check_eq $S/payload-dirs 7 "$IC_DIRS" check_eq $S/payload-links 0 "$IC_LINKS" check_eq $S/payload-bytes 319978 "$IC_BYTES" # THE STRUCTURE, named. This is the case a recipe that flattened skins/*/* into # skins/ would redden first, and it is stated as the exact list rather than as a # count so that losing futurico/ and gaining nothing is not a wash. check_eq $S/payload-dirlist \ 'skins skins/flat skins/futurico skins/line skins/minimal skins/polaris skins/square' \ "$IC_DIRLIST" check_eq $S/payload-by-ext 'css:47 js:2 png:66' "$IC_EXT" # Files and bytes per directory. The six skins are NOT interchangeable: flat, # minimal and square ship 31 files each (a base sprite pair plus nine colours), # line ships 13 (one sprite pair shared by ten stylesheets) and futurico and # polaris ship 3. A glob that dropped one skin moves exactly one field here. check_eq $S/payload-dircensus \ 'root:2:19444 skins:1:1568 skins/flat:31:73165 skins/futurico:3:6503 skins/line:13:43365 skins/minimal:31:55274 skins/polaris:3:24620 skins/square:31:96039' \ "$IC_DIRCENSUS" # ------------------------------------------- content, against x86-64 reference # data/libjs-jquery-icheck.sha256 is the whole 115-file manifest of the upstream # icheck tree at the recipe's own SRCREV (c8c1af84, the 1.0.3 tag), extracted on # x86-64 and put through the recipe's install rules -- the upstream artifact by # its own route, not a copy of the package this image built, which would have # made the comparison tautological. All 115 sums are distinct, so no two entries # can cover for each other. check_eq $S/sha256-reference-entries 115 "$IC_REF_N" check_eq $S/sha256-target-entries 115 "$IC_SUMS_N" check_eq $S/sha256-match '115/115' "$IC_SHA_MATCH" check_eq $S/sha256-first-mismatch '' "$IC_SHA_FIRSTBAD" # Six of them written out here as well, so the manifest file is not the single # place any of this is recorded and a reviewer can check one by hand: the two # scripts, the entry stylesheet, one skin aggregate, and two sprites -- one # base, one retina -- from different skins. check_eq $S/sha256-icheck-js \ 0c37a2d3212ad01d7a0cb008dae6758785383503e2299074cea2e1bf88031921 \ "$(sha256sum "$P/icheck.js" 2>/dev/null | cut -d' ' -f1)" check_eq $S/sha256-icheck-min-js \ 68a72f76afe90409c84fca5c63e5954e370621201481103921cc80aab3452ad7 \ "$(sha256sum "$P/icheck.min.js" 2>/dev/null | cut -d' ' -f1)" check_eq $S/sha256-skins-all-css \ 292fca03a97afd382299c051a1b157d3bccee0b0236004ab5df17bf531419354 \ "$(sha256sum "$P/skins/all.css" 2>/dev/null | cut -d' ' -f1)" check_eq $S/sha256-flat-all-css \ 4e5095e2922c6059511cd34ac2d6cb0537fb5e302bc2263928f9ae791222cb25 \ "$(sha256sum "$P/skins/flat/_all.css" 2>/dev/null | cut -d' ' -f1)" check_eq $S/sha256-flat-png \ 649617bbce32ff4e0a8343c6f011a17116e86b13c50c1d9bfa92c0ee20605bec \ "$(sha256sum "$P/skins/flat/flat.png" 2>/dev/null | cut -d' ' -f1)" check_eq $S/sha256-square-2x-png \ 8ed64c959db4f6f50081d5de7430983af90c88ef10abd334b2b53f9a61424b9d \ "$(sha256sum "$P/skins/square/square@2x.png" 2>/dev/null | cut -d' ' -f1)" # ------------------------------------------------ read back through the target # An INDEPENDENT way of saying the files are complete: cksum reads all 115 files # with a different algorithm and a different reader from sha256sum's, and it # reports a LENGTH per file -- so a short read is localised to the file it # happened in rather than merely detected across the set. Compared against # find's own %s, which came from stat(2) and not from reading the file at all. check_eq $S/readback-entries 115 "$IC_CK_N" check_eq $S/readback-bytes 319978 "$IC_CK_BYTES" check_eq $S/readback-first-short '' "$IC_CK_FIRSTBAD" # The 49 text files through gawk's reader as well, which is a third one. 5540 # records against 150,717 bytes; the 48-file no-final-newline count is what # makes those two numbers consistent, and it is upstream's shape rather than an # artifact of the transfer. check_eq $S/readback-text-records 5540 "$IC_TXT_LINES" check_eq $S/readback-text-bytes 150717 "$IC_TXT_BYTES" check_eq $S/text-no-final-newline 48 "$IC_TXT_NO_FINAL_NL" # Pure ASCII, asserted as zero. Unlike libjs-jquery-globalize (75 bytes above # 0x7f) and like libjs-jquery-cookie, nothing in this payload's text needs more # than seven bits -- which is what makes the LC_ALL=C byte read-back above exact. check_eq $S/text-high-bytes 0 "$IC_HI" # --------------------------------------------------- stylesheet asset graph # THE REAL STATEMENT ABOUT THE INSTALL LAYOUT, and the one thing here that is # not a byte count. Every url() reference in the 47 stylesheets is resolved # against the directory of the file that names it -- the sprite references # `url(flat.png)` inside each skin, and the `@import url("flat/_all.css")` chain # out of skins/all.css. All 170 active references resolve, and every one of the # 66 sprites is reached by at least one of them, because the recipe preserved # the skin directories. # # Reported as counts and as n/total rather than as a list of failures: a # POSITIVE value cannot be satisfied by an unset variable, which is what a # scanner that died hands back. check_eq $S/css-refs 170 "$IC_URL_ACTIVE" check_eq $S/css-refs-resolve '170/170' "$IC_URL_RESOLVED" check_eq $S/css-refs-first-bad '' "$IC_URL_FIRSTBAD" check_eq $S/sprites 66 "$IC_PNG_N" check_eq $S/sprites-referenced '66/66' "$IC_PNG_REFD" # skins/all.css carries a further 40 @import lines COMMENTED OUT -- the # à-la-carte alternative to the four _all.css aggregates it does import. They # are counted separately and asserted to be resolvable too, so that a recipe # change which dropped the per-colour stylesheets would be visible here even # though nothing active references them. check_eq $S/css-refs-commented 40 "$IC_URL_COMMENTED" check_eq $S/css-refs-commented-resolve '40/40' "$IC_URL_COMMENTED_RESOLVED" # ------------------------------------------------------------------ version # READ OUT OF THE PAYLOAD'S OWN BANNERS, not off a path or a package name. Both # scripts banner "iCheck v1.0.3" and "(c) 2013 Damir Sultanov" -- the second of # which is the two-line block LIC_FILES_CHKSUM pins -- and all 47 stylesheets # carry an "iCheck plugin" banner. The negative is what makes this a VERSION # assertion rather than a line count: no file may banner 1.0.2 or earlier, so a # 1.0.2 payload dropped in under the same name fails here while passing every # structural count above. check_eq $S/version-banner-js 2 "$IC_V_JS" check_eq $S/copyright-files 2 "$IC_V_AUTH" check_eq $S/css-banner-files 47 "$IC_CSS_BANNER" check_eq $S/version-pre-1-0-3 0 "$IC_V_OLD" # ------------------------------------------------------------- the sprites # THE SECOND OPINION ON THE BINARY TWO THIRDS, from a decoder rather than a # hash. pngcheck walks each file's chunk structure and verifies every CRC, so it # fails on a corruption the sha256 comparison would also catch -- and, unlike # that comparison, it does not depend on the reference manifest being right. One # exec for all 66. Skipped rather than failed where pngcheck is not on the # image, since it is not this package's dependency. if command -v pngcheck >/dev/null 2>&1; then pngout=$(find "$P" -name '*.png' 2>/dev/null | LC_ALL=C sort | xargs pngcheck -q 2>&1) pngrc=$? if [ "$pngrc" -eq 0 ] && [ -z "$pngout" ]; then bst_ok $S/sprites-decode else bst_notok $S/sprites-decode "rc=$pngrc $(_bst_1line "$pngout")"; fi else bst_skip $S/sprites-decode "pngcheck not on this image" fi # --------------------------------------------------------- the javascript # RUN, NOT WEIGHED. Both scripts are concatenated behind data/…-stub.js (which # supplies the four globals iCheck reads at module scope) and ahead of a # __ICHECK_REPORT() call, then handed to duk. A parse error, a truncation that # landed on a statement boundary, or a registration that silently did not happen # all show up here and nowhere else in this suite. # # The concatenation is how the payload reaches the engine at all: duk's command # line takes a script path and offers no file-reading API to a script, so a # harness that wanted to read icheck.js at runtime could not. It also keeps the # rootfs read-only-safe -- everything written lands under $tmp. if command -v duk >/dev/null 2>&1; then for c in full min; do case $c in full) j=icheck.js ;; min) j=icheck.min.js ;; esac cat "$D/libjs-jquery-icheck-stub.js" "$P/$j" > "$W.$c" 2>/dev/null printf '\n__ICHECK_REPORT();\n' >> "$W.$c" out=$(duk "$W.$c" 2>&1); rc=$? case "$out" in *R-ICHECK-OK*) ran=1 ;; *) ran=0 ;; esac if [ "$rc" -eq 0 ] && [ "$ran" -eq 1 ]; then bst_ok $S/js-$c-runs else bst_notok $S/js-$c-runs "rc=$rc $(_bst_1line "$out")"; fi check_eq $S/js-$c-registers function \ "$(printf '%s\n' "$out" | awk '/^R-ICHECK-TYPE/{print $2}')" # iCheck's entry point is $.fn.iCheck(options, fire) -- two declared # parameters, and it is the ONLY name the plugin adds to $.fn. check_eq $S/js-$c-arity 2 \ "$(printf '%s\n' "$out" | awk '/^R-ICHECK-ARITY/{print $2}')" check_eq $S/js-$c-fn-keys 1 \ "$(printf '%s\n' "$out" | awk '/^R-ICHECK-FNKEYS/{print $2}')" rm -f "$W.$c" done else bst_skip $S/js-runs "duk not on this image" fi # ----------------------------------------------------------------- packaging # THE EXPECTATION IS DERIVED, NOT WRITTEN DOWN. This recipe installs nothing to # ${docdir} at all -- README.md, CHANGELOG.md, bower.json, icheck.jquery.json # and demo/ are left in the checkout -- so no -doc package is even produced, and # the build's own output confirms it: three .debs (libjs-jquery-icheck at 167 kB # carrying the whole payload, -dev and -dbg both EMPTY) and no -doc among them. # Stated in the direction that fails if the javascript ever lands under # ${docdir} instead, which is exactly the packaging mistake this port had to # check for. if [ -d /usr/share/doc/libjs-jquery-icheck ]; then bst_notok $S/doc-not-installed \ "/usr/share/doc/libjs-jquery-icheck exists; this recipe installs no docs" else bst_ok $S/doc-not-installed fi # THE INSTALL RULES, read back off the target. do_install uses `install -d` and # `install -m 0644` throughout, so every one of the 115 files must be 0644 and # every one of the 7 directories 0755. This is the case that notices a recipe # which started copying with cp -a, or an image build that ran under a umask # that leaked into the payload -- neither of which moves a single sha256. check_eq $S/file-modes '644:115' "$IC_FILE_MODES" check_eq $S/dir-modes '755:7' "$IC_DIR_MODES" rm -f "$W.inv" "$W.list" "$W.sums" "$W.ck" "$W.txt" "$W.f1"