test: cover between/hostvar/gcov-merge, class conditions, schema drop-tables, gixsql fixes

This commit is contained in:
hangshuo652
2026-08-09 17:43:16 +08:00
parent 273a3f8211
commit ff51bda962
22 changed files with 2559 additions and 0 deletions
@@ -0,0 +1,135 @@
r"""DB2 schema 限定表名(SCHEMA.TABLE)在数据生成层的归一化测试。
根因:`FROM SALARYDB.EMP-MASTER` 中 `SALARYDB.` 限定符使 core.py 表名正则
`(\w[\w-]*)` 遇 `.` 即停,把种子表解析为 `SALARYDB`build_db_input 把 24 条
EMP 种子行挂到不存在的 `SALARYDB` 表键下,插入时被丢弃 → EMP_MASTER 未播种,
运行时 EMP 正常路径(SEARCH/EVALUATE)无法覆盖。
修复(分层,通用):
- core.py `_parse_sql` 各表名正则捕获完整限定名(SCHEMA.TABLE 不丢失)。
- to_sql.py `collect_sql_meta` 用 `_norm_table` 剥掉限定符取末段(EMP-MASTER),
与 YAML schema 表名一致;种子键归一,`_populate_database` 正常插入。
"""
import sys, os
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))
from cobol_testgen.core import extract_sql_assignments
from cobol_testgen.to_sql import collect_sql_meta, build_db_input
_SRC_DECLARE = (
" PROCEDURE DIVISION.\n"
" EXEC SQL\n"
" DECLARE C2 CURSOR FOR\n"
" SELECT EMP-ID, EMP-NAME, DEPT-CODE, BASE-SALARY\n"
" FROM SALARYDB.EMP-MASTER\n"
" ORDER BY EMP-ID\n"
" END-EXEC.\n"
)
def test_extract_sql_assignments_keeps_full_qualified_table():
"""core.py 表名正则须捕获完整限定名(不丢失 .EMP-MASTER)。"""
assignments = extract_sql_assignments(_SRC_DECLARE)
tables = [a.get("table") for a in assignments.values() for a in a]
assert "SALARYDB.EMP-MASTER" in tables, f"qualified table lost: {tables}"
def test_collect_sql_meta_normalizes_schema_qualified_table():
"""collect_sql_meta 把 SCHEMA.TABLE 归一化为末段表名。"""
assignments = {
"__SQL_CURSOR_C2": [{
"type": "exec_sql_select",
"table": "SALARYDB.EMP-MASTER",
"select_list": "EMP-ID, EMP-NAME, DEPT-CODE, BASE-SALARY",
"into_vars": ["DBV-EMP-ID", "DBV-EMP-NAME", "DBV-DEPT-CODE", "DBV-BASE-SALARY"],
"where": "",
"sql_text": "DECLARE C2 CURSOR FOR SELECT EMP-ID FROM SALARYDB.EMP-MASTER",
}],
}
declared = {"EMP-MASTER": [
{"name": "EMP-ID", "db_type": "CHAR", "size": 8},
{"name": "EMP-NAME", "db_type": "CHAR", "size": 40},
{"name": "DEPT-CODE", "db_type": "CHAR", "size": 2},
{"name": "BASE-SALARY", "db_type": "CHAR", "size": 9},
]}
sql_meta = collect_sql_meta(assignments, declared)
assert len(sql_meta) == 1
assert sql_meta[0]["table"] == "EMP-MASTER", sql_meta[0]["table"]
def test_build_db_input_seeds_emp_master_not_salarydb():
"""种子行键必须是 EMP-MASTER(而非 SALARYDB),否则插入时被丢弃。"""
branch_paths = [
([('SQLCODE', '=', '0', True)], {}),
]
records = [{
"DBV-EMP-ID": "A0000001",
"DBV-EMP-NAME": "TANAKA",
"DBV-DEPT-CODE": "01",
"DBV-BASE-SALARY": "429010",
}]
declared = {"EMP-MASTER": [
{"name": "EMP-ID", "db_type": "CHAR", "size": 8},
{"name": "EMP-NAME", "db_type": "CHAR", "size": 40},
{"name": "DEPT-CODE", "db_type": "CHAR", "size": 2},
{"name": "BASE-SALARY", "db_type": "CHAR", "size": 9},
]}
assignments = {
"__SQL_CURSOR_C2": [{
"type": "exec_sql_select",
"table": "SALARYDB.EMP-MASTER",
"select_list": "EMP-ID, EMP-NAME, DEPT-CODE, BASE-SALARY",
"into_vars": ["DBV-EMP-ID", "DBV-EMP-NAME", "DBV-DEPT-CODE", "DBV-BASE-SALARY"],
"where": "",
"sql_text": "DECLARE C2 CURSOR FOR SELECT EMP-ID FROM SALARYDB.EMP-MASTER",
}],
}
db_input = build_db_input(
branch_paths, [], assignments,
collect_sql_meta(assignments, declared),
declared,
records=records,
)
assert "SALARYDB" not in db_input, f"wrong table key: {list(db_input.keys())}"
assert "EMP-MASTER" in db_input, f"missing EMP-MASTER key: {list(db_input.keys())}"
def test_select_where_accept_fed_hostvar_uses_runtime_default():
"""WHERE 宿主变量由 ACCEPT FROM COMMAND-LINE 馈入时,种子必须用运行时
缺省值(如 SHA02MNC RATES 的 WRK-YEAR-MONTH='202605'),而非记录里的
合成值('I00001')。否则 EFFECTIVE-FROM/TO 不满足 WHERERATES 不装载,
SEARCH/EVALUATE 无法覆盖。"""
branch_paths = [
([('SQLCODE', '=', '0', True)], {}),
]
records = [{"WRK-YEAR-MONTH": "I00001"}]
assignments = {
"WRK-YEAR-MONTH": [
{"type": "accept", "from": "COMMAND-LINE"},
{"type": "move_literal", "literal": "202605"},
],
}
sql_meta = [{
"type": "exec_sql_select",
"table": "INSURANCE-RATES",
"select_list": "EFFECTIVE-FROM, EFFECTIVE-TO",
"into_vars": [],
"where": "EFFECTIVE-FROM <= :WRK-YEAR-MONTH AND EFFECTIVE-TO >= :WRK-YEAR-MONTH",
"where_constraints": [
{"col": "EFFECTIVE-FROM", "type": "host_var", "host_var": "WRK-YEAR-MONTH", "op": "<="},
{"col": "EFFECTIVE-TO", "type": "host_var", "host_var": "WRK-YEAR-MONTH", "op": ">="},
],
}]
declared = {"INSURANCE-RATES": [
{"name": "EFFECTIVE-FROM", "db_type": "CHAR", "size": 6},
{"name": "EFFECTIVE-TO", "db_type": "CHAR", "size": 6},
]}
db_input = build_db_input(
branch_paths, [], assignments, sql_meta, declared, records=records,
)
rows = db_input.get("INSURANCE-RATES", [])
assert rows, "no INSURANCE-RATES seed rows"
assert rows[0]["EFFECTIVE-FROM"].strip() == "202605", (
f"seed EFFECTIVE-FROM={rows[0]['EFFECTIVE-FROM']!r} not runtime default"
)
assert rows[0]["EFFECTIVE-TO"].strip() == "202605"