un-inception/clients/python/sync/tests/test_credentials.py
russell@unturf.com 1e01d09883 feat: per-client Makefile infrastructure for 4-mode testing
Add per-client Makefiles for C, Python, and Go with:
- CLI mode: Tests --help, arg parsing, syntax validation
- Library mode: Unit tests, import verification
- Integration mode: API contract validation (with credentials)
- Functional mode: Real-world scenario tests

C client:
- 22 library tests (SHA-256, HMAC-SHA256, detect_language)
- Full unsandbox.c implementation with examples

Python client (sync + async):
- Delegates to sync/ and async/ subdirectories
- pytest-based test suites with coverage
- Examples for concurrent execution, streaming

Go client:
- Delegates to sync/ and async/ subdirectories
- go test integration with vet and fmt

Also update detect-changes.sh to detect changes in
both root-level un.* files AND clients/ directory.
2026-01-15 16:39:56 -05:00

122 lines
3.6 KiB
Python

"""Tests for credential resolution in unsandbox SDK"""
import os
import tempfile
from pathlib import Path
import pytest
from un import CredentialsError
def test_credentials_from_function_args():
"""Test that function arguments take priority"""
from un import _resolve_credentials
pk, sk = _resolve_credentials("func_pk", "func_sk")
assert pk == "func_pk"
assert sk == "func_sk"
def test_credentials_from_environment():
"""Test that environment variables are used when args are missing"""
from un import _resolve_credentials
# Save original values
orig_pk = os.environ.get("UNSANDBOX_PUBLIC_KEY")
orig_sk = os.environ.get("UNSANDBOX_SECRET_KEY")
try:
os.environ["UNSANDBOX_PUBLIC_KEY"] = "env_pk"
os.environ["UNSANDBOX_SECRET_KEY"] = "env_sk"
pk, sk = _resolve_credentials()
assert pk == "env_pk"
assert sk == "env_sk"
finally:
# Restore original values
if orig_pk is not None:
os.environ["UNSANDBOX_PUBLIC_KEY"] = orig_pk
else:
os.environ.pop("UNSANDBOX_PUBLIC_KEY", None)
if orig_sk is not None:
os.environ["UNSANDBOX_SECRET_KEY"] = orig_sk
else:
os.environ.pop("UNSANDBOX_SECRET_KEY", None)
def test_credentials_from_csv_file():
"""Test loading credentials from CSV file"""
from un import _load_credentials_from_csv
with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False) as f:
f.write("pk1,sk1\n")
f.write("pk2,sk2\n")
temp_path = f.name
try:
# Load first account
pk, sk = _load_credentials_from_csv(Path(temp_path), 0)
assert pk == "pk1"
assert sk == "sk1"
# Load second account
pk, sk = _load_credentials_from_csv(Path(temp_path), 1)
assert pk == "pk2"
assert sk == "sk2"
finally:
os.unlink(temp_path)
def test_credentials_csv_with_comments():
"""Test that CSV loader ignores comments"""
from un import _load_credentials_from_csv
with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False) as f:
f.write("# Comment line\n")
f.write("pk1,sk1\n")
f.write("\n") # Empty line
f.write("pk2,sk2\n")
temp_path = f.name
try:
pk, sk = _load_credentials_from_csv(Path(temp_path), 0)
assert pk == "pk1"
assert sk == "sk1"
finally:
os.unlink(temp_path)
def test_credentials_csv_nonexistent_file():
"""Test that nonexistent CSV returns None"""
from un import _load_credentials_from_csv
result = _load_credentials_from_csv(Path("/nonexistent/file.csv"))
assert result is None
def test_credentials_missing_all():
"""Test that CredentialsError is raised when no credentials available"""
from un import _resolve_credentials
# Save original values
orig_pk = os.environ.get("UNSANDBOX_PUBLIC_KEY")
orig_sk = os.environ.get("UNSANDBOX_SECRET_KEY")
try:
os.environ.pop("UNSANDBOX_PUBLIC_KEY", None)
os.environ.pop("UNSANDBOX_SECRET_KEY", None)
# This should raise because we're not providing args and env vars don't exist
# (and we don't have test CSV files)
with pytest.raises(CredentialsError):
_resolve_credentials()
finally:
if orig_pk is not None:
os.environ["UNSANDBOX_PUBLIC_KEY"] = orig_pk
else:
os.environ.pop("UNSANDBOX_PUBLIC_KEY", None)
if orig_sk is not None:
os.environ["UNSANDBOX_SECRET_KEY"] = orig_sk
else:
os.environ.pop("UNSANDBOX_SECRET_KEY", None)