calc_smoke.py 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. #!/usr/bin/env python3
  2. """Boot the compiled CALC.COM and quit it through its own command menu.
  3. The compile ladder proves the front-end reaches the final '.'. This proves the
  4. linked image is a runnable program: it is loaded above the boot sector, prints
  5. the MicroCalc welcome/grid, accepts `/Q' in the command menu and exits 0.
  6. The loader is the high-image variant of bootcom.s (LOAD_SEG=0x1000, input at
  7. 0x9000); the ordinary fixture harness uses the same default now, while
  8. rt_exec.py keeps the original low loader for its own driver image.
  9. """
  10. import os
  11. import shutil
  12. import subprocess
  13. import sys
  14. import tempfile
  15. HERE = os.path.dirname(os.path.abspath(__file__))
  16. SHELL = os.path.dirname(HERE)
  17. RES = os.path.join(os.path.dirname(SHELL), "Resources", "TP3")
  18. sys.path.insert(0, HERE)
  19. import run_com_exec as r # noqa: E402
  20. def main():
  21. td = tempfile.mkdtemp(prefix="tpcalc-")
  22. try:
  23. for name in ("CALC.PAS", "CALC.INC"):
  24. shutil.copy(os.path.join(RES, name), os.path.join(td, name))
  25. exe = r.ensure_comtest()
  26. src = os.path.join(td, "CALC.PAS")
  27. p = subprocess.run([exe], cwd=td, input=(src + "\n").encode(),
  28. capture_output=True)
  29. coms = [os.path.join(td, n) for n in os.listdir(td)
  30. if n.upper().endswith(".COM")]
  31. if p.returncode != 0 or not coms:
  32. sys.exit("comtest did not produce CALC.COM:\n%s"
  33. % p.stdout.decode(errors="replace"))
  34. com = open(coms[0], "rb").read()
  35. if len(com) > r.COM_MAX:
  36. sys.exit("CALC.COM is %d bytes, past the loader's %d"
  37. % (len(com), r.COM_MAX))
  38. boot = r.build_boot_sector()
  39. img = os.path.join(td, "calc.img")
  40. open(img, "wb").write(r.build_floppy(boot, com, b"\r\r/Q"))
  41. out, rc, note = r.run_qemu(img)
  42. code = r.exit_code_of(rc)
  43. text = out.decode("latin-1")
  44. missing = [s for s in ("Welcome to MicroCalc", "AutoCalc: ON",
  45. "Update, Quit") if s not in text]
  46. if code != 0 or missing:
  47. sys.exit("CALC did not start/quit cleanly: exit=%r note=%s missing=%r\n%s"
  48. % (code, note, missing, r.visible_output(out[:2000])))
  49. print(" CALC.COM PASS com=%d bytes, exit=0, welcome/grid/menu"
  50. % len(com))
  51. return 0
  52. finally:
  53. shutil.rmtree(td, ignore_errors=True)
  54. if __name__ == "__main__":
  55. sys.exit(main())