Skip to content

Commit a71a809

Browse files
committed
add unit-style tests for activityBumpWorkspace
1 parent 1ee5403 commit a71a809

File tree

1 file changed

+175
-0
lines changed

1 file changed

+175
-0
lines changed

coderd/activitybump_internal_test.go

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
package coderd
2+
3+
import (
4+
"database/sql"
5+
"testing"
6+
"time"
7+
8+
"github.com/google/uuid"
9+
10+
"cdr.dev/slog/sloggers/slogtest"
11+
"github.com/coder/coder/v2/coderd/database"
12+
"github.com/coder/coder/v2/coderd/database/dbgen"
13+
"github.com/coder/coder/v2/coderd/database/dbtestutil"
14+
"github.com/coder/coder/v2/coderd/database/dbtime"
15+
"github.com/coder/coder/v2/testutil"
16+
17+
"github.com/stretchr/testify/require"
18+
)
19+
20+
func Test_ActivityBumpWorkspace(t *testing.T) {
21+
t.Parallel()
22+
23+
for _, tt := range []struct {
24+
name string
25+
transition database.WorkspaceTransition
26+
jobCompletedAt sql.NullTime
27+
buildDeadline time.Time
28+
maxDeadline time.Time
29+
workspaceTTL time.Duration
30+
expectedBump time.Duration
31+
}{
32+
{
33+
name: "NotFinishedYet",
34+
transition: database.WorkspaceTransitionStart,
35+
jobCompletedAt: sql.NullTime{},
36+
buildDeadline: dbtime.Now().Add(8 * time.Hour),
37+
workspaceTTL: 8 * time.Hour,
38+
expectedBump: 0,
39+
},
40+
{
41+
name: "ManualShutdown",
42+
transition: database.WorkspaceTransitionStart,
43+
jobCompletedAt: sql.NullTime{Valid: true, Time: dbtime.Now()},
44+
buildDeadline: time.Time{},
45+
expectedBump: 0,
46+
},
47+
{
48+
name: "NotTimeToBumpYet",
49+
transition: database.WorkspaceTransitionStart,
50+
jobCompletedAt: sql.NullTime{Valid: true, Time: dbtime.Now()},
51+
buildDeadline: dbtime.Now().Add(8 * time.Hour),
52+
workspaceTTL: 8 * time.Hour,
53+
expectedBump: 0,
54+
},
55+
{
56+
name: "TimeToBump",
57+
transition: database.WorkspaceTransitionStart,
58+
jobCompletedAt: sql.NullTime{Valid: true, Time: dbtime.Now().Add(-24 * time.Minute)},
59+
buildDeadline: dbtime.Now().Add(8*time.Hour - 24*time.Minute),
60+
workspaceTTL: 8 * time.Hour,
61+
expectedBump: 8 * time.Hour,
62+
},
63+
{
64+
name: "MaxDeadline",
65+
transition: database.WorkspaceTransitionStart,
66+
jobCompletedAt: sql.NullTime{Valid: true, Time: dbtime.Now().Add(-24 * time.Minute)},
67+
buildDeadline: dbtime.Now().Add(time.Minute), // last chance to bump!
68+
maxDeadline: dbtime.Now().Add(time.Hour),
69+
workspaceTTL: 8 * time.Hour,
70+
expectedBump: 1 * time.Hour,
71+
},
72+
{
73+
// A workspace that is still running, has passed its deadline, but has not
74+
// yet been auto-stopped should still bump the deadline.
75+
name: "PastDeadlineStillBumps",
76+
transition: database.WorkspaceTransitionStart,
77+
jobCompletedAt: sql.NullTime{Valid: true, Time: dbtime.Now().Add(-24 * time.Minute)},
78+
buildDeadline: dbtime.Now().Add(-time.Minute),
79+
workspaceTTL: 8 * time.Hour,
80+
expectedBump: 8 * time.Hour,
81+
},
82+
{
83+
// A stopped workspace should never bump.
84+
name: "StoppedWorkspace",
85+
transition: database.WorkspaceTransitionStop,
86+
jobCompletedAt: sql.NullTime{Valid: true, Time: dbtime.Now().Add(-time.Minute)},
87+
buildDeadline: dbtime.Now().Add(-time.Minute),
88+
workspaceTTL: 8 * time.Hour,
89+
expectedBump: 0,
90+
},
91+
} {
92+
tt := tt
93+
t.Run(tt.name, func(t *testing.T) {
94+
t.Parallel()
95+
96+
var (
97+
ctx = testutil.Context(t, testutil.WaitShort)
98+
log = slogtest.Make(t, nil)
99+
db, _ = dbtestutil.NewDB(t)
100+
org = dbgen.Organization(t, db, database.Organization{})
101+
user = dbgen.User(t, db, database.User{
102+
Status: database.UserStatusActive,
103+
})
104+
_ = dbgen.OrganizationMember(t, db, database.OrganizationMember{
105+
UserID: user.ID,
106+
OrganizationID: org.ID,
107+
})
108+
templateVersion = dbgen.TemplateVersion(t, db, database.TemplateVersion{
109+
OrganizationID: org.ID,
110+
CreatedBy: user.ID,
111+
})
112+
template = dbgen.Template(t, db, database.Template{
113+
OrganizationID: org.ID,
114+
ActiveVersionID: templateVersion.ID,
115+
CreatedBy: user.ID,
116+
})
117+
ws = dbgen.Workspace(t, db, database.Workspace{
118+
OwnerID: user.ID,
119+
OrganizationID: org.ID,
120+
TemplateID: template.ID,
121+
Ttl: sql.NullInt64{Valid: true, Int64: int64(tt.workspaceTTL)},
122+
})
123+
job = dbgen.ProvisionerJob(t, db, database.ProvisionerJob{
124+
OrganizationID: org.ID,
125+
CompletedAt: tt.jobCompletedAt,
126+
})
127+
_ = dbgen.WorkspaceResource(t, db, database.WorkspaceResource{
128+
JobID: job.ID,
129+
})
130+
buildID = uuid.New()
131+
)
132+
// dbgen.WorkspaceBuild automatically sets deadline to now+1 hour if not set
133+
err := db.InsertWorkspaceBuild(ctx, database.InsertWorkspaceBuildParams{
134+
ID: buildID,
135+
CreatedAt: dbtime.Now(),
136+
UpdatedAt: dbtime.Now(),
137+
BuildNumber: 1,
138+
InitiatorID: user.ID,
139+
Reason: database.BuildReasonInitiator,
140+
WorkspaceID: ws.ID,
141+
JobID: job.ID,
142+
TemplateVersionID: templateVersion.ID,
143+
Transition: tt.transition,
144+
Deadline: tt.buildDeadline,
145+
MaxDeadline: tt.maxDeadline,
146+
})
147+
require.NoError(t, err, "unexpected error inserting workspace build")
148+
bld, err := db.GetWorkspaceBuildByID(ctx, buildID)
149+
require.NoError(t, err, "unexpected error fetching inserted workspace build")
150+
151+
// Validate our initial state before bump
152+
require.Equal(t, tt.transition, bld.Transition, "unexpected transition before bump")
153+
require.Equal(t, tt.jobCompletedAt.Time.UTC(), job.CompletedAt.Time.UTC(), "unexpected job completed at before bump")
154+
require.Equal(t, tt.buildDeadline.UTC(), bld.Deadline.UTC(), "unexpected build deadline before bump")
155+
require.Equal(t, tt.maxDeadline.UTC(), bld.MaxDeadline.UTC(), "unexpected max deadline before bump")
156+
require.Equal(t, tt.workspaceTTL, time.Duration(ws.Ttl.Int64), "unexpected workspace TTL before bump")
157+
158+
// new deadline is calculated from the time of the bump
159+
approxBumpTime := dbtime.Now()
160+
activityBumpWorkspace(ctx, log, db, bld.WorkspaceID)
161+
162+
// Validate our state after bump
163+
updatedBuild, err := db.GetLatestWorkspaceBuildByWorkspaceID(ctx, bld.WorkspaceID)
164+
require.NoError(t, err, "unexpected error getting latest workspace build")
165+
if tt.expectedBump == 0 {
166+
require.Equal(t, bld.UpdatedAt.UTC(), updatedBuild.UpdatedAt.UTC(), "should not have bumped updated_at")
167+
require.Equal(t, bld.Deadline.UTC(), updatedBuild.Deadline.UTC(), "should not have bumped deadline")
168+
} else {
169+
require.WithinDuration(t, dbtime.Now(), updatedBuild.UpdatedAt, 15*time.Second, "unexpected updated at time after bump")
170+
expectedDeadline := approxBumpTime.Add(tt.expectedBump).UTC()
171+
require.WithinDuration(t, expectedDeadline, updatedBuild.Deadline.UTC(), 15*time.Second, "unexpected deadline after bump")
172+
}
173+
})
174+
}
175+
}

0 commit comments

Comments
 (0)