package engine import ( "strings" "testing" ) // ============================================================ // StrictMode 测试 // ============================================================ func TestStrictMode_Check_PanicsWhenEnabled(t *testing.T) { s := &StrictMode{} obs := &MockObserver{} defer func() { r := recover() if r == nil { t.Fatal("expected panic when strict mode condition is enabled") } msg, ok := r.(string) if !ok { t.Fatal("panic value should be string") } if !strings.Contains(msg, "strict mode violation") { t.Errorf("panic message should contain 'strict mode violation', got: %s", msg) } if !strings.Contains(msg, "test_condition") { t.Errorf("panic message should contain condition name, got: %s", msg) } if !strings.Contains(msg, "some detail") { t.Errorf("panic message should contain detail, got: %s", msg) } }() s.Check("test_condition", true, obs, "some detail") } func TestStrictMode_Check_RecordsEventWhenDisabled(t *testing.T) { s := &StrictMode{} obs := &MockObserver{} s.Check("test_condition", false, obs, "some detail") if len(obs.Events) != 1 { t.Fatalf("expected 1 event, got %d", len(obs.Events)) } evt := obs.Events[0] if evt.Name != "strict_mode_would_fail" { t.Errorf("expected event name 'strict_mode_would_fail', got '%s'", evt.Name) } if evt.Data["condition"] != "test_condition" { t.Errorf("expected condition 'test_condition', got '%v'", evt.Data["condition"]) } if evt.Data["detail"] != "some detail" { t.Errorf("expected detail 'some detail', got '%v'", evt.Data["detail"]) } } func TestStrictMode_Check_NilObserverDoesNotPanic(t *testing.T) { s := &StrictMode{} // nil observer 时 enabled=false 不应该 panic s.Check("test", false, nil, "detail") } func TestStrictMode_CheckToolResultPairing_Panics(t *testing.T) { s := &StrictMode{ToolResultPairing: true} obs := &MockObserver{} defer func() { r := recover() if r == nil { t.Fatal("expected panic") } msg := r.(string) if !strings.Contains(msg, "tool_result_pairing_mismatch") { t.Errorf("expected tool_result_pairing_mismatch in panic message, got: %s", msg) } }() s.CheckToolResultPairing(obs, "diagnostic detail") } func TestStrictMode_CheckToolResultPairing_Records(t *testing.T) { s := &StrictMode{ToolResultPairing: false} obs := &MockObserver{} s.CheckToolResultPairing(obs, "diagnostic detail") if len(obs.Events) != 1 { t.Fatalf("expected 1 event, got %d", len(obs.Events)) } } func TestStrictMode_CheckCompactFailure_Panics(t *testing.T) { s := &StrictMode{CompactFailure: true} obs := &MockObserver{} defer func() { r := recover() if r == nil { t.Fatal("expected panic") } }() s.CheckCompactFailure(obs, "compact failed") } func TestStrictMode_CheckCompactFailure_Records(t *testing.T) { s := &StrictMode{CompactFailure: false} obs := &MockObserver{} s.CheckCompactFailure(obs, "compact failed") if len(obs.Events) != 1 { t.Fatalf("expected 1 event, got %d", len(obs.Events)) } } func TestStrictMode_CheckNormalizerError_Panics(t *testing.T) { s := &StrictMode{NormalizerError: true} obs := &MockObserver{} defer func() { r := recover() if r == nil { t.Fatal("expected panic") } }() s.CheckNormalizerError(obs, "normalizer error") } func TestStrictMode_CheckNormalizerError_Records(t *testing.T) { s := &StrictMode{NormalizerError: false} obs := &MockObserver{} s.CheckNormalizerError(obs, "normalizer error") if len(obs.Events) != 1 { t.Fatalf("expected 1 event, got %d", len(obs.Events)) } } func TestStrictMode_IndependentFlags(t *testing.T) { // 每个标志独立控制 s := &StrictMode{ ToolResultPairing: false, CompactFailure: false, NormalizerError: false, } obs := &MockObserver{} s.CheckToolResultPairing(obs, "") s.CheckCompactFailure(obs, "") s.CheckNormalizerError(obs, "") if len(obs.Events) != 3 { t.Errorf("expected 3 events (all non-panic), got %d", len(obs.Events)) } }