run.sh (4615B)
1 #!/usr/bin/env bash 2 # test/pp/run.sh — data-driven preprocessor golden-diff runner, on the shared 3 # corpus harness (test/lib/kit_corpus.sh). Single positive lane. 4 # 5 # For each test/pp/cases/*.c, runs `kit cc -E` (with -I pointing at the cases 6 # dir so sibling headers resolve) and diffs the output against the matching 7 # .expected file. Leaves <name>.actual files behind in the cases dir on failure 8 # so they can be reviewed and copied over the expected baseline once intentional 9 # output changes are validated. 10 # 11 # To make __DATE__/__TIME__/__FILE__ deterministic across runs and checkouts, 12 # the runner: 13 # - exports SOURCE_DATE_EPOCH=0 (1970-01-01T00:00:00Z), which fixes __DATE__ 14 # to "Jan 1 1970" and __TIME__ to "00:00:00"; 15 # - cd's into the cases dir and uses bare basenames as the corpus glob, so the 16 # source path the preprocessor sees (and thus __FILE__) is the file name 17 # itself with no checkout-path prefix. 18 # 19 # Oracle (lane P): kit cc -E must succeed and its output, normalized to a 20 # token sequence (any run of whitespace incl. newlines collapses to one space; 21 # leading/trailing whitespace stripped), must equal the .expected file similarly 22 # normalized. Line-position preservation, leading-space padding before 23 # macro-expanded `#`, and embed-induced reflow are downstream/cosmetic concerns; 24 # this runner checks only the token sequence (matching the original harness). 25 # 26 # No opt axis. Honors $KIT for the binary path; defaults to build/kit. 27 # 28 # Filtering: ./run.sh [name_filter] (or KIT_TEST_FILTER); substring match 29 # against case basename. 30 # 31 # Parallelism: parallel by default (capped CPU-count); KIT_TEST_JOBS=N caps 32 # concurrency; KIT_PP_PARALLEL=0 forces serial. The lane hook reads/writes the 33 # per-case .expected/.actual next to the case (distinct path per case) and keeps 34 # all scratch under $KIT_WORK, so the summary is identical serial or parallel. 35 36 set -u 37 38 script_dir=$(cd "$(dirname "$0")" && pwd) 39 repo_root=$(cd "$script_dir/../.." && pwd) 40 cases_dir="$script_dir/cases" 41 42 export KIT_LIB_DIR="$repo_root/test/lib" 43 # shellcheck source=../lib/kit_corpus.sh 44 . "$repo_root/test/lib/kit_corpus.sh" 45 46 KIT="${KIT:-$repo_root/build/kit}" 47 48 if [ ! -x "$KIT" ]; then 49 echo "pp: kit binary not found at $KIT" >&2 50 exit 2 51 fi 52 53 # Reproducible-builds: pin __DATE__ and __TIME__ to the Unix epoch. 54 export SOURCE_DATE_EPOCH=0 55 56 # cd into the cases dir so the corpus glob yields bare basenames: the path the 57 # preprocessor sees becomes the file name itself (deterministic __FILE__), and 58 # the .expected/.actual sidecars resolve relative to the same dir. 59 cd "$cases_dir" || exit 2 60 61 BUILD_DIR="$repo_root/build/test/pp" 62 mkdir -p "$BUILD_DIR" 63 64 FILTER="${1:-${KIT_TEST_FILTER:-}}" 65 export KIT_TEST_FILTER="$FILTER" 66 67 # ----- positive lane P: cc -E + normalized golden diff ---------------------- 68 # KIT_SRC is a bare basename (cwd == cases dir); the .expected/.actual sidecars 69 # live alongside it. Scratch (the two normalized token streams) stays in 70 # $KIT_WORK; the reviewable .actual is left in the cases dir on failure, as the 71 # original harness did (a deliberate baseline-update workflow aid). 72 kit_lane_P() { 73 local name="$KIT_BASE" 74 local expected="$KIT_BASE.expected" 75 local actual="$KIT_BASE.actual" 76 77 if [ ! -e "$expected" ]; then 78 kit_fail "$name" "missing $expected" 79 return 80 fi 81 82 if ! "$KIT" cc -E -I . "$KIT_SRC" -o "$actual" >"$KIT_WORK/pp.out" 2>"$KIT_WORK/pp.err"; then 83 kit_fail "$name" "kit exit nonzero; see $actual" 84 return 85 fi 86 87 # Compare token sequences only — collapse every run of whitespace 88 # (including newlines) to a single space, strip leading/trailing space. 89 local exp_strip="$KIT_WORK/exp.strip" 90 local act_strip="$KIT_WORK/act.strip" 91 tr '\n' ' ' < "$expected" | tr -s '[:space:]' ' ' \ 92 | sed -e 's/^ //' -e 's/ $//' > "$exp_strip" || true 93 tr '\n' ' ' < "$actual" | tr -s '[:space:]' ' ' \ 94 | sed -e 's/^ //' -e 's/ $//' > "$act_strip" || true 95 96 if diff -u "$exp_strip" "$act_strip" >/dev/null 2>&1; then 97 kit_pass "$name" 98 rm -f "$actual" 99 else 100 kit_fail "$name" 101 diff -u "$exp_strip" "$act_strip" | sed 's/^/ | /' || true 102 fi 103 } 104 105 # ----- drive the corpus ----------------------------------------------------- 106 107 PAR="${KIT_PP_PARALLEL:-1}" 108 109 KIT_LABEL=test-pp-ok KIT_BUILD_DIR="$BUILD_DIR/cases" \ 110 KIT_CORPUS_GLOBS="*.c" KIT_CORPUS_EXT=c KIT_SIDECAR_DIR="$cases_dir" \ 111 KIT_LANES="P" KIT_OPT_LEVELS="" KIT_TUPLES="none-none" KIT_TARGETS_EXT="" \ 112 KIT_PARALLELIZABLE="$PAR" kit_corpus_run 113 114 kit_summary test-pp-ok 115 kit_exit