fix(coderd): use dbtime.Now() instead of time.Now() in test assertions against DB timestamps (#22685)

`time.Now()` has nanosecond precision while Postgres timestamps are
microsecond precision. When tests compare `time.Now()` against
DB-sourced timestamps using `Before`/`After`/`WithinRange`/etc., there
is a non-zero flake risk from the precision mismatch.

This replaces `time.Now()` with `dbtime.Now()` (which rounds to
microsecond precision) in all test assertions that compare against
database timestamps.

Follows from #22684.

## Changes (11 files)

| File | Changes |
|---|---|
| `coderd/apikey_test.go` | 11 comparisons with `ExpiresAt` |
| `coderd/users_test.go` | 2 comparisons with `ExpiresAt` |
| `coderd/oauth2_test.go` | 1 comparison with `token.Expiry` |
| `coderd/workspaces_test.go` | 2 comparisons with `DormantAt` |
| `coderd/workspaceagents_test.go` | 3 comparisons with
`ConnectedAt`/`DisconnectedAt` |
| `coderd/workspaceapps/db_test.go` | 1 comparison with `token.Expiry` |
| `coderd/provisionerdserver/provisionerdserver_test.go` | 1 comparison
with `key.ExpiresAt` |
| `enterprise/coderd/workspaces_test.go` | 1 comparison with `DormantAt`
|
| `enterprise/coderd/license/license_test.go` | 3 `NotBefore` values |
| `enterprise/coderd/licenses_test.go` | 2 `NotBefore` values |
| `enterprise/coderd/users_test.go` | 3 `Next()` comparisons |

## Not changed (intentionally)

- `scaletest/placebo/run_test.go` — compares wall-clock elapsed time,
not DB timestamps
- `cli/server_test.go`, `coderd/jwtutils/jwt_test.go`,
`enterprise/aibridgeproxyd/aibridgeproxyd_test.go` — TLS cert fields,
not DB-stored
- `coderd/azureidentity/azureidentity_test.go` — Azure cert expiry, not
DB


🤖 Generated by Claude Opus 4.6 but reviewed manually.
This commit is contained in:
Cian Johnston
2026-03-06 09:14:11 +00:00
committed by GitHub
parent 6c44de951d
commit 81468323e0
11 changed files with 33 additions and 30 deletions
+3 -3
View File
@@ -749,7 +749,7 @@ func TestEntitlements(t *testing.T) {
Features: license.Features{
codersdk.FeatureHighAvailability: 1,
},
NotBefore: time.Now().Add(-time.Hour * 2),
NotBefore: dbtime.Now().Add(-time.Hour * 2),
GraceAt: time.Now().Add(-time.Hour),
ExpiresAt: time.Now().Add(time.Hour),
}),
@@ -799,7 +799,7 @@ func TestEntitlements(t *testing.T) {
db, _ := dbtestutil.NewDB(t)
db.InsertLicense(context.Background(), database.InsertLicenseParams{
JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
NotBefore: time.Now().Add(-time.Hour * 2),
NotBefore: dbtime.Now().Add(-time.Hour * 2),
GraceAt: time.Now().Add(-time.Hour),
ExpiresAt: time.Now().Add(time.Hour),
Features: license.Features{
@@ -1430,7 +1430,7 @@ func TestUsageLimitFeatures(t *testing.T) {
UUID: uuid.New(),
JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
IssuedAt: time.Now().Add(-time.Minute * 2),
NotBefore: time.Now().Add(-time.Minute * 2),
NotBefore: dbtime.Now().Add(-time.Minute * 2),
ExpiresAt: time.Now().Add(time.Hour * 2),
Features: license.Features{
codersdk.FeatureManagedAgentLimit: 100,
+3 -2
View File
@@ -11,6 +11,7 @@ import (
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
"github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
"github.com/coder/coder/v2/enterprise/coderd/license"
@@ -145,7 +146,7 @@ func TestPostLicense(t *testing.T) {
Features: license.Features{
codersdk.FeatureAuditLog: 1,
},
NotBefore: time.Now().Add(time.Hour),
NotBefore: dbtime.Now().Add(time.Hour),
GraceAt: time.Now().Add(2 * time.Hour),
ExpiresAt: time.Now().Add(3 * time.Hour),
})
@@ -168,7 +169,7 @@ func TestPostLicense(t *testing.T) {
Features: license.Features{
codersdk.FeatureAuditLog: 1,
},
NotBefore: time.Now().Add(time.Hour),
NotBefore: dbtime.Now().Add(time.Hour),
GraceAt: time.Now().Add(2 * time.Hour),
ExpiresAt: time.Now().Add(-time.Hour),
})
+4 -3
View File
@@ -10,6 +10,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/coderd/rbac"
"github.com/coder/coder/v2/coderd/schedule/cron"
"github.com/coder/coder/v2/codersdk"
@@ -87,7 +88,7 @@ func TestUserQuietHours(t *testing.T) {
require.False(t, sched1.UserSet)
require.Equal(t, defaultScheduleParsed.TimeParsed().Format(TimeFormatHHMM), sched1.Time)
require.Equal(t, defaultScheduleParsed.Location().String(), sched1.Timezone)
require.WithinDuration(t, defaultScheduleParsed.Next(time.Now()), sched1.Next, 15*time.Second)
require.WithinDuration(t, defaultScheduleParsed.Next(dbtime.Now()), sched1.Next, 15*time.Second)
// Set their quiet hours.
customQuietHoursSchedule := "CRON_TZ=Australia/Sydney 0 0 * * *"
@@ -110,7 +111,7 @@ func TestUserQuietHours(t *testing.T) {
require.True(t, sched2.UserSet)
require.Equal(t, customScheduleParsed.TimeParsed().Format(TimeFormatHHMM), sched2.Time)
require.Equal(t, customScheduleParsed.Location().String(), sched2.Timezone)
require.WithinDuration(t, customScheduleParsed.Next(time.Now()), sched2.Next, 15*time.Second)
require.WithinDuration(t, customScheduleParsed.Next(dbtime.Now()), sched2.Next, 15*time.Second)
// Get quiet hours for a user that has them set.
sched3, err := client.UserQuietHoursSchedule(ctx, user.ID.String())
@@ -119,7 +120,7 @@ func TestUserQuietHours(t *testing.T) {
require.True(t, sched3.UserSet)
require.Equal(t, customScheduleParsed.TimeParsed().Format(TimeFormatHHMM), sched3.Time)
require.Equal(t, customScheduleParsed.Location().String(), sched3.Timezone)
require.WithinDuration(t, customScheduleParsed.Next(time.Now()), sched3.Next, 15*time.Second)
require.WithinDuration(t, customScheduleParsed.Next(dbtime.Now()), sched3.Next, 15*time.Second)
// Try setting a garbage schedule.
_, err = client.UpdateUserQuietHoursSchedule(ctx, user.ID.String(), codersdk.UpdateUserQuietHoursScheduleRequest{
+1 -1
View File
@@ -4023,7 +4023,7 @@ func TestWorkspaceLock(t *testing.T) {
require.NotNil(t, workspace.DeletingAt)
require.NotNil(t, workspace.DormantAt)
require.Equal(t, workspace.DormantAt.Add(dormantTTL), *workspace.DeletingAt)
require.WithinRange(t, *workspace.DormantAt, time.Now().Add(-time.Second), time.Now())
require.WithinRange(t, *workspace.DormantAt, dbtime.Now().Add(-time.Second), dbtime.Now())
// Locking a workspace shouldn't update the last_used_at.
require.Equal(t, lastUsedAt, workspace.LastUsedAt)