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
153 lines
4.1 KiB
Go
153 lines
4.1 KiB
Go
package agentruntime
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
sessionreplay "github.com/tutti-os/tutti/packages/agent/session-replay"
|
|
)
|
|
|
|
func TestReplayProviderInputBarrierHoldsConnectionsIndependently(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
barrier := newReplayProviderInputBarrier()
|
|
if err := barrier.setTargets([]sessionreplay.ProviderUnitPosition{
|
|
{ConnectionID: "connection-1", ChunkSeq: 4, UnitIndex: 1},
|
|
{ConnectionID: "connection-2", ChunkSeq: 9, UnitIndex: 2},
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
closed := make(chan struct{})
|
|
firstDone := make(chan error, 1)
|
|
go func() {
|
|
firstDone <- barrier.complete(context.Background(), ProviderInputUnit{
|
|
Position: sessionreplay.ProviderUnitPosition{
|
|
ConnectionID: "connection-1", ChunkSeq: 4, UnitIndex: 1,
|
|
},
|
|
}, closed, nil)
|
|
}()
|
|
|
|
select {
|
|
case err := <-firstDone:
|
|
t.Fatalf("connection-1 was not held: %v", err)
|
|
case <-time.After(20 * time.Millisecond):
|
|
}
|
|
|
|
if err := barrier.complete(context.Background(), ProviderInputUnit{
|
|
Position: sessionreplay.ProviderUnitPosition{
|
|
ConnectionID: "connection-2", ChunkSeq: 9, UnitIndex: 1,
|
|
},
|
|
}, closed, nil); err != nil {
|
|
t.Fatalf("slower connection was blocked before target: %v", err)
|
|
}
|
|
barrier.clearTargets()
|
|
select {
|
|
case err := <-firstDone:
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
case <-time.After(time.Second):
|
|
t.Fatal("connection-1 did not resume")
|
|
}
|
|
}
|
|
|
|
func TestReplayProviderInputBarrierFailsClosedOnOvershoot(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
barrier := newReplayProviderInputBarrier()
|
|
if err := barrier.setTargets([]sessionreplay.ProviderUnitPosition{{
|
|
ConnectionID: "connection-1", ChunkSeq: 4, UnitIndex: 1,
|
|
}}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
err := barrier.complete(context.Background(), ProviderInputUnit{
|
|
Position: sessionreplay.ProviderUnitPosition{
|
|
ConnectionID: "connection-1", ChunkSeq: 4, UnitIndex: 2,
|
|
},
|
|
}, make(chan struct{}), nil)
|
|
if !errors.Is(err, ErrReplayProviderOvershot) {
|
|
t.Fatalf("overshoot error = %v", err)
|
|
}
|
|
}
|
|
|
|
func TestReplayProviderInputBarrierFreezesProviderProgressTimeAtTargets(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
barrier := newReplayProviderInputBarrier()
|
|
first := sessionreplay.ProviderUnitPosition{
|
|
ConnectionID: "connection-1", ChunkSeq: 4, UnitIndex: 1,
|
|
}
|
|
second := sessionreplay.ProviderUnitPosition{
|
|
ConnectionID: "connection-1", ChunkSeq: 5, UnitIndex: 1,
|
|
}
|
|
if err := barrier.setTargets([]sessionreplay.ProviderUnitPosition{first}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
closed := make(chan struct{})
|
|
firstDone := make(chan error, 1)
|
|
go func() {
|
|
firstDone <- barrier.complete(context.Background(), ProviderInputUnit{Position: first}, closed, nil)
|
|
}()
|
|
waitForReplayBarrierPosition(t, barrier, first)
|
|
|
|
waitDone := make(chan error, 1)
|
|
go func() {
|
|
waitDone <- barrier.waitForProgressDuration(
|
|
context.Background(), "connection-1", 30*time.Millisecond, closed,
|
|
)
|
|
}()
|
|
select {
|
|
case err := <-waitDone:
|
|
t.Fatalf("provider progress time expired at first target: %v", err)
|
|
case <-time.After(50 * time.Millisecond):
|
|
}
|
|
|
|
if err := barrier.setTargets([]sessionreplay.ProviderUnitPosition{second}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := <-firstDone; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
secondDone := make(chan error, 1)
|
|
go func() {
|
|
secondDone <- barrier.complete(context.Background(), ProviderInputUnit{Position: second}, closed, nil)
|
|
}()
|
|
waitForReplayBarrierPosition(t, barrier, second)
|
|
select {
|
|
case err := <-waitDone:
|
|
t.Fatalf("provider progress time expired at second target: %v", err)
|
|
case <-time.After(50 * time.Millisecond):
|
|
}
|
|
|
|
barrier.clearTargets()
|
|
if err := <-secondDone; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
select {
|
|
case err := <-waitDone:
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
case <-time.After(time.Second):
|
|
t.Fatal("provider progress time did not resume")
|
|
}
|
|
}
|
|
|
|
func waitForReplayBarrierPosition(
|
|
t *testing.T,
|
|
barrier *replayProviderInputBarrier,
|
|
want sessionreplay.ProviderUnitPosition,
|
|
) {
|
|
t.Helper()
|
|
deadline := time.Now().Add(time.Second)
|
|
for time.Now().Before(deadline) {
|
|
if got := barrier.state()[want.ConnectionID]; got == want {
|
|
return
|
|
}
|
|
time.Sleep(time.Millisecond)
|
|
}
|
|
t.Fatalf("provider barrier did not reach %#v", want)
|
|
}
|