1010import platform
1111import time
1212from concurrent .futures .thread import ThreadPoolExecutor
13- from os import environ , path
13+ from os import path
1414from unittest import mock
1515
1616import asn1crypto .x509
@@ -78,7 +78,7 @@ def overwrite_ocsp_cache(tmpdir):
7878
7979
8080@pytest .fixture (autouse = True )
81- def worker_specific_cache_dir (tmpdir , request ):
81+ def worker_specific_cache_dir (tmpdir , request , monkeypatch ):
8282 """Create worker-specific cache directory to avoid file lock conflicts in parallel execution.
8383
8484 Note: Tests that explicitly manage their own cache directories (like test_ocsp_cache_when_server_is_down)
@@ -88,13 +88,12 @@ def worker_specific_cache_dir(tmpdir, request):
8888 # Get worker ID for parallel execution (pytest-xdist)
8989 worker_id = os .environ .get ("PYTEST_XDIST_WORKER" , "master" )
9090
91- # Store original cache dir environment variable
92- original_cache_dir = os .environ .get ("SF_OCSP_RESPONSE_CACHE_DIR" )
91+ # monkeypatch will automatically handle restoration
9392
9493 # Set worker-specific cache directory to prevent main cache file conflicts
9594 worker_cache_dir = tmpdir .join (f"ocsp_cache_{ worker_id } " )
9695 worker_cache_dir .ensure (dir = True )
97- os . environ [ "SF_OCSP_RESPONSE_CACHE_DIR" ] = str (worker_cache_dir )
96+ monkeypatch . setenv ( "SF_OCSP_RESPONSE_CACHE_DIR" , str (worker_cache_dir ) )
9897
9998 # Only handle the OCSP_RESPONSE_VALIDATION_CACHE to prevent conflicts
10099 # Let tests manage SF_OCSP_RESPONSE_CACHE_DIR themselves if they need to
@@ -131,11 +130,7 @@ def worker_specific_cache_dir(tmpdir, request):
131130 # If modules not available, just yield the directory
132131 yield str (tmpdir )
133132 finally :
134- # Restore original cache directory environment variable
135- if original_cache_dir is not None :
136- os .environ ["SF_OCSP_RESPONSE_CACHE_DIR" ] = original_cache_dir
137- else :
138- os .environ .pop ("SF_OCSP_RESPONSE_CACHE_DIR" , None )
133+ # monkeypatch will automatically restore the original environment variable
139134
140135 # Reset cache dir back to original state
141136 try :
@@ -235,7 +230,7 @@ def test_ocsp_wo_cache_server():
235230 assert ocsp .validate (url , connection ), f"Failed to validate: { url } "
236231
237232
238- def test_ocsp_wo_cache_file ():
233+ def test_ocsp_wo_cache_file (monkeypatch ):
239234 """OCSP tests without File cache.
240235
241236 Notes:
@@ -248,7 +243,7 @@ def test_ocsp_wo_cache_file():
248243 except FileNotFoundError :
249244 # File doesn't exist, which is fine for this test
250245 pass
251- environ [ "SF_OCSP_RESPONSE_CACHE_DIR" ] = "/etc"
246+ monkeypatch . setenv ( "SF_OCSP_RESPONSE_CACHE_DIR" , "/etc" )
252247 OCSPCache .reset_cache_dir ()
253248
254249 try :
@@ -257,11 +252,10 @@ def test_ocsp_wo_cache_file():
257252 connection = _openssl_connect (url )
258253 assert ocsp .validate (url , connection ), f"Failed to validate: { url } "
259254 finally :
260- del environ ["SF_OCSP_RESPONSE_CACHE_DIR" ]
261255 OCSPCache .reset_cache_dir ()
262256
263257
264- def test_ocsp_fail_open_w_single_endpoint ():
258+ def test_ocsp_fail_open_w_single_endpoint (monkeypatch ):
265259 SnowflakeOCSP .clear_cache ()
266260
267261 try :
@@ -270,33 +264,28 @@ def test_ocsp_fail_open_w_single_endpoint():
270264 # File doesn't exist, which is fine for this test
271265 pass
272266
273- environ [ "SF_OCSP_TEST_MODE" ] = "true"
274- environ [ "SF_TEST_OCSP_URL" ] = "http://httpbin.org/delay/10"
275- environ [ "SF_TEST_CA_OCSP_RESPONDER_CONNECTION_TIMEOUT" ] = "5"
267+ monkeypatch . setenv ( "SF_OCSP_TEST_MODE" , "true" )
268+ monkeypatch . setenv ( "SF_TEST_OCSP_URL" , "http://httpbin.org/delay/10" )
269+ monkeypatch . setenv ( "SF_TEST_CA_OCSP_RESPONDER_CONNECTION_TIMEOUT" , "5" )
276270
277271 ocsp = SFOCSP (use_ocsp_cache_server = False )
278272 connection = _openssl_connect ("snowflake.okta.com" )
279273
280- try :
281- assert ocsp .validate (
282- "snowflake.okta.com" , connection
283- ), "Failed to validate: {}" .format ("snowflake.okta.com" )
284- finally :
285- del environ ["SF_OCSP_TEST_MODE" ]
286- del environ ["SF_TEST_OCSP_URL" ]
287- del environ ["SF_TEST_CA_OCSP_RESPONDER_CONNECTION_TIMEOUT" ]
274+ assert ocsp .validate (
275+ "snowflake.okta.com" , connection
276+ ), "Failed to validate: {}" .format ("snowflake.okta.com" )
288277
289278
290279@pytest .mark .skipif (
291280 ER_OCSP_RESPONSE_CERT_STATUS_REVOKED is None ,
292281 reason = "No ER_OCSP_RESPONSE_CERT_STATUS_REVOKED is available." ,
293282)
294- def test_ocsp_fail_close_w_single_endpoint ():
283+ def test_ocsp_fail_close_w_single_endpoint (monkeypatch ):
295284 SnowflakeOCSP .clear_cache ()
296285
297- environ [ "SF_OCSP_TEST_MODE" ] = "true"
298- environ [ "SF_TEST_OCSP_URL" ] = "http://httpbin.org/delay/10"
299- environ [ "SF_TEST_CA_OCSP_RESPONDER_CONNECTION_TIMEOUT" ] = "5"
286+ monkeypatch . setenv ( "SF_OCSP_TEST_MODE" , "true" )
287+ monkeypatch . setenv ( "SF_TEST_OCSP_URL" , "http://httpbin.org/delay/10" )
288+ monkeypatch . setenv ( "SF_TEST_CA_OCSP_RESPONDER_CONNECTION_TIMEOUT" , "5" )
300289
301290 OCSPCache .del_cache_file ()
302291
@@ -306,21 +295,16 @@ def test_ocsp_fail_close_w_single_endpoint():
306295 with pytest .raises (RevocationCheckError ) as ex :
307296 ocsp .validate ("snowflake.okta.com" , connection )
308297
309- try :
310- assert (
311- ex .value .errno == ER_OCSP_RESPONSE_FETCH_FAILURE
312- ), "Connection should have failed"
313- finally :
314- del environ ["SF_OCSP_TEST_MODE" ]
315- del environ ["SF_TEST_OCSP_URL" ]
316- del environ ["SF_TEST_CA_OCSP_RESPONDER_CONNECTION_TIMEOUT" ]
298+ assert (
299+ ex .value .errno == ER_OCSP_RESPONSE_FETCH_FAILURE
300+ ), "Connection should have failed"
317301
318302
319- def test_ocsp_bad_validity ():
303+ def test_ocsp_bad_validity (monkeypatch ):
320304 SnowflakeOCSP .clear_cache ()
321305
322- environ [ "SF_OCSP_TEST_MODE" ] = "true"
323- environ [ "SF_TEST_OCSP_FORCE_BAD_RESPONSE_VALIDITY" ] = "true"
306+ monkeypatch . setenv ( "SF_OCSP_TEST_MODE" , "true" )
307+ monkeypatch . setenv ( "SF_TEST_OCSP_FORCE_BAD_RESPONSE_VALIDITY" , "true" )
324308
325309 try :
326310 OCSPCache .del_cache_file ()
@@ -334,12 +318,10 @@ def test_ocsp_bad_validity():
334318 assert ocsp .validate (
335319 "snowflake.okta.com" , connection
336320 ), "Connection should have passed with fail open"
337- del environ ["SF_OCSP_TEST_MODE" ]
338- del environ ["SF_TEST_OCSP_FORCE_BAD_RESPONSE_VALIDITY" ]
339321
340322
341- def test_ocsp_single_endpoint ():
342- environ [ "SF_OCSP_ACTIVATE_NEW_ENDPOINT" ] = "True"
323+ def test_ocsp_single_endpoint (monkeypatch ):
324+ monkeypatch . setenv ( "SF_OCSP_ACTIVATE_NEW_ENDPOINT" , "True" )
343325 SnowflakeOCSP .clear_cache ()
344326 ocsp = SFOCSP ()
345327 ocsp .OCSP_CACHE_SERVER .NEW_DEFAULT_CACHE_SERVER_BASE_URL = "https://snowflake.preprod3.us-west-2-dev.external-zone.snowflakecomputing.com:8085/ocsp/"
@@ -348,8 +330,6 @@ def test_ocsp_single_endpoint():
348330 "snowflake.okta.com" , connection
349331 ), "Failed to validate: {}" .format ("snowflake.okta.com" )
350332
351- del environ ["SF_OCSP_ACTIVATE_NEW_ENDPOINT" ]
352-
353333
354334def test_ocsp_by_post_method ():
355335 """OCSP tests."""
@@ -375,15 +355,17 @@ def test_ocsp_with_file_cache(tmpdir):
375355
376356
377357@pytest .mark .skipolddriver
378- def test_ocsp_with_bogus_cache_files (tmpdir , random_ocsp_response_validation_cache ):
358+ def test_ocsp_with_bogus_cache_files (
359+ tmpdir , random_ocsp_response_validation_cache , monkeypatch
360+ ):
379361 with mock .patch (
380362 "snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE" ,
381363 random_ocsp_response_validation_cache ,
382364 ):
383365 from snowflake .connector .ocsp_snowflake import OCSPResponseValidationResult
384366
385367 """Attempts to use bogus OCSP response data."""
386- cache_file_name , target_hosts = _store_cache_in_file (tmpdir )
368+ cache_file_name , target_hosts = _store_cache_in_file (monkeypatch , tmpdir )
387369
388370 ocsp = SFOCSP ()
389371 OCSPCache .read_ocsp_response_cache_file (ocsp , cache_file_name )
@@ -414,15 +396,17 @@ def test_ocsp_with_bogus_cache_files(tmpdir, random_ocsp_response_validation_cac
414396
415397
416398@pytest .mark .skipolddriver
417- def test_ocsp_with_outdated_cache (tmpdir , random_ocsp_response_validation_cache ):
399+ def test_ocsp_with_outdated_cache (
400+ tmpdir , random_ocsp_response_validation_cache , monkeypatch
401+ ):
418402 with mock .patch (
419403 "snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE" ,
420404 random_ocsp_response_validation_cache ,
421405 ):
422406 from snowflake .connector .ocsp_snowflake import OCSPResponseValidationResult
423407
424408 """Attempts to use outdated OCSP response cache file."""
425- cache_file_name , target_hosts = _store_cache_in_file (tmpdir )
409+ cache_file_name , target_hosts = _store_cache_in_file (monkeypatch , tmpdir )
426410
427411 ocsp = SFOCSP ()
428412
@@ -452,10 +436,8 @@ def test_ocsp_with_outdated_cache(tmpdir, random_ocsp_response_validation_cache)
452436 ), "must be empty. outdated cache should not be loaded"
453437
454438
455- def _store_cache_in_file (tmpdir , target_hosts = None ):
456- if target_hosts is None :
457- target_hosts = TARGET_HOSTS
458- os .environ ["SF_OCSP_RESPONSE_CACHE_DIR" ] = str (tmpdir )
439+ def _store_cache_in_file (monkeypatch , tmpdir ):
440+ monkeypatch .setenv ("SF_OCSP_RESPONSE_CACHE_DIR" , str (tmpdir ))
459441 OCSPCache .reset_cache_dir ()
460442 filename = path .join (str (tmpdir ), "ocsp_response_cache.json" )
461443
@@ -464,13 +446,13 @@ def _store_cache_in_file(tmpdir, target_hosts=None):
464446 ocsp = SFOCSP (
465447 ocsp_response_cache_uri = "file://" + filename , use_ocsp_cache_server = False
466448 )
467- for hostname in target_hosts :
449+ for hostname in TARGET_HOSTS :
468450 connection = _openssl_connect (hostname )
469451 assert ocsp .validate (hostname , connection ), "Failed to validate: {}" .format (
470452 hostname
471453 )
472454 assert path .exists (filename ), "OCSP response cache file"
473- return filename , target_hosts
455+ return filename , TARGET_HOSTS
474456
475457
476458def test_ocsp_with_invalid_cache_file ():
@@ -658,11 +640,11 @@ def test_building_retry_url():
658640 assert OCSP_SERVER .OCSP_RETRY_URL is None
659641
660642
661- def test_building_new_retry ():
643+ def test_building_new_retry (monkeypatch ):
662644 OCSP_SERVER = OCSPServer ()
663645 OCSP_SERVER .OCSP_RETRY_URL = None
664646 hname = "a1.us-east-1.snowflakecomputing.com"
665- os . environ [ "SF_OCSP_ACTIVATE_NEW_ENDPOINT" ] = "true"
647+ monkeypatch . setenv ( "SF_OCSP_ACTIVATE_NEW_ENDPOINT" , "true" )
666648 OCSP_SERVER .reset_ocsp_endpoint (hname )
667649 assert (
668650 OCSP_SERVER .CACHE_SERVER_URL
@@ -698,8 +680,6 @@ def test_building_new_retry():
698680 == "https://ocspssd.snowflakecomputing.com/ocsp/retry"
699681 )
700682
701- del os .environ ["SF_OCSP_ACTIVATE_NEW_ENDPOINT" ]
702-
703683
704684@pytest .mark .parametrize (
705685 "hash_algorithm" ,
0 commit comments