fix: pass in time parameter to prevent flakes (#11023)

Co-authored-by: Dean Sheather <dean@deansheather.com>
This commit is contained in:
Garrett Delfosse 2023-12-04 12:20:22 -05:00 committed by GitHub
parent a42b6c185d
commit 1e6ea6133c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 13 deletions

View File

@ -89,7 +89,7 @@ func (api *API) insightsUserActivity(rw http.ResponseWriter, r *http.Request) {
return
}
startTime, endTime, ok := parseInsightsStartAndEndTime(ctx, rw, startTimeString, endTimeString)
startTime, endTime, ok := parseInsightsStartAndEndTime(ctx, rw, time.Now(), startTimeString, endTimeString)
if !ok {
return
}
@ -176,7 +176,7 @@ func (api *API) insightsUserLatency(rw http.ResponseWriter, r *http.Request) {
return
}
startTime, endTime, ok := parseInsightsStartAndEndTime(ctx, rw, startTimeString, endTimeString)
startTime, endTime, ok := parseInsightsStartAndEndTime(ctx, rw, time.Now(), startTimeString, endTimeString)
if !ok {
return
}
@ -268,7 +268,7 @@ func (api *API) insightsTemplates(rw http.ResponseWriter, r *http.Request) {
return
}
startTime, endTime, ok := parseInsightsStartAndEndTime(ctx, rw, startTimeString, endTimeString)
startTime, endTime, ok := parseInsightsStartAndEndTime(ctx, rw, time.Now(), startTimeString, endTimeString)
if !ok {
return
}
@ -539,9 +539,7 @@ func convertTemplateInsightsApps(usage database.GetTemplateInsightsRow, appUsage
// time are not zero and that the end time is not before the start time. The
// clock must be set to 00:00:00, except for "today", where end time is allowed
// to provide the hour of the day (e.g. 14:00:00).
func parseInsightsStartAndEndTime(ctx context.Context, rw http.ResponseWriter, startTimeString, endTimeString string) (startTime, endTime time.Time, ok bool) {
now := time.Now()
func parseInsightsStartAndEndTime(ctx context.Context, rw http.ResponseWriter, now time.Time, startTimeString, endTimeString string) (startTime, endTime time.Time, ok bool) {
for _, qp := range []struct {
name, value string
dest *time.Time
@ -563,6 +561,9 @@ func parseInsightsStartAndEndTime(ctx context.Context, rw http.ResponseWriter, s
return time.Time{}, time.Time{}, false
}
// Change now to the same timezone as the parsed time.
now := now.In(t.Location())
if t.IsZero() {
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: "Query parameter has invalid value.",
@ -604,7 +605,7 @@ func parseInsightsStartAndEndTime(ctx context.Context, rw http.ResponseWriter, s
Validations: []codersdk.ValidationError{
{
Field: qp.name,
Detail: fmt.Sprintf("Query param %q must have the clock set to 00:00:00", qp.name),
Detail: fmt.Sprintf("Query param %q must have the clock set to 00:00:00, got %s", qp.name, qp.value),
},
},
})
@ -615,7 +616,7 @@ func parseInsightsStartAndEndTime(ctx context.Context, rw http.ResponseWriter, s
Validations: []codersdk.ValidationError{
{
Field: qp.name,
Detail: fmt.Sprintf("Query param %q must have the clock set to %02d:00:00", qp.name, h),
Detail: fmt.Sprintf("Query param %q must have the clock set to %02d:00:00, got %s", qp.name, h, qp.value),
},
},
})

View File

@ -15,12 +15,18 @@ import (
func Test_parseInsightsStartAndEndTime(t *testing.T) {
t.Parallel()
t.Logf("machine location: %s", time.Now().Location())
layout := insightsTimeLayout
now := time.Now().UTC()
t.Logf("now: %s", now)
t.Logf("now location: %s", now.Location())
y, m, d := now.Date()
today := time.Date(y, m, d, 0, 0, 0, 0, time.UTC)
t.Logf("today: %s", today)
thisHour := time.Date(y, m, d, now.Hour(), 0, 0, 0, time.UTC)
t.Logf("thisHour: %s", thisHour)
thisHourRoundUp := thisHour.Add(time.Hour)
t.Logf("thisHourRoundUp: %s", thisHourRoundUp)
helsinki, err := time.LoadLocation("Europe/Helsinki")
require.NoError(t, err)
@ -36,6 +42,16 @@ func Test_parseInsightsStartAndEndTime(t *testing.T) {
wantEndTime time.Time
wantOk bool
}{
{
name: "Same",
args: args{
startTime: "2023-07-10T00:00:00Z",
endTime: "2023-07-10T00:00:00Z",
},
wantStartTime: time.Date(2023, 7, 10, 0, 0, 0, 0, time.UTC),
wantEndTime: time.Date(2023, 7, 10, 0, 0, 0, 0, time.UTC),
wantOk: true,
},
{
name: "Week",
args: args{
@ -132,13 +148,21 @@ func Test_parseInsightsStartAndEndTime(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
t.Log("startTime: ", tt.args.startTime)
t.Log("endTime: ", tt.args.endTime)
if tt.wantOk {
t.Log("wantStartTime: ", tt.wantStartTime)
t.Log("wantEndTime: ", tt.wantEndTime)
}
rw := httptest.NewRecorder()
gotStartTime, gotEndTime, gotOk := parseInsightsStartAndEndTime(context.Background(), rw, tt.args.startTime, tt.args.endTime)
gotStartTime, gotEndTime, gotOk := parseInsightsStartAndEndTime(context.Background(), rw, now, tt.args.startTime, tt.args.endTime)
if !assert.Equal(t, tt.wantOk, gotOk) {
//nolint:bodyclose
t.Log("Status: ", rw.Result().StatusCode)
t.Log("Body: ", rw.Body.String())
return
}
// assert.Equal is unable to test time equality with different
// (but same) locations because the *time.Location names differ
@ -158,7 +182,7 @@ func Test_parseInsightsInterval_week(t *testing.T) {
sydneyLoc, err := time.LoadLocation("Australia/Sydney") // Random location
require.NoError(t, err)
now := time.Now()
now := time.Now().In(sydneyLoc)
t.Logf("now: %s", now)
y, m, d := now.Date()
@ -206,7 +230,7 @@ func Test_parseInsightsInterval_week(t *testing.T) {
name: "6 days are acceptable",
args: args{
startTime: sixDaysAgo.Format(layout),
endTime: thisHour.Format(layout),
endTime: stripTime(thisHour).Format(layout),
},
wantOk: true,
},
@ -222,18 +246,22 @@ func Test_parseInsightsInterval_week(t *testing.T) {
name: "9 days (7 + 2) are not acceptable",
args: args{
startTime: nineDaysAgo.Format(layout),
endTime: thisHour.Format(layout),
endTime: stripTime(thisHour).Format(layout),
},
wantOk: false,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
t.Log("startTime: ", tt.args.startTime)
t.Log("endTime: ", tt.args.endTime)
rw := httptest.NewRecorder()
startTime, endTime, ok := parseInsightsStartAndEndTime(context.Background(), rw, tt.args.startTime, tt.args.endTime)
startTime, endTime, ok := parseInsightsStartAndEndTime(context.Background(), rw, now, tt.args.startTime, tt.args.endTime)
if !ok {
//nolint:bodyclose
t.Log("Status: ", rw.Result().StatusCode)
@ -246,6 +274,7 @@ func Test_parseInsightsInterval_week(t *testing.T) {
//nolint:bodyclose
t.Log("Status: ", rw.Result().StatusCode)
t.Log("Body: ", rw.Body.String())
return
}
if tt.wantOk {
assert.Equal(t, codersdk.InsightsReportIntervalWeek, parsedInterval)
@ -296,6 +325,10 @@ func TestLastReportIntervalHasAtLeastSixDays(t *testing.T) {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
t.Log("startTime: ", tc.startTime)
t.Log("endTime: ", tc.endTime)
result := lastReportIntervalHasAtLeastSixDays(tc.startTime, tc.endTime)
if result != tc.expected {
t.Errorf("Expected %v, but got %v for start time %v and end time %v", tc.expected, result, tc.startTime, tc.endTime)
@ -303,3 +336,9 @@ func TestLastReportIntervalHasAtLeastSixDays(t *testing.T) {
})
}
}
// stripTime strips the time from a time.Time value, but keeps the date and TZ.
func stripTime(t time.Time) time.Time {
y, m, d := t.Date()
return time.Date(y, m, d, 0, 0, 0, 0, t.Location())
}