Skip to content

feat(coderd/database/dbtestutil): set default database timezone to non-UTC in unit tests #9672

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
remove deprecation and add linter rule
  • Loading branch information
johnstcn committed Sep 14, 2023
commit d051bbbbad0d11a7f10e19a15f84c1c4b86e0112
9 changes: 3 additions & 6 deletions coderd/database/dbtestutil/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ type options struct {

type Option func(*options)

// WithTimezone sets the database to the defined timezone instead of
// to a random one.
//
// Deprecated: If you need to use this, you may have a timezone-related bug.
// WithTimezone sets the database to the defined timezone.
func WithTimezone(tz string) Option {
return func(o *options) {
o.fixedTimezone = tz
Expand Down Expand Up @@ -90,14 +87,14 @@ func NewDB(t testing.TB, opts ...Option) (database.Store, pubsub.Pubsub) {
}

// setRandDBTimezone sets the timezone of the database to the given timezone.
// Note that the updated timezone only comes into effect on reconnect, so we
// create our own connnection for this and close the DB after we're done.
func setDBTimezone(t testing.TB, dbURL, dbname, tz string) {
t.Helper()

sqlDB, err := sql.Open("postgres", dbURL)
require.NoError(t, err)
defer func() {
// The updated timezone only comes into effect on reconnect, so close
// the DB after we're done.
_ = sqlDB.Close()
}()

Expand Down
1 change: 1 addition & 0 deletions coderd/workspaceagents_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,7 @@ func TestWorkspaceAgent_LifecycleState(t *testing.T) {
func TestWorkspaceAgent_Metadata(t *testing.T) {
t.Parallel()

// nolint:gocritic // https://github.com/coder/coder/issues/9682
db, ps := dbtestutil.NewDB(t, dbtestutil.WithTimezone("UTC"))
client := coderdtest.New(t, &coderdtest.Options{
IncludeProvisionerDaemon: true,
Expand Down
2 changes: 2 additions & 0 deletions coderd/workspaces_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1510,6 +1510,8 @@ func TestWorkspaceFilterManual(t *testing.T) {

t.Run("LastUsed", func(t *testing.T) {
t.Parallel()

// nolint:gocritic // https://github.com/coder/coder/issues/9682
db, ps := dbtestutil.NewDB(t, dbtestutil.WithTimezone("UTC"))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

review: LastUsed is apparently TIMESTAMP WITHOUT TIME ZONE. Not sure why this is.

Copy link
Member

@mafredri mafredri Sep 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no comment on the DB field explaining the reasoning, so it's definitely a bug.

The migration that added it made a mistake of using timestamp vs timestamptz.

000043_workspace_last_used.up.sql
2:    ADD COLUMN last_used_at timestamp NOT NULL DEFAULT '0001-01-01 00:00:00+00:00';

(See conflict between default value and field type.)

We should probably lint this somehow and prevent addition of timestamp columns unless //nolinted.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same bug in users table with last_seen_at.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed #9682 to follow up.

client, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
IncludeProvisionerDaemon: true,
Expand Down
1 change: 1 addition & 0 deletions enterprise/coderd/templates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ func TestTemplates(t *testing.T) {
t.Run("UpdateLastUsedAt", func(t *testing.T) {
t.Parallel()

// nolint:gocritic // https://github.com/coder/coder/issues/9682
db, ps := dbtestutil.NewDB(t, dbtestutil.WithTimezone("UTC"))
ctx := testutil.Context(t, testutil.WaitMedium)
client, user := coderdenttest.New(t, &coderdenttest.Options{
Expand Down
1 change: 1 addition & 0 deletions enterprise/coderd/workspaces_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ func TestWorkspacesFiltering(t *testing.T) {

dormantTTL := 24 * time.Hour

// nolint:gocritic // https://github.com/coder/coder/issues/9682
db, ps := dbtestutil.NewDB(t, dbtestutil.WithTimezone("UTC"))

client, user := coderdenttest.New(t, &coderdenttest.Options{
Expand Down
13 changes: 13 additions & 0 deletions scripts/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,3 +395,16 @@ func slogError(m dsl.Matcher) {
Where(m["name"].Const && m["value"].Type.Is("error") && !m["name"].Text.Matches(`^"internal_error"$`)).
Report(`Error should be logged using "slog.Error" instead.`)
}

// withTimezoneUTC ensures that we don't just sprinkle dbtestutil.WithTimezone("UTC") about
// to work around real timezone bugs in our code.
//
//nolint:unused,deadcode,varnamelen
func withTimezoneUTC(m dsl.Matcher) {
m.Match(
`dbtestutil.WithTimezone($tz)`,
).Where(
m["tz"].Text.Matches(`[uU][tT][cC]"$`),
).Report(`Setting database timezone to UTC may mask timezone-related bugs.`).
At(m["tz"])
}