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>
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
"""RH-01~07: Retry Handler — 分层重试 + heal/simple 分离"""
|
||||
|
||||
import sys, os
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))
|
||||
from hina.retry import RetryHandler, HEALING_FIXES
|
||||
from data.diff_result import VerificationRun
|
||||
|
||||
|
||||
def _vr(status="PASS", build_log=""):
|
||||
vr = VerificationRun(status=status, program="TEST")
|
||||
if build_log:
|
||||
vr.debug = {"cobol_build": {"log": build_log}}
|
||||
return vr
|
||||
|
||||
|
||||
def test_immediate_pass():
|
||||
"""RH-01: 1次 PASS → heal=0, simple=0"""
|
||||
h = RetryHandler()
|
||||
vr = h.run(lambda: _vr("PASS"))
|
||||
assert vr.status == "PASS"
|
||||
assert vr.heal_retry == 0
|
||||
assert vr.simple_retry == 0
|
||||
|
||||
|
||||
def test_heal_recovery():
|
||||
"""RH-02: BLOCKED(not found) → heal修复→PASS"""
|
||||
calls = [0]
|
||||
def fn():
|
||||
calls[0] += 1
|
||||
if calls[0] == 1:
|
||||
return _vr("BLOCKED", build_log="file not found: libcob.so")
|
||||
return _vr("PASS")
|
||||
h = RetryHandler()
|
||||
vr = h.run(fn)
|
||||
assert vr.status == "PASS"
|
||||
assert vr.heal_retry >= 1
|
||||
assert vr.simple_retry == 0
|
||||
|
||||
|
||||
def test_simple_retry():
|
||||
"""RH-03: BLOCKED→重试→PASS (无 heal 匹配)"""
|
||||
calls = [0]
|
||||
def fn():
|
||||
calls[0] += 1
|
||||
if calls[0] == 1:
|
||||
return _vr("BLOCKED", build_log="some random error")
|
||||
return _vr("PASS")
|
||||
h = RetryHandler()
|
||||
vr = h.run(fn)
|
||||
assert vr.status == "PASS"
|
||||
assert vr.simple_retry >= 1
|
||||
|
||||
|
||||
def test_max_retries_exceeded():
|
||||
"""RH-04: 全部失败 → FATAL"""
|
||||
h = RetryHandler(max_heal=1, max_simple=1)
|
||||
vr = h.run(lambda: _vr("BLOCKED"))
|
||||
assert vr.status == "FATAL"
|
||||
assert vr.exit_code == 4
|
||||
|
||||
|
||||
def test_quality_warn_no_retry():
|
||||
"""RH-05: QUALITY_WARN → 立即返回 不重试"""
|
||||
h = RetryHandler()
|
||||
vr = h.run(lambda: _vr("QUALITY_WARN"))
|
||||
assert vr.status == "QUALITY_WARN"
|
||||
assert vr.heal_retry == 0
|
||||
assert vr.simple_retry == 0
|
||||
|
||||
|
||||
def test_heal_fails_then_simple():
|
||||
"""RH-06: heal 尝试但仍然 BLOCKED → 回退 simple"""
|
||||
calls = [0]
|
||||
def fn():
|
||||
calls[0] += 1
|
||||
return _vr("BLOCKED", build_log="file not found: libcob.so")
|
||||
h = RetryHandler(max_heal=2, max_simple=2)
|
||||
vr = h.run(fn)
|
||||
assert vr.status == "FATAL"
|
||||
# 应已消耗所有 heal+simple
|
||||
assert vr.heal_retry + vr.simple_retry >= 1
|
||||
|
||||
|
||||
def test_concurrent_count_separation():
|
||||
"""RH-07: heal 和 simple 计数互不影响"""
|
||||
h = RetryHandler(max_heal=2, max_simple=2)
|
||||
calls = [0, False] # [count, callable flag]
|
||||
def fn():
|
||||
calls[0] += 1
|
||||
if calls[0] == 1:
|
||||
return _vr("BLOCKED", build_log="file not found: libcob.so")
|
||||
return _vr("PASS")
|
||||
h._try_set_env = lambda k, v: None # no-op fix
|
||||
# Mock fix to succeed on first heal
|
||||
original_fix = HEALING_FIXES["compile_error"]["fix"]
|
||||
HEALING_FIXES["compile_error"]["fix"] = lambda: None
|
||||
try:
|
||||
vr = h.run(fn)
|
||||
assert vr.heal_retry >= 0
|
||||
assert vr.simple_retry >= 0
|
||||
# heal 和 simple 的计数不会混淆
|
||||
finally:
|
||||
HEALING_FIXES["compile_error"]["fix"] = original_fix
|
||||
|
||||
|
||||
def test_history_records():
|
||||
"""所有 VR 被记录到 history"""
|
||||
h = RetryHandler(max_heal=0, max_simple=2)
|
||||
results = []
|
||||
def fn():
|
||||
vr = _vr("BLOCKED") if len(results) < 2 else _vr("PASS")
|
||||
results.append(vr)
|
||||
return vr
|
||||
h.run(fn)
|
||||
assert len(h.history) >= 2
|
||||
Reference in New Issue
Block a user