tests(normalized): split normalized_joinir_min into modules
This commit is contained in:
File diff suppressed because it is too large
Load Diff
444
tests/normalized_joinir_min/basic.rs
Normal file
444
tests/normalized_joinir_min/basic.rs
Normal file
@ -0,0 +1,444 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn build_structured_pattern1() -> JoinModule {
|
||||||
|
let mut module = JoinModule::new();
|
||||||
|
let mut loop_fn = JoinFunction::new(
|
||||||
|
JoinFuncId::new(1),
|
||||||
|
"loop_step".to_string(),
|
||||||
|
vec![ValueId(10)],
|
||||||
|
);
|
||||||
|
|
||||||
|
loop_fn.body.push(JoinInst::Compute(MirLikeInst::Const {
|
||||||
|
dst: ValueId(11),
|
||||||
|
value: ConstValue::Integer(0),
|
||||||
|
}));
|
||||||
|
loop_fn.body.push(JoinInst::Compute(MirLikeInst::BinOp {
|
||||||
|
dst: ValueId(12),
|
||||||
|
op: BinOpKind::Add,
|
||||||
|
lhs: ValueId(10),
|
||||||
|
rhs: ValueId(11),
|
||||||
|
}));
|
||||||
|
loop_fn.body.push(JoinInst::Jump {
|
||||||
|
cont: JoinContId(2),
|
||||||
|
args: vec![ValueId(12)],
|
||||||
|
cond: None, // 単純経路: 無条件で k_exit に渡して終了
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut k_exit = JoinFunction::new(JoinFuncId::new(2), "k_exit".to_string(), vec![ValueId(12)]);
|
||||||
|
k_exit.body.push(JoinInst::Ret {
|
||||||
|
value: Some(ValueId(12)),
|
||||||
|
});
|
||||||
|
|
||||||
|
module.entry = Some(loop_fn.id);
|
||||||
|
module.add_function(loop_fn);
|
||||||
|
module.add_function(k_exit);
|
||||||
|
module
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern1_minimal_smoke() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_structured_pattern1();
|
||||||
|
let normalized = normalize_pattern1_minimal(&structured);
|
||||||
|
|
||||||
|
assert_eq!(normalized.phase, JoinIrPhase::Normalized);
|
||||||
|
assert!(!normalized.env_layouts.is_empty());
|
||||||
|
assert!(!normalized.functions.is_empty());
|
||||||
|
|
||||||
|
let restored = normalized
|
||||||
|
.to_structured()
|
||||||
|
.expect("should retain structured backup");
|
||||||
|
assert!(restored.is_structured());
|
||||||
|
assert_eq!(restored.functions.len(), structured.functions.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern1_roundtrip_structured_equivalent() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_structured_pattern1();
|
||||||
|
let normalized = normalize_pattern1_minimal(&structured);
|
||||||
|
let reconstructed = normalized_pattern1_to_structured(&normalized);
|
||||||
|
|
||||||
|
assert!(reconstructed.is_structured());
|
||||||
|
assert_eq!(reconstructed.functions.len(), structured.functions.len());
|
||||||
|
|
||||||
|
for (fid, func) in &structured.functions {
|
||||||
|
let recon = reconstructed
|
||||||
|
.functions
|
||||||
|
.get(fid)
|
||||||
|
.expect("function missing after reconstruction");
|
||||||
|
assert_eq!(recon.params.len(), func.params.len());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern1_exec_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_structured_pattern1();
|
||||||
|
let normalized = normalize_pattern1_minimal(&structured);
|
||||||
|
let reconstructed = normalized_pattern1_to_structured(&normalized);
|
||||||
|
|
||||||
|
let entry = structured.entry.unwrap_or(JoinFuncId::new(1));
|
||||||
|
let input = [JoinValue::Int(0)];
|
||||||
|
|
||||||
|
let result_structured = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let result_norm = run_joinir_vm_bridge(&reconstructed, entry, &input, false);
|
||||||
|
|
||||||
|
assert_eq!(result_structured, result_norm);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern1_exec_matches_structured_roundtrip_backup() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_structured_pattern1();
|
||||||
|
let normalized = normalize_pattern1_minimal(&structured);
|
||||||
|
let reconstructed = normalized_pattern1_to_structured(&normalized);
|
||||||
|
let restored_backup = normalized
|
||||||
|
.to_structured()
|
||||||
|
.expect("structured backup should be present");
|
||||||
|
|
||||||
|
let entry = structured.entry.unwrap_or(JoinFuncId::new(1));
|
||||||
|
let input = [JoinValue::Int(0)];
|
||||||
|
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let recon = run_joinir_vm_bridge(&reconstructed, entry, &input, false);
|
||||||
|
let restored = run_joinir_vm_bridge(&restored_backup, entry, &input, false);
|
||||||
|
|
||||||
|
assert_eq!(base, recon);
|
||||||
|
assert_eq!(base, restored);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern2_roundtrip_structure() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_pattern2_minimal_structured();
|
||||||
|
let normalized = normalize_pattern2_minimal(&structured);
|
||||||
|
assert_eq!(normalized.phase, JoinIrPhase::Normalized);
|
||||||
|
|
||||||
|
let reconstructed = normalized_pattern2_to_structured(&normalized);
|
||||||
|
assert!(reconstructed.is_structured());
|
||||||
|
assert_eq!(reconstructed.functions.len(), structured.functions.len());
|
||||||
|
|
||||||
|
for name in ["main", "loop_step", "k_exit"] {
|
||||||
|
let original_has = structured.functions.values().any(|f| f.name == name);
|
||||||
|
let reconstructed_has = reconstructed.functions.values().any(|f| f.name == name);
|
||||||
|
assert!(
|
||||||
|
original_has && reconstructed_has,
|
||||||
|
"expected function '{}' to exist in both modules",
|
||||||
|
name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern2_jsonparser_parse_number_real_vm_bridge_direct_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_jsonparser_parse_number_real_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
let cases = [
|
||||||
|
("42", 0, "42"),
|
||||||
|
("123abc", 0, "123"),
|
||||||
|
("9", 0, "9"),
|
||||||
|
("abc", 0, ""),
|
||||||
|
("xx7yy", 2, "7"),
|
||||||
|
("007", 0, "007"),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (s, pos, expected) in cases {
|
||||||
|
let input = [JoinValue::Str(s.to_string()), JoinValue::Int(pos)];
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(base, dev, "vm bridge mismatch for input '{}'", s);
|
||||||
|
assert_eq!(
|
||||||
|
dev,
|
||||||
|
JoinValue::Str(expected.to_string()),
|
||||||
|
"unexpected result for input '{}' (pos={}) (expected num_str)",
|
||||||
|
s,
|
||||||
|
pos
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern2_exec_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_pattern2_minimal_structured();
|
||||||
|
let normalized = normalize_pattern2_minimal(&structured);
|
||||||
|
let reconstructed = normalized_pattern2_to_structured(&normalized);
|
||||||
|
|
||||||
|
let entry = structured.entry.unwrap_or(JoinFuncId::new(0));
|
||||||
|
let input = [JoinValue::Int(0)];
|
||||||
|
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let recon = run_joinir_vm_bridge(&reconstructed, entry, &input, false);
|
||||||
|
|
||||||
|
assert_eq!(base, recon);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "normalize_pattern2_minimal")]
|
||||||
|
fn normalized_pattern2_rejects_non_pattern2_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
// Pattern1 Structured module should be rejected by Pattern2 normalizer.
|
||||||
|
let structured = build_structured_pattern1();
|
||||||
|
let _ = normalize_pattern2_minimal(&structured);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern2_real_loop_roundtrip_structure() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_pattern2_break_fixture_structured();
|
||||||
|
let normalized = normalize_pattern2_minimal(&structured);
|
||||||
|
let reconstructed = normalized_pattern2_to_structured(&normalized);
|
||||||
|
|
||||||
|
assert!(reconstructed.is_structured());
|
||||||
|
assert_eq!(structured.functions.len(), reconstructed.functions.len());
|
||||||
|
assert_eq!(structured.entry, reconstructed.entry);
|
||||||
|
|
||||||
|
let original_names: Vec<_> = structured
|
||||||
|
.functions
|
||||||
|
.values()
|
||||||
|
.map(|f| f.name.clone())
|
||||||
|
.collect();
|
||||||
|
for name in original_names {
|
||||||
|
let reconstructed_has = reconstructed.functions.values().any(|f| f.name == name);
|
||||||
|
assert!(
|
||||||
|
reconstructed_has,
|
||||||
|
"function '{}' missing after roundtrip",
|
||||||
|
name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern2_real_loop_exec_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_pattern2_break_fixture_structured();
|
||||||
|
let normalized = normalize_pattern2_minimal(&structured);
|
||||||
|
let reconstructed = normalized_pattern2_to_structured(&normalized);
|
||||||
|
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
let cases = [0, 1, 3, 5];
|
||||||
|
|
||||||
|
for n in cases {
|
||||||
|
let input = [JoinValue::Int(n)];
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let recon = run_joinir_vm_bridge(&reconstructed, entry, &input, false);
|
||||||
|
|
||||||
|
assert_eq!(base, recon, "mismatch at n={}", n);
|
||||||
|
let expected_sum = n * (n.saturating_sub(1)) / 2;
|
||||||
|
assert_eq!(
|
||||||
|
base,
|
||||||
|
JoinValue::Int(expected_sum),
|
||||||
|
"unexpected loop result at n={}",
|
||||||
|
n
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern1_runner_dev_switch_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_structured_pattern1();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
let input = [JoinValue::Int(7)];
|
||||||
|
|
||||||
|
let base = run_joinir_runner(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_runner(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(base, dev);
|
||||||
|
assert_eq!(base, JoinValue::Int(7));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern2_runner_dev_switch_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_pattern2_break_fixture_structured();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
let cases = [0, 1, 3, 5];
|
||||||
|
|
||||||
|
for n in cases {
|
||||||
|
let input = [JoinValue::Int(n)];
|
||||||
|
let base = run_joinir_runner(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_runner(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(base, dev, "runner mismatch at n={}", n);
|
||||||
|
let expected_sum = n * (n.saturating_sub(1)) / 2;
|
||||||
|
assert_eq!(
|
||||||
|
dev,
|
||||||
|
JoinValue::Int(expected_sum),
|
||||||
|
"runner result mismatch at n={}",
|
||||||
|
n
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern2_jsonparser_runner_dev_switch_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_jsonparser_skip_ws_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
let cases = [0, 1, 2, 5];
|
||||||
|
|
||||||
|
for len in cases {
|
||||||
|
let input = [JoinValue::Int(len)];
|
||||||
|
let base = run_joinir_runner(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_runner(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(base, dev, "runner mismatch at len={}", len);
|
||||||
|
assert_eq!(dev, JoinValue::Int(len), "unexpected result at len={}", len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern2_vm_bridge_direct_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_pattern2_break_fixture_structured();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
let cases = [0, 1, 3, 5];
|
||||||
|
|
||||||
|
for n in cases {
|
||||||
|
let input = [JoinValue::Int(n)];
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(base, dev, "vm bridge mismatch at n={}", n);
|
||||||
|
let expected_sum = n * (n.saturating_sub(1)) / 2;
|
||||||
|
assert_eq!(
|
||||||
|
dev,
|
||||||
|
JoinValue::Int(expected_sum),
|
||||||
|
"vm bridge result mismatch at n={}",
|
||||||
|
n
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern1_vm_bridge_direct_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_structured_pattern1();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
let cases = [0, 5, 7];
|
||||||
|
|
||||||
|
for n in cases {
|
||||||
|
let input = [JoinValue::Int(n)];
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(base, dev, "vm bridge mismatch at n={}", n);
|
||||||
|
assert_eq!(dev, JoinValue::Int(n), "unexpected result at n={}", n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern2_jsonparser_vm_bridge_direct_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_jsonparser_skip_ws_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
let cases = [0, 1, 2, 5];
|
||||||
|
|
||||||
|
for len in cases {
|
||||||
|
let input = [JoinValue::Int(len)];
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(base, dev, "vm bridge mismatch at len={}", len);
|
||||||
|
assert_eq!(dev, JoinValue::Int(len), "unexpected result at len={}", len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern2_jsonparser_skip_ws_real_vm_bridge_direct_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_jsonparser_skip_ws_real_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
let cases = [
|
||||||
|
(" abc", 0, 3),
|
||||||
|
("abc", 0, 0),
|
||||||
|
(" \t\nx", 0, 3),
|
||||||
|
(" \t\nx", 2, 3),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (s, pos, expected) in cases {
|
||||||
|
let input = [JoinValue::Str(s.to_string()), JoinValue::Int(pos)];
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(base, dev, "vm bridge mismatch for input '{}'", s);
|
||||||
|
assert_eq!(
|
||||||
|
dev,
|
||||||
|
JoinValue::Int(expected),
|
||||||
|
"unexpected result for input '{}' (pos={})",
|
||||||
|
s,
|
||||||
|
pos
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern2_jsonparser_atoi_vm_bridge_direct_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_jsonparser_atoi_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
let cases = [("42", 2, 42), ("123abc", 6, 123), ("007", 3, 7), ("", 0, 0)];
|
||||||
|
|
||||||
|
for (s, len, expected) in cases {
|
||||||
|
let input = [JoinValue::Str(s.to_string()), JoinValue::Int(len)];
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(base, dev, "vm bridge mismatch for input '{}'", s);
|
||||||
|
assert_eq!(
|
||||||
|
dev,
|
||||||
|
JoinValue::Int(expected),
|
||||||
|
"unexpected result for input '{}'",
|
||||||
|
s
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern2_jsonparser_atoi_real_vm_bridge_direct_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_jsonparser_atoi_real_structured_for_normalized_dev();
|
||||||
|
if nyash_rust::config::env::joinir_test_debug_enabled() {
|
||||||
|
eprintln!(
|
||||||
|
"[joinir/normalized-dev/test] structured jsonparser_atoi_real: {:#?}",
|
||||||
|
structured
|
||||||
|
);
|
||||||
|
let normalized = normalize_pattern2_minimal(&structured);
|
||||||
|
eprintln!(
|
||||||
|
"[joinir/normalized-dev/test] normalized jsonparser_atoi_real: {:#?}",
|
||||||
|
normalized
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
let cases = [
|
||||||
|
("42", 42),
|
||||||
|
("123abc", 123),
|
||||||
|
("007", 7),
|
||||||
|
("", 0),
|
||||||
|
("abc", 0),
|
||||||
|
("-42", -42),
|
||||||
|
("+7", 7),
|
||||||
|
("-0", 0),
|
||||||
|
("-12x", -12),
|
||||||
|
("+", 0),
|
||||||
|
("-", 0),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (s, expected) in cases {
|
||||||
|
let input = [JoinValue::Str(s.to_string())];
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(base, dev, "vm bridge mismatch for input '{}'", s);
|
||||||
|
assert_eq!(
|
||||||
|
dev,
|
||||||
|
JoinValue::Int(expected),
|
||||||
|
"unexpected result for input '{}'",
|
||||||
|
s
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
1231
tests/normalized_joinir_min/ownership.rs
Normal file
1231
tests/normalized_joinir_min/ownership.rs
Normal file
File diff suppressed because it is too large
Load Diff
149
tests/normalized_joinir_min/selfhost.rs
Normal file
149
tests/normalized_joinir_min/selfhost.rs
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_selfhost_token_scan_p2_vm_bridge_direct_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_selfhost_token_scan_p2_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
let cases = [0, 1, 3, 5];
|
||||||
|
|
||||||
|
for n in cases {
|
||||||
|
let input = [JoinValue::Int(n)];
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(base, dev, "vm bridge mismatch for n={}", n);
|
||||||
|
assert_eq!(
|
||||||
|
dev,
|
||||||
|
JoinValue::Int(n),
|
||||||
|
"unexpected result for selfhost_token_scan_p2 n={}",
|
||||||
|
n
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_selfhost_token_scan_p2_accum_vm_bridge_direct_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_selfhost_token_scan_p2_accum_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
let cases = [0, 1, 3, 5];
|
||||||
|
|
||||||
|
for n in cases {
|
||||||
|
let input = [JoinValue::Int(n)];
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
base, dev,
|
||||||
|
"vm bridge mismatch for selfhost_token_scan_p2_accum n={}",
|
||||||
|
n
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_selfhost_if_sum_p3_vm_bridge_direct_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_selfhost_if_sum_p3_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
let cases = [0, 1, 3, 4, 5];
|
||||||
|
|
||||||
|
for n in cases {
|
||||||
|
let input = [JoinValue::Int(n)];
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
base, dev,
|
||||||
|
"vm bridge mismatch for selfhost_if_sum_p3 n={}",
|
||||||
|
n
|
||||||
|
);
|
||||||
|
assert_eq!(dev, JoinValue::Int(expected_selfhost_if_sum_p3(n)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_selfhost_if_sum_p3_ext_vm_bridge_direct_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_selfhost_if_sum_p3_ext_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
let cases = [0, 1, 3, 4, 5];
|
||||||
|
|
||||||
|
for n in cases {
|
||||||
|
let input = [JoinValue::Int(n)];
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
base, dev,
|
||||||
|
"vm bridge mismatch for selfhost_if_sum_p3_ext n={}",
|
||||||
|
n
|
||||||
|
);
|
||||||
|
assert_eq!(dev, JoinValue::Int(expected_selfhost_if_sum_p3_ext(n)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expected_selfhost_if_sum_p3(n: i64) -> i64 {
|
||||||
|
if n <= 1 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
let sum = (n - 1) * n / 2;
|
||||||
|
let count = n - 1;
|
||||||
|
sum + count
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expected_selfhost_if_sum_p3_ext(n: i64) -> i64 {
|
||||||
|
if n <= 0 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// i=0: sum += 1
|
||||||
|
// i=1..n-1: sum += i, count += 1
|
||||||
|
let sum = 1 + (n - 1) * n / 2;
|
||||||
|
let count = n - 1;
|
||||||
|
sum + count
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Phase 53: selfhost args-parse P2 (practical variation with string carrier)
|
||||||
|
#[test]
|
||||||
|
fn normalized_selfhost_args_parse_p2_vm_bridge_direct_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_selfhost_args_parse_p2_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
// Test different argc values: 0, 1, 2, 3
|
||||||
|
let cases = [0, 1, 2, 3];
|
||||||
|
|
||||||
|
for argc in cases {
|
||||||
|
let input = [JoinValue::Int(argc)];
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
base, dev,
|
||||||
|
"vm bridge mismatch for selfhost_args_parse_p2 argc={}",
|
||||||
|
argc
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Phase 53: selfhost stmt-count P3 (practical variation with multi-branch if-else)
|
||||||
|
#[test]
|
||||||
|
fn normalized_selfhost_stmt_count_p3_vm_bridge_direct_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_selfhost_stmt_count_p3_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
// Test different statement counts: 0, 5, 10, 15
|
||||||
|
let cases = [0, 5, 10, 15];
|
||||||
|
|
||||||
|
for n in cases {
|
||||||
|
let input = [JoinValue::Int(n)];
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
base, dev,
|
||||||
|
"vm bridge mismatch for selfhost_stmt_count_p3 n={}",
|
||||||
|
n
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
462
tests/normalized_joinir_min/shapes.rs
Normal file
462
tests/normalized_joinir_min/shapes.rs
Normal file
@ -0,0 +1,462 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern3_if_sum_minimal_runner_dev_switch_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_pattern3_if_sum_min_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
|
||||||
|
// phase212_if_sum_min.hako 相当: sum=2 になることを期待
|
||||||
|
let input: [JoinValue; 0] = [];
|
||||||
|
|
||||||
|
let base = run_joinir_runner(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_runner(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(base, dev, "runner mismatch for P3 minimal if-sum");
|
||||||
|
assert_eq!(
|
||||||
|
dev,
|
||||||
|
JoinValue::Int(2),
|
||||||
|
"unexpected result for P3 minimal if-sum (expected sum=2)",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern3_if_sum_multi_vm_bridge_direct_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_pattern3_if_sum_multi_min_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
let input = [JoinValue::Int(0)];
|
||||||
|
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(base, dev, "vm bridge mismatch for P3 if-sum multi");
|
||||||
|
assert_eq!(
|
||||||
|
dev,
|
||||||
|
JoinValue::Int(2),
|
||||||
|
"unexpected result for P3 if-sum multi (expected sum=2)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn normalized_pattern3_json_if_sum_min_vm_bridge_direct_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_pattern3_json_if_sum_min_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
let input = [JoinValue::Int(0)];
|
||||||
|
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(base, dev, "vm bridge mismatch for P3 json if-sum");
|
||||||
|
assert_eq!(
|
||||||
|
dev,
|
||||||
|
JoinValue::Int(10),
|
||||||
|
"unexpected result for P3 json if-sum (expected sum=10)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "normalized_dev")]
|
||||||
|
#[test]
|
||||||
|
fn test_phase46_canonical_set_includes_p2_mid() {
|
||||||
|
use nyash_rust::mir::join_ir::normalized::shape_guard::{
|
||||||
|
is_canonical_shape, NormalizedDevShape,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Phase 46: Verify P2-Mid patterns are canonical
|
||||||
|
assert!(is_canonical_shape(&NormalizedDevShape::JsonparserAtoiReal));
|
||||||
|
assert!(is_canonical_shape(
|
||||||
|
&NormalizedDevShape::JsonparserParseNumberReal
|
||||||
|
));
|
||||||
|
assert!(is_canonical_shape(
|
||||||
|
&NormalizedDevShape::Pattern3IfSumMinimal
|
||||||
|
));
|
||||||
|
assert!(is_canonical_shape(&NormalizedDevShape::Pattern3IfSumMulti));
|
||||||
|
assert!(is_canonical_shape(&NormalizedDevShape::Pattern3IfSumJson));
|
||||||
|
|
||||||
|
// Verify P2-Core patterns still canonical
|
||||||
|
assert!(is_canonical_shape(&NormalizedDevShape::Pattern2Mini));
|
||||||
|
assert!(is_canonical_shape(
|
||||||
|
&NormalizedDevShape::JsonparserSkipWsMini
|
||||||
|
));
|
||||||
|
assert!(is_canonical_shape(
|
||||||
|
&NormalizedDevShape::JsonparserSkipWsReal
|
||||||
|
));
|
||||||
|
assert!(is_canonical_shape(&NormalizedDevShape::JsonparserAtoiMini));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Phase 47-A: Test P3 minimal normalization
|
||||||
|
#[test]
|
||||||
|
fn test_phase47a_pattern3_if_sum_minimal_normalization() {
|
||||||
|
use nyash_rust::mir::join_ir::normalized::normalize_pattern3_if_sum_minimal;
|
||||||
|
|
||||||
|
let module = build_pattern3_if_sum_min_structured_for_normalized_dev();
|
||||||
|
|
||||||
|
// Test that normalization succeeds (includes shape detection internally)
|
||||||
|
let result = normalize_pattern3_if_sum_minimal(&module);
|
||||||
|
assert!(
|
||||||
|
result.is_ok(),
|
||||||
|
"P3 normalization should succeed (shape detection + normalization): {:?}",
|
||||||
|
result.err()
|
||||||
|
);
|
||||||
|
|
||||||
|
let normalized = result.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
normalized.functions.len(),
|
||||||
|
module.functions.len(),
|
||||||
|
"Normalized function count should match Structured"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Verify normalized module has proper phase
|
||||||
|
assert_eq!(
|
||||||
|
normalized.phase,
|
||||||
|
nyash_rust::mir::join_ir::JoinIrPhase::Normalized,
|
||||||
|
"Normalized module should have Normalized phase"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Phase 47-A: Test P3 VM execution (basic smoke test)
|
||||||
|
#[test]
|
||||||
|
fn test_phase47a_pattern3_if_sum_minimal_runner() {
|
||||||
|
let module = build_pattern3_if_sum_min_structured_for_normalized_dev();
|
||||||
|
|
||||||
|
// Basic test: module should be runnable through JoinIR runner
|
||||||
|
// This test verifies the P3 fixture is valid and generates proper JoinIR
|
||||||
|
assert_eq!(module.functions.len(), 3, "P3 should have 3 functions");
|
||||||
|
|
||||||
|
let entry = module.entry.expect("P3 should have entry function");
|
||||||
|
assert_eq!(entry.0, 0, "Entry should be function 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Phase 48-A: Test P4 minimal normalization
|
||||||
|
#[test]
|
||||||
|
fn test_phase48a_pattern4_continue_minimal_normalization() {
|
||||||
|
use nyash_rust::mir::join_ir::normalized::normalize_pattern4_continue_minimal;
|
||||||
|
|
||||||
|
let module = build_pattern4_continue_min_structured_for_normalized_dev();
|
||||||
|
|
||||||
|
// Test that normalization succeeds (includes shape detection internally)
|
||||||
|
let result = normalize_pattern4_continue_minimal(&module);
|
||||||
|
assert!(
|
||||||
|
result.is_ok(),
|
||||||
|
"P4 normalization should succeed (shape detection + normalization): {:?}",
|
||||||
|
result.err()
|
||||||
|
);
|
||||||
|
|
||||||
|
let normalized = result.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
normalized.functions.len(),
|
||||||
|
module.functions.len(),
|
||||||
|
"Normalized function count should match Structured"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Verify normalized module has proper phase
|
||||||
|
assert_eq!(
|
||||||
|
normalized.phase,
|
||||||
|
nyash_rust::mir::join_ir::JoinIrPhase::Normalized,
|
||||||
|
"Normalized module should have Normalized phase"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Phase 48-A: Test P4 VM execution (basic smoke test)
|
||||||
|
#[test]
|
||||||
|
fn test_phase48a_pattern4_continue_minimal_runner() {
|
||||||
|
let module = build_pattern4_continue_min_structured_for_normalized_dev();
|
||||||
|
|
||||||
|
// Basic test: module should be runnable through JoinIR runner
|
||||||
|
// This test verifies the P4 fixture is valid and generates proper JoinIR
|
||||||
|
assert_eq!(module.functions.len(), 3, "P4 should have 3 functions");
|
||||||
|
|
||||||
|
let entry = module.entry.expect("P4 should have entry function");
|
||||||
|
assert_eq!(entry.0, 0, "Entry should be function 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Phase 48-A: Test P4 minimal Runner dev switch matches Structured
|
||||||
|
#[test]
|
||||||
|
fn test_normalized_pattern4_continue_minimal_runner_dev_switch_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_pattern4_continue_min_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
|
||||||
|
// pattern4_continue_min fixture: acc=4 (skipped i==2, so counted 0,1,3,4)
|
||||||
|
let input = [JoinValue::Int(5)]; // n = 5
|
||||||
|
|
||||||
|
let base = run_joinir_runner(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_runner(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(base, dev, "runner mismatch for P4 minimal continue");
|
||||||
|
assert_eq!(
|
||||||
|
dev,
|
||||||
|
JoinValue::Int(4),
|
||||||
|
"unexpected result for P4 minimal continue (expected acc=4, skipped i==2)",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Phase 48-A: Test P4 minimal VM Bridge direct matches Structured
|
||||||
|
#[test]
|
||||||
|
fn test_normalized_pattern4_continue_minimal_vm_bridge_direct_matches_structured() {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_pattern4_continue_min_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
|
||||||
|
// pattern4_continue_min fixture: acc=4 (skipped i==2)
|
||||||
|
let input = [JoinValue::Int(5)]; // n = 5
|
||||||
|
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &input, true);
|
||||||
|
|
||||||
|
assert_eq!(base, dev, "vm bridge mismatch for P4 minimal continue");
|
||||||
|
assert_eq!(
|
||||||
|
dev,
|
||||||
|
JoinValue::Int(4),
|
||||||
|
"unexpected result for P4 minimal continue (expected acc=4)",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Phase 48-C: P4 minimal should use canonical normalized route even without env
|
||||||
|
#[test]
|
||||||
|
fn test_normalized_pattern4_continue_minimal_canonical_matches_structured() {
|
||||||
|
let structured = build_pattern4_continue_min_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
|
||||||
|
let input = [JoinValue::Int(5)];
|
||||||
|
let structured_res = run_joinir_vm_bridge_structured_only(&structured, entry, &input);
|
||||||
|
let canonical = run_joinir_vm_bridge(&structured, entry, &input, false);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
structured_res, canonical,
|
||||||
|
"canonical P4 minimal result mismatch"
|
||||||
|
);
|
||||||
|
assert_eq!(canonical, JoinValue::Int(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Phase 48-B: JsonParser _parse_array continue skip_ws (dev-only) VM Bridge comparison
|
||||||
|
#[test]
|
||||||
|
fn test_normalized_pattern4_jsonparser_parse_array_continue_skip_ws_vm_bridge_direct_matches_structured(
|
||||||
|
) {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_jsonparser_parse_array_continue_skip_ws_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
|
||||||
|
// Fixture mirrors pattern4_continue_min: skip i == 2
|
||||||
|
let cases = [3, 5, 7];
|
||||||
|
|
||||||
|
for n in cases {
|
||||||
|
let args = [JoinValue::Int(n)];
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &args, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &args, true);
|
||||||
|
assert_eq!(
|
||||||
|
base, dev,
|
||||||
|
"vm bridge mismatch for array continue case n={}",
|
||||||
|
n
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Phase 48-C: JsonParser _parse_array continue skip_ws canonical route should match Structured
|
||||||
|
#[test]
|
||||||
|
fn test_normalized_pattern4_jsonparser_parse_array_continue_skip_ws_canonical_matches_structured() {
|
||||||
|
let structured = build_jsonparser_parse_array_continue_skip_ws_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
|
||||||
|
let cases = [3, 5, 7];
|
||||||
|
for n in cases {
|
||||||
|
let args = [JoinValue::Int(n)];
|
||||||
|
let structured_res = run_joinir_vm_bridge_structured_only(&structured, entry, &args);
|
||||||
|
let canonical = run_joinir_vm_bridge(&structured, entry, &args, false);
|
||||||
|
assert_eq!(
|
||||||
|
structured_res, canonical,
|
||||||
|
"canonical array continue mismatch n={}",
|
||||||
|
n
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Phase 48-B: JsonParser _parse_object continue skip_ws (dev-only) VM Bridge comparison
|
||||||
|
#[test]
|
||||||
|
fn test_normalized_pattern4_jsonparser_parse_object_continue_skip_ws_vm_bridge_direct_matches_structured(
|
||||||
|
) {
|
||||||
|
let _ctx = normalized_dev_test_ctx();
|
||||||
|
let structured = build_jsonparser_parse_object_continue_skip_ws_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
|
||||||
|
// Fixture mirrors pattern4_continue_min: skip i == 2
|
||||||
|
let cases = [4, 6, 8];
|
||||||
|
|
||||||
|
for n in cases {
|
||||||
|
let args = [JoinValue::Int(n)];
|
||||||
|
let base = run_joinir_vm_bridge(&structured, entry, &args, false);
|
||||||
|
let dev = run_joinir_vm_bridge(&structured, entry, &args, true);
|
||||||
|
assert_eq!(
|
||||||
|
base, dev,
|
||||||
|
"vm bridge mismatch for object continue case n={}",
|
||||||
|
n
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Phase 48-C: JsonParser _parse_object continue skip_ws canonical route should match Structured
|
||||||
|
#[test]
|
||||||
|
fn test_normalized_pattern4_jsonparser_parse_object_continue_skip_ws_canonical_matches_structured()
|
||||||
|
{
|
||||||
|
let structured = build_jsonparser_parse_object_continue_skip_ws_structured_for_normalized_dev();
|
||||||
|
let entry = structured.entry.expect("structured entry required");
|
||||||
|
|
||||||
|
let cases = [4, 6, 8];
|
||||||
|
for n in cases {
|
||||||
|
let args = [JoinValue::Int(n)];
|
||||||
|
let structured_res = run_joinir_vm_bridge_structured_only(&structured, entry, &args);
|
||||||
|
let canonical = run_joinir_vm_bridge(&structured, entry, &args, false);
|
||||||
|
assert_eq!(
|
||||||
|
structured_res, canonical,
|
||||||
|
"canonical object continue mismatch n={}",
|
||||||
|
n
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Phase 54: False positive observation test - P2 structural axis discrimination
|
||||||
|
///
|
||||||
|
/// This test validates that structural detection can discriminate between
|
||||||
|
/// canonical P2 and selfhost P2 shapes using structural features alone.
|
||||||
|
#[test]
|
||||||
|
fn test_phase54_structural_axis_discrimination_p2() {
|
||||||
|
use nyash_rust::mir::join_ir::normalized::shape_guard::{
|
||||||
|
detect_shapes, is_canonical_shape, NormalizedDevShape,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Canonical P2 shapes
|
||||||
|
let canonical_p2_shapes = vec![
|
||||||
|
build_pattern2_minimal_structured(),
|
||||||
|
build_jsonparser_skip_ws_structured_for_normalized_dev(),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Selfhost P2 shapes (Phase 53)
|
||||||
|
let selfhost_p2_shapes = vec![
|
||||||
|
build_selfhost_args_parse_p2_structured_for_normalized_dev(),
|
||||||
|
build_selfhost_token_scan_p2_structured_for_normalized_dev(),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Canonical P2 should be detected as canonical, NOT selfhost
|
||||||
|
for canonical in &canonical_p2_shapes {
|
||||||
|
let shapes = detect_shapes(canonical);
|
||||||
|
let has_canonical = shapes.iter().any(|s| is_canonical_shape(s));
|
||||||
|
let has_selfhost_p2 = shapes.iter().any(|s| {
|
||||||
|
matches!(
|
||||||
|
s,
|
||||||
|
NormalizedDevShape::SelfhostArgsParseP2
|
||||||
|
| NormalizedDevShape::SelfhostTokenScanP2
|
||||||
|
| NormalizedDevShape::SelfhostTokenScanP2Accum
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
has_canonical,
|
||||||
|
"canonical P2 should be detected as canonical: {:?}",
|
||||||
|
shapes
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
!has_selfhost_p2,
|
||||||
|
"canonical P2 should NOT be detected as selfhost: {:?}",
|
||||||
|
shapes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Selfhost P2 should be detected as selfhost, NOT canonical
|
||||||
|
for selfhost in &selfhost_p2_shapes {
|
||||||
|
let shapes = detect_shapes(selfhost);
|
||||||
|
let has_canonical = shapes.iter().any(|s| is_canonical_shape(s));
|
||||||
|
let has_selfhost_p2 = shapes.iter().any(|s| {
|
||||||
|
matches!(
|
||||||
|
s,
|
||||||
|
NormalizedDevShape::SelfhostArgsParseP2
|
||||||
|
| NormalizedDevShape::SelfhostTokenScanP2
|
||||||
|
| NormalizedDevShape::SelfhostTokenScanP2Accum
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
!has_canonical,
|
||||||
|
"selfhost P2 should NOT be detected as canonical: {:?}",
|
||||||
|
shapes
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
has_selfhost_p2,
|
||||||
|
"selfhost P2 should be detected as selfhost (with name guard): {:?}",
|
||||||
|
shapes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Phase 54: False positive observation test - P3 structural axis discrimination
|
||||||
|
///
|
||||||
|
/// This test validates that structural detection can discriminate between
|
||||||
|
/// canonical P3 and selfhost P3 shapes using structural features alone.
|
||||||
|
#[test]
|
||||||
|
fn test_phase54_structural_axis_discrimination_p3() {
|
||||||
|
use nyash_rust::mir::join_ir::normalized::shape_guard::{
|
||||||
|
detect_shapes, is_canonical_shape, NormalizedDevShape,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Canonical P3 shapes
|
||||||
|
let canonical_p3_shapes = vec![
|
||||||
|
build_pattern3_if_sum_min_structured_for_normalized_dev(),
|
||||||
|
build_pattern3_if_sum_multi_min_structured_for_normalized_dev(),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Selfhost P3 shapes (Phase 53)
|
||||||
|
let selfhost_p3_shapes = vec![
|
||||||
|
build_selfhost_stmt_count_p3_structured_for_normalized_dev(),
|
||||||
|
build_selfhost_if_sum_p3_structured_for_normalized_dev(),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Canonical P3 should be detected as canonical, NOT selfhost
|
||||||
|
for canonical in &canonical_p3_shapes {
|
||||||
|
let shapes = detect_shapes(canonical);
|
||||||
|
let has_canonical = shapes.iter().any(|s| is_canonical_shape(s));
|
||||||
|
let has_selfhost_p3 = shapes.iter().any(|s| {
|
||||||
|
matches!(
|
||||||
|
s,
|
||||||
|
NormalizedDevShape::SelfhostStmtCountP3
|
||||||
|
| NormalizedDevShape::SelfhostIfSumP3
|
||||||
|
| NormalizedDevShape::SelfhostIfSumP3Ext
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
has_canonical,
|
||||||
|
"canonical P3 should be detected as canonical: {:?}",
|
||||||
|
shapes
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
!has_selfhost_p3,
|
||||||
|
"canonical P3 should NOT be detected as selfhost: {:?}",
|
||||||
|
shapes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Selfhost P3 should be detected as selfhost, NOT canonical
|
||||||
|
for selfhost in &selfhost_p3_shapes {
|
||||||
|
let shapes = detect_shapes(selfhost);
|
||||||
|
let has_canonical = shapes.iter().any(|s| is_canonical_shape(s));
|
||||||
|
let has_selfhost_p3 = shapes.iter().any(|s| {
|
||||||
|
matches!(
|
||||||
|
s,
|
||||||
|
NormalizedDevShape::SelfhostStmtCountP3
|
||||||
|
| NormalizedDevShape::SelfhostIfSumP3
|
||||||
|
| NormalizedDevShape::SelfhostIfSumP3Ext
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
!has_canonical,
|
||||||
|
"selfhost P3 should NOT be detected as canonical: {:?}",
|
||||||
|
shapes
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
has_selfhost_p3,
|
||||||
|
"selfhost P3 should be detected as selfhost (with name guard): {:?}",
|
||||||
|
shapes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user