run_tests.sh 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #!/bin/sh
  2. # Regression for M2comp step 2 (Coco/R + SymTab semantic analysis).
  3. # Usage: ./run_tests.sh (from the m2comp directory)
  4. pass=0; fail=0
  5. expect_ok() {
  6. if ./M2comp "$1" 2>&1 | grep -q "Parsed correctly"; then
  7. pass=$((pass+1)); echo "PASS(ok): $1"
  8. else
  9. fail=$((fail+1)); echo "FAIL(ok, rejected): $1"
  10. fi
  11. collect_mcd
  12. }
  13. expect_fail() {
  14. # $1 = test file (with dir); $2 = optional message expected in .LST
  15. if ./M2comp "$1" 2>&1 | grep -q "Incorrect source"; then
  16. :
  17. else
  18. fail=$((fail+1)); echo "FAIL(fail, accepted): $1"
  19. collect_mcd
  20. return
  21. fi
  22. collect_mcd
  23. if [ -z "$2" ]; then
  24. pass=$((pass+1)); echo "PASS(fail): $1"
  25. return
  26. fi
  27. lst=$(echo "$1" | sed 's/\.[^.]*$/.LST/')
  28. if grep -q "$2" "$lst" 2>/dev/null; then
  29. pass=$((pass+1)); echo "PASS(fail): $1 [$2]"
  30. else
  31. fail=$((fail+1)); echo "FAIL(fail): [$2] not found in $lst"
  32. fi
  33. }
  34. expect_dump() {
  35. if ./M2comp "$1" 2>&1 | grep -q "$2"; then
  36. pass=$((pass+1)); echo "PASS(ast): $1 [$2]"
  37. else
  38. fail=$((fail+1)); echo "FAIL(ast): $1 [$2]"
  39. fi
  40. collect_mcd
  41. }
  42. MCINT="${MCINT:-../m-code-64/mcint}"
  43. mkdir -p MC4
  44. MCTIMEOUT="${MCTIMEOUT:-10}"
  45. # MGen emits <Module>.MC4 in the current directory; the run helpers
  46. # below collect it into MC4/ and run it from there.
  47. collect_mcd() {
  48. for f in *.MC4; do
  49. [ -f "$f" ] && mv -f "$f" MC4/
  50. done
  51. }
  52. expect_run() {
  53. # $1 = test file, $2 = expected printed ExitCode value
  54. name="$1"
  55. want="$2"
  56. mod=$(head -n 1 "tests/$name" | cut -d' ' -f2 | cut -d';' -f1)
  57. mcd="MC4/$mod.MC4"
  58. rm -f "$mcd" "$mod.MC4"
  59. if ./M2comp "tests/$name" 2>&1 | grep -q "Incorrect source"; then
  60. fail=$((fail+1)); echo "FAIL(run): $name rejected"; return
  61. fi
  62. [ -f "$mod.MC4" ] && mv -f "$mod.MC4" "$mcd"
  63. if [ ! -f "$mcd" ]; then
  64. fail=$((fail+1)); echo "FAIL(run): $name no $mcd"; return
  65. fi
  66. timeout "$MCTIMEOUT" "$MCINT" "$mcd" > /tmp/m2comp_out.txt 2>&1; rc=$?
  67. if [ "$rc" -ne 0 ]; then
  68. fail=$((fail+1)); echo "FAIL(run): $name vm rc=$rc (diverges?)"; return
  69. fi
  70. got=$(head -n 1 /tmp/m2comp_out.txt | tr -d '\r')
  71. if [ "$got" = "$want" ]; then
  72. pass=$((pass+1)); echo "PASS(run): $name -> $got"
  73. else
  74. fail=$((fail+1)); echo "FAIL(run): $name printed [$got], want [$want]"
  75. fi
  76. }
  77. expect_run_none() {
  78. # $1 = test file — must compile and run silent (terminating)
  79. name="$1"
  80. mod=$(head -n 1 "tests/$name" | cut -d' ' -f2 | cut -d';' -f1)
  81. mcd="MC4/$mod.MC4"
  82. rm -f "$mcd" "$mod.MC4"
  83. if ./M2comp "tests/$name" 2>&1 | grep -q "Incorrect source"; then
  84. fail=$((fail+1)); echo "FAIL(silent): $name rejected"; return
  85. fi
  86. [ -f "$mod.MC4" ] && mv -f "$mod.MC4" "$mcd"
  87. if [ ! -f "$mcd" ]; then
  88. fail=$((fail+1)); echo "FAIL(silent): $name no $mcd"; return
  89. fi
  90. timeout "$MCTIMEOUT" "$MCINT" "$mcd" > /tmp/m2comp_out.txt 2>&1; rc=$?
  91. if [ "$rc" -ne 0 ]; then
  92. fail=$((fail+1)); echo "FAIL(silent): $name vm rc=$rc (diverges?)"; return
  93. fi
  94. got=$(head -n 1 /tmp/m2comp_out.txt)
  95. if [ -z "$got" ]; then
  96. pass=$((pass+1)); echo "PASS(silent): $name runs silent"
  97. else
  98. fail=$((fail+1)); echo "FAIL(silent): $name output [$got]"
  99. fi
  100. }
  101. expect_run_files() {
  102. # $1 = program module (MC4 base), $2 = expected value, rest = sources
  103. # (definitions, then implementations, then the program).
  104. prog="$1"
  105. want="$2"
  106. shift 2
  107. mcd="MC4/$prog.MC4"
  108. rm -f "$mcd" "$prog.MC4"
  109. if ./M2comp "$@" 2>&1 | grep -q "Incorrect source"; then
  110. fail=$((fail+1)); echo "FAIL(run): $prog rejected"; return
  111. fi
  112. [ -f "$prog.MC4" ] && mv -f "$prog.MC4" "$mcd"
  113. collect_mcd
  114. if [ ! -f "$mcd" ]; then
  115. fail=$((fail+1)); echo "FAIL(run): $prog no $mcd"; return
  116. fi
  117. timeout "$MCTIMEOUT" "$MCINT" "$mcd" > /tmp/m2comp_out.txt 2>&1; rc=$?
  118. if [ "$rc" -ne 0 ]; then
  119. fail=$((fail+1)); echo "FAIL(run): $prog vm rc=$rc (diverges?)"; return
  120. fi
  121. got=$(head -n 1 /tmp/m2comp_out.txt | tr -d '\r')
  122. if [ "$got" = "$want" ]; then
  123. pass=$((pass+1)); echo "PASS(run): $prog -> $got"
  124. else
  125. fail=$((fail+1)); echo "FAIL(run): $prog printed [$got], want [$want]"
  126. fi
  127. }
  128. expect_fail_files() {
  129. # $1 = message in the failing file's .LST, rest = sources.
  130. want="$1"
  131. shift
  132. if ./M2comp "$@" 2>&1 | grep -q "Incorrect source"; then
  133. :
  134. else
  135. fail=$((fail+1)); echo "FAIL(fail, accepted): $*"; return
  136. fi
  137. collect_mcd
  138. last=""
  139. for f in "$@"; do last="$f"; done
  140. lst=$(echo "$last" | sed 's/\.[^.]*$/.LST/')
  141. if grep -q "$want" "$lst" 2>/dev/null; then
  142. pass=$((pass+1)); echo "PASS(fail): $last [$want]"
  143. else
  144. fail=$((fail+1)); echo "FAIL(fail): [$want] not found in $lst"
  145. fi
  146. }
  147. expect_fail_multi() {
  148. # stdout-only rejection: a second program trips the driver's
  149. # program-last gate (both programs parse clean, so no .LST mark).
  150. if ./M2comp "$@" 2>&1 | grep -q "Incorrect source"; then
  151. pass=$((pass+1)); echo "PASS(fail): $*"
  152. else
  153. fail=$((fail+1)); echo "FAIL(fail, accepted): $*"
  154. fi
  155. collect_mcd
  156. }
  157. expect_code() {
  158. # $1 = test file (with dir), $2 = pattern expected in backend listing.
  159. if ./M2comp "$1" 2>&1 | grep -q "$2"; then
  160. pass=$((pass+1)); echo "PASS(code): $1 [$2]"
  161. else
  162. fail=$((fail+1)); echo "FAIL(code): $1 [$2]"
  163. fi
  164. collect_mcd
  165. }
  166. expect_ok tests/ok_minimal.mod
  167. expect_ok tests/ok_proc.mod
  168. expect_ok tests/showcase.mod
  169. expect_fail tests/bad_mismatch.mod
  170. expect_fail tests/t_dup.mod
  171. expect_fail tests/t_undecl.mod
  172. expect_fail tests/t_assign.mod
  173. expect_fail tests/t_arith.mod
  174. expect_fail tests/t_bool.mod
  175. expect_fail tests/t_rel.mod
  176. expect_fail tests/t_cond.mod
  177. expect_fail tests/t_field.mod
  178. expect_fail tests/t_index.mod
  179. expect_fail tests/t_ptr.mod
  180. expect_fail tests/t_for.mod
  181. expect_fail tests/t_call.mod
  182. expect_fail tests/t_call2.mod
  183. expect_fail tests/t_return.mod
  184. expect_fail tests/t_exit.mod
  185. expect_dump tests/showcase.mod "Module Showcase"
  186. expect_dump tests/showcase.mod "Proc Work"
  187. expect_dump tests/showcase.mod "CallExpr"
  188. expect_dump tests/showcase.mod "Field q"
  189. expect_dump tests/showcase.mod "Int 255"
  190. expect_dump tests/ok_proc.mod "Proc P"
  191. expect_run_none ok_minimal.mod
  192. expect_run_none ok_proc.mod
  193. expect_run r_arith.mod 8
  194. expect_run r_flow.mod 69
  195. expect_run r_bool.mod 11
  196. expect_run r_real.mod 1111
  197. expect_run r_proc.mod 162
  198. expect_run r_varpar.mod 48
  199. expect_run r_nested.mod 213
  200. expect_run r_array.mod 39
  201. expect_run r_record.mod 15
  202. expect_run r_set.mod 12
  203. expect_run r_string.mod 111
  204. expect_run r_ptr.mod 111
  205. expect_run r_module.mod 83
  206. expect_run r_const.mod 1102
  207. expect_run r_rcmp.mod 31
  208. echo "=== Step-6 run tests (WITH, CASE) ==="
  209. expect_run t_with.mod 51
  210. expect_run t_case.mod 138
  211. echo "=== Step-6 rejection tests ==="
  212. expect_fail tests/t_bad_with.mod "not a RECORD type"
  213. expect_fail tests/t_bad_case.mod "incompatible comparison"
  214. expect_fail tests/t_bad_caselbl.mod "not supported in this phase"
  215. echo "=== Step-7 backend listing checks ==="
  216. expect_code tests/r_real.mod "realCmp"
  217. expect_code tests/r_proc.mod "proc.*2.*at"
  218. expect_code tests/t_case.mod "jpfalse"
  219. expect_code tests/t_with.mod "storeIndir0"
  220. echo "=== Step-5 run tests (DEFINITION/IMPLEMENTATION/IMPORT) ==="
  221. expect_run_files DBasic 60 tests/d_lib.def tests/d_lib.mod tests/d_basic.mod
  222. expect_run_files DFrom 35 tests/d_lib.def tests/d_lib.mod tests/d_lib2.def tests/d_lib2.mod tests/d_from.mod
  223. expect_run_files DMulti 68 tests/d_lib.def tests/d_lib.mod tests/d_lib2.def tests/d_lib2.mod tests/d_multi.mod
  224. expect_run_files DInit 7 tests/d_lib.def tests/d_lib.mod tests/d_init.mod
  225. expect_run_files DFunc 81 tests/d_lib.def tests/d_lib.mod tests/d_func.mod
  226. expect_run_files DType 40 tests/d_lib.def tests/d_lib.mod tests/d_type.mod
  227. expect_run_files Showcase5 46 tests/s5lib.def tests/s5lib.mod tests/showcase5.mod
  228. echo "=== Step-5 rejection tests ==="
  229. expect_fail_files "undeclared identifier" tests/d_bad_nodef.mod
  230. expect_fail_files "procedure forward mismatch" tests/d_lib.def tests/d_bad_sig.mod
  231. expect_fail_files "procedure forward mismatch" tests/d_lib.def tests/d_bad_nobody.mod
  232. expect_fail_files "undeclared identifier" tests/d_lib.def tests/d_bad_noimpl.mod
  233. expect_fail_files "duplicate identifier" tests/d_lib.def tests/d_bad_dup.def
  234. expect_fail_files "undeclared identifier" tests/d_lib.def tests/d_lib.mod tests/d_bad_priv.mod
  235. expect_fail_multi tests/d_lib.def tests/d_lib.mod tests/d_second.mod tests/d_basic.mod
  236. echo "--- $pass passed, $fail failed ---"
  237. [ "$fail" -eq 0 ]