Skip to content

Commit aa5e50b

Browse files
authored
SNOW-901801: fix flaky test of ocsp cache in regression test (#1825)
1 parent 7bd365c commit aa5e50b

File tree

2 files changed

+123
-68
lines changed

2 files changed

+123
-68
lines changed

ci/test_darwin.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ for PYTHON_VERSION in ${PYTHON_VERSIONS}; do
2929
echo "[Info] Testing with ${PYTHON_VERSION}"
3030
SHORT_VERSION=$(python3 -c "print('${PYTHON_VERSION}'.replace('.', ''))")
3131
CONNECTOR_WHL=$(ls ${CONNECTOR_DIR}/dist/snowflake_connector_python*cp${SHORT_VERSION}*.whl)
32-
TEST_ENVLIST=py${SHORT_VERSION}-{unit,integ,pandas,sso}-ci
32+
TEST_ENVLIST=fix_lint,py${SHORT_VERSION}-{unit,integ,pandas,sso}-ci,py${SHORT_VERSION}-coverage
3333
echo "[Info] Running tox for ${TEST_ENVLIST}"
3434
tox -e ${TEST_ENVLIST} --external_wheels ${CONNECTOR_WHL}
3535
done

test/unit/test_ocsp.py

Lines changed: 122 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,17 @@
77

88
import logging
99
import os
10+
import platform
1011
import time
1112
from concurrent.futures.thread import ThreadPoolExecutor
1213
from os import environ, path
1314
from unittest import mock
1415

16+
try:
17+
from snowflake.connector.util_text import random_string
18+
except ImportError:
19+
from ..randomize import random_string
20+
1521
import pytest
1622

1723
import snowflake.connector.ocsp_snowflake
@@ -62,6 +68,41 @@ def overwrite_ocsp_cache(tmpdir):
6268
THIS_DIR = path.dirname(path.realpath(__file__))
6369

6470

71+
@pytest.fixture(autouse=True)
72+
def random_ocsp_response_validation_cache():
73+
file_path = {
74+
"linux": os.path.join(
75+
"~",
76+
".cache",
77+
"snowflake",
78+
f"ocsp_response_validation_cache{random_string()}",
79+
),
80+
"darwin": os.path.join(
81+
"~",
82+
"Library",
83+
"Caches",
84+
"Snowflake",
85+
f"ocsp_response_validation_cache{random_string()}",
86+
),
87+
"windows": os.path.join(
88+
"~",
89+
"AppData",
90+
"Local",
91+
"Snowflake",
92+
"Caches",
93+
f"ocsp_response_validation_cache{random_string()}",
94+
),
95+
}
96+
yield SFDictFileCache(
97+
entry_lifetime=3600,
98+
file_path=file_path,
99+
)
100+
try:
101+
os.unlink(file_path[platform.system().lower()])
102+
except BaseException:
103+
pass
104+
105+
65106
def test_ocsp():
66107
"""OCSP tests."""
67108
# reset the memory cache
@@ -209,73 +250,81 @@ def test_ocsp_with_file_cache(tmpdir):
209250

210251

211252
@pytest.mark.skipolddriver
212-
def test_ocsp_with_bogus_cache_files(tmpdir):
213-
from snowflake.connector.ocsp_snowflake import OCSPResponseValidationResult
214-
215-
"""Attempts to use bogus OCSP response data."""
216-
cache_file_name, target_hosts = _store_cache_in_file(tmpdir)
253+
def test_ocsp_with_bogus_cache_files(tmpdir, random_ocsp_response_validation_cache):
254+
with mock.patch(
255+
"snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE",
256+
random_ocsp_response_validation_cache,
257+
):
258+
from snowflake.connector.ocsp_snowflake import OCSPResponseValidationResult
217259

218-
ocsp = SFOCSP()
219-
OCSPCache.read_ocsp_response_cache_file(ocsp, cache_file_name)
220-
cache_data = snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE
221-
assert cache_data, "more than one cache entries should be stored."
222-
223-
# setting bogus data
224-
current_time = int(time.time())
225-
for k, _ in cache_data.items():
226-
cache_data[k] = OCSPResponseValidationResult(
227-
ocsp_response=b"bogus",
228-
ts=current_time,
229-
validated=True,
230-
)
260+
"""Attempts to use bogus OCSP response data."""
261+
cache_file_name, target_hosts = _store_cache_in_file(tmpdir)
231262

232-
# write back the cache file
233-
OCSPCache.CACHE = cache_data
234-
OCSPCache.write_ocsp_response_cache_file(ocsp, cache_file_name)
235-
236-
# forces to use the bogus cache file but it should raise errors
237-
SnowflakeOCSP.clear_cache()
238-
ocsp = SFOCSP()
239-
for hostname in target_hosts:
240-
connection = _openssl_connect(hostname)
241-
assert ocsp.validate(hostname, connection), "Failed to validate: {}".format(
242-
hostname
243-
)
263+
ocsp = SFOCSP()
264+
OCSPCache.read_ocsp_response_cache_file(ocsp, cache_file_name)
265+
cache_data = snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE
266+
assert cache_data, "more than one cache entries should be stored."
267+
268+
# setting bogus data
269+
current_time = int(time.time())
270+
for k, _ in cache_data.items():
271+
cache_data[k] = OCSPResponseValidationResult(
272+
ocsp_response=b"bogus",
273+
ts=current_time,
274+
validated=True,
275+
)
276+
277+
# write back the cache file
278+
OCSPCache.CACHE = cache_data
279+
OCSPCache.write_ocsp_response_cache_file(ocsp, cache_file_name)
280+
281+
# forces to use the bogus cache file but it should raise errors
282+
SnowflakeOCSP.clear_cache()
283+
ocsp = SFOCSP()
284+
for hostname in target_hosts:
285+
connection = _openssl_connect(hostname)
286+
assert ocsp.validate(hostname, connection), "Failed to validate: {}".format(
287+
hostname
288+
)
244289

245290

246291
@pytest.mark.skipolddriver
247-
def test_ocsp_with_outdated_cache(tmpdir):
248-
from snowflake.connector.ocsp_snowflake import OCSPResponseValidationResult
249-
250-
"""Attempts to use outdated OCSP response cache file."""
251-
cache_file_name, target_hosts = _store_cache_in_file(tmpdir)
292+
def test_ocsp_with_outdated_cache(tmpdir, random_ocsp_response_validation_cache):
293+
with mock.patch(
294+
"snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE",
295+
random_ocsp_response_validation_cache,
296+
):
297+
from snowflake.connector.ocsp_snowflake import OCSPResponseValidationResult
252298

253-
ocsp = SFOCSP()
299+
"""Attempts to use outdated OCSP response cache file."""
300+
cache_file_name, target_hosts = _store_cache_in_file(tmpdir)
254301

255-
# reading cache file
256-
OCSPCache.read_ocsp_response_cache_file(ocsp, cache_file_name)
257-
cache_data = snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE
258-
assert cache_data, "more than one cache entries should be stored."
259-
260-
# setting outdated data
261-
current_time = int(time.time())
262-
for k, v in cache_data.items():
263-
cache_data[k] = OCSPResponseValidationResult(
264-
ocsp_response=v.ocsp_response,
265-
ts=current_time - 144 * 60 * 60,
266-
validated=True,
267-
)
268-
269-
# write back the cache file
270-
OCSPCache.CACHE = cache_data
271-
OCSPCache.write_ocsp_response_cache_file(ocsp, cache_file_name)
302+
ocsp = SFOCSP()
272303

273-
# forces to use the bogus cache file but it should raise errors
274-
SnowflakeOCSP.clear_cache() # reset the memory cache
275-
SFOCSP()
276-
assert (
277-
SnowflakeOCSP.cache_size() == 0
278-
), "must be empty. outdated cache should not be loaded"
304+
# reading cache file
305+
OCSPCache.read_ocsp_response_cache_file(ocsp, cache_file_name)
306+
cache_data = snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE
307+
assert cache_data, "more than one cache entries should be stored."
308+
309+
# setting outdated data
310+
current_time = int(time.time())
311+
for k, v in cache_data.items():
312+
cache_data[k] = OCSPResponseValidationResult(
313+
ocsp_response=v.ocsp_response,
314+
ts=current_time - 144 * 60 * 60,
315+
validated=True,
316+
)
317+
318+
# write back the cache file
319+
OCSPCache.CACHE = cache_data
320+
OCSPCache.write_ocsp_response_cache_file(ocsp, cache_file_name)
321+
322+
# forces to use the bogus cache file but it should raise errors
323+
SnowflakeOCSP.clear_cache() # reset the memory cache
324+
SFOCSP()
325+
assert (
326+
SnowflakeOCSP.cache_size() == 0
327+
), "must be empty. outdated cache should not be loaded"
279328

280329

281330
def _store_cache_in_file(tmpdir, target_hosts=None):
@@ -312,16 +361,22 @@ def test_ocsp_with_invalid_cache_file():
312361
"snowflake.connector.ocsp_snowflake.SnowflakeOCSP._fetch_ocsp_response",
313362
side_effect=BrokenPipeError("fake error"),
314363
)
315-
def test_ocsp_cache_when_server_is_down(mock_fetch_ocsp_response, tmpdir):
316-
ocsp = SFOCSP()
364+
def test_ocsp_cache_when_server_is_down(
365+
mock_fetch_ocsp_response, tmpdir, random_ocsp_response_validation_cache
366+
):
367+
with mock.patch(
368+
"snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE",
369+
random_ocsp_response_validation_cache,
370+
):
371+
ocsp = SFOCSP()
317372

318-
"""Attempts to use outdated OCSP response cache file."""
319-
cache_file_name, target_hosts = _store_cache_in_file(tmpdir)
373+
"""Attempts to use outdated OCSP response cache file."""
374+
cache_file_name, target_hosts = _store_cache_in_file(tmpdir)
320375

321-
# reading cache file
322-
OCSPCache.read_ocsp_response_cache_file(ocsp, cache_file_name)
323-
cache_data = snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE
324-
assert not cache_data, "no cache should present because of broken pipe"
376+
# reading cache file
377+
OCSPCache.read_ocsp_response_cache_file(ocsp, cache_file_name)
378+
cache_data = snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE
379+
assert not cache_data, "no cache should present because of broken pipe"
325380

326381

327382
def test_concurrent_ocsp_requests(tmpdir):

0 commit comments

Comments
 (0)