11import json
22import os
3+ import re
34import time
45from typing import Generator
56from unittest .mock import mock_open , patch
1718 _firebolt_cache ,
1819)
1920from firebolt .utils .file_operations import FernetEncrypter , generate_salt
21+ from tests .unit .response import Response
2022
2123
2224@fixture
@@ -136,29 +138,59 @@ def mock_connection_flow(httpx_mock, auth_url, api_endpoint):
136138 """Mock the connection flow for testing."""
137139
138140 def _mock_flow (account_name = "mock_account_name" ):
139- # Mock authentication with correct URL pattern from existing tests
140- httpx_mock .add_response (
141+ # Mock authentication with reusable responses
142+ def auth_callback (request ):
143+ return Response (
144+ status_code = 200 ,
145+ json = {"access_token" : "mock_token" , "expires_in" : 3600 },
146+ )
147+
148+ def engine_url_callback (request ):
149+ return Response (
150+ status_code = 200 ,
151+ json = {"engineUrl" : "https://system.mock.firebolt.io" },
152+ )
153+
154+ def system_engine_callback (request ):
155+ query_response = {
156+ "meta" : [],
157+ "data" : [],
158+ "rows" : 0 ,
159+ "statistics" : {
160+ "elapsed" : 0.116907717 ,
161+ "rows_read" : 0 ,
162+ "bytes_read" : 0 ,
163+ "time_before_execution" : 0.012180623 ,
164+ "time_to_execute" : 0.104614307 ,
165+ "scanned_bytes_cache" : 0 ,
166+ "scanned_bytes_storage" : 0 ,
167+ },
168+ }
169+ return Response (
170+ status_code = 200 ,
171+ json = query_response ,
172+ )
173+
174+ # Add all callbacks as reusable
175+ httpx_mock .add_callback (
176+ auth_callback ,
177+ url = auth_url ,
141178 method = "POST" ,
142- url = auth_url , # Use the correct auth_url fixture
143- json = {"access_token" : "mock_token" , "expires_in" : 3600 },
179+ is_reusable = True ,
144180 )
145181
146- # Mock system engine URL - this is the actual URL pattern used
147- httpx_mock .add_response (
148- method = "GET" ,
182+ httpx_mock .add_callback (
183+ engine_url_callback ,
149184 url = f"https://{ api_endpoint } /web/v3/account/{ account_name } /engineUrl" ,
150- json = {"engineUrl" : "https://system.mock.firebolt.io" },
185+ method = "GET" ,
186+ is_reusable = True ,
151187 )
152188
153- # Mock queries to the system engine (this handles all POST requests to system.mock.firebolt.io)
154- # This will catch USE DATABASE, USE ENGINE queries and any other queries
155- def system_engine_callback (request ):
156- return {"meta" : [], "data" : [], "rows" : 0 , "statistics" : {}}
157-
158189 httpx_mock .add_callback (
159190 system_engine_callback ,
160- url = "https://system.mock.firebolt.io/" ,
191+ url = re . compile ( r "https://system\ .mock\ .firebolt\ .io(/.*)?(\?.*)?" ) ,
161192 method = "POST" ,
193+ is_reusable = True ,
162194 )
163195
164196 return _mock_flow
@@ -169,14 +201,22 @@ def clean_cache():
169201 """Provide a clean cache for each test."""
170202 original_memory = _firebolt_cache .memory_cache ._cache .copy ()
171203 original_file_cache_disabled = _firebolt_cache .disabled
204+ original_data_dir = _firebolt_cache ._data_dir
172205
173206 _firebolt_cache .clear ()
174207 _firebolt_cache .enable () # Enable cache for connection flow tests
208+
209+ # For tests using fake filesystem, set the cache directory to a path in the fake fs
210+ # This works because pyfakefs creates its fake filesystem before this fixture runs
211+ _firebolt_cache ._data_dir = "/tmp/test_firebolt_cache"
212+ os .makedirs (_firebolt_cache ._data_dir , exist_ok = True )
213+
175214 yield _firebolt_cache
176215
177216 # Restore original state
178217 _firebolt_cache .memory_cache ._cache = original_memory
179218 _firebolt_cache .disabled = original_file_cache_disabled
219+ _firebolt_cache ._data_dir = original_data_dir
180220
181221
182222def test_cache_set_and_get (cache , sample_cache_key , sample_connection_info ):
@@ -1061,6 +1101,7 @@ def test_cache_stores_connection_data(
10611101def test_different_accounts_isolated_cache_entries (
10621102 clean_cache ,
10631103 auth_client_1 ,
1104+ auth_client_2 ,
10641105 mock_connection_flow ,
10651106 api_endpoint ,
10661107):
@@ -1072,7 +1113,7 @@ def test_different_accounts_isolated_cache_entries(
10721113 mock_connection_flow (account_1 )
10731114 mock_connection_flow (account_2 )
10741115
1075- # Connect to first account
1116+ # Connect to first account with first auth client
10761117 with connect (
10771118 database = "test_db" ,
10781119 engine_name = "test_engine" ,
@@ -1088,18 +1129,18 @@ def test_different_accounts_isolated_cache_entries(
10881129 cache_1 = _firebolt_cache .get (key_account_1 )
10891130 assert cache_1 is not None , "Account 1 should have cache entry"
10901131
1091- # Connect to second account with same credentials
1132+ # Connect to second account with second auth client (different credentials)
10921133 with connect (
10931134 database = "test_db" ,
10941135 engine_name = "test_engine" ,
1095- auth = auth_client_1 ,
1136+ auth = auth_client_2 ,
10961137 account_name = account_2 ,
10971138 api_endpoint = api_endpoint ,
10981139 ):
10991140 # Get second cache entry
11001141 key_account_2 = SecureCacheKey (
1101- [auth_client_1 .principal , auth_client_1 .secret , account_2 ],
1102- auth_client_1 .secret ,
1142+ [auth_client_2 .principal , auth_client_2 .secret , account_2 ],
1143+ auth_client_2 .secret ,
11031144 )
11041145 cache_2 = _firebolt_cache .get (key_account_2 )
11051146 assert cache_2 is not None , "Account 2 should have cache entry"
@@ -1228,9 +1269,9 @@ def test_memory_first_disk_fallback_with_connections(
12281269 assert memory_data is not None , "Data should be in memory cache"
12291270
12301271 # Verify cache file exists in fake filesystem
1231- cache_dir = os . path . expanduser ( "~/.firebolt" )
1272+ cache_dir = _firebolt_cache . _data_dir
12321273 if os .path .exists (cache_dir ):
1233- cache_files = [f for f in os .listdir (cache_dir ) if f .endswith (".json " )]
1274+ cache_files = [f for f in os .listdir (cache_dir ) if f .endswith (".txt " )]
12341275 assert len (cache_files ) > 0 , "Cache files should be created"
12351276
12361277 # Clear memory cache but keep disk cache
@@ -1265,9 +1306,9 @@ def test_disk_file_operations_with_pyfakefs(
12651306 api_endpoint = api_endpoint ,
12661307 ):
12671308 # Verify cache file was created in fake filesystem
1268- cache_dir = os . path . expanduser ( "~/.firebolt" )
1309+ cache_dir = _firebolt_cache . _data_dir
12691310 if os .path .exists (cache_dir ):
1270- cache_files = [f for f in os .listdir (cache_dir ) if f .endswith (".json " )]
1311+ cache_files = [f for f in os .listdir (cache_dir ) if f .endswith (".txt " )]
12711312 # May or may not have files depending on implementation
12721313 assert isinstance (cache_files , list ), "Cache files list should be valid"
12731314
0 commit comments