Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

574 lines
17 KiB
Go

package linkmanager
import (
"context"
"errors"
"net"
"sync"
"sync/atomic"
"testing"
"time"
)
type testMetadata struct {
Peer string
}
type blockingCloseLink struct {
*fakeLink
closeStarted chan struct{}
releaseClose chan struct{}
startOnce sync.Once
}
func newBlockingCloseLink() *blockingCloseLink {
return &blockingCloseLink{
fakeLink: newFakeLink(),
closeStarted: make(chan struct{}),
releaseClose: make(chan struct{}),
}
}
func (link *blockingCloseLink) Close() error {
link.startOnce.Do(func() { close(link.closeStarted) })
<-link.releaseClose
return link.fakeLink.Close()
}
func TestManagerReusesLinkAndExpiresOnlyAfterLastStreamCloses(t *testing.T) {
t.Parallel()
manager := NewManager[string, testMetadata](ManagerConfig[string, testMetadata]{
IdleGrace: 30 * time.Millisecond,
})
link := newFakeLink()
registerTestLink(t, manager, "peer", "connection", link, nil)
stream, err := manager.OpenStream(context.Background(), "peer")
if err != nil {
t.Fatal(err)
}
time.Sleep(60 * time.Millisecond)
if !manager.Ready("peer") {
t.Fatal("active stream did not keep the pooled link ready")
}
if err := stream.Close(); err != nil {
t.Fatal(err)
}
waitFor(t, time.Second, func() bool {
return !manager.Ready("peer") && link.closeCount.Load() == 1
})
}
func TestManagerRejectsLateLinkAfterGenerationInvalidation(t *testing.T) {
t.Parallel()
manager := NewManager[string, testMetadata](ManagerConfig[string, testMetadata]{})
admission, err := manager.Admit(context.Background(), "peer")
if err != nil {
t.Fatal(err)
}
manager.Invalidate("peer")
if !errors.Is(context.Cause(admission.Context()), ErrAdmissionInvalidated) {
t.Fatalf("admission cause = %v, want invalidated", context.Cause(admission.Context()))
}
link := newFakeLink()
_, err = manager.Register(admission, Registration[string, testMetadata]{
Key: "peer", ConnectionID: "late", Link: link,
})
if !errors.Is(err, ErrAdmissionInvalidated) {
t.Fatalf("Register error = %v, want invalidated", err)
}
if link.closeCount.Load() != 1 || manager.Ready("peer") {
t.Fatalf("late link close=%d ready=%v", link.closeCount.Load(), manager.Ready("peer"))
}
admission.Close()
}
func TestManagerRetireDoesNotMakeReplacementWaitForOldClose(t *testing.T) {
t.Parallel()
manager := NewManager[string, testMetadata](ManagerConfig[string, testMetadata]{
IdleGrace: time.Minute,
})
old := newBlockingCloseLink()
registerTestLink(t, manager, "peer", "old", old, nil)
retired := manager.Retire("peer")
if manager.Ready("peer") {
t.Fatal("retired link remained ready")
}
closeDone := make(chan error, 1)
go func() { closeDone <- retired.Close() }()
select {
case <-old.closeStarted:
case <-time.After(time.Second):
t.Fatal("old physical close did not start")
}
replacement := newFakeLink()
registerTestLink(t, manager, "peer", "replacement", replacement, nil)
if !manager.Ready("peer") {
t.Fatal("replacement did not become ready while old close was blocked")
}
stream, err := manager.OpenStream(context.Background(), "peer")
if err != nil {
t.Fatalf("OpenStream through replacement: %v", err)
}
_ = stream.Close()
close(old.releaseClose)
select {
case err := <-closeDone:
if err != nil {
t.Fatalf("old retirement close: %v", err)
}
case <-time.After(time.Second):
t.Fatal("old retirement close did not finish")
}
if !manager.Ready("peer") {
t.Fatal("late old close removed the replacement")
}
if replacement.closeCount.Load() != 0 {
t.Fatalf("late old close closed replacement %d times", replacement.closeCount.Load())
}
manager.Invalidate("peer")
}
func TestManagerRetireAllReturnsExactIndependentHandles(t *testing.T) {
t.Parallel()
manager := NewManager[string, testMetadata](ManagerConfig[string, testMetadata]{
IdleGrace: time.Minute,
})
first := newFakeLink()
second := newFakeLink()
registerTestLink(t, manager, "first", "first-old", first, nil)
registerTestLink(t, manager, "second", "second-old", second, nil)
retirements := manager.RetireAll()
if len(retirements) != 2 {
t.Fatalf("RetireAll returned %d handles, want 2", len(retirements))
}
if manager.Ready("first") || manager.Ready("second") {
t.Fatal("RetireAll left an old link ready")
}
replacement := newFakeLink()
registerTestLink(t, manager, "first", "first-new", replacement, nil)
for index := range retirements {
if err := retirements[index].Close(); err != nil {
t.Fatalf("close retirement: %v", err)
}
}
if !manager.Ready("first") || replacement.closeCount.Load() != 0 {
t.Fatal("retired handle affected the replacement")
}
manager.Invalidate("first")
}
func TestManagerRejectsLinkAfterAdmissionContextCancellation(t *testing.T) {
t.Parallel()
manager := NewManager[string, testMetadata](ManagerConfig[string, testMetadata]{})
ctx, cancel := context.WithCancel(context.Background())
admission, err := manager.Admit(ctx, "peer")
if err != nil {
t.Fatal(err)
}
defer admission.Close()
cancel()
link := newFakeLink()
_, err = manager.Register(admission, Registration[string, testMetadata]{
Key: "peer", ConnectionID: "late", Link: link,
})
if !errors.Is(err, ErrAdmissionInvalidated) {
t.Fatalf("Register error = %v, want invalidated", err)
}
if link.closeCount.Load() != 1 || manager.Ready("peer") {
t.Fatalf("canceled link close=%d ready=%v", link.closeCount.Load(), manager.Ready("peer"))
}
}
func TestManagerDisableFencesAttemptsUntilReenabled(t *testing.T) {
t.Parallel()
manager := NewManager[string, testMetadata](ManagerConfig[string, testMetadata]{})
admission, err := manager.Admit(context.Background(), "peer")
if err != nil {
t.Fatal(err)
}
defer admission.Close()
if err := manager.SetEnabled(false); err != nil {
t.Fatal(err)
}
if !errors.Is(context.Cause(admission.Context()), ErrAdmissionInvalidated) {
t.Fatalf("disabled admission cause = %v, want invalidated", context.Cause(admission.Context()))
}
if _, err := manager.Admit(context.Background(), "peer"); !errors.Is(err, ErrManagerDisabled) {
t.Fatalf("Admit while disabled error = %v, want disabled", err)
}
late := newFakeLink()
if _, err := manager.Register(admission, Registration[string, testMetadata]{
Key: "peer", ConnectionID: "late", Link: late,
}); !errors.Is(err, ErrAdmissionInvalidated) {
t.Fatalf("late Register error = %v, want invalidated", err)
}
if late.closeCount.Load() != 1 {
t.Fatalf("late link close count = %d, want 1", late.closeCount.Load())
}
if err := manager.SetEnabled(true); err != nil {
t.Fatal(err)
}
replacement := newFakeLink()
registerTestLink(t, manager, "peer", "replacement", replacement, nil)
if !manager.Ready("peer") {
t.Fatal("manager did not admit a link after re-enable")
}
manager.InvalidateAll()
}
func TestManagerReenableDoesNotWaitForStaleEstablishmentFlight(t *testing.T) {
t.Parallel()
manager := NewManager[string, testMetadata](ManagerConfig[string, testMetadata]{
IdleGrace: time.Minute,
})
oldStarted := make(chan struct{})
releaseOld := make(chan struct{})
oldResult := make(chan error, 1)
go func() {
stream, err := manager.OpenOrConnect(
context.Background(),
"peer",
func(context.Context, *Admission[string, testMetadata]) (Registration[string, testMetadata], error) {
close(oldStarted)
<-releaseOld
return Registration[string, testMetadata]{
Key: "peer", ConnectionID: "old", Link: newFakeLink(),
}, nil
},
)
if stream != nil {
_ = stream.Close()
}
oldResult <- err
}()
<-oldStarted
if err := manager.SetEnabled(false); err != nil {
t.Fatal(err)
}
if err := manager.SetEnabled(true); err != nil {
t.Fatal(err)
}
freshResult := make(chan error, 1)
go func() {
stream, err := manager.OpenOrConnect(
context.Background(),
"peer",
func(context.Context, *Admission[string, testMetadata]) (Registration[string, testMetadata], error) {
return Registration[string, testMetadata]{
Key: "peer", ConnectionID: "fresh", Link: newFakeLink(),
}, nil
},
)
if stream != nil {
_ = stream.Close()
}
freshResult <- err
}()
select {
case err := <-freshResult:
if err != nil {
t.Fatalf("fresh establishment: %v", err)
}
case <-time.After(time.Second):
t.Fatal("fresh establishment waited for stale flight")
}
close(releaseOld)
if err := <-oldResult; !errors.Is(err, ErrAdmissionInvalidated) {
t.Fatalf("stale establishment error = %v, want invalidated", err)
}
manager.InvalidateAll()
}
func TestManagerResolvesCollisionDeterministically(t *testing.T) {
t.Parallel()
now := time.Unix(100, 0)
manager := NewManager[string, testMetadata](ManagerConfig[string, testMetadata]{
Now: func() time.Time { return now },
CollisionWindow: 5 * time.Second,
})
incumbent := newFakeLink()
registerTestLink(t, manager, "peer", "b", incumbent, nil)
winner := newFakeLink()
if disposition := registerTestLink(t, manager, "peer", "a", winner, nil); disposition != RegisterReplaced {
t.Fatalf("lower connection id disposition = %q, want replaced", disposition)
}
if incumbent.closeCount.Load() != 1 || winner.closeCount.Load() != 0 {
t.Fatalf("collision close counts incumbent=%d winner=%d", incumbent.closeCount.Load(), winner.closeCount.Load())
}
rejected := newFakeLink()
if disposition := registerTestLink(t, manager, "peer", "z", rejected, nil); disposition != RegisterKeptExisting {
t.Fatalf("higher connection id disposition = %q, want kept_existing", disposition)
}
if rejected.closeCount.Load() != 1 {
t.Fatalf("rejected link close count = %d, want 1", rejected.closeCount.Load())
}
now = now.Add(6 * time.Second)
outsideWindow := newFakeLink()
if disposition := registerTestLink(t, manager, "peer", "0", outsideWindow, nil); disposition != RegisterKeptExisting {
t.Fatalf("outside-window disposition = %q, want kept_existing", disposition)
}
manager.Invalidate("peer")
if winner.closeCount.Load() != 1 {
t.Fatalf("winning link close count = %d, want 1", winner.closeCount.Load())
}
}
func TestManagerOpenOrConnectSerializesEstablishmentPerKey(t *testing.T) {
t.Parallel()
manager := NewManager[string, testMetadata](ManagerConfig[string, testMetadata]{
IdleGrace: time.Minute,
})
var establishCalls atomic.Int32
release := make(chan struct{})
establish := func(
ctx context.Context,
_ *Admission[string, testMetadata],
) (Registration[string, testMetadata], error) {
establishCalls.Add(1)
select {
case <-ctx.Done():
return Registration[string, testMetadata]{}, ctx.Err()
case <-release:
}
return Registration[string, testMetadata]{
Key: "peer", ConnectionID: "connection", Link: newFakeLink(),
}, nil
}
const callers = 8
start := make(chan struct{})
results := make(chan error, callers)
var ready sync.WaitGroup
ready.Add(callers)
for range callers {
go func() {
ready.Done()
<-start
stream, err := manager.OpenOrConnect(context.Background(), "peer", establish)
if stream != nil {
_ = stream.Close()
}
results <- err
}()
}
ready.Wait()
close(start)
waitFor(t, time.Second, func() bool { return establishCalls.Load() == 1 })
close(release)
for range callers {
if err := <-results; err != nil {
t.Fatal(err)
}
}
if establishCalls.Load() != 1 {
t.Fatalf("establish calls = %d, want 1", establishCalls.Load())
}
manager.InvalidateAll()
}
func TestManagerCanceledOpenDoesNotCloseHealthySharedLink(t *testing.T) {
t.Parallel()
manager := NewManager[string, testMetadata](ManagerConfig[string, testMetadata]{
IdleGrace: time.Minute,
})
link := &cancelableOpenLink{fakeLink: newFakeLink()}
registerTestLink(t, manager, "peer", "connection", link, nil)
active, err := manager.OpenStream(context.Background(), "peer")
if err != nil {
t.Fatal(err)
}
link.cancelNext.Store(true)
ctx, cancel := context.WithCancel(context.Background())
cancel()
if _, err := manager.OpenStream(ctx, "peer"); !errors.Is(err, context.Canceled) {
t.Fatalf("canceled OpenStream error = %v, want context canceled", err)
}
if !manager.Ready("peer") || link.closeCount.Load() != 0 {
t.Fatalf("canceled open removed healthy link: ready=%v close=%d", manager.Ready("peer"), link.closeCount.Load())
}
link.cancelNext.Store(true)
var establishCalls atomic.Int32
if _, err := manager.OpenOrConnect(ctx, "peer", func(
context.Context,
*Admission[string, testMetadata],
) (Registration[string, testMetadata], error) {
establishCalls.Add(1)
return Registration[string, testMetadata]{}, errors.New("unexpected establish")
}); !errors.Is(err, context.Canceled) {
t.Fatalf("canceled OpenOrConnect error = %v, want context canceled", err)
}
if establishCalls.Load() != 0 {
t.Fatalf("canceled OpenOrConnect establish calls = %d, want 0", establishCalls.Load())
}
if err := active.Close(); err != nil {
t.Fatal(err)
}
manager.Invalidate("peer")
}
func TestManagerEventsProvideTerminalSequenceAcrossConcurrentCallbacks(t *testing.T) {
t.Parallel()
var (
mu sync.Mutex
events []LinkEvent[string, testMetadata]
readySeen = make(chan struct{})
release = make(chan struct{})
)
manager := NewManager[string, testMetadata](ManagerConfig[string, testMetadata]{
IdleGrace: time.Minute,
Observe: func(event LinkEvent[string, testMetadata]) {
if event.State == LinkReady && event.Sequence == 2 {
close(readySeen)
<-release
}
mu.Lock()
events = append(events, event)
mu.Unlock()
},
})
link := newFakeLink()
registerTestLink(t, manager, "peer", "connection", link, nil)
opened := make(chan net.Conn, 1)
go func() {
stream, _ := manager.OpenStream(context.Background(), "peer")
opened <- stream
}()
select {
case <-readySeen:
case <-time.After(time.Second):
t.Fatal("second ready callback did not start")
}
manager.Invalidate("peer")
close(release)
if stream := <-opened; stream != nil {
_ = stream.Close()
}
mu.Lock()
defer mu.Unlock()
if len(events) != 3 {
t.Fatalf("events = %#v, want initial ready, disconnected, delayed ready", events)
}
if events[1].State != LinkDisconnected || events[1].Sequence != 3 ||
events[2].State != LinkReady || events[2].Sequence != 2 {
t.Fatalf("callback completion order = %#v, want terminal sequence to dominate delayed ready", events)
}
}
func TestManagerRoutesIncomingStreamWithTypedMetadata(t *testing.T) {
t.Parallel()
manager := NewManager[string, testMetadata](ManagerConfig[string, testMetadata]{})
link := newFakeLink()
handled := make(chan IncomingStream[string, testMetadata], 1)
registerTestLink(t, manager, "peer", "connection", link, func(
_ context.Context,
stream IncomingStream[string, testMetadata],
) error {
handled <- stream
return nil
})
link.queueIncoming(newTrackingConn())
select {
case incoming := <-handled:
if incoming.Key != "peer" || incoming.ConnectionID != "connection" || incoming.Metadata.Peer != "peer-label" {
t.Fatalf("incoming stream = %#v", incoming)
}
case <-time.After(time.Second):
t.Fatal("incoming stream was not handled")
}
manager.Invalidate("peer")
}
func TestManagerQuiescenceCancelsAdmissionsAndRejectsNewWork(t *testing.T) {
t.Parallel()
manager := NewManager[string, testMetadata](ManagerConfig[string, testMetadata]{})
admission, err := manager.Admit(context.Background(), "peer")
if err != nil {
t.Fatal(err)
}
manager.BeginQuiescence()
if !errors.Is(context.Cause(admission.Context()), ErrAdmissionInvalidated) {
t.Fatalf("admission cause = %v, want invalidated", context.Cause(admission.Context()))
}
if _, err := manager.Admit(context.Background(), "peer"); !errors.Is(err, ErrManagerClosed) {
t.Fatalf("Admit after quiescence error = %v, want manager closed", err)
}
admission.Close()
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
if err := manager.WaitForQuiescence(ctx); err != nil {
t.Fatal(err)
}
}
func TestManagerWaitForQuiescenceBeginsShutdown(t *testing.T) {
t.Parallel()
manager := NewManager[string, testMetadata](ManagerConfig[string, testMetadata]{})
admission, err := manager.Admit(context.Background(), "peer")
if err != nil {
t.Fatal(err)
}
waited := make(chan error, 1)
go func() {
waited <- manager.WaitForQuiescence(context.Background())
}()
waitFor(t, time.Second, func() bool {
return errors.Is(context.Cause(admission.Context()), ErrAdmissionInvalidated)
})
if _, err := manager.Admit(context.Background(), "peer"); !errors.Is(err, ErrManagerClosed) {
t.Fatalf("Admit while waiting error = %v, want manager closed", err)
}
admission.Close()
select {
case err := <-waited:
if err != nil {
t.Fatal(err)
}
case <-time.After(time.Second):
t.Fatal("WaitForQuiescence did not finish")
}
}
func registerTestLink(
t *testing.T,
manager *Manager[string, testMetadata],
key, connectionID string,
link Link,
handler IncomingHandler[string, testMetadata],
) RegisterDisposition {
t.Helper()
admission, err := manager.Admit(context.Background(), key)
if err != nil {
t.Fatal(err)
}
defer admission.Close()
disposition, err := manager.Register(admission, Registration[string, testMetadata]{
Key: key,
ConnectionID: connectionID,
Link: link,
Metadata: testMetadata{Peer: "peer-label"},
HandleIncoming: handler,
})
if err != nil {
t.Fatal(err)
}
return disposition
}
func waitFor(t *testing.T, timeout time.Duration, condition func() bool) {
t.Helper()
deadline := time.Now().Add(timeout)
for !condition() {
if time.Now().After(deadline) {
t.Fatal("condition was not satisfied before timeout")
}
time.Sleep(time.Millisecond)
}
}
var _ net.Conn = (*trackingConn)(nil)