This commit is contained in:
2026-06-22 08:55:57 +08:00
parent dbb87823e8
commit 6ade6e8fa9
325 changed files with 41131 additions and 855 deletions
+75
View File
@@ -0,0 +1,75 @@
package acp_test
import (
"context"
"sync"
"sync/atomic"
"testing"
"time"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/yan1h/agent-coding-workflow/internal/acp"
)
func TestTurnBus_FanoutToMultipleSubscribers(t *testing.T) {
t.Parallel()
bus := acp.NewTurnBus(nil)
var wg sync.WaitGroup
wg.Add(2)
var a, b atomic.Int32
bus.Subscribe("a", func(_ context.Context, _ acp.TurnEvent) { a.Add(1); wg.Done() })
bus.Subscribe("b", func(_ context.Context, _ acp.TurnEvent) { b.Add(1); wg.Done() })
bus.Publish(context.Background(), acp.TurnEvent{SessionID: uuid.New(), Kind: acp.TurnCompletedEvent})
done := make(chan struct{})
go func() { wg.Wait(); close(done) }()
select {
case <-done:
case <-time.After(2 * time.Second):
t.Fatal("subscribers not invoked in time")
}
assert.Equal(t, int32(1), a.Load())
assert.Equal(t, int32(1), b.Load())
}
func TestTurnBus_PanicIsolatedAndNonBlocking(t *testing.T) {
t.Parallel()
bus := acp.NewTurnBus(nil)
var good atomic.Int32
var wg sync.WaitGroup
wg.Add(1)
bus.Subscribe("panicky", func(_ context.Context, _ acp.TurnEvent) { panic("boom") })
bus.Subscribe("good", func(_ context.Context, _ acp.TurnEvent) { good.Add(1); wg.Done() })
// Publish 必须立即返回(非阻塞),且 panicky 订阅者的 panic 被 recover 隔离,
// 不影响 good 订阅者执行。
bus.Publish(context.Background(), acp.TurnEvent{Kind: acp.SessionIdleEvent})
done := make(chan struct{})
go func() { wg.Wait(); close(done) }()
select {
case <-done:
case <-time.After(2 * time.Second):
t.Fatal("good subscriber not invoked despite panicky peer")
}
assert.Equal(t, int32(1), good.Load())
}
func TestTurnBus_PublishDoesNotBlockOnSlowSubscriber(t *testing.T) {
t.Parallel()
bus := acp.NewTurnBus(nil)
release := make(chan struct{})
bus.Subscribe("slow", func(_ context.Context, _ acp.TurnEvent) { <-release })
start := time.Now()
bus.Publish(context.Background(), acp.TurnEvent{Kind: acp.SessionIdleEvent})
// Publish 应远快于订阅者的阻塞时长。
require.Less(t, time.Since(start), 500*time.Millisecond, "Publish must not block on slow subscriber")
close(release)
}