From fb7d953202393a6da2c1c53047dadf64dc5566da Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 18 May 2026 21:30:52 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=B9=20Fix=20parseNumber=20edge=20cases?= =?UTF-8?q?=20handling=20NaN=20and=20+Inf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: theRebelliousNerd <187437903+theRebelliousNerd@users.noreply.github.com> --- internal/campaign/edge_case_detector.go | 11 +++--- .../campaign/edge_case_detector_gaps_test.go | 15 ++++---- internal/campaign/edge_case_detector_test.go | 36 ++++++++++++++++--- 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/internal/campaign/edge_case_detector.go b/internal/campaign/edge_case_detector.go index 6a84513f..a1a6427e 100644 --- a/internal/campaign/edge_case_detector.go +++ b/internal/campaign/edge_case_detector.go @@ -6,6 +6,7 @@ package campaign import ( "context" "fmt" + "math" "path/filepath" "sort" "strings" @@ -585,7 +586,11 @@ func (d *EdgeCaseDetector) parseNumber(arg interface{}) (float64, bool) { case float32: return float64(v), true case float64: - return v, true + if math.IsNaN(v) || math.IsInf(v, 0) { + return 0, false + } else { + return v, true + } default: return 0, false } @@ -808,10 +813,6 @@ func (a *EdgeCaseAnalysis) GetPreworkTasks() []string { // If an empty IntelligenceReport is passed, missing dependencies or metrics could lead // to incorrect Action decisions. -// TODO: Missing Edge Case - Type Coercion: parseNumber handling NaN and +Inf. -// Check if Mangle returns NaN/Inf for floats; complexity logic might permanently -// trigger ActionRefactorFirst or create panics on math operations. - // TODO: Missing Edge Case - User Request Extremes: Unknown file extensions. // For `.xyz` or unrecognized file extensions, suggestSplits appends hardcoded // golang/typescript-style suffixes (`_types`, `_helpers`) which could be invalid syntax. diff --git a/internal/campaign/edge_case_detector_gaps_test.go b/internal/campaign/edge_case_detector_gaps_test.go index a9cd9be9..73c5c34e 100644 --- a/internal/campaign/edge_case_detector_gaps_test.go +++ b/internal/campaign/edge_case_detector_gaps_test.go @@ -7,7 +7,6 @@ import ( "strings" "testing" "time" - ) // ============================================================================ @@ -18,7 +17,7 @@ import ( // TestEdgeCaseDetectorGap_AnalyzeFiles_CanceledContext (Vector 1: Empty/Nil Contexts) func TestEdgeCaseDetectorGap_AnalyzeFiles_CanceledContext(t *testing.T) { detector := NewEdgeCaseDetector(nil, nil) - + ctx, cancel := context.WithCancel(context.Background()) cancel() // Cancel immediately @@ -37,7 +36,7 @@ func TestEdgeCaseDetectorGap_AnalyzeFiles_CanceledContext(t *testing.T) { // TestEdgeCaseDetectorGap_AnalyzeFiles_EmptyIntelligence (Vector 1: Empty Intel) func TestEdgeCaseDetectorGap_AnalyzeFiles_EmptyIntelligence(t *testing.T) { detector := NewEdgeCaseDetector(nil, nil) - + // Initialized but empty intelligence report intel := &IntelligenceReport{ FileTopology: make(map[string]FileInfo), @@ -79,13 +78,13 @@ func TestEdgeCaseDetectorGap_TypeCoercion(t *testing.T) { // Test NaN nanVal, ok := detector.parseNumber(math.NaN()) - if !ok || !math.IsNaN(nanVal) { + if ok || nanVal != 0 { t.Errorf("parseNumber failed to handle NaN") } // Test Inf infVal, ok := detector.parseNumber(math.Inf(1)) - if !ok || !math.IsInf(infVal, 1) { + if ok || infVal != 0 { t.Errorf("parseNumber failed to handle Inf") } @@ -124,7 +123,7 @@ func TestEdgeCaseDetectorGap_ImpactScoreBounds(t *testing.T) { decision := FileDecision{ Dependents: []string{}, // length 0 } - + // Simulate queryDependencies impact calculation decision.ImpactScore = len(decision.Dependents) if decision.ImpactScore < 0 { @@ -142,7 +141,7 @@ func TestEdgeCaseDetectorGap_FormatForContext_Limits(t *testing.T) { } output := analysis.FormatForContext() - + // Should truncate and show "and X more" if !strings.Contains(output, "and 4990 more") { t.Errorf("Expected truncation message 'and 4990 more', output was: %s", output) @@ -173,7 +172,7 @@ func TestEdgeCaseDetectorGap_GodFile(t *testing.T) { // TestEdgeCaseDetectorGap_Concurrency (Vector 4: Concurrency Safety) func TestEdgeCaseDetectorGap_Concurrency(t *testing.T) { detector := NewEdgeCaseDetector(nil, nil) - + // Run 10 goroutines calling AnalyzeFiles with the same detector to check for race conditions done := make(chan bool) for i := 0; i < 10; i++ { diff --git a/internal/campaign/edge_case_detector_test.go b/internal/campaign/edge_case_detector_test.go index 30bceb09..3dd73957 100644 --- a/internal/campaign/edge_case_detector_test.go +++ b/internal/campaign/edge_case_detector_test.go @@ -2,6 +2,7 @@ package campaign import ( "context" + "math" "strings" "testing" "time" @@ -307,11 +308,6 @@ func TestEdgeCaseAnalysis_FileCategories(t *testing.T) { // Test with `IntelligenceReport{FileTopology: map[string]FileInfo{}, GitChurnHotspots: []GitChurn{}}`. // Expected behavior: Should default to ActionCreate gracefully. -// TODO: Missing Edge Case - Type Coercion: parseNumber handling NaN and +Inf. -// Test passing a float64 representing math.NaN() or math.Inf(1) to parseNumber. -// Expected behavior: If Mangle returns an anomalous float, complexity should not become infinite -// or cause ActionRefactorFirst permanently. - // TODO: Missing Edge Case - User Request Extremes: Unknown file extensions. // Test `detectLanguage` with an esoteric extension like `.zig` or `.mojo` or `.xyz`. // Expected behavior: Should return "unknown" and suggestions must still be logically sound without crashing. @@ -329,3 +325,33 @@ func TestEdgeCaseAnalysis_FileCategories(t *testing.T) { // TODO: Missing Edge Case - Extreme Values: Max file size boundaries. // Test determineAction with `LineCount = math.MaxInt32`. // Expected behavior: Should cleanly suggest ActionModularize without overflow in heuristics (e.g., complexity calc). + +func TestEdgeCaseDetector_ParseNumber(t *testing.T) { + detector := NewEdgeCaseDetector(nil, nil) + + tests := []struct { + name string + input interface{} + expected float64 + ok bool + }{ + {"Valid int", 42, 42.0, true}, + {"Valid float64", 3.14, 3.14, true}, + {"NaN", math.NaN(), 0, false}, + {"Positive Infinity", math.Inf(1), 0, false}, + {"Negative Infinity", math.Inf(-1), 0, false}, + {"Invalid type", "not a number", 0, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, ok := detector.parseNumber(tt.input) + if ok != tt.ok { + t.Errorf("parseNumber() ok = %v, want %v", ok, tt.ok) + } + if ok && result != tt.expected { + t.Errorf("parseNumber() result = %v, want %v", result, tt.expected) + } + }) + } +}