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.
122 lines
3.6 KiB
Python
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)
|