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

Commit6bf5f6a

Browse files
committed
update tests, add test for error during initial data
1 parente225434 commit6bf5f6a

File tree

1 file changed

+82
-38
lines changed

1 file changed

+82
-38
lines changed

‎agent/agentcontainers/api_test.go

Lines changed: 82 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,16 @@ func TestAPI(t *testing.T) {
161161
return codersdk.WorkspaceAgentListContainersResponse{Containers:cts}
162162
}
163163

164+
typeinitialDataPayloadstruct {
165+
val codersdk.WorkspaceAgentListContainersResponse
166+
errerror
167+
}
168+
164169
// Each test case is called multiple times to ensure idempotency
165170
for_,tc:=range []struct {
166171
namestring
167172
// initialData to be stored in the handler
168-
initialDatacodersdk.WorkspaceAgentListContainersResponse
173+
initialDatainitialDataPayload
169174
// function to set up expectations for the mock
170175
setupMockfunc(mcl*acmock.MockLister,preReq*gomock.Call)
171176
// expected result
@@ -175,72 +180,99 @@ func TestAPI(t *testing.T) {
175180
}{
176181
{
177182
name:"no initial data",
178-
initialData:makeResponse(),
183+
initialData:initialDataPayload{makeResponse(),nil},
179184
setupMock:func(mcl*acmock.MockLister,preReq*gomock.Call) {
180185
mcl.EXPECT().List(gomock.Any()).Return(makeResponse(fakeCt),nil).After(preReq).AnyTimes()
181186
},
182187
expected:makeResponse(fakeCt),
183188
},
184189
{
185190
name:"repeat initial data",
186-
initialData:makeResponse(fakeCt),
191+
initialData:initialDataPayload{makeResponse(fakeCt),nil},
187192
expected:makeResponse(fakeCt),
188193
},
189194
{
190-
name:"lister error",
195+
name:"lister error always",
196+
initialData:initialDataPayload{makeResponse(),assert.AnError},
197+
expectedErr:assert.AnError.Error(),
198+
},
199+
{
200+
name:"lister error only during initial data",
201+
initialData:initialDataPayload{makeResponse(),assert.AnError},
202+
setupMock:func(mcl*acmock.MockLister,preReq*gomock.Call) {
203+
mcl.EXPECT().List(gomock.Any()).Return(makeResponse(fakeCt),nil).After(preReq).AnyTimes()
204+
},
205+
expectedErr:assert.AnError.Error(),
206+
},
207+
{
208+
name:"lister error after initial data",
209+
initialData:initialDataPayload{makeResponse(fakeCt),nil},
191210
setupMock:func(mcl*acmock.MockLister,preReq*gomock.Call) {
192211
mcl.EXPECT().List(gomock.Any()).Return(makeResponse(),assert.AnError).After(preReq).AnyTimes()
193212
},
194213
expectedErr:assert.AnError.Error(),
195214
},
196215
{
197216
name:"updated data",
198-
initialData:makeResponse(fakeCt),
217+
initialData:initialDataPayload{makeResponse(fakeCt),nil},
199218
setupMock:func(mcl*acmock.MockLister,preReq*gomock.Call) {
200219
mcl.EXPECT().List(gomock.Any()).Return(makeResponse(fakeCt2),nil).After(preReq).AnyTimes()
201220
},
202221
expected:makeResponse(fakeCt2),
203222
},
204223
} {
205-
tc:=tc
206224
t.Run(tc.name,func(t*testing.T) {
207225
t.Parallel()
208226
var (
209227
ctx=testutil.Context(t,testutil.WaitShort)
210-
clk=quartz.NewMock(t)
211-
ctrl=gomock.NewController(t)
212-
mockLister=acmock.NewMockLister(ctrl)
228+
mClock=quartz.NewMock(t)
229+
tickerTrap=mClock.Trap().TickerFunc("updaterLoop")
230+
mCtrl=gomock.NewController(t)
231+
mLister=acmock.NewMockLister(mCtrl)
213232
logger=slogtest.Make(t,&slogtest.Options{IgnoreErrors:true}).Leveled(slog.LevelDebug)
214233
r=chi.NewRouter()
215234
)
216235

217-
initialData:=mockLister.EXPECT().List(gomock.Any()).Return(tc.initialData,nil)
236+
initialDataCall:=mLister.EXPECT().List(gomock.Any()).Return(tc.initialData.val,tc.initialData.err)
218237
iftc.setupMock!=nil {
219-
tc.setupMock(mockLister,initialData.Times(1))
238+
tc.setupMock(mLister,initialDataCall.Times(1))
220239
}else {
221-
initialData.AnyTimes()
240+
initialDataCall.AnyTimes()
222241
}
223242

224243
api:=agentcontainers.NewAPI(logger,
225-
agentcontainers.WithClock(clk),
226-
agentcontainers.WithLister(mockLister),
244+
agentcontainers.WithClock(mClock),
245+
agentcontainers.WithLister(mLister),
227246
)
228247
deferapi.Close()
229248
r.Mount("/",api.Routes())
230249

250+
// Make sure the ticker function has been registered
251+
// before advancing the clock.
252+
tickerTrap.MustWait(ctx).Release()
253+
tickerTrap.Close()
254+
231255
// Initial request returns the initial data.
232256
req:=httptest.NewRequest(http.MethodGet,"/",nil).
233257
WithContext(ctx)
234258
rec:=httptest.NewRecorder()
235259
r.ServeHTTP(rec,req)
236260

237-
vargot codersdk.WorkspaceAgentListContainersResponse
238-
err:=json.NewDecoder(rec.Body).Decode(&got)
239-
require.NoError(t,err,"unmarshal response failed")
240-
require.Equal(t,tc.initialData,got,"want initial data")
261+
iftc.initialData.err!=nil {
262+
got:=&codersdk.Error{}
263+
err:=json.NewDecoder(rec.Body).Decode(got)
264+
require.NoError(t,err,"unmarshal response failed")
265+
require.ErrorContains(t,got,tc.initialData.err.Error(),"want error")
266+
return
267+
}else {
268+
vargot codersdk.WorkspaceAgentListContainersResponse
269+
err:=json.NewDecoder(rec.Body).Decode(&got)
270+
require.NoError(t,err,"unmarshal response failed")
271+
require.Equal(t,tc.initialData.val,got,"want initial data")
272+
}
241273

242-
// Advance the clock to runupdateLoop.
243-
_,aw:=clk.AdvanceNext()
274+
// Advance the clock to runupdaterLoop.
275+
_,aw:=mClock.AdvanceNext()
244276
aw.MustWait(ctx)
245277

246278
// Second request returns the updated data.
@@ -750,34 +782,40 @@ func TestAPI(t *testing.T) {
750782
ConfigPath:"/home/coder/project/.devcontainer/devcontainer.json",
751783
}
752784

785+
ctx:=testutil.Context(t,testutil.WaitShort)
786+
753787
logger:=slogtest.Make(t,nil).Leveled(slog.LevelDebug)
754-
lister:=&fakeLister{
788+
fLister:=&fakeLister{
755789
containers: codersdk.WorkspaceAgentListContainersResponse{
756790
Containers: []codersdk.WorkspaceAgentContainer{container},
757791
},
758792
}
759-
watcher:=newFakeWatcher(t)
760-
clk:=quartz.NewMock(t)
793+
fWatcher:=newFakeWatcher(t)
794+
mClock:=quartz.NewMock(t)
795+
mClock.Set(time.Now()).MustWait(ctx)
796+
tickerTrap:=mClock.Trap().TickerFunc("updaterLoop")
797+
761798
api:=agentcontainers.NewAPI(logger,
762-
agentcontainers.WithClock(clk),
763-
agentcontainers.WithLister(lister),
764-
agentcontainers.WithWatcher(watcher),
799+
agentcontainers.WithClock(mClock),
800+
agentcontainers.WithLister(fLister),
801+
agentcontainers.WithWatcher(fWatcher),
765802
agentcontainers.WithDevcontainers(
766803
[]codersdk.WorkspaceAgentDevcontainer{dc},
767804
[]codersdk.WorkspaceAgentScript{{LogSourceID:uuid.New(),ID:dc.ID}},
768805
),
769806
)
770807
deferapi.Close()
771808

772-
ctx:=testutil.Context(t,testutil.WaitShort)
773-
774-
clk.Set(time.Now()).MustWait(ctx)
809+
// Make sure the ticker function has been registered
810+
// before advancing any use of mClock.Advance.
811+
tickerTrap.MustWait(ctx).Release()
812+
tickerTrap.Close()
775813

776814
// Make sure the start loop has been called.
777-
watcher.waitNext(ctx)
815+
fWatcher.waitNext(ctx)
778816

779817
// Simulate a file modification event to make the devcontainer dirty.
780-
watcher.sendEventWaitNextCalled(ctx, fsnotify.Event{
818+
fWatcher.sendEventWaitNextCalled(ctx, fsnotify.Event{
781819
Name:"/home/coder/project/.devcontainer/devcontainer.json",
782820
Op:fsnotify.Write,
783821
})
@@ -799,11 +837,11 @@ func TestAPI(t *testing.T) {
799837

800838
// Next, simulate a situation where the container is no longer
801839
// running.
802-
lister.containers.Containers= []codersdk.WorkspaceAgentContainer{}
840+
fLister.containers.Containers= []codersdk.WorkspaceAgentContainer{}
803841

804842
// Trigger a refresh which will use the second response from mock
805843
// lister (no containers).
806-
_,aw:=clk.AdvanceNext()
844+
_,aw:=mClock.AdvanceNext()
807845
aw.MustWait(ctx)
808846

809847
// Afterwards the devcontainer should not be running and not dirty.
@@ -828,9 +866,6 @@ func TestAPI(t *testing.T) {
828866
ctx:=testutil.Context(t,testutil.WaitShort)
829867

830868
startTime:=time.Date(2025,1,1,12,0,0,0,time.UTC)
831-
mClock:=quartz.NewMock(t)
832-
mClock.Set(startTime)
833-
fWatcher:=newFakeWatcher(t)
834869

835870
// Create a fake container with a config file.
836871
configPath:="/workspace/project/.devcontainer/devcontainer.json"
@@ -845,6 +880,10 @@ func TestAPI(t *testing.T) {
845880
},
846881
}
847882

883+
mClock:=quartz.NewMock(t)
884+
mClock.Set(startTime)
885+
tickerTrap:=mClock.Trap().TickerFunc("updaterLoop")
886+
fWatcher:=newFakeWatcher(t)
848887
fLister:=&fakeLister{
849888
containers: codersdk.WorkspaceAgentListContainersResponse{
850889
Containers: []codersdk.WorkspaceAgentContainer{container},
@@ -863,6 +902,11 @@ func TestAPI(t *testing.T) {
863902
r:=chi.NewRouter()
864903
r.Mount("/",api.Routes())
865904

905+
// Make sure the ticker function has been registered
906+
// before advancing any use of mClock.Advance.
907+
tickerTrap.MustWait(ctx)
908+
tickerTrap.Close()
909+
866910
// Call the list endpoint first to ensure config files are
867911
// detected and watched.
868912
req:=httptest.NewRequest(http.MethodGet,"/devcontainers",nil).
@@ -895,7 +939,7 @@ func TestAPI(t *testing.T) {
895939
Op:fsnotify.Write,
896940
})
897941

898-
// Advance the clock to runupdateLoop.
942+
// Advance the clock to runupdaterLoop.
899943
_,aw:=mClock.AdvanceNext()
900944
aw.MustWait(ctx)
901945

@@ -920,7 +964,7 @@ func TestAPI(t *testing.T) {
920964
container.CreatedAt=mClock.Now()// Update the creation time.
921965
fLister.containers.Containers= []codersdk.WorkspaceAgentContainer{container}
922966

923-
// Advance the clock to runupdateLoop.
967+
// Advance the clock to runupdaterLoop.
924968
_,aw=mClock.AdvanceNext()
925969
aw.MustWait(ctx)
926970

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp