]> git.giacomolli.uk - onechat/blob - daemon_test.go
Make two WhatsApp tests independent of the load
[onechat] / daemon_test.go
1 package main
2
3 import (
4         "io"
5         "net/http"
6         "os"
7         "path/filepath"
8         "strings"
9         "testing"
10
11         "github.com/stretchr/testify/require"
12 )
13
14 func TestClientsSeeTheTurnAsItHappens(t *testing.T) {
15         server := newModelFake(t)
16         server.reply = func(w http.ResponseWriter, call ModelFakeCall) {
17                 if call.number == 0 {
18                         modelWriteEvents(w, modelCompletedEvent([]any{modelFunctionCallItem("fc_1", "call_1", "shell", `{"command":"echo hi"}`)}, 100, 0, 5))
19                         return
20                 }
21
22                 modelWriteEvents(w, modelCompletedEvent([]any{modelMessageItem("It said hi.")}, 100, 0, 5))
23         }
24
25         socket := daemonStartTest(t, server)
26         first := terminalStartTestClient(t, socket)
27         second := terminalStartTestClient(t, socket)
28         first.WaitFor(t, "[connected to OneChat]")
29         second.WaitFor(t, "[connected to OneChat]")
30
31         first.Type("Run echo hi.")
32         for _, client := range []*TerminalTestClient{first, second} {
33                 client.WaitFor(t, "[done]")
34                 require.Equal(t, "[connected to OneChat]\n[working]\n[tool] shell {\"command\":\"echo hi\"}\n[result] hi\nIt said hi.\n[done]\n", client.Output())
35         }
36
37         first.Type(stopCommand)
38         first.WaitFor(t, "[error] no turn runs")
39         first.Type(stopCommand + " BlueFox")
40         first.WaitFor(t, "[error] no subagent BlueFox runs")
41         require.NotContains(t, second.Output(), "no turn runs")
42         require.NoError(t, first.Close())
43 }
44
45 func TestStopInterruptsTheTurn(t *testing.T) {
46         server := newModelFake(t)
47         arrived := make(chan struct{})
48         release := make(chan struct{})
49         t.Cleanup(func() {
50                 close(release)
51         })
52
53         server.reply = func(w http.ResponseWriter, call ModelFakeCall) {
54                 close(arrived)
55                 <-release
56         }
57
58         socket := daemonStartTest(t, server)
59         client := terminalStartTestClient(t, socket)
60         client.Type("a long task")
61         <-arrived
62
63         late := terminalStartTestClient(t, socket)
64         late.WaitFor(t, "[connected to OneChat]\n[working]")
65
66         client.Type(stopCommand)
67         client.WaitFor(t, "[error] interrupted\n[done]")
68 }
69
70 func TestListenSocketReplacesAnOldSocketFile(t *testing.T) {
71         path := filepath.Join(t.TempDir(), socketFileName)
72         require.NoError(t, os.WriteFile(path, nil, 0o600))
73
74         listener, err := daemonListenSocket(path)
75         require.NoError(t, err)
76
77         info, err := os.Stat(path)
78         require.NoError(t, err)
79         require.Equal(t, os.ModeSocket, info.Mode().Type())
80         require.Equal(t, os.FileMode(0o600), info.Mode().Perm())
81         require.NoError(t, listener.Close())
82 }
83
84 func TestListenSocketRefusesALongPath(t *testing.T) {
85         _, err := daemonListenSocket(filepath.Join(t.TempDir(), strings.Repeat("d", 100), socketFileName))
86         require.ErrorContains(t, err, "set ONECHAT_DIR to a shorter path")
87 }
88
89 func TestDaemonWritesNoFileForALongSocketPath(t *testing.T) {
90         dir := filepath.Join(t.TempDir(), strings.Repeat("d", 100))
91         t.Setenv("ONECHAT_DIR", dir)
92
93         err := daemon(t.Context(), io.Discard)
94         require.ErrorContains(t, err, "set ONECHAT_DIR to a shorter path")
95
96         entries, err := os.ReadDir(dir)
97         require.NoError(t, err)
98         require.Empty(t, entries)
99 }
100
101 // daemonStartTest serves a new agent on a socket in a temporary directory and
102 // returns the socket path. The commands of the agent run in a temporary
103 // directory.
104 func daemonStartTest(t *testing.T, server *ModelFake) string {
105         t.Helper()
106
107         return daemonStartTestWithBot(t, server, nil)
108 }