X-Git-Url: https://git.giacomolli.uk/onechat/blobdiff_plain/790279faf0fda789d93a75f6f5996e65d5de4a18..3cdbd017da9ae7a7045f4272f16d4b262fd01c79:/whatsapp_test.go diff --git a/whatsapp_test.go b/whatsapp_test.go index 96ec2df..c1471e9 100644 --- a/whatsapp_test.go +++ b/whatsapp_test.go @@ -1,7 +1,6 @@ package main import ( - "context" "errors" "os" "path/filepath" @@ -250,12 +249,12 @@ func TestWhatsAppLongFirstConnectionOutageGivesOneNotice(t *testing.T) { since := time.Now().Format(whatsappTimeLayout) - time.Sleep(whatsappNoticeDelay) + time.Sleep(whatsappOutageNoticeDelay) synctest.Wait() require.Equal(t, 1, test.events.Count("notice")) require.Equal(t, "WhatsApp is disconnected since "+since+". OneChat tries again.", test.events.Last("notice")) - time.Sleep(whatsappNoticeDelay) + time.Sleep(whatsappOutageNoticeDelay) synctest.Wait() require.Equal(t, 1, test.events.Count("notice")) test.fake.mutex.Lock() @@ -606,34 +605,33 @@ func TestWhatsAppLogoutFromThePhone(t *testing.T) { } func TestWhatsAppLongDisconnectionGivesOneNotice(t *testing.T) { - dir := t.TempDir() - whatsappTestSession(t, dir, true) - - clock := newTestClock() - whatsapp, fake, _ := whatsappStartTest(t, dir, clock) - whatsapp.noticeDelay = 300 * time.Millisecond - socket, _ := daemonStartTestWithWhatsApp(t, newModelFake(t), nil, whatsapp) - client := terminalStartTestClient(t, socket) - client.WaitFor(t, "[connected to OneChat]") - <-fake.connects - - require.True(t, fake.Emit(&events.Connected{})) - require.True(t, fake.Emit(&events.Disconnected{})) - require.True(t, fake.Emit(&events.Connected{})) - time.Sleep(400 * time.Millisecond) - require.Equal(t, "[connected to OneChat]\n", client.Output()) + synctest.Test(t, func(t *testing.T) { + test := whatsappRetryTest(t) + test.start(t) + synctest.Wait() - clock.now = clock.now.Add(time.Hour) + require.True(t, test.fake.Emit(&events.Connected{})) + require.True(t, test.fake.Emit(&events.Disconnected{})) + require.True(t, test.fake.Emit(&events.Connected{})) + time.Sleep(whatsappOutageNoticeDelay + time.Second) + synctest.Wait() + require.Zero(t, test.events.Count("notice")) - require.True(t, fake.Emit(&events.Disconnected{})) - require.True(t, fake.Emit(&events.Disconnected{})) - client.WaitFor(t, "WhatsApp is disconnected since 2026-01-01 13:00. OneChat tries again.\n") - require.True(t, fake.Emit(&events.Disconnected{})) - time.Sleep(400 * time.Millisecond) + require.True(t, test.fake.Emit(&events.Disconnected{})) + require.True(t, test.fake.Emit(&events.Disconnected{})) + time.Sleep(whatsappOutageNoticeDelay) + synctest.Wait() + require.Equal(t, 1, test.events.Count("notice")) + require.Contains(t, test.events.Last("notice"), "OneChat tries again.") + require.True(t, test.fake.Emit(&events.Disconnected{})) + time.Sleep(whatsappOutageNoticeDelay) + synctest.Wait() + require.Equal(t, 1, test.events.Count("notice")) - require.True(t, fake.Emit(&events.Connected{})) - client.WaitFor(t, "WhatsApp is connected again.\n") - require.Equal(t, 1, strings.Count(client.Output(), "WhatsApp is disconnected since")) + require.True(t, test.fake.Emit(&events.Connected{})) + require.Equal(t, 2, test.events.Count("notice")) + require.Equal(t, "WhatsApp is connected again.", test.events.Last("notice")) + }) } func TestWhatsAppDisconnectionWithNoRetryGivesANoticeAtOnce(t *testing.T) { @@ -755,62 +753,3 @@ func TestSubagentHasNoWhatsAppTools(t *testing.T) { require.Equal(t, `error: unknown tool "whatsapp_find"`, box.run(t.Context(), "whatsapp_find", `{"name":"ana"}`)) require.Equal(t, `error: unknown tool "whatsapp_send"`, box.run(t.Context(), "whatsapp_send", `{"id":"a","chat":"15550002222@s.whatsapp.net","text":"hi"}`)) } - -// WhatsAppRetryTest runs WhatsApp without a model or network client call. All -// timers and channels belong to its synctest bubble, so backoff uses fake time. -type WhatsAppRetryTest struct { - whatsapp *WhatsApp - fake *WhatsAppFake - logs *SyncBuffer - loop *TurnLoop - events *TurnEventRecorder - cancel context.CancelFunc - done chan error -} - -func (r *WhatsAppRetryTest) start(t *testing.T) { - t.Helper() - - ctx, cancel := context.WithCancel(t.Context()) - r.cancel = cancel - r.done = make(chan error, 1) - go func() { - r.done <- r.whatsapp.Run(ctx, r.loop, r.events.Add) - }() - - t.Cleanup(func() { - cancel() - synctest.Wait() - }) -} - -func whatsappRetryTest(t *testing.T) *WhatsAppRetryTest { - t.Helper() - - dir := t.TempDir() - whatsappTestSession(t, dir, true) - - whatsapp, fake, logs := whatsappStartTest(t, dir, newTestClock()) - whatsapp.clock = time.Now - agent, err := openAgent(t.TempDir()) - require.NoError(t, err) - - memory, err := openMemory(t.Context(), agent.dir, time.Now, newFakeSummarizer(), discardLog()) - require.NoError(t, err) - t.Cleanup(func() { - require.NoError(t, memory.Close()) - }) - - events := &TurnEventRecorder{} - client := newModelClient("https://example.com", ModelAPIKey(modelTestKey), agent.CacheKey(), filepath.Join(agent.dir, "usage.jsonl")) - loop, err := newTurnLoop(agent, memory, newTestSubagents(t), whatsapp, newTestSchedules(t, time.Now), client, time.Now, discardLog(), events.Add) - require.NoError(t, err) - - return &WhatsAppRetryTest{ - whatsapp: whatsapp, - fake: fake, - logs: logs, - loop: loop, - events: events, - } -}