Skip to content

Commit 1067cee

Browse files
test: remove hardcoded defaults from functional test config and add soak test
Env vars (ATHENA_HOST, OAUTH_AUTH_URL, OAUTH_AUDIENCE) now fall back to their SDK defaults when unset rather than overriding with stale hard-coded values. Adds proactive_refresh_threshold to CredentialHelper and a new classify_single soak test that validates hash-check classification success rate over 1000 iterations. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 0b93a07 commit 1067cee

2 files changed

Lines changed: 85 additions & 13 deletions

File tree

tests/functional/conftest.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,23 +79,25 @@ async def credential_helper() -> CredentialHelper:
7979
_ = load_dotenv()
8080
client_id = os.environ["OAUTH_CLIENT_ID"]
8181
client_secret = os.environ["OAUTH_CLIENT_SECRET"]
82-
auth_url = os.getenv(
83-
"OAUTH_AUTH_URL", "https://crispthinking.auth0.com/oauth/token"
84-
)
85-
audience = os.getenv("OAUTH_AUDIENCE", "crisp-athena-live")
82+
auth_url = os.getenv("OAUTH_AUTH_URL")
83+
audience = os.getenv("OAUTH_AUDIENCE")
8684

8785
# Create credential helper
88-
return CredentialHelper(
89-
client_id=client_id,
90-
client_secret=client_secret,
91-
auth_url=auth_url,
92-
audience=audience,
93-
)
86+
kwargs: dict[str, str] = {
87+
"client_id": client_id,
88+
"client_secret": client_secret,
89+
}
90+
if auth_url:
91+
kwargs["auth_url"] = auth_url
92+
if audience:
93+
kwargs["audience"] = audience
94+
95+
return CredentialHelper(proactive_refresh_threshold=0.25, **kwargs)
9496

9597

9698
def _load_options() -> AthenaOptions:
9799
_ = load_dotenv()
98-
host = os.getenv("ATHENA_HOST", "localhost")
100+
host = os.getenv("ATHENA_HOST")
99101

100102
deployment_id = f"functional-test-{uuid.uuid4()}"
101103
if len(deployment_id) > MAX_DEPLOYMENT_ID_LENGTH:
@@ -104,8 +106,7 @@ def _load_options() -> AthenaOptions:
104106
affiliate = os.environ["ATHENA_TEST_AFFILIATE"]
105107

106108
# Run classification with OAuth authentication
107-
return AthenaOptions(
108-
host=host,
109+
opts = AthenaOptions(
109110
resize_images=True,
110111
deployment_id=deployment_id,
111112
compress_images=True,
@@ -115,6 +116,11 @@ def _load_options() -> AthenaOptions:
115116
compression_quality=2,
116117
)
117118

119+
if host:
120+
opts.host = host
121+
122+
return opts
123+
118124

119125
@pytest.fixture
120126
def athena_options() -> AthenaOptions:
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import grpc
2+
import pytest
3+
4+
from common_utils.image_generation import create_test_image
5+
from resolver_athena_client.client.athena_client import AthenaClient
6+
from resolver_athena_client.client.athena_options import AthenaOptions
7+
from resolver_athena_client.client.channel import (
8+
CredentialHelper,
9+
create_channel_with_credentials,
10+
)
11+
from resolver_athena_client.client.models import ImageData
12+
13+
SOAK_ITERATIONS = 1000
14+
MIN_HASH_CHECK_SUCCESS_RATE = 0.95
15+
16+
17+
@pytest.mark.asyncio
18+
@pytest.mark.functional
19+
@pytest.mark.soak
20+
async def test_classify_single_hash_check_soak(
21+
athena_options: AthenaOptions, credential_helper: CredentialHelper
22+
) -> None:
23+
"""Soak test: classify images and assert hash check result exists."""
24+
25+
channel = await create_channel_with_credentials(
26+
athena_options.host, credential_helper
27+
)
28+
29+
async with AthenaClient(channel, athena_options) as client:
30+
successes = 0
31+
failures: list[str] = []
32+
33+
for i in range(SOAK_ITERATIONS):
34+
image_bytes = create_test_image()
35+
image_data = ImageData(image_bytes)
36+
37+
try:
38+
result = await client.classify_single(image_data)
39+
except grpc.aio.AioRpcError as e:
40+
failures.append(
41+
f"Iteration {i}: gRPC error {e.code()} - {e.details()}"
42+
)
43+
continue
44+
45+
if result.error.code:
46+
failures.append(
47+
f"Iteration {i}: error {result.error.code}"
48+
f" - {result.error.message}"
49+
)
50+
continue
51+
52+
found_hash_check = any(
53+
c.label.startswith("KnownCSAM-") for c in result.classifications
54+
)
55+
if found_hash_check:
56+
successes += 1
57+
else:
58+
failures.append(
59+
f"Iteration {i}: no KnownCSAM- classification found"
60+
)
61+
62+
success_rate = successes / SOAK_ITERATIONS
63+
assert success_rate >= MIN_HASH_CHECK_SUCCESS_RATE, (
64+
f"Hash check success rate {success_rate:.1%} is below 95%. "
65+
f"{len(failures)} failures:\n" + "\n".join(failures[:20])
66+
)

0 commit comments

Comments
 (0)