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

Commit9167cbf

Browse files
refactor: claim prebuilt workspace tests (#17567)
Follow-up to:#17458Specifically it addresses these discussions:-#17458 (comment)
1 parent3ab3ef8 commit9167cbf

File tree

1 file changed

+57
-206
lines changed

1 file changed

+57
-206
lines changed

‎enterprise/coderd/prebuilds/claim_test.go

Lines changed: 57 additions & 206 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package prebuilds_test
33
import (
44
"context"
55
"database/sql"
6+
"errors"
67
"slices"
78
"strings"
89
"sync/atomic"
@@ -35,21 +36,25 @@ type storeSpy struct {
3536
claims*atomic.Int32
3637
claimParams*atomic.Pointer[database.ClaimPrebuiltWorkspaceParams]
3738
claimedWorkspace*atomic.Pointer[database.ClaimPrebuiltWorkspaceRow]
39+
40+
// if claimingErr is not nil - error will be returned when ClaimPrebuiltWorkspace is called
41+
claimingErrerror
3842
}
3943

40-
funcnewStoreSpy(db database.Store)*storeSpy {
44+
funcnewStoreSpy(db database.Store,claimingErrerror)*storeSpy {
4145
return&storeSpy{
4246
Store:db,
4347
claims:&atomic.Int32{},
4448
claimParams:&atomic.Pointer[database.ClaimPrebuiltWorkspaceParams]{},
4549
claimedWorkspace:&atomic.Pointer[database.ClaimPrebuiltWorkspaceRow]{},
50+
claimingErr:claimingErr,
4651
}
4752
}
4853

4954
func (m*storeSpy)InTx(fnfunc(store database.Store)error,opts*database.TxOptions)error {
5055
// Pass spy down into transaction store.
5156
returnm.Store.InTx(func(store database.Store)error {
52-
spy:=newStoreSpy(store)
57+
spy:=newStoreSpy(store,m.claimingErr)
5358
spy.claims=m.claims
5459
spy.claimParams=m.claimParams
5560
spy.claimedWorkspace=m.claimedWorkspace
@@ -59,6 +64,10 @@ func (m *storeSpy) InTx(fn func(store database.Store) error, opts *database.TxOp
5964
}
6065

6166
func (m*storeSpy)ClaimPrebuiltWorkspace(ctx context.Context,arg database.ClaimPrebuiltWorkspaceParams) (database.ClaimPrebuiltWorkspaceRow,error) {
67+
ifm.claimingErr!=nil {
68+
return database.ClaimPrebuiltWorkspaceRow{},m.claimingErr
69+
}
70+
6271
m.claims.Add(1)
6372
m.claimParams.Store(&arg)
6473
result,err:=m.Store.ClaimPrebuiltWorkspace(ctx,arg)
@@ -68,32 +77,6 @@ func (m *storeSpy) ClaimPrebuiltWorkspace(ctx context.Context, arg database.Clai
6877
returnresult,err
6978
}
7079

71-
typeerrorStorestruct {
72-
claimingErrerror
73-
74-
database.Store
75-
}
76-
77-
funcnewErrorStore(db database.Store,claimingErrerror)*errorStore {
78-
return&errorStore{
79-
Store:db,
80-
claimingErr:claimingErr,
81-
}
82-
}
83-
84-
func (es*errorStore)InTx(fnfunc(store database.Store)error,opts*database.TxOptions)error {
85-
// Pass failure store down into transaction store.
86-
returnes.Store.InTx(func(store database.Store)error {
87-
newES:=newErrorStore(store,es.claimingErr)
88-
89-
returnfn(newES)
90-
},opts)
91-
}
92-
93-
func (es*errorStore)ClaimPrebuiltWorkspace(ctx context.Context,arg database.ClaimPrebuiltWorkspaceParams) (database.ClaimPrebuiltWorkspaceRow,error) {
94-
return database.ClaimPrebuiltWorkspaceRow{},es.claimingErr
95-
}
96-
9780
funcTestClaimPrebuild(t*testing.T) {
9881
t.Parallel()
9982

@@ -106,9 +89,13 @@ func TestClaimPrebuild(t *testing.T) {
10689
presetCount=2
10790
)
10891

92+
unexpectedClaimingError:=xerrors.New("unexpected claiming error")
93+
10994
cases:=map[string]struct {
11095
expectPrebuildClaimedbool
11196
markPrebuildsClaimablebool
97+
// if claimingErr is not nil - error will be returned when ClaimPrebuiltWorkspace is called
98+
claimingErrerror
11299
}{
113100
"no eligible prebuilds to claim": {
114101
expectPrebuildClaimed:false,
@@ -118,6 +105,17 @@ func TestClaimPrebuild(t *testing.T) {
118105
expectPrebuildClaimed:true,
119106
markPrebuildsClaimable:true,
120107
},
108+
109+
"no claimable prebuilt workspaces error is returned": {
110+
expectPrebuildClaimed:false,
111+
markPrebuildsClaimable:true,
112+
claimingErr:agplprebuilds.ErrNoClaimablePrebuiltWorkspaces,
113+
},
114+
"unexpected claiming error is returned": {
115+
expectPrebuildClaimed:false,
116+
markPrebuildsClaimable:true,
117+
claimingErr:unexpectedClaimingError,
118+
},
121119
}
122120

123121
forname,tc:=rangecases {
@@ -129,7 +127,8 @@ func TestClaimPrebuild(t *testing.T) {
129127
// Setup.
130128
ctx:=testutil.Context(t,testutil.WaitSuperLong)
131129
db,pubsub:=dbtestutil.NewDB(t)
132-
spy:=newStoreSpy(db)
130+
131+
spy:=newStoreSpy(db,tc.claimingErr)
133132
expectedPrebuildsCount:=desiredInstances*presetCount
134133

135134
logger:=testutil.Logger(t)
@@ -225,8 +224,35 @@ func TestClaimPrebuild(t *testing.T) {
225224
TemplateVersionPresetID:presets[0].ID,
226225
})
227226

228-
require.NoError(t,err)
229-
coderdtest.AwaitWorkspaceBuildJobCompleted(t,userClient,userWorkspace.LatestBuild.ID)
227+
switch {
228+
casetc.claimingErr!=nil&&errors.Is(tc.claimingErr,agplprebuilds.ErrNoClaimablePrebuiltWorkspaces):
229+
require.NoError(t,err)
230+
coderdtest.AwaitWorkspaceBuildJobCompleted(t,userClient,userWorkspace.LatestBuild.ID)
231+
232+
// Then: the number of running prebuilds hasn't changed because claiming prebuild is failed and we fallback to creating new workspace.
233+
currentPrebuilds,err:=spy.GetRunningPrebuiltWorkspaces(ctx)
234+
require.NoError(t,err)
235+
require.Equal(t,expectedPrebuildsCount,len(currentPrebuilds))
236+
return
237+
238+
casetc.claimingErr!=nil&&errors.Is(tc.claimingErr,unexpectedClaimingError):
239+
// Then: unexpected error happened and was propagated all the way to the caller
240+
require.Error(t,err)
241+
require.ErrorContains(t,err,unexpectedClaimingError.Error())
242+
243+
// Then: the number of running prebuilds hasn't changed because claiming prebuild is failed.
244+
currentPrebuilds,err:=spy.GetRunningPrebuiltWorkspaces(ctx)
245+
require.NoError(t,err)
246+
require.Equal(t,expectedPrebuildsCount,len(currentPrebuilds))
247+
return
248+
249+
default:
250+
// tc.claimingErr is nil scenario
251+
require.NoError(t,err)
252+
coderdtest.AwaitWorkspaceBuildJobCompleted(t,userClient,userWorkspace.LatestBuild.ID)
253+
}
254+
255+
// at this point we know that tc.claimingErr is nil
230256

231257
// Then: a prebuild should have been claimed.
232258
require.EqualValues(t,spy.claims.Load(),1)
@@ -315,181 +341,6 @@ func TestClaimPrebuild(t *testing.T) {
315341
}
316342
}
317343

318-
funcTestClaimPrebuild_CheckDifferentErrors(t*testing.T) {
319-
t.Parallel()
320-
321-
if!dbtestutil.WillUsePostgres() {
322-
t.Skip("This test requires postgres")
323-
}
324-
325-
const (
326-
desiredInstances=1
327-
presetCount=2
328-
329-
expectedPrebuildsCount=desiredInstances*presetCount
330-
)
331-
332-
cases:=map[string]struct {
333-
claimingErrerror
334-
checkFnfunc(
335-
t*testing.T,
336-
ctx context.Context,
337-
store database.Store,
338-
userClient*codersdk.Client,
339-
user codersdk.User,
340-
templateVersionID uuid.UUID,
341-
presetID uuid.UUID,
342-
)
343-
}{
344-
"ErrNoClaimablePrebuiltWorkspaces is returned": {
345-
claimingErr:agplprebuilds.ErrNoClaimablePrebuiltWorkspaces,
346-
checkFn:func(
347-
t*testing.T,
348-
ctx context.Context,
349-
store database.Store,
350-
userClient*codersdk.Client,
351-
user codersdk.User,
352-
templateVersionID uuid.UUID,
353-
presetID uuid.UUID,
354-
) {
355-
// When: a user creates a new workspace with a preset for which prebuilds are configured.
356-
workspaceName:=strings.ReplaceAll(testutil.GetRandomName(t),"_","-")
357-
userWorkspace,err:=userClient.CreateUserWorkspace(ctx,user.Username, codersdk.CreateWorkspaceRequest{
358-
TemplateVersionID:templateVersionID,
359-
Name:workspaceName,
360-
TemplateVersionPresetID:presetID,
361-
})
362-
363-
require.NoError(t,err)
364-
coderdtest.AwaitWorkspaceBuildJobCompleted(t,userClient,userWorkspace.LatestBuild.ID)
365-
366-
// Then: the number of running prebuilds hasn't changed because claiming prebuild is failed and we fallback to creating new workspace.
367-
currentPrebuilds,err:=store.GetRunningPrebuiltWorkspaces(ctx)
368-
require.NoError(t,err)
369-
require.Equal(t,expectedPrebuildsCount,len(currentPrebuilds))
370-
},
371-
},
372-
"unexpected error during claim is returned": {
373-
claimingErr:xerrors.New("unexpected error during claim"),
374-
checkFn:func(
375-
t*testing.T,
376-
ctx context.Context,
377-
store database.Store,
378-
userClient*codersdk.Client,
379-
user codersdk.User,
380-
templateVersionID uuid.UUID,
381-
presetID uuid.UUID,
382-
) {
383-
// When: a user creates a new workspace with a preset for which prebuilds are configured.
384-
workspaceName:=strings.ReplaceAll(testutil.GetRandomName(t),"_","-")
385-
_,err:=userClient.CreateUserWorkspace(ctx,user.Username, codersdk.CreateWorkspaceRequest{
386-
TemplateVersionID:templateVersionID,
387-
Name:workspaceName,
388-
TemplateVersionPresetID:presetID,
389-
})
390-
391-
// Then: unexpected error happened and was propagated all the way to the caller
392-
require.Error(t,err)
393-
require.ErrorContains(t,err,"unexpected error during claim")
394-
395-
// Then: the number of running prebuilds hasn't changed because claiming prebuild is failed.
396-
currentPrebuilds,err:=store.GetRunningPrebuiltWorkspaces(ctx)
397-
require.NoError(t,err)
398-
require.Equal(t,expectedPrebuildsCount,len(currentPrebuilds))
399-
},
400-
},
401-
}
402-
403-
forname,tc:=rangecases {
404-
t.Run(name,func(t*testing.T) {
405-
t.Parallel()
406-
407-
// Setup.
408-
ctx:=testutil.Context(t,testutil.WaitSuperLong)
409-
db,pubsub:=dbtestutil.NewDB(t)
410-
errorStore:=newErrorStore(db,tc.claimingErr)
411-
412-
logger:=testutil.Logger(t)
413-
client,_,api,owner:=coderdenttest.NewWithAPI(t,&coderdenttest.Options{
414-
Options:&coderdtest.Options{
415-
IncludeProvisionerDaemon:true,
416-
Database:errorStore,
417-
Pubsub:pubsub,
418-
},
419-
420-
EntitlementsUpdateInterval:time.Second,
421-
})
422-
423-
reconciler:=prebuilds.NewStoreReconciler(errorStore,pubsub, codersdk.PrebuildsConfig{},logger,quartz.NewMock(t),api.PrometheusRegistry)
424-
varclaimer agplprebuilds.Claimer=prebuilds.NewEnterpriseClaimer(errorStore)
425-
api.AGPL.PrebuildsClaimer.Store(&claimer)
426-
427-
version:=coderdtest.CreateTemplateVersion(t,client,owner.OrganizationID,templateWithAgentAndPresetsWithPrebuilds(desiredInstances))
428-
_=coderdtest.AwaitTemplateVersionJobCompleted(t,client,version.ID)
429-
coderdtest.CreateTemplate(t,client,owner.OrganizationID,version.ID)
430-
presets,err:=client.TemplateVersionPresets(ctx,version.ID)
431-
require.NoError(t,err)
432-
require.Len(t,presets,presetCount)
433-
434-
userClient,user:=coderdtest.CreateAnotherUser(t,client,owner.OrganizationID,rbac.RoleMember())
435-
436-
// Given: the reconciliation state is snapshot.
437-
state,err:=reconciler.SnapshotState(ctx,errorStore)
438-
require.NoError(t,err)
439-
require.Len(t,state.Presets,presetCount)
440-
441-
// When: a reconciliation is setup for each preset.
442-
for_,preset:=rangepresets {
443-
ps,err:=state.FilterByPreset(preset.ID)
444-
require.NoError(t,err)
445-
require.NotNil(t,ps)
446-
actions,err:=reconciler.CalculateActions(ctx,*ps)
447-
require.NoError(t,err)
448-
require.NotNil(t,actions)
449-
450-
require.NoError(t,reconciler.ReconcilePreset(ctx,*ps))
451-
}
452-
453-
// Given: a set of running, eligible prebuilds eventually starts up.
454-
runningPrebuilds:=make(map[uuid.UUID]database.GetRunningPrebuiltWorkspacesRow,desiredInstances*presetCount)
455-
require.Eventually(t,func()bool {
456-
rows,err:=errorStore.GetRunningPrebuiltWorkspaces(ctx)
457-
iferr!=nil {
458-
returnfalse
459-
}
460-
461-
for_,row:=rangerows {
462-
runningPrebuilds[row.CurrentPresetID.UUID]=row
463-
464-
agents,err:=db.GetWorkspaceAgentsInLatestBuildByWorkspaceID(ctx,row.ID)
465-
iferr!=nil {
466-
returnfalse
467-
}
468-
469-
// Workspaces are eligible once its agent is marked "ready".
470-
for_,agent:=rangeagents {
471-
err=db.UpdateWorkspaceAgentLifecycleStateByID(ctx, database.UpdateWorkspaceAgentLifecycleStateByIDParams{
472-
ID:agent.ID,
473-
LifecycleState:database.WorkspaceAgentLifecycleStateReady,
474-
StartedAt: sql.NullTime{Time:time.Now().Add(time.Hour),Valid:true},
475-
ReadyAt: sql.NullTime{Time:time.Now().Add(-1*time.Hour),Valid:true},
476-
})
477-
iferr!=nil {
478-
returnfalse
479-
}
480-
}
481-
}
482-
483-
t.Logf("found %d running prebuilds so far, want %d",len(runningPrebuilds),expectedPrebuildsCount)
484-
485-
returnlen(runningPrebuilds)==expectedPrebuildsCount
486-
},testutil.WaitSuperLong,testutil.IntervalSlow)
487-
488-
tc.checkFn(t,ctx,errorStore,userClient,user,version.ID,presets[0].ID)
489-
})
490-
}
491-
}
492-
493344
functemplateWithAgentAndPresetsWithPrebuilds(desiredInstancesint32)*echo.Responses {
494345
return&echo.Responses{
495346
Parse:echo.ParseComplete,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp