#!/bin/sh # M2make regression tests. Builds M2make with both compilers (via the # sibling build scripts) and exercises ordering, up-to-date checks, # rebuilds, cycles, and real builds. # Usage: ./run_tests.sh (from the tools/m2make directory) pass=0; fail=0 ok() { pass=$((pass+1)); echo "PASS: $1"; } no() { fail=$((fail+1)); echo "FAIL: $1"; } # --- bootstrapping: both compilers must build M2make --- ./build_gm2.sh > /tmp/m2make_t.log 2>&1 if [ -x b_gm2/M2make ]; then ok "gm2 builds M2make"; else no "gm2 builds M2make"; fi ./build_m2.sh > /tmp/m2make_t.log 2>&1 if [ -x b_v3/M2make ]; then ok "M2 builds M2make"; else no "M2 builds M2make"; fi GM2=b_gm2/M2make V3M=b_v3/M2make # --- dry-run ordering (both binaries must agree) --- for bin in "$GM2" "$V3M"; do out=$($bin -n -c gm2 tests/Main2.mod 2>&1) calc_line=$(printf '%s\n' "$out" | grep -n "Calc :" | cut -d: -f1) main_line=$(printf '%s\n' "$out" | grep -n "M2makeMain" | cut -d: -f1) if [ -n "$calc_line" ] && [ -n "$main_line" ] && [ "$calc_line" -lt "$main_line" ]; then ok "$bin order (Calc before Main2)" else no "$bin order (Calc before Main2): $out" fi case "$out" in *"Add"*) no "$bin leaks FROM-items as modules: $out" ;; *) ok "$bin ignores FROM-items" ;; esac done # --- cycle detection --- for bin in "$GM2" "$V3M"; do out=$($bin -n -c gm2 tests/CycA.mod 2>&1); rc=$? case "$out" in *"cyclic import"*) ok "$bin reports cycle" ;; *) no "$bin reports cycle: $out" ;; esac if [ "$rc" = "1" ]; then ok "$bin cycle exit code 1"; else no "$bin cycle exit code ($rc)"; fi done # --- real gm2 build, run, up-to-date, rebuild --- rm -f Main2 *.o if $GM2 -c gm2 -o Main2 tests/Main2.mod > /tmp/m2make_t.log 2>&1; then ok "gm2-mode real build" else no "gm2-mode real build" fi if [ "$(./Main2 2>/dev/null)" = "ok42" ]; then ok "gm2-built program runs (ok42)" else no "gm2-built program runs" fi out=$($GM2 -c gm2 -o Main2 tests/Main2.mod 2>&1) case "$out" in *"up to date"*) ok "gm2-mode up-to-date skip" ;; *) no "gm2-mode up-to-date skip: $out" ;; esac sleep 1 touch tests/Calc.mod out=$($GM2 -c gm2 -o Main2 tests/Main2.mod 2>&1) case "$out" in *"-c tests/Calc.mod"*) ok "gm2-mode recompiles touched dep" ;; *) no "gm2-mode recompiles touched dep: $out" ;; esac touch tests/Calc.def tests/Calc.mod tests/Main2.mod # --- real m2 build via the V3-built M2make --- rm -rf gen_ssa Main m2make.log if $V3M -c m2 --m2bin ../../compiler/M2 --shim ../../runtime/syslib/shim.c \ -I ../../lib/common -o Main tests/Main.mod > /tmp/m2make_t.log 2>&1; then ok "m2-mode real build (V3 M2make)" else no "m2-mode real build (V3 M2make)" fi if ./Main 2>/dev/null | grep -q "42"; then ok "m2-built program runs (42)" else no "m2-built program runs" fi out=$($V3M -c m2 --m2bin ../../compiler/M2 --shim ../../runtime/syslib/shim.c \ -I ../../lib/common -o Main tests/Main.mod 2>&1) case "$out" in *"up to date"*) ok "m2-mode up-to-date skip" ;; *) no "m2-mode up-to-date skip: $out" ;; esac # --- separate-object build, up-to-date, incremental relink --- rm -rf gen_ssa SepMain m2make.log if $V3M --separate -c m2 --m2bin ../../compiler/M2 --shim ../../runtime/syslib/shim.c \ -I ../../lib/common -o SepMain tests/Main.mod > /tmp/m2make_t.log 2>&1; then ok "separate-mode real build" else no "separate-mode real build" fi if ./SepMain 2>/dev/null | grep -q "42"; then ok "separate-built program runs (42)" else no "separate-built program runs" fi out=$($V3M --separate -c m2 --m2bin ../../compiler/M2 --shim ../../runtime/syslib/shim.c \ -I ../../lib/common -o SepMain tests/Main.mod 2>&1) case "$out" in *"up to date"*) ok "separate-mode up-to-date skip" ;; *) no "separate-mode up-to-date skip: $out" ;; esac sleep 1 touch tests/Calc.mod out=$($V3M --separate -c m2 --m2bin ../../compiler/M2 --shim ../../runtime/syslib/shim.c \ -I ../../lib/common -o SepMain tests/Main.mod 2>&1) case "$out" in *"tests/Calc.mod"*) ok "separate-mode recompiles changed object" ;; *) no "separate-mode recompiles changed object: $out" ;; esac if ./SepMain 2>/dev/null | grep -q "42"; then ok "separate relink runs (42)" else no "separate relink runs" fi sleep 1 touch tests/Calc.def out=$($V3M --separate -c m2 --m2bin ../../compiler/M2 --shim ../../runtime/syslib/shim.c \ -I ../../lib/common -o SepMain tests/Main.mod 2>&1) case "$out" in *"tests/Main.mod"*) ok "separate-mode recompiles importer after .def change" ;; *) no "separate-mode .def rebuild: $out" ;; esac touch tests/Calc.def tests/Calc.mod tests/Main.mod # --- definition-only class object --- rm -rf gen_ssa CDefProg if $V3M --separate -c m2 --m2bin ../../compiler/M2 --shim ../../runtime/syslib/shim.c \ -I . -o CDefProg tests/CProg.mod > /tmp/m2make_t.log 2>&1; then ./CDefProg > /dev/null 2>&1; rc=$? if [ "$rc" = "8" ]; then ok "separate-mode definition-only class object" else no "separate-mode definition-only class object (rc=$rc)"; fi else no "separate-mode definition-only class object (build)" fi # --- generic instance as its own object --- rm -rf gen_ssa GenProg if $V3M --separate -c m2 --m2bin ../../compiler/M2 --shim ../../runtime/syslib/shim.c \ -I . -o GenProg tests/GenProg.mod > /tmp/m2make_t.log 2>&1; then ./GenProg > /dev/null 2>&1; rc=$? if [ "$rc" = "42" ]; then ok "separate-mode generic instance object" else no "separate-mode generic instance object (rc=$rc)"; fi else no "separate-mode generic instance object (build)" fi # --- generic class instance object --- rm -rf gen_ssa GCProg if $V3M --separate -c m2 --m2bin ../../compiler/M2 --shim ../../runtime/syslib/shim.c \ -I . -o GCProg tests/GCProg.mod > /tmp/m2make_t.log 2>&1; then ./GCProg > /dev/null 2>&1; rc=$? if [ "$rc" = "42" ]; then ok "separate-mode generic class object" else no "separate-mode generic class object (rc=$rc)"; fi else no "separate-mode generic class object (build)" fi # --- content ABI stamp --- rm -f gen_ssa/.m2abi out=$($V3M --separate -c m2 --m2bin ../../compiler/M2 --shim ../../runtime/syslib/shim.c \ -I . -o CDefProg tests/CProg.mod 2>&1) case "$out" in *"tests/CProg.mod"*) ok "separate-mode ABI stamp forces rebuild" ;; *) no "separate-mode ABI stamp: $out" ;; esac # --- cross-check: gm2-built M2make drives an m2 build too --- rm -rf gen_ssa MainX m2make.log if $GM2 -c m2 --m2bin ../../compiler/M2 --shim ../../runtime/syslib/shim.c \ -I ../../lib/common -o MainX tests/Main.mod > /tmp/m2make_t.log 2>&1 \ && ./MainX 2>/dev/null | grep -q "42"; then ok "gm2-built M2make drives m2 build" else no "gm2-built M2make drives m2 build" fi rm -f Main MainX Main2 SepMain CDefProg GenProg GCProg *.o rm -rf gen_ssa rm -f m2make.log echo "--- $pass passed, $fail failed ---" [ "$fail" -eq 0 ]