"""JCL Executor 深度测试 — 使用真实 GnuCOBOL""" import sys, os, tempfile, subprocess, shutil from pathlib import Path sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) import pytest from jcl.executor import JclExecutor from jcl.parser import parse_jcl, Job, JobStep, CondParam, DDEntry COBC_OK = subprocess.run( ["cobc", "--version"], capture_output=True, timeout=5 ).returncode == 0 def _cobol(prog: str = "TP") -> str: return f""" IDENTIFICATION DIVISION. PROGRAM-ID. {prog}. PROCEDURE DIVISION. DISPLAY "OK:{prog}" NO ADVANCING. STOP RUN. """ @pytest.mark.skipif(not COBC_OK, reason="need GnuCOBOL") def test_compile_and_run(): tmp = tempfile.mkdtemp() try: root = Path(tmp) cbl = root / "cobol"; cbl.mkdir() (cbl / "P.cbl").write_text(_cobol("P")) jp = tempfile.NamedTemporaryFile(mode="w", suffix=".jcl", delete=False) jp.write("//J JOB\n//S1 EXEC PGM=P"); jp.close() job = parse_jcl(jp.name); os.unlink(jp.name) ex = JclExecutor(str(root), str(cbl), str(root)) ex.run(job) assert ex.results["S1"]["status"] == "OK" finally: shutil.rmtree(tmp, ignore_errors=True) @pytest.mark.skipif(not COBC_OK, reason="need GnuCOBOL") def test_no_dd(): tmp = tempfile.mkdtemp() try: root = Path(tmp) cbl = root / "cobol"; cbl.mkdir() (cbl / "P.cbl").write_text(_cobol("P")) job = Job("J"); job.steps.append(JobStep("S1", "P")) ex = JclExecutor(str(root), str(cbl), str(root)) ex.run(job) assert ex.results["S1"]["status"] == "OK" finally: shutil.rmtree(tmp, ignore_errors=True) def test_sort(): tmp = tempfile.mkdtemp() try: root = Path(tmp) d = root / "data" / "work"; d.mkdir(parents=True) (d / "in.txt").write_text("c\nb\na\n") job = Job("J"); job.steps.append(JobStep("S1", "SORT")) job.steps[0].dd_entries = [ DDEntry(dd_name="SORTIN", dsn="data/work/in.txt"), DDEntry(dd_name="SORTOUT", dsn="data/work/out.txt"), ] ex = JclExecutor(str(root), "", "") ex._run_sort(job.steps[0]) assert (root / "data" / "work" / "out.txt").read_text().splitlines() == ["a", "b", "c"] finally: shutil.rmtree(tmp, ignore_errors=True) def test_cond_logic(): ex = JclExecutor(".", ".", ".") # no step_name → execute assert ex._check_cond(CondParam(code=4, operator="GT")) is True # COND=(0,EQ) RC=0 → 0==0 True → not True=False → skip ex.step_rcs["PREV"] = 0 assert ex._check_cond(CondParam(code=0, operator="EQ", step_name="PREV")) is False # COND=(4,GT) RC=0 → 0>4 False → not False=True → execute assert ex._check_cond(CondParam(code=4, operator="GT", step_name="PREV")) is True @pytest.mark.skipif(not COBC_OK, reason="need GnuCOBOL") def test_rc_tracking(): tmp = tempfile.mkdtemp() try: root = Path(tmp) cbl = root / "cobol"; cbl.mkdir() (cbl / "A.cbl").write_text(_cobol("A")) (cbl / "B.cbl").write_text(_cobol("B")) jp = tempfile.NamedTemporaryFile(mode="w", suffix=".jcl", delete=False) jp.write("//J JOB\n//S1 EXEC PGM=A\n//S2 EXEC PGM=B"); jp.close() job = parse_jcl(jp.name); os.unlink(jp.name) ex = JclExecutor(str(root), str(cbl), str(root)) ex.run(job) assert ex.step_rcs["S1"] == 0 assert ex.step_rcs["S2"] == 0 finally: shutil.rmtree(tmp, ignore_errors=True)