"""L1 验证 — COBOL 语句样本的 generate_data 分支覆盖验证""" from pathlib import Path import pytest from cobol_testgen import extract_structure, generate_data FIXTURES = Path(__file__).parents[3] / "test-data" / "cobol" / "statement_arithmetic" def _verify_data_generates(cbl_path: str, min_records: int = 1): source = (FIXTURES / cbl_path).read_text("utf-8") struct = extract_structure(source) data = generate_data(source, struct) assert data is not None, f"{cbl_path}: generate_data returned None" # For file-based programs, 0 records may be valid return data # ── 文件类样本 (statement_file) 使用通用 fixture ── FILE_FIXTURES = Path(__file__).parents[3] / "test-data" / "cobol" / "statement_file" MOVE_FIXTURES = Path(__file__).parents[3] / "test-data" / "cobol" / "statement_move" CTRL_FIXTURES = Path(__file__).parents[3] / "test-data" / "cobol" / "statement_control" PERF_FIXTURES = Path(__file__).parents[3] / "test-data" / "cobol" / "statement_perform" INSP_FIXTURES = Path(__file__).parents[3] / "test-data" / "cobol" / "statement_inspect" SRCH_FIXTURES = Path(__file__).parents[3] / "test-data" / "cobol" / "statement_search" def _exists(path: Path) -> bool: return path.exists() def test_l1_arithmetic_data(): """算术样本至少生成 1 条记录""" for name in ["ST-ADD-TO", "ST-ADD-GIVING", "ST-ADD-ROUNDED", "ST-SUB-FROM", "ST-SUB-GIVING", "ST-MUL-BY", "ST-MUL-GIVING", "ST-DIV-BY-GIVING", "ST-COMPLEX"]: path = FIXTURES / f"{name}.cbl" if not path.exists(): continue source = path.read_text("utf-8") struct = extract_structure(source) data = generate_data(source, struct) assert data is not None, f"{name}: generate_data returned None" assert len(data) >= 1, f"{name}: expected >= 1 record, got {len(data)}" # Verify records contain expected fields assert isinstance(data[0], dict), f"{name}: first record not a dict" def test_l1_move_data(): """数据搬移样本至少生成 1 条记录""" for name in ["ST-MOVE-GROUP", "ST-INI-MULTI", "ST-INI-REPLACE", "ST-STRING-DELIM", "ST-UNSTRING-BASIC"]: path = MOVE_FIXTURES / f"{name}.cbl" if not path.exists(): continue source = path.read_text("utf-8") struct = extract_structure(source) data = generate_data(source, struct) assert data is not None, f"{name}: generate_data returned None" # move/file samples may produce 0 records if len(data) == 0: continue def test_l1_control_data(): """控制流样本(含 IF)应生成覆盖所有分支的数据""" for name in ["ST-IF-COMP", "ST-IF-DEEP", "ST-EVAL-ALSO"]: path = CTRL_FIXTURES / f"{name}.cbl" if not path.exists(): continue source = path.read_text("utf-8") struct = extract_structure(source) data = generate_data(source, struct) assert data is not None, f"{name}: generate_data returned None" assert len(data) >= 1, f"{name}: expected >= 1 record" # IF-DEEP has 3 IFs → should produce at least 1-2 records # IF-COMP has 2 IFs → should produce at least 1-2 records def test_l1_call_data(): """CALL 样本生成数据""" for name in ["ST-CALL-CONTENT", "ST-CALL-VALUE"]: path = CTRL_FIXTURES / f"{name}.cbl" if not path.exists(): continue source = path.read_text("utf-8") struct = extract_structure(source) data = generate_data(source, struct) assert data is not None, f"{name}: returned None" def test_l1_perform_data(): """PERFORM 样本生成数据验证""" for name in ["ST-PERF-VARY", "ST-PERF-UNTIL", "ST-PERF-TIMES"]: path = PERF_FIXTURES / f"{name}.cbl" if not path.exists(): continue source = path.read_text("utf-8") struct = extract_structure(source) data = generate_data(source, struct) assert data is not None, f"{name}: returned None" def test_l1_inspect_data(): """INSPECT/ACCEPT 样本生成数据验证""" for name in ["ST-INSP-CONVERT", "ST-INSP-BEFORE", "ST-ACCEPT-DATE"]: path = INSP_FIXTURES / f"{name}.cbl" if not path.exists(): continue source = path.read_text("utf-8") struct = extract_structure(source) data = generate_data(source, struct) assert data is not None, f"{name}: returned None" def test_l1_search_data(): """SEARCH/SET 样本生成数据验证""" for name in ["ST-SEARCH-ALL", "ST-SET-88"]: path = SRCH_FIXTURES / f"{name}.cbl" if not path.exists(): continue source = path.read_text("utf-8") struct = extract_structure(source) data = generate_data(source, struct) assert data is not None, f"{name}: returned None" def test_l1_file_data(): """文件操作样本至少不崩溃""" for name in ["ST-READ-INTO", "ST-READ-AT-END", "ST-WRITE-AFTER", "ST-REWRITE-FROM", "ST-DELETE", "ST-START"]: path = FILE_FIXTURES / f"{name}.cbl" if not path.exists(): continue source = path.read_text("utf-8") struct = extract_structure(source) # File programs may not generate data (external deps), just don't crash data = generate_data(source, struct) assert data is not None or True