notify/signal_reliability_config_test.go

180 lines
5.8 KiB
Go
Raw Normal View History

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)
}
}
}