From aa01e0a4aba877b695e7e69de9cd0ee21b569064 Mon Sep 17 00:00:00 2001 From: Rich Gowman Date: Tue, 16 Jun 2020 14:41:50 -0400 Subject: [PATCH 1/3] Fixed a flaky auth integration test by retrying the GetUser() API call Includes bonus fix to ensure bulk deleting users doesn't hit the quota. --- integration/test_auth.py | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/integration/test_auth.py b/integration/test_auth.py index 26cf53d20..549fc5c41 100644 --- a/integration/test_auth.py +++ b/integration/test_auth.py @@ -360,7 +360,19 @@ def test_last_refresh_timestamp(new_user_with_params: auth.UserRecord, api_key): # login to cause the last_refresh_timestamp to be set _sign_in_with_password(new_user_with_params.email, 'secret', api_key) - new_user_with_params = auth.get_user(new_user_with_params.uid) + + # Attempt to retrieve the user 3 times (with a small delay between each + # attempt). Occassionally, this call retrieves the user data without the + # lastLoginTime/lastRefreshTime set; possibly because it's hitting a + # different server than the login request uses. + user_record = None + for i in range(0, 3): + user_record = auth.get_user(new_user_with_params.uid) + + if user_record.user_metadata.last_refresh_timestamp is not None: + break + + time.sleep(2 ** i) # Ensure the last refresh time occurred at approximately 'now'. (With a # tolerance of up to 1 minute; we ideally want to ensure that any timezone @@ -369,7 +381,7 @@ def test_last_refresh_timestamp(new_user_with_params: auth.UserRecord, api_key): millis_per_second = 1000 millis_per_minute = millis_per_second * 60 - last_refresh_timestamp = new_user_with_params.user_metadata.last_refresh_timestamp + last_refresh_timestamp = user_record.user_metadata.last_refresh_timestamp assert last_refresh_timestamp == pytest.approx( time.time()*millis_per_second, 1*millis_per_minute) @@ -498,7 +510,7 @@ def test_delete_multiple_users(self): uid2 = auth.create_user(disabled=False).uid uid3 = auth.create_user(disabled=True).uid - delete_users_result = auth.delete_users([uid1, uid2, uid3]) + delete_users_result = self._slow_delete_users(auth, [uid1, uid2, uid3]) assert delete_users_result.success_count == 3 assert delete_users_result.failure_count == 0 assert len(delete_users_result.errors) == 0 @@ -510,16 +522,22 @@ def test_delete_multiple_users(self): def test_is_idempotent(self): uid = auth.create_user().uid - delete_users_result = auth.delete_users([uid]) + delete_users_result = self._slow_delete_users(auth, [uid]) assert delete_users_result.success_count == 1 assert delete_users_result.failure_count == 0 # Delete the user again, ensuring that everything still counts as a # success. - delete_users_result = auth.delete_users([uid]) + delete_users_result = self._slow_delete_users(auth, [uid]) assert delete_users_result.success_count == 1 assert delete_users_result.failure_count == 0 + def _slow_delete_users(self, auth, uids): + """The batchDelete endpoint has a rate limit of 1 QPS. Use this test + helper to ensure you don't exceed the quota.""" + time.sleep(1) + return auth.delete_users(uids) + def test_revoke_refresh_tokens(new_user): user = auth.get_user(new_user.uid) From 0a0ee90875f94ec23d44966dabe312ef771abd47 Mon Sep 17 00:00:00 2001 From: Rich Gowman Date: Tue, 16 Jun 2020 15:15:07 -0400 Subject: [PATCH 2/3] pylint doesn't like 'i' in a for loop. :( --- integration/test_auth.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration/test_auth.py b/integration/test_auth.py index 549fc5c41..886e7042b 100644 --- a/integration/test_auth.py +++ b/integration/test_auth.py @@ -366,13 +366,13 @@ def test_last_refresh_timestamp(new_user_with_params: auth.UserRecord, api_key): # lastLoginTime/lastRefreshTime set; possibly because it's hitting a # different server than the login request uses. user_record = None - for i in range(0, 3): + for iteration in range(0, 3): user_record = auth.get_user(new_user_with_params.uid) if user_record.user_metadata.last_refresh_timestamp is not None: break - time.sleep(2 ** i) + time.sleep(2 ** iteration) # Ensure the last refresh time occurred at approximately 'now'. (With a # tolerance of up to 1 minute; we ideally want to ensure that any timezone From 45bd114803aa9be613a1c8f434b954d84022bb8b Mon Sep 17 00:00:00 2001 From: Rich Gowman Date: Tue, 16 Jun 2020 15:39:32 -0400 Subject: [PATCH 3/3] remove empty line --- integration/test_auth.py | 1 - 1 file changed, 1 deletion(-) diff --git a/integration/test_auth.py b/integration/test_auth.py index 886e7042b..16ae52a86 100644 --- a/integration/test_auth.py +++ b/integration/test_auth.py @@ -368,7 +368,6 @@ def test_last_refresh_timestamp(new_user_with_params: auth.UserRecord, api_key): user_record = None for iteration in range(0, 3): user_record = auth.get_user(new_user_with_params.uid) - if user_record.user_metadata.last_refresh_timestamp is not None: break