From e18e3ab78348a658ac856bb33e377df60f87a3cc Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 31 May 2024 17:08:57 -0400 Subject: [PATCH] test: Fix tests due to time (#4855) * test(billing): Calculate time deltas from a fixed time Some time calculations are impacted when using the current day vs. the start of the month. * test(db): Conditionally skip tests at end of month Certain tests fail when run on the last day of the month because of edge cases in the setup of test data (for example, if today is May 31 and NZ time is June 1). This adds conditional logic to skip those tests when run on the last day of a month. * CR: typo --- internal/billing/repository_test.go | 20 +- .../handlers/billing/billing_service_test.go | 12 +- .../monthly_active_users_all_timezone.sql | 210 ++++++++++-------- 3 files changed, 147 insertions(+), 95 deletions(-) diff --git a/internal/billing/repository_test.go b/internal/billing/repository_test.go index 3a8b00976e..8276136ac6 100644 --- a/internal/billing/repository_test.go +++ b/internal/billing/repository_test.go @@ -74,8 +74,16 @@ func TestRepository_MonthlyActiveUsers(t *testing.T) { TestGenerateActiveUsers(t, conn) today := time.Now().UTC() - threeMonthsAgo := time.Date(today.AddDate(0, -3, 0).Year(), today.AddDate(0, -3, 0).Month(), 1, 0, 0, 0, 0, time.UTC) - oneMonthAgo := time.Date(today.AddDate(0, -1, 0).Year(), today.AddDate(0, -1, 0).Month(), 1, 0, 0, 0, 0, time.UTC) + // Some time calculations are impacted when using the current day vs. the + // start of the month. For example, if... + // today -> May 30th + // today.AddDate(0, -3, 0).Month() -> March + // February was expected here, but we get March. This seems to be a + // rounding thing since February 30th is not a valid date. Instead, the + // start of the month is used to ensure the correct months are calculated. + monthStart := time.Date(today.Year(), today.Month(), 1, 0, 0, 0, 0, time.UTC) + threeMonthsAgo := time.Date(monthStart.AddDate(0, -3, 0).Year(), monthStart.AddDate(0, -3, 0).Month(), 1, 0, 0, 0, 0, time.UTC) + oneMonthAgo := time.Date(monthStart.AddDate(0, -1, 0).Year(), monthStart.AddDate(0, -1, 0).Month(), 1, 0, 0, 0, 0, time.UTC) midMonth := time.Date(today.Year(), today.Month(), 15, 0, 0, 0, 0, time.UTC) t.Run("valid-no-options", func(t *testing.T) { @@ -125,14 +133,14 @@ func TestRepository_MonthlyActiveUsers(t *testing.T) { activeUsers, err := repo.MonthlyActiveUsers(ctx, WithStartTime(&threeMonthsAgo), WithEndTime(&oneMonthAgo)) assert.NoError(t, err) require.Len(t, activeUsers, 2) - expectedStartTime := time.Date(today.AddDate(0, -2, 0).Year(), today.AddDate(0, -2, 0).Month(), 1, 0, 0, 0, 0, time.UTC) - expectedEndTime := time.Date(today.AddDate(0, -1, 0).Year(), today.AddDate(0, -1, 0).Month(), 1, 0, 0, 0, 0, time.UTC) + expectedStartTime := time.Date(monthStart.AddDate(0, -2, 0).Year(), monthStart.AddDate(0, -2, 0).Month(), 1, 0, 0, 0, 0, time.UTC) + expectedEndTime := time.Date(monthStart.AddDate(0, -1, 0).Year(), monthStart.AddDate(0, -1, 0).Month(), 1, 0, 0, 0, 0, time.UTC) require.Equal(t, uint32(6), activeUsers[0].ActiveUsersCount) assert.Equal(t, expectedStartTime, activeUsers[0].StartTime) assert.Equal(t, expectedEndTime, activeUsers[0].EndTime) - expectedStartTime = time.Date(today.AddDate(0, -3, 0).Year(), today.AddDate(0, -3, 0).Month(), 1, 0, 0, 0, 0, time.UTC) - expectedEndTime = time.Date(today.AddDate(0, -2, 0).Year(), today.AddDate(0, -2, 0).Month(), 1, 0, 0, 0, 0, time.UTC) + expectedStartTime = time.Date(monthStart.AddDate(0, -3, 0).Year(), monthStart.AddDate(0, -3, 0).Month(), 1, 0, 0, 0, 0, time.UTC) + expectedEndTime = time.Date(monthStart.AddDate(0, -2, 0).Year(), monthStart.AddDate(0, -2, 0).Month(), 1, 0, 0, 0, 0, time.UTC) require.Equal(t, uint32(6), activeUsers[1].ActiveUsersCount) assert.Equal(t, expectedStartTime, activeUsers[1].StartTime) assert.Equal(t, expectedEndTime, activeUsers[1].EndTime) diff --git a/internal/daemon/controller/handlers/billing/billing_service_test.go b/internal/daemon/controller/handlers/billing/billing_service_test.go index 07ec26b743..beeb2c5ce1 100644 --- a/internal/daemon/controller/handlers/billing/billing_service_test.go +++ b/internal/daemon/controller/handlers/billing/billing_service_test.go @@ -41,8 +41,16 @@ func Test_MonthlyActiveUsers(t *testing.T) { } today := time.Now().UTC() - threeMonthsAgo := time.Date(today.AddDate(0, -3, 0).Year(), today.AddDate(0, -3, 0).Month(), 1, 0, 0, 0, 0, time.UTC).Format("2006-01") - oneMonthAgo := time.Date(today.AddDate(0, -1, 0).Year(), today.AddDate(0, -1, 0).Month(), 1, 0, 0, 0, 0, time.UTC).Format("2006-01") + // Some time calculations are impacted when using the current day vs. the + // start of the month. For example, if... + // today -> May 30th + // today.AddDate(0, -3, 0).Month() -> March + // February was expected here, but we get March. This seems to be a + // rounding thing since February 30th is not a valid date. Instead, the + // start of the month is used to ensure the correct months are calculated. + monthStart := time.Date(today.Year(), today.Month(), 1, 0, 0, 0, 0, time.UTC) + threeMonthsAgo := time.Date(monthStart.AddDate(0, -3, 0).Year(), monthStart.AddDate(0, -3, 0).Month(), 1, 0, 0, 0, 0, time.UTC).Format("2006-01") + oneMonthAgo := time.Date(monthStart.AddDate(0, -1, 0).Year(), monthStart.AddDate(0, -1, 0).Month(), 1, 0, 0, 0, 0, time.UTC).Format("2006-01") badFormat := time.Date(today.Year(), today.Month(), 15, 0, 0, 0, 0, time.UTC).String() cases := []struct { diff --git a/internal/db/sqltest/tests/hcp/billing/monthly_active_users_all_timezone.sql b/internal/db/sqltest/tests/hcp/billing/monthly_active_users_all_timezone.sql index c6828a98aa..d5f46bd7b2 100644 --- a/internal/db/sqltest/tests/hcp/billing/monthly_active_users_all_timezone.sql +++ b/internal/db/sqltest/tests/hcp/billing/monthly_active_users_all_timezone.sql @@ -2,7 +2,18 @@ -- SPDX-License-Identifier: BUSL-1.1 begin; - select plan(11); + select plan(27); + + create function test_is_not_same_month(start_time timestamptz, end_time timestamptz) returns boolean + as $$ + begin + if date_trunc('month', start_time) != date_trunc('month', end_time) then + return true; + end if; + return false; + end; + $$ language plpgsql; + select lives_ok('truncate wh_auth_token_accumulating_fact, wh_user_dimension, wh_session_accumulating_fact, @@ -82,98 +93,123 @@ begin; select is(count(*), 6::bigint, 'wh_user_dimension is not empty') from wh_user_dimension; -- calling the view directly yields results at NZ month boundaries. - select results_eq( - 'select * from hcp_billing_monthly_active_users_all', - $$ - values (date_trunc('month', now(), 'nz'), date_trunc('hour', now(), 'nz'), 0::bigint), - (date_trunc('month', now() - interval '1 month', 'nz'), date_trunc('month', now(), 'nz'), 6::bigint), - (date_trunc('month', now() - interval '2 month', 'nz'), date_trunc('month', now() - interval '1 month', 'nz'), 6::bigint), - (date_trunc('month', now() - interval '3 month', 'nz'), date_trunc('month', now() - interval '2 month', 'nz'), 6::bigint), - (date_trunc('month', now() - interval '4 month', 'nz'), date_trunc('month', now() - interval '3 month', 'nz'), 6::bigint), - (date_trunc('month', now() - interval '5 month', 'nz'), date_trunc('month', now() - interval '4 month', 'nz'), 6::bigint), - (date_trunc('month', now() - interval '6 month', 'nz'), date_trunc('month', now() - interval '5 month', 'nz'), 6::bigint), - (date_trunc('month', now() - interval '7 month', 'nz'), date_trunc('month', now() - interval '6 month', 'nz'), 6::bigint), - (date_trunc('month', now() - interval '8 month', 'nz'), date_trunc('month', now() - interval '7 month', 'nz'), 6::bigint), - (date_trunc('month', now() - interval '9 month', 'nz'), date_trunc('month', now() - interval '8 month', 'nz'), 6::bigint), - (date_trunc('month', now() - interval '10 month', 'nz'), date_trunc('month', now() - interval '9 month', 'nz'), 6::bigint), - (date_trunc('month', now() - interval '11 month', 'nz'), date_trunc('month', now() - interval '10 month', 'nz'), 6::bigint), - (date_trunc('month', now() - interval '12 month', 'nz'), date_trunc('month', now() - interval '11 month', 'nz'), 6::bigint) - $$); + select case when test_is_not_same_month('yesterday'::timestamptz, now()) + then skip('certain tests don''t work on the first day of the month', 3) + else results_eq( + 'select * from hcp_billing_monthly_active_users_all', + $$ + values (date_trunc('month', now(), 'nz'), date_trunc('hour', now(), 'nz'), 0::bigint), + (date_trunc('month', now() - interval '1 month', 'nz'), date_trunc('month', now(), 'nz'), 6::bigint), + (date_trunc('month', now() - interval '2 month', 'nz'), date_trunc('month', now() - interval '1 month', 'nz'), 6::bigint), + (date_trunc('month', now() - interval '3 month', 'nz'), date_trunc('month', now() - interval '2 month', 'nz'), 6::bigint), + (date_trunc('month', now() - interval '4 month', 'nz'), date_trunc('month', now() - interval '3 month', 'nz'), 6::bigint), + (date_trunc('month', now() - interval '5 month', 'nz'), date_trunc('month', now() - interval '4 month', 'nz'), 6::bigint), + (date_trunc('month', now() - interval '6 month', 'nz'), date_trunc('month', now() - interval '5 month', 'nz'), 6::bigint), + (date_trunc('month', now() - interval '7 month', 'nz'), date_trunc('month', now() - interval '6 month', 'nz'), 6::bigint), + (date_trunc('month', now() - interval '8 month', 'nz'), date_trunc('month', now() - interval '7 month', 'nz'), 6::bigint), + (date_trunc('month', now() - interval '9 month', 'nz'), date_trunc('month', now() - interval '8 month', 'nz'), 6::bigint), + (date_trunc('month', now() - interval '10 month', 'nz'), date_trunc('month', now() - interval '9 month', 'nz'), 6::bigint), + (date_trunc('month', now() - interval '11 month', 'nz'), date_trunc('month', now() - interval '10 month', 'nz'), 6::bigint), + (date_trunc('month', now() - interval '12 month', 'nz'), date_trunc('month', now() - interval '11 month', 'nz'), 6::bigint) + $$) + end; + -- calling the function yields results at UTC month boundaries. - select results_eq( - 'select count(*) from hcp_billing_monthly_active_users_all()', - $$ - values (14::bigint); - $$); - select results_eq( - 'select * from hcp_billing_monthly_active_users_all()', - $$ - values (date_trunc('month', now(), 'utc'), date_trunc('hour', now(), 'utc'), 0::bigint), - (date_trunc('month', now() - interval '1 month', 'utc'), date_trunc('month', now(), 'utc'), 0::bigint), - (date_trunc('month', now() - interval '2 month', 'utc'), date_trunc('month', now() - interval '1 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '3 month', 'utc'), date_trunc('month', now() - interval '2 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '4 month', 'utc'), date_trunc('month', now() - interval '3 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '5 month', 'utc'), date_trunc('month', now() - interval '4 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '6 month', 'utc'), date_trunc('month', now() - interval '5 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '7 month', 'utc'), date_trunc('month', now() - interval '6 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '8 month', 'utc'), date_trunc('month', now() - interval '7 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '9 month', 'utc'), date_trunc('month', now() - interval '8 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '10 month', 'utc'), date_trunc('month', now() - interval '9 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '11 month', 'utc'), date_trunc('month', now() - interval '10 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '12 month', 'utc'), date_trunc('month', now() - interval '11 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '13 month', 'utc'), date_trunc('month', now() - interval '12 month', 'utc'), 6::bigint) - $$); - select results_ne( + select case when test_is_not_same_month('yesterday'::timestamptz, now()) + then skip('certain tests don''t work on the first day of the month', 3) + else results_eq( + 'select count(*) from hcp_billing_monthly_active_users_all()', + $$ + values (14::bigint); + $$) + end; + select case when test_is_not_same_month('yesterday'::timestamptz, now()) + then skip('certain tests don''t work on the first day of the month', 3) + else results_eq( + 'select * from hcp_billing_monthly_active_users_all()', + $$ + values (date_trunc('month', now(), 'utc'), date_trunc('hour', now(), 'utc'), 0::bigint), + (date_trunc('month', now() - interval '1 month', 'utc'), date_trunc('month', now(), 'utc'), 0::bigint), + (date_trunc('month', now() - interval '2 month', 'utc'), date_trunc('month', now() - interval '1 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '3 month', 'utc'), date_trunc('month', now() - interval '2 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '4 month', 'utc'), date_trunc('month', now() - interval '3 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '5 month', 'utc'), date_trunc('month', now() - interval '4 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '6 month', 'utc'), date_trunc('month', now() - interval '5 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '7 month', 'utc'), date_trunc('month', now() - interval '6 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '8 month', 'utc'), date_trunc('month', now() - interval '7 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '9 month', 'utc'), date_trunc('month', now() - interval '8 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '10 month', 'utc'), date_trunc('month', now() - interval '9 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '11 month', 'utc'), date_trunc('month', now() - interval '10 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '12 month', 'utc'), date_trunc('month', now() - interval '11 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '13 month', 'utc'), date_trunc('month', now() - interval '12 month', 'utc'), 6::bigint) + $$) + end; + select case when test_is_not_same_month('yesterday'::timestamptz, now()) + then skip('certain tests don''t work on the first day of the month', 3) + else results_ne( 'select * from hcp_billing_monthly_active_users_all()', - 'select * from hcp_billing_monthly_active_users_all'); + 'select * from hcp_billing_monthly_active_users_all') + end; -- can provide a start time (inclusive) to limit the results. - select results_eq( - $$ - select * from hcp_billing_monthly_active_users_all(date_trunc('month', now() - interval '5 month', 'utc')); - $$, - $$ - values (date_trunc('month', now(), 'utc'), date_trunc('hour', now(), 'utc'), 0::bigint), - (date_trunc('month', now() - interval '1 month', 'utc'), date_trunc('month', now(), 'utc'), 0::bigint), - (date_trunc('month', now() - interval '2 month', 'utc'), date_trunc('month', now() - interval '1 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '3 month', 'utc'), date_trunc('month', now() - interval '2 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '4 month', 'utc'), date_trunc('month', now() - interval '3 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '5 month', 'utc'), date_trunc('month', now() - interval '4 month', 'utc'), 6::bigint) - $$); - -- can provide a start time (inclusive) and end time (exclusive) to limit results. - select results_eq( - $$ - select * from hcp_billing_monthly_active_users_all(date_trunc('month', now() - interval '5 month', 'utc'), - date_trunc('month', now() - interval '3 month', 'utc')); - $$, - $$ - values (date_trunc('month', now() - interval '4 month', 'utc'), date_trunc('month', now() - interval '3 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '5 month', 'utc'), date_trunc('month', now() - interval '4 month', 'utc'), 6::bigint) - $$); + select case when test_is_not_same_month('yesterday'::timestamptz, now()) + then skip('certain tests don''t work on the first day of the month', 3) + else results_eq( + $$ + select * from hcp_billing_monthly_active_users_all(date_trunc('month', now() - interval '5 month', 'utc')); + $$, + $$ + values (date_trunc('month', now(), 'utc'), date_trunc('hour', now(), 'utc'), 0::bigint), + (date_trunc('month', now() - interval '1 month', 'utc'), date_trunc('month', now(), 'utc'), 0::bigint), + (date_trunc('month', now() - interval '2 month', 'utc'), date_trunc('month', now() - interval '1 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '3 month', 'utc'), date_trunc('month', now() - interval '2 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '4 month', 'utc'), date_trunc('month', now() - interval '3 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '5 month', 'utc'), date_trunc('month', now() - interval '4 month', 'utc'), 6::bigint) + $$) + end; + -- can provide a start time (inclusive) and end time (exclusive) to limit results. + select case when test_is_not_same_month('yesterday'::timestamptz, now()) + then skip('certain tests don''t work on the first day of the month', 3) + else results_eq( + $$ + select * from hcp_billing_monthly_active_users_all(date_trunc('month', now() - interval '5 month', 'utc'), + date_trunc('month', now() - interval '3 month', 'utc')); + $$, + $$ + values (date_trunc('month', now() - interval '4 month', 'utc'), date_trunc('month', now() - interval '3 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '5 month', 'utc'), date_trunc('month', now() - interval '4 month', 'utc'), 6::bigint) + $$) + end; -- can provide an end time (exclusive) to limit results. - select results_eq( - $$ - select * from hcp_billing_monthly_active_users_all(null, - date_trunc('month', now() - interval '3 month', 'utc')); - $$, - $$ - values (date_trunc('month', now() - interval '4 month', 'utc'), date_trunc('month', now() - interval '3 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '5 month', 'utc'), date_trunc('month', now() - interval '4 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '6 month', 'utc'), date_trunc('month', now() - interval '5 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '7 month', 'utc'), date_trunc('month', now() - interval '6 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '8 month', 'utc'), date_trunc('month', now() - interval '7 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '9 month', 'utc'), date_trunc('month', now() - interval '8 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '10 month', 'utc'), date_trunc('month', now() - interval '9 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '11 month', 'utc'), date_trunc('month', now() - interval '10 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '12 month', 'utc'), date_trunc('month', now() - interval '11 month', 'utc'), 6::bigint), - (date_trunc('month', now() - interval '13 month', 'utc'), date_trunc('month', now() - interval '12 month', 'utc'), 6::bigint) - $$); + select case when test_is_not_same_month('yesterday'::timestamptz, now()) + then skip('certain tests don''t work on the first day of the month', 3) + else results_eq( + $$ + select * from hcp_billing_monthly_active_users_all(null, + date_trunc('month', now() - interval '3 month', 'utc')); + $$, + $$ + values (date_trunc('month', now() - interval '4 month', 'utc'), date_trunc('month', now() - interval '3 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '5 month', 'utc'), date_trunc('month', now() - interval '4 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '6 month', 'utc'), date_trunc('month', now() - interval '5 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '7 month', 'utc'), date_trunc('month', now() - interval '6 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '8 month', 'utc'), date_trunc('month', now() - interval '7 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '9 month', 'utc'), date_trunc('month', now() - interval '8 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '10 month', 'utc'), date_trunc('month', now() - interval '9 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '11 month', 'utc'), date_trunc('month', now() - interval '10 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '12 month', 'utc'), date_trunc('month', now() - interval '11 month', 'utc'), 6::bigint), + (date_trunc('month', now() - interval '13 month', 'utc'), date_trunc('month', now() - interval '12 month', 'utc'), 6::bigint) + $$) + end; -- an end time that is before the start time will yield no results. - select is_empty( - $$ - select * from hcp_billing_monthly_active_users_all(date_trunc('month', now() - interval '2 month', 'utc'), - date_trunc('month', now() - interval '5 month', 'utc')); - $$); + select case when test_is_not_same_month('yesterday'::timestamptz, now()) + then skip('certain tests don''t work on the first day of the month', 3) + else is_empty( + $$ + select * from hcp_billing_monthly_active_users_all(date_trunc('month', now() - interval '2 month', 'utc'), + date_trunc('month', now() - interval '5 month', 'utc')); + $$) + end; select * from finish(); rollback;