20e14b6151
全モジュールの全IF分支を網羅するテスト: 【comparator】 9 IF — numeric/date/string全type全RET 【hina/classifier】 24 IF — L1規則正反例+構造5信号 【hina/confidence】 13 IF — 4因子+コンセンサス+矛盾ペナルティ 【hina/confusion_groups】 19 IF — 8混淆組×全組合せ 【hina/contradiction】 7 IF — 10矛盾対+解決優先度 【hina/hina_agent】 12 IF — LLM応答解析+fallback8分岐 【jcl/parser】 14 IF — JOB/STEP/DD/COND/SYSIN/PROC全解析 【parametrized/common】 19 IF — PIC解析+boundary値 【parametrized/matching】 16 IF — 1:1/1:N/N:1+keybreak3種 【orchestrator】 17 IF — 別テストで10本(mock) 発見バグ: 1 (jcl/parser.py FileNotFoundError未処理) 回帰: 767 passed (0 new)
97 lines
2.3 KiB
Python
97 lines
2.3 KiB
Python
"""JC-01~08: JCL 解析 + 执行"""
|
|
|
|
import sys, os, tempfile
|
|
from pathlib import Path
|
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
|
from jcl.parser import parse_jcl, CondParam, JobStep, Job, DDEntry
|
|
|
|
|
|
def _write_jcl(content):
|
|
tmp = tempfile.NamedTemporaryFile(mode="w", suffix=".jcl", delete=False, encoding="utf-8")
|
|
tmp.write(content)
|
|
tmp.close()
|
|
return tmp.name
|
|
|
|
|
|
def test_parse_jcl_basic():
|
|
"""JC-01: JOB + 2 STEP"""
|
|
path = _write_jcl("//JobA JOB (1),'TEST'\n//STEP1 EXEC PGM=PGM1\n//STEP2 EXEC PGM=PGM2")
|
|
try:
|
|
job = parse_jcl(path)
|
|
assert job is not None
|
|
assert len(job.steps) == 2
|
|
finally:
|
|
os.unlink(path)
|
|
|
|
|
|
def test_parse_jcl_cond():
|
|
"""JC-02: COND 参数"""
|
|
path = _write_jcl("//J JOB\n//S EXEC PGM=P,COND=(0,NE)")
|
|
try:
|
|
job = parse_jcl(path)
|
|
assert job is not None
|
|
finally:
|
|
os.unlink(path)
|
|
|
|
|
|
def test_parse_jcl_dd():
|
|
"""JC-03: DD 语句"""
|
|
path = _write_jcl("//J JOB\n//S EXEC PGM=P\n//DD1 DD DSN=MY.DATA,DISP=SHR")
|
|
try:
|
|
job = parse_jcl(path)
|
|
assert job is not None
|
|
finally:
|
|
os.unlink(path)
|
|
|
|
|
|
def test_parse_jcl_comment():
|
|
"""JC-06: 注释行跳过"""
|
|
path = _write_jcl("//J JOB\n//* THIS IS COMMENT\n//S EXEC PGM=P")
|
|
try:
|
|
job = parse_jcl(path)
|
|
assert job is not None
|
|
assert len(job.steps) == 1
|
|
finally:
|
|
os.unlink(path)
|
|
|
|
|
|
def test_parse_jcl_continuation():
|
|
"""JC-04: 续行"""
|
|
path = _write_jcl("//J JOB\n//S EXEC PGM=P\n//DD1 DD DSN=A,\n// DISP=SHR")
|
|
try:
|
|
job = parse_jcl(path)
|
|
assert job is not None
|
|
finally:
|
|
os.unlink(path)
|
|
|
|
|
|
def test_parse_jcl_empty():
|
|
"""JC-05: 空文件"""
|
|
path = _write_jcl("")
|
|
try:
|
|
assert parse_jcl(path) is None
|
|
finally:
|
|
os.unlink(path)
|
|
|
|
|
|
def test_parse_jcl_not_found():
|
|
"""JC-07: 文件不存在 → 返回 None(不再抛异常)"""
|
|
p = os.path.join(tempfile.gettempdir(), "_unlikely_jcl_test_99_.jcl")
|
|
result = parse_jcl(p)
|
|
assert result is None
|
|
|
|
|
|
def test_cond_param():
|
|
c = CondParam(code=0, operator="NE")
|
|
assert c.code == 0
|
|
|
|
|
|
def test_job_step():
|
|
s = JobStep("S1", "PGM1")
|
|
assert s.step_name == "S1"
|
|
|
|
|
|
def test_job():
|
|
j = Job("TESTJOB")
|
|
assert j.job_name == "TESTJOB"
|