Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9d3785d

Browse files
authored
test(cli/cliui): make agent tests more robust (#10415)
Fixes#10408
1 parent2a6fd90 commit9d3785d

File tree

1 file changed

+101
-43
lines changed

1 file changed

+101
-43
lines changed

‎cli/cliui/agent_test.go

Lines changed: 101 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import (
55
"bytes"
66
"context"
77
"io"
8+
"os"
89
"strings"
910
"sync/atomic"
1011
"testing"
1112
"time"
1213

1314
"github.com/google/uuid"
15+
"github.com/stretchr/testify/assert"
1416
"github.com/stretchr/testify/require"
1517
"golang.org/x/xerrors"
1618

@@ -25,9 +27,31 @@ import (
2527
funcTestAgent(t*testing.T) {
2628
t.Parallel()
2729

30+
waitLines:=func(t*testing.T,output<-chanstring,lines...string)error {
31+
t.Helper()
32+
33+
vargot []string
34+
outerLoop:
35+
for_,want:=rangelines {
36+
for {
37+
select {
38+
caseline:=<-output:
39+
got=append(got,line)
40+
ifstrings.Contains(line,want) {
41+
continue outerLoop
42+
}
43+
case<-time.After(testutil.WaitShort):
44+
assert.Failf(t,"timed out waiting for line","want: %q; got: %q",want,got)
45+
returnxerrors.Errorf("timed out waiting for line: %q; got: %q",want,got)
46+
}
47+
}
48+
}
49+
returnnil
50+
}
51+
2852
for_,tc:=range []struct {
2953
namestring
30-
iter []func(context.Context,*codersdk.WorkspaceAgent,chan []codersdk.WorkspaceAgentLog)error
54+
iter []func(context.Context,*testing.T,*codersdk.WorkspaceAgent,<-chanstring,chan []codersdk.WorkspaceAgentLog)error
3155
logschan []codersdk.WorkspaceAgentLog
3256
opts cliui.AgentOptions
3357
want []string
@@ -38,12 +62,15 @@ func TestAgent(t *testing.T) {
3862
opts: cliui.AgentOptions{
3963
FetchInterval:time.Millisecond,
4064
},
41-
iter: []func(context.Context,*codersdk.WorkspaceAgent,chan []codersdk.WorkspaceAgentLog)error{
42-
func(_ context.Context,agent*codersdk.WorkspaceAgent,_chan []codersdk.WorkspaceAgentLog)error {
65+
iter: []func(context.Context,*testing.T,*codersdk.WorkspaceAgent,<-chanstring,chan []codersdk.WorkspaceAgentLog)error{
66+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,_<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
4367
agent.Status=codersdk.WorkspaceAgentConnecting
4468
returnnil
4569
},
46-
func(_ context.Context,agent*codersdk.WorkspaceAgent,logschan []codersdk.WorkspaceAgentLog)error {
70+
func(_ context.Context,t*testing.T,agent*codersdk.WorkspaceAgent,output<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
71+
returnwaitLines(t,output,"⧗ Waiting for the workspace agent to connect")
72+
},
73+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,_<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
4774
agent.Status=codersdk.WorkspaceAgentConnected
4875
agent.FirstConnectedAt=ptr.Ref(time.Now())
4976
returnnil
@@ -62,12 +89,15 @@ func TestAgent(t *testing.T) {
6289
opts: cliui.AgentOptions{
6390
FetchInterval:time.Millisecond,
6491
},
65-
iter: []func(context.Context,*codersdk.WorkspaceAgent,chan []codersdk.WorkspaceAgentLog)error{
66-
func(_ context.Context,agent*codersdk.WorkspaceAgent,_chan []codersdk.WorkspaceAgentLog)error {
92+
iter: []func(context.Context,*testing.T,*codersdk.WorkspaceAgent,<-chanstring,chan []codersdk.WorkspaceAgentLog)error{
93+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,_<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
6794
agent.Status=codersdk.WorkspaceAgentConnecting
6895
returnnil
6996
},
70-
func(_ context.Context,agent*codersdk.WorkspaceAgent,logschan []codersdk.WorkspaceAgentLog)error {
97+
func(_ context.Context,t*testing.T,agent*codersdk.WorkspaceAgent,output<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
98+
returnwaitLines(t,output,"⧗ Waiting for the workspace agent to connect")
99+
},
100+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,_<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
71101
agent.Status=codersdk.WorkspaceAgentConnected
72102
agent.LifecycleState=codersdk.WorkspaceAgentLifecycleStartTimeout
73103
agent.FirstConnectedAt=ptr.Ref(time.Now())
@@ -87,18 +117,24 @@ func TestAgent(t *testing.T) {
87117
opts: cliui.AgentOptions{
88118
FetchInterval:1*time.Millisecond,
89119
},
90-
iter: []func(context.Context,*codersdk.WorkspaceAgent,chan []codersdk.WorkspaceAgentLog)error{
91-
func(_ context.Context,agent*codersdk.WorkspaceAgent,_chan []codersdk.WorkspaceAgentLog)error {
120+
iter: []func(context.Context,*testing.T,*codersdk.WorkspaceAgent,<-chanstring,chan []codersdk.WorkspaceAgentLog)error{
121+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,_<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
92122
agent.Status=codersdk.WorkspaceAgentConnecting
93123
agent.LifecycleState=codersdk.WorkspaceAgentLifecycleStarting
94124
agent.StartedAt=ptr.Ref(time.Now())
95125
returnnil
96126
},
97-
func(_ context.Context,agent*codersdk.WorkspaceAgent,_chan []codersdk.WorkspaceAgentLog)error {
127+
func(_ context.Context,t*testing.T,agent*codersdk.WorkspaceAgent,output<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
128+
returnwaitLines(t,output,"⧗ Waiting for the workspace agent to connect")
129+
},
130+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,_<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
98131
agent.Status=codersdk.WorkspaceAgentTimeout
99132
returnnil
100133
},
101-
func(_ context.Context,agent*codersdk.WorkspaceAgent,logschan []codersdk.WorkspaceAgentLog)error {
134+
func(_ context.Context,t*testing.T,agent*codersdk.WorkspaceAgent,output<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
135+
returnwaitLines(t,output,"The workspace agent is having trouble connecting, wait for it to connect or restart your workspace.")
136+
},
137+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,_<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
102138
agent.Status=codersdk.WorkspaceAgentConnected
103139
agent.FirstConnectedAt=ptr.Ref(time.Now())
104140
agent.LifecycleState=codersdk.WorkspaceAgentLifecycleReady
@@ -120,8 +156,8 @@ func TestAgent(t *testing.T) {
120156
opts: cliui.AgentOptions{
121157
FetchInterval:1*time.Millisecond,
122158
},
123-
iter: []func(context.Context,*codersdk.WorkspaceAgent,chan []codersdk.WorkspaceAgentLog)error{
124-
func(_ context.Context,agent*codersdk.WorkspaceAgent,_chan []codersdk.WorkspaceAgentLog)error {
159+
iter: []func(context.Context,*testing.T,*codersdk.WorkspaceAgent,<-chanstring,chan []codersdk.WorkspaceAgentLog)error{
160+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,_<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
125161
agent.Status=codersdk.WorkspaceAgentDisconnected
126162
agent.FirstConnectedAt=ptr.Ref(time.Now().Add(-1*time.Minute))
127163
agent.LastConnectedAt=ptr.Ref(time.Now().Add(-1*time.Minute))
@@ -131,7 +167,10 @@ func TestAgent(t *testing.T) {
131167
agent.ReadyAt=ptr.Ref(time.Now())
132168
returnnil
133169
},
134-
func(_ context.Context,agent*codersdk.WorkspaceAgent,_chan []codersdk.WorkspaceAgentLog)error {
170+
func(_ context.Context,t*testing.T,agent*codersdk.WorkspaceAgent,output<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
171+
returnwaitLines(t,output,"⧗ The workspace agent lost connection")
172+
},
173+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,_<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
135174
agent.Status=codersdk.WorkspaceAgentConnected
136175
agent.DisconnectedAt=nil
137176
agent.LastConnectedAt=ptr.Ref(time.Now())
@@ -151,8 +190,8 @@ func TestAgent(t *testing.T) {
151190
FetchInterval:time.Millisecond,
152191
Wait:true,
153192
},
154-
iter: []func(context.Context,*codersdk.WorkspaceAgent,chan []codersdk.WorkspaceAgentLog)error{
155-
func(_ context.Context,agent*codersdk.WorkspaceAgent,logschan []codersdk.WorkspaceAgentLog)error {
193+
iter: []func(context.Context,*testing.T,*codersdk.WorkspaceAgent,<-chanstring,chan []codersdk.WorkspaceAgentLog)error{
194+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,_<-chanstring,logschan []codersdk.WorkspaceAgentLog)error {
156195
agent.Status=codersdk.WorkspaceAgentConnected
157196
agent.FirstConnectedAt=ptr.Ref(time.Now())
158197
agent.LifecycleState=codersdk.WorkspaceAgentLifecycleStarting
@@ -170,7 +209,7 @@ func TestAgent(t *testing.T) {
170209
}
171210
returnnil
172211
},
173-
func(_ context.Context,agent*codersdk.WorkspaceAgent,logschan []codersdk.WorkspaceAgentLog)error {
212+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,_<-chanstring,logschan []codersdk.WorkspaceAgentLog)error {
174213
agent.LifecycleState=codersdk.WorkspaceAgentLifecycleReady
175214
agent.ReadyAt=ptr.Ref(time.Now())
176215
logs<- []codersdk.WorkspaceAgentLog{
@@ -195,8 +234,8 @@ func TestAgent(t *testing.T) {
195234
FetchInterval:time.Millisecond,
196235
Wait:true,
197236
},
198-
iter: []func(context.Context,*codersdk.WorkspaceAgent,chan []codersdk.WorkspaceAgentLog)error{
199-
func(_ context.Context,agent*codersdk.WorkspaceAgent,logschan []codersdk.WorkspaceAgentLog)error {
237+
iter: []func(context.Context,*testing.T,*codersdk.WorkspaceAgent,<-chanstring,chan []codersdk.WorkspaceAgentLog)error{
238+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,output<-chanstring,logschan []codersdk.WorkspaceAgentLog)error {
200239
agent.Status=codersdk.WorkspaceAgentConnected
201240
agent.FirstConnectedAt=ptr.Ref(time.Now())
202241
agent.StartedAt=ptr.Ref(time.Now())
@@ -224,8 +263,8 @@ func TestAgent(t *testing.T) {
224263
opts: cliui.AgentOptions{
225264
FetchInterval:time.Millisecond,
226265
},
227-
iter: []func(context.Context,*codersdk.WorkspaceAgent,chan []codersdk.WorkspaceAgentLog)error{
228-
func(_ context.Context,agent*codersdk.WorkspaceAgent,logschan []codersdk.WorkspaceAgentLog)error {
266+
iter: []func(context.Context,*testing.T,*codersdk.WorkspaceAgent,<-chanstring,chan []codersdk.WorkspaceAgentLog)error{
267+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,output<-chanstring,logschan []codersdk.WorkspaceAgentLog)error {
229268
agent.Status=codersdk.WorkspaceAgentDisconnected
230269
agent.LifecycleState=codersdk.WorkspaceAgentLifecycleOff
231270
returnnil
@@ -239,8 +278,8 @@ func TestAgent(t *testing.T) {
239278
FetchInterval:time.Millisecond,
240279
Wait:true,
241280
},
242-
iter: []func(context.Context,*codersdk.WorkspaceAgent,chan []codersdk.WorkspaceAgentLog)error{
243-
func(_ context.Context,agent*codersdk.WorkspaceAgent,logschan []codersdk.WorkspaceAgentLog)error {
281+
iter: []func(context.Context,*testing.T,*codersdk.WorkspaceAgent,<-chanstring,chan []codersdk.WorkspaceAgentLog)error{
282+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,output<-chanstring,logschan []codersdk.WorkspaceAgentLog)error {
244283
agent.Status=codersdk.WorkspaceAgentConnected
245284
agent.FirstConnectedAt=ptr.Ref(time.Now())
246285
agent.LifecycleState=codersdk.WorkspaceAgentLifecycleStarting
@@ -253,7 +292,10 @@ func TestAgent(t *testing.T) {
253292
}
254293
returnnil
255294
},
256-
func(_ context.Context,agent*codersdk.WorkspaceAgent,logschan []codersdk.WorkspaceAgentLog)error {
295+
func(_ context.Context,t*testing.T,agent*codersdk.WorkspaceAgent,output<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
296+
returnwaitLines(t,output,"Hello world")
297+
},
298+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,_<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
257299
agent.ReadyAt=ptr.Ref(time.Now())
258300
agent.LifecycleState=codersdk.WorkspaceAgentLifecycleShuttingDown
259301
returnnil
@@ -272,12 +314,15 @@ func TestAgent(t *testing.T) {
272314
FetchInterval:time.Millisecond,
273315
Wait:true,
274316
},
275-
iter: []func(context.Context,*codersdk.WorkspaceAgent,chan []codersdk.WorkspaceAgentLog)error{
276-
func(_ context.Context,agent*codersdk.WorkspaceAgent,_chan []codersdk.WorkspaceAgentLog)error {
317+
iter: []func(context.Context,*testing.T,*codersdk.WorkspaceAgent,<-chanstring,chan []codersdk.WorkspaceAgentLog)error{
318+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,_<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
277319
agent.Status=codersdk.WorkspaceAgentConnecting
278320
returnnil
279321
},
280-
func(_ context.Context,agent*codersdk.WorkspaceAgent,_chan []codersdk.WorkspaceAgentLog)error {
322+
func(_ context.Context,t*testing.T,agent*codersdk.WorkspaceAgent,output<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
323+
returnwaitLines(t,output,"⧗ Waiting for the workspace agent to connect")
324+
},
325+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,_<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
281326
returnxerrors.New("bad")
282327
},
283328
},
@@ -292,13 +337,16 @@ func TestAgent(t *testing.T) {
292337
FetchInterval:time.Millisecond,
293338
Wait:true,
294339
},
295-
iter: []func(context.Context,*codersdk.WorkspaceAgent,chan []codersdk.WorkspaceAgentLog)error{
296-
func(_ context.Context,agent*codersdk.WorkspaceAgent,_chan []codersdk.WorkspaceAgentLog)error {
340+
iter: []func(context.Context,*testing.T,*codersdk.WorkspaceAgent,<-chanstring,chan []codersdk.WorkspaceAgentLog)error{
341+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,_<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
297342
agent.Status=codersdk.WorkspaceAgentTimeout
298343
agent.TroubleshootingURL="https://troubleshoot"
299344
returnnil
300345
},
301-
func(_ context.Context,agent*codersdk.WorkspaceAgent,_chan []codersdk.WorkspaceAgentLog)error {
346+
func(_ context.Context,t*testing.T,agent*codersdk.WorkspaceAgent,output<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
347+
returnwaitLines(t,output,"The workspace agent is having trouble connecting, wait for it to connect or restart your workspace.")
348+
},
349+
func(_ context.Context,_*testing.T,agent*codersdk.WorkspaceAgent,output<-chanstring,_chan []codersdk.WorkspaceAgentLog)error {
302350
returnxerrors.New("bad")
303351
},
304352
},
@@ -317,21 +365,27 @@ func TestAgent(t *testing.T) {
317365
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitShort)
318366
defercancel()
319367

320-
varbuf bytes.Buffer
368+
r,w,err:=os.Pipe()
369+
require.NoError(t,err,"create pipe failed")
370+
deferr.Close()
371+
deferw.Close()
372+
321373
agent:= codersdk.WorkspaceAgent{
322374
ID:uuid.New(),
323375
Status:codersdk.WorkspaceAgentConnecting,
324376
CreatedAt:time.Now(),
325377
LifecycleState:codersdk.WorkspaceAgentLifecycleCreated,
326378
}
379+
output:=make(chanstring,100)// Buffered to avoid blocking, overflow is discarded.
327380
logs:=make(chan []codersdk.WorkspaceAgentLog,1)
328381

329382
cmd:=&clibase.Cmd{
330383
Handler:func(inv*clibase.Invocation)error {
331384
tc.opts.Fetch=func(_ context.Context,_ uuid.UUID) (codersdk.WorkspaceAgent,error) {
385+
t.Log("iter",len(tc.iter))
332386
varerrerror
333387
iflen(tc.iter)>0 {
334-
err=tc.iter[0](ctx,&agent,logs)
388+
err=tc.iter[0](ctx,t,&agent,output,logs)
335389
tc.iter=tc.iter[1:]
336390
}
337391
returnagent,err
@@ -352,27 +406,25 @@ func TestAgent(t *testing.T) {
352406
close(fetchLogs)
353407
returnfetchLogs,closeFunc(func()error {returnnil }),nil
354408
}
355-
err:=cliui.Agent(inv.Context(),&buf,uuid.Nil,tc.opts)
409+
err:=cliui.Agent(inv.Context(),w,uuid.Nil,tc.opts)
410+
_=w.Close()
356411
returnerr
357412
},
358413
}
359414
inv:=cmd.Invoke()
360415

361-
w:=clitest.StartWithWaiter(t,inv)
362-
iftc.wantErr {
363-
w.RequireError()
364-
}else {
365-
w.RequireSuccess()
366-
}
416+
waiter:=clitest.StartWithWaiter(t,inv)
367417

368-
s:=bufio.NewScanner(&buf)
418+
s:=bufio.NewScanner(r)
369419
fors.Scan() {
370420
line:=s.Text()
371421
t.Log(line)
422+
select {
423+
caseoutput<-line:
424+
default:
425+
t.Logf("output overflow: %s",line)
426+
}
372427
iflen(tc.want)==0 {
373-
fori:=0;i<5;i++ {
374-
t.Log(line)
375-
}
376428
require.Fail(t,"unexpected line",line)
377429
}
378430
require.Contains(t,line,tc.want[0])
@@ -382,6 +434,12 @@ func TestAgent(t *testing.T) {
382434
iflen(tc.want)>0 {
383435
require.Fail(t,"missing lines: "+strings.Join(tc.want,", "))
384436
}
437+
438+
iftc.wantErr {
439+
waiter.RequireError()
440+
}else {
441+
waiter.RequireSuccess()
442+
}
385443
})
386444
}
387445

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp