package notify import ( "errors" "sync" "testing" "time" ) func TestDefaultSignalReliabilityOptions(t *testing.T) { opts := DefaultSignalReliabilityOptions() if !opts.Enabled { t.Fatal("Enabled should default to true in exported options") } if got, want := opts.AckTimeout, defaultSignalAckTimeout; got != want { t.Fatalf("AckTimeout mismatch: got %v want %v", got, want) } if got, want := opts.SendRetry, defaultSignalSendRetry; got != want { t.Fatalf("SendRetry mismatch: got %d want %d", got, want) } if got, want := opts.ReceiveCacheLimit, defaultReceivedSignalCacheLimit; got != want { t.Fatalf("ReceiveCacheLimit mismatch: got %d want %d", got, want) } } func TestUseSignalReliabilityClientAppliesAndTrimsCache(t *testing.T) { client := NewClient().(*ClientCommon) cache := client.getReceivedSignalCache() cache.seenOrRemember("client", 1) cache.seenOrRemember("client", 2) cache.seenOrRemember("client", 3) err := UseSignalReliabilityClient(client, &SignalReliabilityOptions{ Enabled: true, AckTimeout: 25 * time.Millisecond, SendRetry: 5, ReceiveCacheLimit: 2, }) if err != nil { t.Fatalf("UseSignalReliabilityClient failed: %v", err) } cfg := client.getSignalReliabilityConfig() if got, want := cfg.AckTimeout, 25*time.Millisecond; got != want { t.Fatalf("AckTimeout mismatch: got %v want %v", got, want) } if got, want := cfg.SendRetry, 5; got != want { t.Fatalf("SendRetry mismatch: got %d want %d", got, want) } if got, want := cfg.ReceiveCacheLimit, 2; got != want { t.Fatalf("ReceiveCacheLimit mismatch: got %d want %d", got, want) } if !cfg.Enabled || !cfg.EnableConfigured { t.Fatalf("signal reliability enable state mismatch: %+v", cfg) } if duplicate := cache.seenOrRemember("client", 1); duplicate { t.Fatal("oldest signal should be trimmed after shrinking receive cache limit") } } func TestUseSignalReliabilityServerNormalizesInvalidValues(t *testing.T) { server := NewServer().(*ServerCommon) err := UseSignalReliabilityServer(server, &SignalReliabilityOptions{ Enabled: false, AckTimeout: 0, SendRetry: 0, ReceiveCacheLimit: 0, }) if err != nil { t.Fatalf("UseSignalReliabilityServer failed: %v", err) } cfg := server.getSignalReliabilityConfig() if got, want := cfg.AckTimeout, defaultSignalAckTimeout; got != want { t.Fatalf("AckTimeout mismatch: got %v want %v", got, want) } if got, want := cfg.SendRetry, defaultSignalSendRetry; got != want { t.Fatalf("SendRetry mismatch: got %d want %d", got, want) } if got, want := cfg.ReceiveCacheLimit, defaultReceivedSignalCacheLimit; got != want { t.Fatalf("ReceiveCacheLimit mismatch: got %d want %d", got, want) } if cfg.Enabled || !cfg.EnableConfigured { t.Fatalf("signal reliability enable state mismatch: %+v", cfg) } } func TestUseSignalReliabilityRejectsNilTarget(t *testing.T) { if err := UseSignalReliabilityClient(nil, nil); !errors.Is(err, errSignalReliabilityClientNil) { t.Fatalf("UseSignalReliabilityClient nil target error = %v, want %v", err, errSignalReliabilityClientNil) } if err := UseSignalReliabilityServer(nil, nil); !errors.Is(err, errSignalReliabilityServerNil) { t.Fatalf("UseSignalReliabilityServer nil target error = %v, want %v", err, errSignalReliabilityServerNil) } } func TestSignalReliabilityTransportDefaultByNetwork(t *testing.T) { client := NewClient().(*ClientCommon) client.applySignalReliabilityTransportDefault(false) if cfg := client.getSignalReliabilityConfig(); cfg.Enabled { t.Fatalf("client tcp/unix default should be disabled: %+v", cfg) } udpClient := NewClient().(*ClientCommon) udpClient.applySignalReliabilityTransportDefault(true) if cfg := udpClient.getSignalReliabilityConfig(); !cfg.Enabled { t.Fatalf("client udp default should be enabled: %+v", cfg) } server := NewServer().(*ServerCommon) server.applySignalReliabilityTransportDefault(false) if cfg := server.getSignalReliabilityConfig(); cfg.Enabled { t.Fatalf("server tcp/unix default should be disabled: %+v", cfg) } udpServer := NewServer().(*ServerCommon) udpServer.applySignalReliabilityTransportDefault(true) if cfg := udpServer.getSignalReliabilityConfig(); !cfg.Enabled { t.Fatalf("server udp default should be enabled: %+v", cfg) } } func TestSignalReliabilityTransportDefaultDoesNotOverrideExplicitEnable(t *testing.T) { client := NewClient().(*ClientCommon) if err := UseSignalReliabilityClient(client, &SignalReliabilityOptions{ Enabled: false, }); err != nil { t.Fatalf("UseSignalReliabilityClient failed: %v", err) } client.applySignalReliabilityTransportDefault(true) if cfg := client.getSignalReliabilityConfig(); cfg.Enabled { t.Fatalf("explicit client disable should not be overridden by transport default: %+v", cfg) } server := NewServer().(*ServerCommon) if err := UseSignalReliabilityServer(server, &SignalReliabilityOptions{ Enabled: true, }); err != nil { t.Fatalf("UseSignalReliabilityServer failed: %v", err) } server.applySignalReliabilityTransportDefault(false) if cfg := server.getSignalReliabilityConfig(); !cfg.Enabled { t.Fatalf("explicit server enable should not be overridden by transport default: %+v", cfg) } } func TestSendSignalWithAckConcurrent(t *testing.T) { const workers = 48 pool := newSignalAckPool() var wg sync.WaitGroup errCh := make(chan error, workers) for i := 0; i < workers; i++ { wg.Add(1) go func(i int) { defer wg.Done() signalID := uint64(1000 + i) err := sendSignalWithAck("scope-concurrent", signalID, 100*time.Millisecond, pool, func() error { go func() { time.Sleep(time.Millisecond) pool.deliver("scope-concurrent", signalID) }() return nil }) errCh <- err }(i) } wg.Wait() close(errCh) for err := range errCh { if err != nil { t.Fatalf("sendSignalWithAck concurrent failed: %v", err) } } }