Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 2d9b18c

Browse files
jonathanedeygoogle-labs-jules[bot]
andauthored
chore: Use mock time for consistent token generation and verification tests (#881)
* Fix(tests): Use mock time for consistent token generation and verification tests Patches time.time and google.auth.jwt._helpers.utcnow to use a fixed timestamp (MOCK_CURRENT_TIME) throughout tests/test_token_gen.py. This addresses test flakiness and inconsistencies by ensuring that: 1. Tokens and cookies are generated with predictable `iat` and `exp` claims based on MOCK_CURRENT_TIME. 2. The verification logic within the Firebase Admin SDK and the underlying google-auth library also uses MOCK_CURRENT_TIME. Helper functions _get_id_token and _get_session_cookie were updated to default to using MOCK_CURRENT_TIME for their internal time calculations, simplifying test code. Relevant fixtures and token definitions were updated to rely on these new defaults and the fixed timestamp. The setup_method in TestVerifyIdToken, TestVerifySessionCookie, TestCertificateCaching, and TestCertificateFetchTimeout now mock time.time and google.auth.jwt._helpers.utcnow to ensure that all time-sensitive operations during testing use the MOCK_CURRENT_TIME. * Fix(tests): Apply time mocking to test_tenant_mgt.py Extends the time mocking strategy (using a fixed MOCK_CURRENT_TIME) to tests in `tests/test_tenant_mgt.py` to ensure consistency with changes previously made in `tests/test_token_gen.py`. Specifically: - Imported `MOCK_CURRENT_TIME` from `tests.test_token_gen`. - Added `setup_method` (and `teardown_method`) to the `TestVerifyIdToken` and `TestCreateCustomToken` classes. - These setup methods patch `time.time` and `google.auth.jwt._helpers.utcnow` to return `MOCK_CURRENT_TIME` (or its datetime equivalent). This ensures that token generation (for custom tokens) and token verification within `test_tenant_mgt.py` align with the mocked timeline, preventing potential flakiness or failures due to time inconsistencies. All tests in `test_tenant_mgt.py` pass with these changes. * fix lint and refactor --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
1 parent 70013c8 commit 2d9b18c

File tree

2 files changed

+92
-20
lines changed

2 files changed

+92
-20
lines changed

‎tests/test_tenant_mgt.py‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"""Test cases for the firebase_admin.tenant_mgt module."""
1616

1717
import json
18+
import unittest.mock
1819
from urllib import parse
1920

2021
import pytest
@@ -29,6 +30,7 @@
2930
from firebase_admin import _utils
3031
from tests import testutils
3132
from tests import test_token_gen
33+
from tests.test_token_gen import MOCK_CURRENT_TIME, MOCK_CURRENT_TIME_UTC
3234

3335

3436
GET_TENANT_RESPONSE = """{
@@ -964,6 +966,17 @@ def _assert_saml_provider_config(self, provider_config, want_id='saml.provider')
964966

965967
class TestVerifyIdToken:
966968

969+
def setup_method(self):
970+
self.time_patch = unittest.mock.patch('time.time', return_value=MOCK_CURRENT_TIME)
971+
self.mock_time = self.time_patch.start()
972+
self.utcnow_patch = unittest.mock.patch(
973+
'google.auth.jwt._helpers.utcnow', return_value=MOCK_CURRENT_TIME_UTC)
974+
self.mock_utcnow = self.utcnow_patch.start()
975+
976+
def teardown_method(self):
977+
self.time_patch.stop()
978+
self.utcnow_patch.stop()
979+
967980
def test_valid_token(self, tenant_mgt_app):
968981
client = tenant_mgt.auth_for_tenant('test-tenant', app=tenant_mgt_app)
969982
client._token_verifier.request = test_token_gen.MOCK_REQUEST
@@ -997,6 +1010,17 @@ def tenant_aware_custom_token_app():
9971010

9981011
class TestCreateCustomToken:
9991012

1013+
def setup_method(self):
1014+
self.time_patch = unittest.mock.patch('time.time', return_value=MOCK_CURRENT_TIME)
1015+
self.mock_time = self.time_patch.start()
1016+
self.utcnow_patch = unittest.mock.patch(
1017+
'google.auth.jwt._helpers.utcnow', return_value=MOCK_CURRENT_TIME_UTC)
1018+
self.mock_utcnow = self.utcnow_patch.start()
1019+
1020+
def teardown_method(self):
1021+
self.time_patch.stop()
1022+
self.utcnow_patch.stop()
1023+
10001024
def test_custom_token(self, tenant_aware_custom_token_app):
10011025
client = tenant_mgt.auth_for_tenant('test-tenant', app=tenant_aware_custom_token_app)
10021026

‎tests/test_token_gen.py‎

Lines changed: 68 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import json
2020
import os
2121
import time
22+
import unittest.mock
2223

2324
from google.auth import crypt
2425
from google.auth import jwt
@@ -36,6 +37,9 @@
3637
from tests import testutils
3738

3839

40+
MOCK_CURRENT_TIME = 1500000000
41+
MOCK_CURRENT_TIME_UTC = datetime.datetime.fromtimestamp(
42+
MOCK_CURRENT_TIME, tz=datetime.timezone.utc)
3943
MOCK_UID = 'user1'
4044
MOCK_CREDENTIAL = credentials.Certificate(
4145
testutils.resource_filename('service_account.json'))
@@ -105,16 +109,17 @@ def verify_custom_token(custom_token, expected_claims, tenant_id=None):
105109
for key, value in expected_claims.items():
106110
assert value == token['claims'][key]
107111

108-
def _get_id_token(payload_overrides=None, header_overrides=None):
112+
def _get_id_token(payload_overrides=None, header_overrides=None, current_time=MOCK_CURRENT_TIME):
109113
signer = crypt.RSASigner.from_string(MOCK_PRIVATE_KEY)
110114
headers = {
111115
'kid': 'mock-key-id-1'
112116
}
117+
now = int(current_time if current_time is not None else time.time())
113118
payload = {
114119
'aud': MOCK_CREDENTIAL.project_id,
115120
'iss': 'https://securetoken.google.com/' + MOCK_CREDENTIAL.project_id,
116-
'iat': int(time.time()) - 100,
117-
'exp': int(time.time()) + 3600,
121+
'iat': now - 100,
122+
'exp': now + 3600,
118123
'sub': '1234567890',
119124
'admin': True,
120125
'firebase': {
@@ -127,12 +132,13 @@ def _get_id_token(payload_overrides=None, header_overrides=None):
127132
payload = _merge_jwt_claims(payload, payload_overrides)
128133
return jwt.encode(signer, payload, header=headers)
129134

130-
def _get_session_cookie(payload_overrides=None, header_overrides=None):
135+
def _get_session_cookie(
136+
payload_overrides=None, header_overrides=None, current_time=MOCK_CURRENT_TIME):
131137
payload_overrides = payload_overrides or {}
132138
if 'iss' not in payload_overrides:
133139
payload_overrides['iss'] = 'https://session.firebase.google.com/{0}'.format(
134140
MOCK_CREDENTIAL.project_id)
135-
return _get_id_token(payload_overrides, header_overrides)
141+
return _get_id_token(payload_overrides, header_overrides, current_time=current_time)
136142

137143
def _instrument_user_manager(app, status, payload):
138144
client = auth._get_client(app)
@@ -205,7 +211,7 @@ def env_var_app(request):
205211
@pytest.fixture(scope='module')
206212
def revoked_tokens():
207213
mock_user = json.loads(testutils.resource('get_user.json'))
208-
mock_user['users'][0]['validSince'] = str(int(time.time())+100)
214+
mock_user['users'][0]['validSince'] = str(MOCK_CURRENT_TIME+100)
209215
return json.dumps(mock_user)
210216

211217
@pytest.fixture(scope='module')
@@ -218,7 +224,7 @@ def user_disabled():
218224
def user_disabled_and_revoked():
219225
mock_user = json.loads(testutils.resource('get_user.json'))
220226
mock_user['users'][0]['disabled'] = True
221-
mock_user['users'][0]['validSince'] = str(int(time.time())+100)
227+
mock_user['users'][0]['validSince'] = str(MOCK_CURRENT_TIME+100)
222228
return json.dumps(mock_user)
223229

224230

@@ -420,6 +426,17 @@ def test_unexpected_response(self, user_mgt_app):
420426

421427
class TestVerifyIdToken:
422428

429+
def setup_method(self):
430+
self.time_patch = unittest.mock.patch('time.time', return_value=MOCK_CURRENT_TIME)
431+
self.time_patch.start()
432+
self.utcnow_patch = unittest.mock.patch(
433+
'google.auth.jwt._helpers.utcnow', return_value=MOCK_CURRENT_TIME_UTC)
434+
self.utcnow_patch.start()
435+
436+
def teardown_method(self):
437+
self.time_patch.stop()
438+
self.utcnow_patch.stop()
439+
423440
valid_tokens = {
424441
'BinaryToken': TEST_ID_TOKEN,
425442
'TextToken': TEST_ID_TOKEN.decode('utf-8'),
@@ -435,14 +452,14 @@ class TestVerifyIdToken:
435452
'EmptySubject': _get_id_token({'sub': ''}),
436453
'IntSubject': _get_id_token({'sub': 10}),
437454
'LongStrSubject': _get_id_token({'sub': 'a' * 129}),
438-
'FutureToken': _get_id_token({'iat': int(time.time()) + 1000}),
455+
'FutureToken': _get_id_token({'iat': MOCK_CURRENT_TIME + 1000}),
439456
'ExpiredToken': _get_id_token({
440-
'iat': int(time.time()) - 10000,
441-
'exp': int(time.time()) - 3600
457+
'iat': MOCK_CURRENT_TIME - 10000,
458+
'exp': MOCK_CURRENT_TIME - 3600
442459
}),
443460
'ExpiredTokenShort': _get_id_token({
444-
'iat': int(time.time()) - 10000,
445-
'exp': int(time.time()) - 30
461+
'iat': MOCK_CURRENT_TIME - 10000,
462+
'exp': MOCK_CURRENT_TIME - 30
446463
}),
447464
'BadFormatToken': 'foobar'
448465
}
@@ -618,6 +635,17 @@ def test_certificate_request_failure(self, user_mgt_app):
618635

619636
class TestVerifySessionCookie:
620637

638+
def setup_method(self):
639+
self.time_patch = unittest.mock.patch('time.time', return_value=MOCK_CURRENT_TIME)
640+
self.time_patch.start()
641+
self.utcnow_patch = unittest.mock.patch(
642+
'google.auth.jwt._helpers.utcnow', return_value=MOCK_CURRENT_TIME_UTC)
643+
self.utcnow_patch.start()
644+
645+
def teardown_method(self):
646+
self.time_patch.stop()
647+
self.utcnow_patch.stop()
648+
621649
valid_cookies = {
622650
'BinaryCookie': TEST_SESSION_COOKIE,
623651
'TextCookie': TEST_SESSION_COOKIE.decode('utf-8'),
@@ -633,14 +661,14 @@ class TestVerifySessionCookie:
633661
'EmptySubject': _get_session_cookie({'sub': ''}),
634662
'IntSubject': _get_session_cookie({'sub': 10}),
635663
'LongStrSubject': _get_session_cookie({'sub': 'a' * 129}),
636-
'FutureCookie': _get_session_cookie({'iat': int(time.time()) + 1000}),
664+
'FutureCookie': _get_session_cookie({'iat': MOCK_CURRENT_TIME + 1000}),
637665
'ExpiredCookie': _get_session_cookie({
638-
'iat': int(time.time()) - 10000,
639-
'exp': int(time.time()) - 3600
666+
'iat': MOCK_CURRENT_TIME - 10000,
667+
'exp': MOCK_CURRENT_TIME - 3600
640668
}),
641669
'ExpiredCookieShort': _get_session_cookie({
642-
'iat': int(time.time()) - 10000,
643-
'exp': int(time.time()) - 30
670+
'iat': MOCK_CURRENT_TIME - 10000,
671+
'exp': MOCK_CURRENT_TIME - 30
644672
}),
645673
'BadFormatCookie': 'foobar',
646674
'IDToken': TEST_ID_TOKEN,
@@ -792,6 +820,17 @@ def test_certificate_request_failure(self, user_mgt_app):
792820

793821
class TestCertificateCaching:
794822

823+
def setup_method(self):
824+
self.time_patch = unittest.mock.patch('time.time', return_value=MOCK_CURRENT_TIME)
825+
self.time_patch.start()
826+
self.utcnow_patch = unittest.mock.patch(
827+
'google.auth.jwt._helpers.utcnow', return_value=MOCK_CURRENT_TIME_UTC)
828+
self.utcnow_patch.start()
829+
830+
def teardown_method(self):
831+
self.time_patch.stop()
832+
self.utcnow_patch.stop()
833+
795834
def test_certificate_caching(self, user_mgt_app, httpserver):
796835
httpserver.serve_content(MOCK_PUBLIC_CERTS, 200, headers={'Cache-Control': 'max-age=3600'})
797836
verifier = _token_gen.TokenVerifier(user_mgt_app)
@@ -810,6 +849,18 @@ def test_certificate_caching(self, user_mgt_app, httpserver):
810849

811850
class TestCertificateFetchTimeout:
812851

852+
def setup_method(self):
853+
self.time_patch = unittest.mock.patch('time.time', return_value=MOCK_CURRENT_TIME)
854+
self.time_patch.start()
855+
self.utcnow_patch = unittest.mock.patch(
856+
'google.auth.jwt._helpers.utcnow', return_value=MOCK_CURRENT_TIME_UTC)
857+
self.utcnow_patch.start()
858+
859+
def teardown_method(self):
860+
self.time_patch.stop()
861+
self.utcnow_patch.stop()
862+
testutils.cleanup_apps()
863+
813864
timeout_configs = [
814865
({'httpTimeout': 4}, 4),
815866
({'httpTimeout': None}, None),
@@ -852,6 +903,3 @@ def _instrument_session(self, app):
852903
recorder = []
853904
request.session.mount('https://', testutils.MockAdapter(MOCK_PUBLIC_CERTS, 200, recorder))
854905
return recorder
855-
856-
def teardown_method(self):
857-
testutils.cleanup_apps()

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /