# BST-TIMEOUT: 900 # ~35 rpcgen runs, each forking the shim preprocessor . "$BST_LIB" require rpcgen rpcsvc-proto/present S=rpcsvc-proto CTL=$BST_DATA/rpcsvc-native.txt INC=/usr/include/rpcsvc # The 11 protocol definitions the image ships. rquota.[hx] is not among them: # poky's do_install:append removes it because the quota recipe owns that name. SHIPPED="bootparam_prot key_prot klm_prot mount nfs_prot nlm_prot rex rstat rusers sm_inter spray" D=${TMPDIR:-/tmp}/bst-rpcsvc.$$ rm -rf "$D" if ! mkdir -p "$D/shim" "$D/gen"; then bst_notok $S/workdir "cannot create $D" exit 0 fi trap 'cd /; rm -rf "$D"' EXIT INT TERM if [ ! -s "$CTL" ]; then bst_notok $S/control "$CTL missing or empty -- nothing to compare against" exit 0 fi # Pull one control section out of rpcsvc-native.txt. sect() { awk -v s="@@@@RPCSVC-NATIVE $1@@@@" ' $0 == s { on = 1; next } /^@@@@RPCSVC-NATIVE / { if (on) exit } on { print } ' "$CTL" } # cmp_ctl
cmp_ctl() { sect "$2" > "$D/expect.out" if [ ! -s "$D/expect.out" ]; then bst_notok "$S/$1" "no control section '$2' in rpcsvc-native.txt" elif [ ! -f "$3" ]; then bst_notok "$S/$1" "rpcgen produced no $3" elif cmp -s "$D/expect.out" "$3"; then bst_ok "$S/$1" else bst_notok "$S/$1" "differs from x86_64 control: $(_bst_1line "$(diff "$D/expect.out" "$3" | head -4)")" fi } # --- the stand-in preprocessor ----------------------------------------------- # rpcgen forks `cpp -C -D ` once per generation pass, and this image # ships no C preprocessor, so every generation below goes through -Y and the # shim. The shim covers exactly the directives the rpcsvc .x files use and # refuses anything else, so an unhandled directive is a visible failure rather # than a silently wrong header. The x86_64 control is generated through the same # shim, so any difference below is the target's. cp "$BST_DATA/rpcsvc-cpp.sh" "$D/shim/cpp" chmod 755 "$D/shim/cpp" check_out $S/shim-runs "PROBE_MAXNAME" "$D/shim/cpp" -C -DRPC_HDR "$BST_DATA/rpcsvc-probe.x" # --- what shipped ------------------------------------------------------------ check_eq $S/rpcgen-path /usr/bin/rpcgen "$(command -v rpcgen)" check_out $S/version "rpcgen (rpcsvc-proto) 1.4.4" rpcgen --version check $S/incdir test -d "$INC" want_x=""; want_h="" for b in $SHIPPED; do want_x="$want_x$b.x " want_h="$want_h$b.h " done check_eq $S/x-list "$want_x" "$(ls "$INC" 2>/dev/null | grep '\.x$' | sort | tr '\n' ' ')" check_eq $S/h-list "$want_h" "$(ls "$INC" 2>/dev/null | grep '\.h$' | sort | tr '\n' ' ')" if [ -e "$INC/rquota.x" ] || [ -e "$INC/rquota.h" ]; then bst_notok $S/rquota-absent "rquota.[hx] present -- the recipe's do_install:append no longer removes it" else bst_ok $S/rquota-absent fi # The .x definitions and the headers the cross build generated from them, byte # for byte against an x86_64 build of the same commit. This is the half of the # port that is data rather than behaviour: if a header the image ships differs # from what the same rpcgen produces on a machine known to work, the cross # generation is wrong however well rpcgen itself then runs on target. sect md5/installed > "$D/md5.txt" for b in $SHIPPED; do for e in x h; do want=$(awk -v n="$b.$e" '$2 == n { print $1 }' "$D/md5.txt") got=$(md5sum "$INC/$b.$e" 2>/dev/null | cut -d' ' -f1) if [ -z "$want" ]; then bst_notok "$S/installed-$b.$e" "no md5 for $b.$e in the control" else check_eq "$S/installed-$b.$e" "$want" "$got" fi done done # --- rpcgen's error paths ---------------------------------------------------- rpcgen >/dev/null 2>"$D/usage.txt"; rc=$? if [ "$rc" -eq 1 ] && grep -q '^usage:' "$D/usage.txt"; then bst_ok $S/usage-no-args else bst_notok $S/usage-no-args "rc=$rc $(_bst_1line "$(cat "$D/usage.txt")")" fi # This image has no C preprocessor at all, which is why -Y is not optional here. # Asserted rather than assumed: the case below only means what it says while # both of these are absent. if command -v cpp >/dev/null 2>&1 || [ -x /lib/cpp ]; then bst_notok $S/no-cpp-on-image "a cpp is present -- rpcgen's -Y requirement below no longer holds" else bst_ok $S/no-cpp-on-image fi cd "$D/gen" || { bst_notok $S/workdir "cannot cd $D/gen"; exit 0; } cp "$BST_DATA/rpcsvc-probe.x" rpcsvc-probe.x out=$(rpcgen -h -o nocpp.h rpcsvc-probe.x 2>&1); rc=$? case "$out" in *"cannot find C preprocessor"*) hit=1 ;; *) hit=0 ;; esac if [ "$rc" -ne 0 ] && [ "$hit" -eq 1 ]; then bst_ok $S/no-cpp else bst_notok $S/no-cpp "rc=$rc want the missing-cpp diagnostic, got:'$(_bst_1line "$out")'" fi out=$(rpcgen -Y "$D/nonesuch" -h -o badY.h rpcsvc-probe.x 2>&1); rc=$? case "$out" in *"cannot find C preprocessor: $D/nonesuch/cpp"*) hit=1 ;; *) hit=0 ;; esac if [ "$rc" -ne 0 ] && [ "$hit" -eq 1 ]; then bst_ok $S/bad-cpp-dir else bst_notok $S/bad-cpp-dir "rc=$rc got:'$(_bst_1line "$out")'" fi printf 'struct broken {\n\tint ;\n' > bad.x out=$(rpcgen -Y "$D/shim" -h -o bad.h bad.x 2>&1); rc=$? case "$out" in *"expected"*) hit=1 ;; *) hit=0 ;; esac if [ "$rc" -ne 0 ] && [ "$hit" -eq 1 ]; then bst_ok $S/parse-error else bst_notok $S/parse-error "rc=$rc got:'$(_bst_1line "$out")'" fi printf '#include \nconst A = 1;\n' > directive.x out=$(rpcgen -Y "$D/shim" -h -o directive.h directive.x 2>&1); rc=$? case "$out" in *"unsupported directive"*) hit=1 ;; *) hit=0 ;; esac if [ "$rc" -ne 0 ] && [ "$hit" -eq 1 ]; then bst_ok $S/shim-refuses-unknown else bst_notok $S/shim-refuses-unknown "rc=$rc got:'$(_bst_1line "$out")'" fi # --- generate every artifact rpcgen knows how to write ----------------------- for m in h c l m t Sc Ss; do rm -f "out.$m" rpcgen -Y "$D/shim" "-$m" -o "out.$m" rpcsvc-probe.x >"$D/gen.log" 2>&1 || bst_notok "$S/run-$m" "rc=$? $(_bst_1line "$(cat "$D/gen.log")")" done rm -f out.Nh out.Nc out.Mh out.Th out.Sm rpcgen -Y "$D/shim" -N -h -o out.Nh rpcsvc-probe.x >"$D/gen.log" 2>&1 || bst_notok "$S/run-Nh" "$(_bst_1line "$(cat "$D/gen.log")")" rpcgen -Y "$D/shim" -N -c -o out.Nc rpcsvc-probe.x >"$D/gen.log" 2>&1 || bst_notok "$S/run-Nc" "$(_bst_1line "$(cat "$D/gen.log")")" rpcgen -Y "$D/shim" -M -h -o out.Mh rpcsvc-probe.x >"$D/gen.log" 2>&1 || bst_notok "$S/run-Mh" "$(_bst_1line "$(cat "$D/gen.log")")" rpcgen -Y "$D/shim" -T -h -o out.Th rpcsvc-probe.x >"$D/gen.log" 2>&1 || bst_notok "$S/run-Th" "$(_bst_1line "$(cat "$D/gen.log")")" rpcgen -Y "$D/shim" -Sm rpcsvc-probe.x > out.Sm 2>"$D/gen.log" || bst_notok "$S/run-Sm" "$(_bst_1line "$(cat "$D/gen.log")")" for m in h c l m t Sc Ss Sm Nh Nc Mh Th; do cmp_ctl "gen-$m" "probe/out.$m" "out.$m" done # rpcgen refuses to clobber an output it did not just create; with no tty to # answer its prompt that is an exit 1, which is why every generation above # removes its target first. out=$(rpcgen -Y "$D/shim" -h -o out.h rpcsvc-probe.x 2>&1); rc=$? case "$out" in *"already exists"*) hit=1 ;; *) hit=0 ;; esac if [ "$rc" -ne 0 ] && [ "$hit" -eq 1 ]; then bst_ok $S/no-clobber else bst_notok $S/no-clobber "rc=$rc got:'$(_bst_1line "$out")'" fi # --- what the generated code says, independent of the control ---------------- # The comparisons above go red as one block if anything at all shifts. These # name the things a reader would want to know are right, so a red control still # says what survived. check_out $S/landmark-prog "#define PROBE_PROG 0x20000199" cat out.h check_out $S/landmark-vers2 "#define PROBE_VERS2 2" cat out.h check_out $S/landmark-enum "enum probe_kind {" cat out.h check_out $S/landmark-hyper "quad_t big;" cat out.h check_out $S/landmark-xdr-decl "extern bool_t xdr_probe_chain (XDR *, probe_chain*);" cat out.h check_out $S/landmark-xdr-str "xdr_string (xdrs, objp, PROBE_MAXNAME)" cat out.c check_out $S/landmark-xdr-ptr "xdr_pointer (xdrs, (char **)&objp->next" cat out.c check_out $S/landmark-xdr-var "xdr_bytes (xdrs," cat out.c check_out $S/landmark-clnt "clnt_call (clnt, PROBE_ECHO," cat out.l check_out $S/landmark-svc "probe_prog_1(struct svc_req *rqstp" cat out.m check_out $S/landmark-table "struct rpcgen_table probe_prog_1_table[]" cat out.t check_out $S/landmark-sample "probe_prog_1(char *host)" cat out.Sc # --- regenerate every shipped definition ------------------------------------- # nfs_prot.x alone is 1.4k lines of XDR, so this is the parser's real workout; # key_prot.x, nlm_prot.x, rstat.x and rusers.x additionally carry #ifdef blocks, # which is what the shim is there to resolve. for b in $SHIPPED; do cp "$INC/$b.x" "$b.x" 2>/dev/null rm -f "$b.h" rpcgen -Y "$D/shim" -h -o "$b.h" "$b.x" >"$D/regen.log" 2>&1 || bst_notok "$S/run-$b" "rc=$? $(_bst_1line "$(cat "$D/regen.log")")" cmp_ctl "regen-$b" "rpcsvc/$b.h" "$b.h" done check_out $S/nfs-program "#define NFS_PROGRAM 100003" cat nfs_prot.h check_out $S/mount-prog "#define MOUNTPROG 100005" cat mount.h cd / rm -rf "$D"