Files
cobol-java-v3/tests/parametrized/test_call_search.py
hangshuo652 bc1d56d1a4 feat: Phase 2 complete — 13 Phases of COBOL type classification and test benchmark
P0.6: gcov infrastructure
P1: extract_structure output expansion (11 new feature fields)
P2: Confusion group rule engine (8 pairs + contradiction + backtrack)
P3: 4-factor confidence calculation + quality gate update
P4: 33+2 COBOL program type test samples (22 files, 7 categories)
P5: parametrized/ test data generation engine
P6: japanese_data.py lookup tables
P7-10: Type-specific test suites (~159 parametrized tests)
P11: Full classification pipeline (classify_program) + orchestrator integration
P12: Documentation (module-interfaces, test-plan v3.0, coverage-matrix)

Architecture decisions:
- classification_pipeline/ merged to hina/pipeline/
- parametrized/ as independent module
- japanese_data.py as root-level file
- hina/__all__ only exports classify_program()

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-19 23:51:55 +08:00

239 lines
5.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Phase 8: CALL / SEARCH ALL 系测试。
测试覆盖:
- CALL 参数传递逻辑(by reference / by value / by content
- SEARCH ALL 二分查找逻辑(找到 / 未找到 / 重复键 / 空表)
"""
from __future__ import annotations
from typing import Any
# ── CALL 模拟
def _call_by_reference(param: list) -> list:
"""模拟 COBOL CALL BY REFERENCE: 修改外部变量。"""
param[0] = param[0] * 2
return param
def _call_by_value(param: int) -> int:
"""模拟 COBOL CALL BY VALUE: 传入副本。"""
return param * 2
def _call_by_content(param: list) -> list:
"""模拟 COBOL CALL BY CONTENT: 传入副本,不修改原始值。"""
copy = param.copy()
copy[0] = copy[0] * 2
return copy
def _call_with_multiple(
a: int,
b: int,
c: str = "",
) -> dict[str, Any]:
"""模拟多参数 CALL。"""
return {"sum": a + b, "concat": c * 2}
# ── SEARCH ALL 模拟 ──
def _search_all(table: list[dict], key_field: str, target: Any) -> int | None:
"""模拟 COBOL SEARCH ALL(二分查找)。
要求 table 已按 key_field 升序排列。
参数
----------
table : list[dict]
已排序的表。
key_field : str
待查找的键字段名。
target : Any
目标值。
返回
-------
int | None
找到时返回下标;未找到返回 None。
"""
lo, hi = 0, len(table) - 1
while lo <= hi:
mid = (lo + hi) // 2
val = table[mid][key_field]
if val == target:
return mid
elif val < target:
lo = mid + 1
else:
hi = mid - 1
return None
def _search_all_duplicate_keys(
table: list[dict],
key_field: str,
target: Any,
) -> list[int]:
"""查找所有匹配的记录下标(处理重复键)。"""
indices: list[int] = []
first = _search_all(table, key_field, target)
if first is None:
return []
# 向前扫描
i = first
while i >= 0 and table[i][key_field] == target:
indices.append(i)
i -= 1
indices.reverse()
# 向后扫描
i = first + 1
while i < len(table) and table[i][key_field] == target:
indices.append(i)
i += 1
return indices
# ── 测试: CALL ──
class TestCallByReference:
"""CALL BY REFERENCE 参数传递"""
def test_by_reference_modifies_original(self):
data = [5]
result = _call_by_reference(data)
assert data[0] == 10, "BY REFERENCE 应修改原始值"
assert result == [10]
def test_by_reference_string(self):
data = ["hello"]
_call_by_reference(data)
assert data[0] == "hellohello"
class TestCallByValue:
"""CALL BY VALUE 参数传递"""
def test_by_value_no_side_effect(self):
x = 5
result = _call_by_value(x)
assert x == 5, "BY VALUE 不应修改原始值"
assert result == 10
def test_by_value_zero(self):
assert _call_by_value(0) == 0
def test_by_value_negative(self):
assert _call_by_value(-3) == -6
class TestCallByContent:
"""CALL BY CONTENT 参数传递"""
def test_by_content_preserves_original(self):
data = [5]
result = _call_by_content(data)
assert data[0] == 5, "BY CONTENT 不应修改原始值"
assert result == [10]
class TestCallMultipleParameters:
"""多参数 CALL"""
def test_multiple_params(self):
result = _call_with_multiple(3, 4)
assert result["sum"] == 7
def test_multiple_params_with_string(self):
result = _call_with_multiple(1, 2, c="ab")
assert result["sum"] == 3
assert result["concat"] == "abab"
def test_multiple_params_default(self):
result = _call_with_multiple(10, 20)
assert result["concat"] == ""
# ── 测试: SEARCH ALL ──
class TestSearchAllFound:
"""SEARCH ALL — 找到"""
def test_search_found_first(self):
table = [{"K": 1}, {"K": 3}, {"K": 5}, {"K": 7}]
idx = _search_all(table, "K", 1)
assert idx == 0
def test_search_found_last(self):
table = [{"K": 1}, {"K": 3}, {"K": 5}, {"K": 7}]
idx = _search_all(table, "K", 7)
assert idx == 3
def test_search_found_middle(self):
table = [{"K": 1}, {"K": 3}, {"K": 5}, {"K": 7}]
idx = _search_all(table, "K", 5)
assert idx == 2
def test_search_string_keys(self):
table = [{"K": "a"}, {"K": "b"}, {"K": "c"}, {"K": "d"}]
idx = _search_all(table, "K", "c")
assert idx == 2
class TestSearchAllNotFound:
"""SEARCH ALL — 未找到"""
def test_search_not_found(self):
table = [{"K": 1}, {"K": 3}, {"K": 5}]
idx = _search_all(table, "K", 4)
assert idx is None
def test_search_below_all(self):
table = [{"K": 10}, {"K": 20}]
idx = _search_all(table, "K", 5)
assert idx is None
def test_search_above_all(self):
table = [{"K": 10}, {"K": 20}]
idx = _search_all(table, "K", 25)
assert idx is None
class TestSearchAllDuplicateKeys:
"""SEARCH ALL — 重复键"""
def test_search_duplicate_keys(self):
table = [{"K": 1}, {"K": 2}, {"K": 2}, {"K": 2}, {"K": 3}]
indices = _search_all_duplicate_keys(table, "K", 2)
assert indices == [1, 2, 3]
def test_search_no_duplicate(self):
table = [{"K": 1}, {"K": 2}, {"K": 3}]
indices = _search_all_duplicate_keys(table, "K", 2)
assert indices == [1]
class TestSearchAllEdgeCases:
"""SEARCH ALL — 边界"""
def test_search_empty_table(self):
idx = _search_all([], "K", 1)
assert idx is None
def test_search_single_element_found(self):
table = [{"K": 42}]
idx = _search_all(table, "K", 42)
assert idx == 0
def test_search_single_element_not_found(self):
table = [{"K": 42}]
idx = _search_all(table, "K", 99)
assert idx is None