run.sh (6030B)
1 #!/bin/sh 2 # Driver-level checks for `kit make`. 3 # Self-checking (no golden files): each case builds a fixture makefile in a 4 # fresh work dir, runs `kit make`, and asserts exit status and output/artifacts 5 # via the shared kit_* verbs (ok/not_ok) recorded over $work. 6 7 set -u 8 9 script_dir=$(cd "$(dirname "$0")" && pwd) 10 repo_root=$(cd "$script_dir/../.." && pwd) 11 12 KIT="${KIT:-$repo_root/build/kit}" 13 14 if [ ! -x "$KIT" ]; then 15 echo "make: kit binary not found at $KIT" >&2 16 exit 2 17 fi 18 19 work=$(mktemp -d "${TMPDIR:-/tmp}/kit-make-test.XXXXXX") 20 trap 'rm -rf "$work"' EXIT 21 22 KIT_KIT_DIR="$repo_root/test/lib" 23 . "$repo_root/test/lib/kit_sh_kit.sh" 24 kit_report_init 25 26 n=0 27 # fresh_dir: make a new numbered case directory and echo its path. 28 fresh_dir() { 29 n=$((n + 1)) 30 d="$work/case$n" 31 mkdir -p "$d" 32 echo "$d" 33 } 34 35 # expect_status WANT NAME DIR ARGS...: run `kit make ARGS` in DIR, assert exit. 36 expect_status() { 37 es_want=$1; es_name=$2; es_dir=$3; shift 3 38 ( cd "$es_dir" && "$KIT" make "$@" ) > "$es_dir/out" 2> "$es_dir/err" 39 es_got=$? 40 if [ "$es_got" -eq "$es_want" ]; then 41 ok "$es_name" 42 else 43 { printf 'wanted exit %s, got %s\n' "$es_want" "$es_got"; cat "$es_dir/err"; } \ 44 > "$es_dir/diag" 45 not_ok "$es_name" "$es_dir/diag" 46 fi 47 } 48 49 # assert_contains NAME FILE NEEDLE 50 assert_contains() { 51 if grep -q -- "$3" "$2" 2>/dev/null; then 52 ok "$1" 53 else 54 { printf 'expected to find: %s\nin:\n' "$3"; cat "$2"; } > "$work/c.diag" 55 not_ok "$1" "$work/c.diag" 56 fi 57 } 58 59 # ---- 1. basic build: prerequisite ordering + recipe execution ------------- 60 d=$(fresh_dir) 61 cat > "$d/Makefile" <<'EOF' 62 all: out.txt 63 out.txt: in.txt 64 printf 'built\n' > out.txt 65 cat in.txt >> out.txt 66 in.txt: 67 printf 'src\n' > in.txt 68 EOF 69 expect_status 0 build_ok "$d" 70 assert_contains build_made_out "$d/out.txt" built 71 assert_contains build_made_dep "$d/out.txt" src 72 73 # ---- 2. up-to-date short-circuit ------------------------------------------ 74 expect_status 0 uptodate "$d" 75 assert_contains uptodate_msg "$d/out" "up to date\|nothing to be done" 76 77 # ---- 3. dry run (-n): echoes recipes, runs nothing ------------------------ 78 d=$(fresh_dir) 79 cat > "$d/Makefile" <<'EOF' 80 t: 81 printf 'ran\n' > witness 82 EOF 83 expect_status 0 dryrun "$d" -n t 84 if [ -e "$d/witness" ]; then not_ok dryrun_noop "$d/out"; else ok dryrun_noop; fi 85 86 # ---- 4. print database (-p) ----------------------------------------------- 87 d=$(fresh_dir) 88 cat > "$d/Makefile" <<'EOF' 89 FOO = barval 90 t: ; @true 91 EOF 92 expect_status 0 printdb "$d" -p 93 assert_contains printdb_macro "$d/out" 'FOO = barval' 94 95 # ---- 5. macros: =, :=, != and command-line override ----------------------- 96 d=$(fresh_dir) 97 cat > "$d/Makefile" <<'EOF' 98 NAME = default 99 CAP != printf 'captured' 100 show: 101 @printf 'name=%s cap=%s\n' "$(NAME)" "$(CAP)" 102 EOF 103 expect_status 0 macro_run "$d" show NAME=override 104 assert_contains macro_override "$d/out" 'name=override' 105 assert_contains macro_capture "$d/out" 'cap=captured' 106 107 # ---- 6. include directive ------------------------------------------------- 108 d=$(fresh_dir) 109 printf 'INCVAR = included\n' > "$d/conf.mk" 110 cat > "$d/Makefile" <<'EOF' 111 include conf.mk 112 show: 113 @printf '[%s]\n' "$(INCVAR)" 114 EOF 115 expect_status 0 include_run "$d" show 116 assert_contains include_val "$d/out" '\[included\]' 117 118 # ---- 7. inference rule (.c.o) --------------------------------------------- 119 d=$(fresh_dir) 120 printf 'int f(void){return 0;}\n' > "$d/u.c" 121 cat > "$d/Makefile" <<'EOF' 122 CFLAGS = -O0 123 u.o: u.c 124 EOF 125 expect_status 0 inference "$d" u.o 126 if [ -e "$d/u.o" ]; then ok inference_artifact; else not_ok inference_artifact "$d/err"; fi 127 128 # ---- 8. failing recipe -> exit 2 ------------------------------------------ 129 d=$(fresh_dir) 130 cat > "$d/Makefile" <<'EOF' 131 bad: ; false 132 EOF 133 expect_status 2 fail_exit "$d" bad 134 135 # ---- 9. -k keeps going, still fails --------------------------------------- 136 d=$(fresh_dir) 137 cat > "$d/Makefile" <<'EOF' 138 all: a b 139 a: ; @false 140 b: ; @printf 'b-ran\n' > witness 141 EOF 142 expect_status 1 keepgoing "$d" -k all 143 if [ -e "$d/witness" ]; then ok keepgoing_ran_b; else not_ok keepgoing_ran_b "$d/err"; fi 144 145 # ---- 10. --posix injects `set -e` ----------------------------------------- 146 d=$(fresh_dir) 147 cat > "$d/Makefile" <<'EOF' 148 t: 149 printf 'before\n'; false; printf 'after\n' 150 EOF 151 expect_status 2 posix_seterr "$d" --posix t 152 # `after` also appears in the echoed recipe line, so match a whole output line: 153 # with set -e the second printf must not run, so no line is exactly "after". 154 if grep -qx after "$d/out"; then not_ok posix_stops "$d/out"; else ok posix_stops; fi 155 156 # ---- 11. -q question mode: stale -> exit 1 -------------------------------- 157 d=$(fresh_dir) 158 cat > "$d/Makefile" <<'EOF' 159 out: src 160 cp src out 161 src: 162 printf 'x\n' > src 163 EOF 164 expect_status 1 question_stale "$d" -q out 165 166 # ---- 12. bad usage -> exit 2 ---------------------------------------------- 167 d=$(fresh_dir) 168 : > "$d/Makefile" 169 expect_status 2 unknown_opt "$d" -Z 170 171 # ---- 13. $(shell ...) function (incl. nested macro) ----------------------- 172 d=$(fresh_dir) 173 printf 'W = world\nOUT := $(shell echo hello-$(W))\nt:\n\t@echo "[$(OUT)]"\n' \ 174 > "$d/Makefile" 175 expect_status 0 shell_func "$d" t 176 assert_contains shell_func_val "$d/out" '\[hello-world\]' 177 178 # ---- 14. -C builds in the target dir without chdir'ing -------------------- 179 d=$(fresh_dir) 180 mkdir -p "$d/sub" 181 printf 'out.txt:\n\tprintf done > out.txt\n' > "$d/sub/Makefile" 182 expect_status 0 dashC "$d" -C sub 183 if [ -e "$d/sub/out.txt" ]; then ok dashC_artifact; else not_ok dashC_artifact "$d/err"; fi 184 185 # ---- 15. MAKEFLAGS: recursive make inherits flags + macros ---------------- 186 d=$(fresh_dir) 187 printf 'all:\n\t@$(MAKE) -f inner.mk child\n' > "$d/Makefile" 188 printf 'child:\n\t@echo "mf=[$(MAKEFLAGS)] v=[$(V)]"\n' > "$d/inner.mk" 189 ( cd "$d" && MAKE="$KIT make" "$KIT" make -k V=xyz all ) > "$d/out" 2> "$d/err" 190 if [ $? -eq 0 ]; then ok makeflags_run; else not_ok makeflags_run "$d/err"; fi 191 assert_contains makeflags_flag "$d/out" 'mf=\[.*-k' 192 assert_contains makeflags_macro "$d/out" 'v=\[xyz\]' 193 194 kit_summary make-driver 195 kit_exit