162 lines
3.5 KiB
Go
162 lines
3.5 KiB
Go
package session
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestSetCwd_ExpandsTilde(t *testing.T) {
|
|
home, err := os.UserHomeDir()
|
|
if err != nil || home == "" {
|
|
t.Skip("cannot determine home directory")
|
|
}
|
|
|
|
s := &Session{}
|
|
s.SetCwd("~/projects")
|
|
|
|
want := home + "/projects"
|
|
if got := s.Cwd(); got != want {
|
|
t.Errorf("SetCwd(~/projects): got %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestSetCwd_ExpandsEnvVars(t *testing.T) {
|
|
t.Setenv("OLLIE_TEST_DIR", "/tmp/testdir")
|
|
|
|
s := &Session{}
|
|
s.SetCwd("$OLLIE_TEST_DIR/sub")
|
|
|
|
want := "/tmp/testdir/sub"
|
|
if got := s.Cwd(); got != want {
|
|
t.Errorf("SetCwd($OLLIE_TEST_DIR/sub): got %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestSetCwd_AbsolutePathUnchanged(t *testing.T) {
|
|
s := &Session{}
|
|
s.SetCwd("/usr/local/bin")
|
|
|
|
want := "/usr/local/bin"
|
|
if got := s.Cwd(); got != want {
|
|
t.Errorf("SetCwd(/usr/local/bin): got %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestEventSubscription(t *testing.T) {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
ch := SubscribeEvents(ctx)
|
|
|
|
// Give subscription time to register
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
// Publish events
|
|
for i := 0; i < 5; i++ {
|
|
PublishEvent(fmt.Sprintf("test.event.%d", i), fmt.Sprintf("payload%d", i))
|
|
}
|
|
|
|
// Collect events
|
|
timeout := time.After(1 * time.Second)
|
|
var received []Event
|
|
for {
|
|
select {
|
|
case ev := <-ch:
|
|
received = append(received, ev)
|
|
if len(received) >= 5 {
|
|
goto done
|
|
}
|
|
case <-timeout:
|
|
goto done
|
|
}
|
|
}
|
|
done:
|
|
if len(received) < 5 {
|
|
t.Errorf("Expected 5 events, got %d", len(received))
|
|
for i, ev := range received {
|
|
t.Logf(" [%d] topic=%s payload=%s", i, ev.Topic, ev.Payload)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEventSubscriptionFiltered(t *testing.T) {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
ch := SubscribeEventsFiltered(ctx, "*")
|
|
|
|
// Give subscription time to register
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
// Publish events
|
|
for i := 0; i < 5; i++ {
|
|
PublishEvent(fmt.Sprintf("test.event.%d", i), fmt.Sprintf("payload%d", i))
|
|
}
|
|
|
|
// Collect events
|
|
timeout := time.After(1 * time.Second)
|
|
var received []Event
|
|
for {
|
|
select {
|
|
case ev := <-ch:
|
|
received = append(received, ev)
|
|
if len(received) >= 5 {
|
|
goto done
|
|
}
|
|
case <-timeout:
|
|
goto done
|
|
}
|
|
}
|
|
done:
|
|
if len(received) < 5 {
|
|
t.Errorf("Expected 5 events, got %d", len(received))
|
|
for i, ev := range received {
|
|
t.Logf(" [%d] topic=%s payload=%s", i, ev.Topic, ev.Payload)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEventSubscriptionRapidFire(t *testing.T) {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
ch := SubscribeEventsFiltered(ctx, "*")
|
|
|
|
// Give subscription time to register
|
|
time.Sleep(50 * time.Millisecond)
|
|
|
|
// Rapid-fire publish (simulating state changes during a turn)
|
|
states := []string{"thinking", "calling: shell", "thinking", "calling: file_read", "thinking", "idle"}
|
|
for _, state := range states {
|
|
PublishEvent("session.abc.agent.xyz.state", state)
|
|
}
|
|
|
|
// Collect events
|
|
timeout := time.After(2 * time.Second)
|
|
var received []Event
|
|
for {
|
|
select {
|
|
case ev := <-ch:
|
|
received = append(received, ev)
|
|
t.Logf("Received: topic=%s payload=%s", ev.Topic, ev.Payload)
|
|
if len(received) >= len(states) {
|
|
goto done
|
|
}
|
|
case <-timeout:
|
|
goto done
|
|
}
|
|
}
|
|
done:
|
|
if len(received) != len(states) {
|
|
t.Errorf("Expected %d events, got %d", len(states), len(received))
|
|
}
|
|
for i, ev := range received {
|
|
if i < len(states) && ev.Payload != states[i] {
|
|
t.Errorf("Event %d: expected payload %q, got %q", i, states[i], ev.Payload)
|
|
}
|
|
}
|
|
}
|