- 引入 LogicalConn/TransportConn 分层,ClientConn 保留兼容适配层 - 新增 Stream、Bulk、RecordStream 三条数据面能力及对应控制路径 - 完成 transfer/file 传输内核与状态快照、诊断能力 - 补齐 reconnect、inbound dispatcher、modern psk 等基础模块 - 增加大规模回归、并发与基准测试覆盖 - 更新依赖库
180 lines
5.8 KiB
Go
180 lines
5.8 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|