-
Notifications
You must be signed in to change notification settings - Fork 887
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
Conversation
t.Logf("setting timezone of database %q to %q", dbname, tz) | ||
// We apparently can't use placeholders here, sadly. | ||
// nolint: gosec // This is not user input and this is only executed in tests | ||
_, err = sqlDB.Exec(fmt.Sprintf("ALTER DATABASE %s SET TIMEZONE TO %q", dbname, tz)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self-review: I hate this but it appears necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's fine in tests, IMO. It's an unfortunate limitation of some PostgreSQL queries.
Some chaos could find a decent amount of TZ bugs |
aa070c4
to
355b16b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like I had timezone-related bug in #9652 that this surfaced.
coderd/database/dbtestutil/db.go
Outdated
// 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. | ||
func WithTimezone(tz string) Option { | ||
return func(o *options) { | ||
o.fixedTimezone = tz | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
review: I originally exposed this as WithFixedTimezone()
but I quickly realized that it's useful to be able to set a specific timezone in unit tests, especially when you're trying to narrow down the root cause of a timezone-related bug.
@@ -1510,8 +1510,11 @@ func TestWorkspaceFilterManual(t *testing.T) { | |||
|
|||
t.Run("LastUsed", func(t *testing.T) { | |||
t.Parallel() | |||
db, ps := dbtestutil.NewDB(t, dbtestutil.WithTimezone("UTC")) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 //nolint
ed.
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
review: I initially had been setting a random timezone for each unit test, but I quickly found that way too chaotic to be useful.
It's more useful to pick random timezone once and going with that for all subsequent invocations. If things fail, they will at least fail consistently that run.
@johnstcn Could you please provide some description so we can see the reasoning behind it? |
Updated description, you beat me in the data race :-) |
I think it's generally a lot better to have deterministic tests than stochastic ones. Flaky tests lower the teams trust in our test suite, and eat a lot of time. In features that have dependencies on the database time zone, we should be adding (possibly exhaustive) test cases that use different time zones. |
That's a good point. Instead, I can set to a fixed non-UTC timezone by default that does have a DST component, and keep the option of having a random timezone. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice addition!
t.Logf("setting timezone of database %q to %q", dbname, tz) | ||
// We apparently can't use placeholders here, sadly. | ||
// nolint: gosec // This is not user input and this is only executed in tests | ||
_, err = sqlDB.Exec(fmt.Sprintf("ALTER DATABASE %s SET TIMEZONE TO %q", dbname, tz)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's fine in tests, IMO. It's an unfortunate limitation of some PostgreSQL queries.
coderd/database/dbtestutil/db.go
Outdated
require.NoError(t, err) | ||
|
||
// Set the timezone for the database. | ||
t.Logf("setting timezone of database %q to %q", dbname, tz) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for addressing the feedback!
…ld hopefully be greater than win32 max timer resolution
…t equal max_deadline" to actually be "deadline must not exceed max_deadline" as comments suggest
This PR:
dbtestutil.WithTimezone(tz)
to allow setting the timezone for a test database.randtz.Name()
to pick a random timezone which is consistent across subtests (viasync.Once
).This has already surfaced a few timezone-related bugs that we can fix in follow-up PRs, but which are now obvious and trackable via their use of
dbtestutil.WithTimezone("UTC")
.