kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

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