package observability import ( "sync" "sync/atomic" "testing" ) func TestMaxSeen_FirstObservationExports(t *testing.T) { m := NewMaxSeen() var got string var val float64 var calls int m.RecordAndExport("src-A", 1, func(k string, v float64) { got = k val = v calls++ }) if calls != 1 || got != "src-A" || val != 1 { t.Fatalf("first: want 1 export src-A=1, got calls=%d key=%q val=%v", calls, got, val) } if m.Get("src-A") != 1 { t.Fatalf("Get: want 1, got %d", m.Get("src-A")) } } func TestMaxSeen_StrictlyMonotonic(t *testing.T) { m := NewMaxSeen() var calls int exp := func(string, float64) { calls++ } m.RecordAndExport("src-A", 5, exp) m.RecordAndExport("src-A", 3, exp) // smaller: should not export m.RecordAndExport("src-A", 5, exp) // equal: should not export m.RecordAndExport("src-A", 7, exp) // larger: should export m.RecordAndExport("src-A", 2, exp) // smaller: should not export m.RecordAndExport("src-A", 10, exp) // larger: should export if calls != 3 { t.Fatalf("want 3 exports (1, 7, 10), got %d", calls) } if m.Get("src-A") != 10 { t.Fatalf("Get: want 10, got %d", m.Get("src-A")) } } func TestMaxSeen_PerKeyIsolation(t *testing.T) { m := NewMaxSeen() exp := func(string, float64) {} m.RecordAndExport("src-A", 100, exp) m.RecordAndExport("src-B", 5, exp) if m.Get("src-A") != 100 { t.Fatalf("src-A: want 100, got %d", m.Get("src-A")) } if m.Get("src-B") != 5 { t.Fatalf("src-B: want 5, got %d", m.Get("src-B")) } if m.Get("src-C") != 0 { t.Fatalf("src-C (unseen): want 0, got %d", m.Get("src-C")) } } func TestMaxSeen_ConcurrentSameKey(t *testing.T) { m := NewMaxSeen() var exports atomic.Int64 exp := func(string, float64) { exports.Add(1) } var wg sync.WaitGroup for g := 0; g < 8; g++ { wg.Add(1) go func(g int) { defer wg.Done() for v := 1; v <= 1000; v++ { // Each goroutine uses a different value range // so we know the global max is 8*1000 - 7 = 7993 // (8 goroutines, each writes its own values // shifted by g*1000). Just write all of them. _ = g m.RecordAndExport("src", uint32(v), exp) } }(g) } wg.Wait() // We don't assert on the number of exports (it can vary // based on CAS contention); we assert that the final // observed max is the actual global max written. if m.Get("src") != 1000 { t.Fatalf("final max: want 1000, got %d", m.Get("src")) } if exports.Load() < 1 { t.Fatalf("expected ≥1 export, got %d", exports.Load()) } } func TestMaxSeen_NilExportIsNoOp(t *testing.T) { m := NewMaxSeen() // Should not panic. m.RecordAndExport("src-A", 1, nil) m.RecordAndExport("src-A", 5, nil) if m.Get("src-A") != 5 { t.Fatalf("nil export should still update state; got %d", m.Get("src-A")) } }