test: add unit tests for signing, bypass, and hook
This commit is contained in:
parent
cd790313e1
commit
047094759d
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
36
tests/conftest.py
Normal file
36
tests/conftest.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# pyright: reportMissingImports=false, reportUnknownMemberType=false, reportUntypedFunctionDecorator=false, reportUnknownParameterType=false, reportMissingParameterType=false, reportUnknownVariableType=false, reportUnknownArgumentType=false
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def simple_messages():
|
||||||
|
return [{"role": "user", "content": "hello world"}]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def complex_messages():
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": [
|
||||||
|
{"type": "image", "source": {"type": "base64", "data": "abc"}},
|
||||||
|
{"type": "text", "text": "hello world"},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def basic_api_kwargs(simple_messages):
|
||||||
|
return {
|
||||||
|
"system": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"text": "You are Claude Code, Anthropic's official CLI for Claude.\nStay helpful.",
|
||||||
|
},
|
||||||
|
{"type": "text", "text": "Extra system guidance"},
|
||||||
|
],
|
||||||
|
"messages": [dict(message) for message in simple_messages],
|
||||||
|
"model": "claude-opus-4-6-20260101",
|
||||||
|
}
|
||||||
95
tests/test_bypass.py
Normal file
95
tests/test_bypass.py
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
# pyright: reportPrivateUsage=false, reportUnknownParameterType=false, reportMissingParameterType=false, reportUnknownArgumentType=false, reportUnknownVariableType=false, reportUnknownMemberType=false, reportArgumentType=false
|
||||||
|
|
||||||
|
import copy
|
||||||
|
|
||||||
|
from anthropic_billing_bypass import (
|
||||||
|
_SYSTEM_IDENTITY,
|
||||||
|
_fix_temperature_for_oauth_adaptive,
|
||||||
|
apply_claude_code_bypass,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_claude_code_bypass_injects_billing_header_and_preserves_identity(
|
||||||
|
basic_api_kwargs,
|
||||||
|
):
|
||||||
|
apply_claude_code_bypass(basic_api_kwargs, "2.1.90")
|
||||||
|
|
||||||
|
system = basic_api_kwargs["system"]
|
||||||
|
assert system[0]["text"].startswith("x-anthropic-billing-header: ")
|
||||||
|
assert system[1]["text"] == _SYSTEM_IDENTITY
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_claude_code_bypass_relocates_non_identity_system_text_to_first_user_message(
|
||||||
|
basic_api_kwargs,
|
||||||
|
):
|
||||||
|
apply_claude_code_bypass(basic_api_kwargs, "2.1.90")
|
||||||
|
|
||||||
|
user_content = basic_api_kwargs["messages"][0]["content"]
|
||||||
|
assert isinstance(user_content, list)
|
||||||
|
text = user_content[0]["text"]
|
||||||
|
assert "<system-reminder>\nStay helpful.\n</system-reminder>" in text
|
||||||
|
assert "<system-reminder>\nExtra system guidance\n</system-reminder>" in text
|
||||||
|
assert text.endswith("hello world")
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_claude_code_bypass_is_idempotent(basic_api_kwargs):
|
||||||
|
apply_claude_code_bypass(basic_api_kwargs, "2.1.90")
|
||||||
|
once = copy.deepcopy(basic_api_kwargs)
|
||||||
|
|
||||||
|
apply_claude_code_bypass(basic_api_kwargs, "2.1.90")
|
||||||
|
|
||||||
|
assert len(basic_api_kwargs["system"]) == 2
|
||||||
|
assert basic_api_kwargs["system"][0]["text"].startswith(
|
||||||
|
"x-anthropic-billing-header: "
|
||||||
|
)
|
||||||
|
assert basic_api_kwargs["system"][1]["text"] == _SYSTEM_IDENTITY
|
||||||
|
assert basic_api_kwargs["messages"] == once["messages"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_claude_code_bypass_normalizes_string_system(simple_messages):
|
||||||
|
api_kwargs = {
|
||||||
|
"system": "plain system",
|
||||||
|
"messages": [dict(message) for message in simple_messages],
|
||||||
|
"model": "claude-opus-4-6-20260101",
|
||||||
|
}
|
||||||
|
|
||||||
|
apply_claude_code_bypass(api_kwargs, "2.1.90")
|
||||||
|
|
||||||
|
assert isinstance(api_kwargs["system"], list)
|
||||||
|
assert api_kwargs["system"][1]["text"] == _SYSTEM_IDENTITY
|
||||||
|
assert (
|
||||||
|
"<system-reminder>\nplain system\n</system-reminder>"
|
||||||
|
in api_kwargs["messages"][0]["content"][0]["text"]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_claude_code_bypass_without_messages_is_noop():
|
||||||
|
api_kwargs = {"system": "plain system", "model": "claude-opus-4-6-20260101"}
|
||||||
|
|
||||||
|
apply_claude_code_bypass(api_kwargs, "2.1.90")
|
||||||
|
|
||||||
|
assert api_kwargs == {"system": "plain system", "model": "claude-opus-4-6-20260101"}
|
||||||
|
|
||||||
|
|
||||||
|
def test_fix_temperature_for_oauth_adaptive_removes_non_default_temperature():
|
||||||
|
api_kwargs = {"model": "claude-opus-4-6-20260101", "temperature": 0.2}
|
||||||
|
_fix_temperature_for_oauth_adaptive(api_kwargs, site="test")
|
||||||
|
assert "temperature" not in api_kwargs
|
||||||
|
|
||||||
|
|
||||||
|
def test_fix_temperature_for_oauth_adaptive_keeps_temperature_one():
|
||||||
|
api_kwargs = {"model": "claude-opus-4-6-20260101", "temperature": 1}
|
||||||
|
_fix_temperature_for_oauth_adaptive(api_kwargs, site="test")
|
||||||
|
assert api_kwargs["temperature"] == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_fix_temperature_for_oauth_adaptive_keeps_temperature_for_other_models():
|
||||||
|
api_kwargs = {"model": "claude-3-7-sonnet", "temperature": 0.2}
|
||||||
|
_fix_temperature_for_oauth_adaptive(api_kwargs, site="test")
|
||||||
|
assert api_kwargs["temperature"] == 0.2
|
||||||
|
|
||||||
|
|
||||||
|
def test_fix_temperature_for_oauth_adaptive_without_temperature_is_noop():
|
||||||
|
api_kwargs = {"model": "claude-opus-4-6-20260101"}
|
||||||
|
_fix_temperature_for_oauth_adaptive(api_kwargs, site="test")
|
||||||
|
assert api_kwargs == {"model": "claude-opus-4-6-20260101"}
|
||||||
101
tests/test_hook.py
Normal file
101
tests/test_hook.py
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
# pyright: reportMissingImports=false, reportUnknownMemberType=false, reportUntypedFunctionDecorator=false, reportUnknownParameterType=false, reportMissingParameterType=false, reportUnusedParameter=false, reportArgumentType=false, reportCallIssue=false, reportUnknownVariableType=false, reportUnknownArgumentType=false, reportAttributeAccessIssue=false
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
import importlib.machinery
|
||||||
|
import importlib.util
|
||||||
|
import sys
|
||||||
|
import types
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
def _clear_bypass_finders():
|
||||||
|
sys.meta_path[:] = [
|
||||||
|
finder
|
||||||
|
for finder in sys.meta_path
|
||||||
|
if finder.__class__.__name__ != "_ClaudeCodeBypassFinder"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def hook_module(monkeypatch):
|
||||||
|
_clear_bypass_finders()
|
||||||
|
module = importlib.import_module("sitecustomize_hook")
|
||||||
|
module = importlib.reload(module)
|
||||||
|
_clear_bypass_finders()
|
||||||
|
yield module
|
||||||
|
_clear_bypass_finders()
|
||||||
|
|
||||||
|
|
||||||
|
def test_install_hook_registers_finder(hook_module):
|
||||||
|
hook_module._install_hook()
|
||||||
|
|
||||||
|
assert any(
|
||||||
|
finder.__class__.__name__ == "_ClaudeCodeBypassFinder"
|
||||||
|
for finder in sys.meta_path
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_finder_only_targets_agent_anthropic_adapter(hook_module, monkeypatch):
|
||||||
|
calls = []
|
||||||
|
|
||||||
|
class Loader:
|
||||||
|
def exec_module(self, module):
|
||||||
|
module.loaded = True
|
||||||
|
|
||||||
|
spec = importlib.machinery.ModuleSpec(hook_module._TARGET_MODULE, Loader())
|
||||||
|
|
||||||
|
def fake_find_spec(fullname):
|
||||||
|
calls.append(fullname)
|
||||||
|
return spec if fullname == hook_module._TARGET_MODULE else None
|
||||||
|
|
||||||
|
monkeypatch.setattr(importlib.util, "find_spec", fake_find_spec)
|
||||||
|
hook_module._install_hook()
|
||||||
|
finder = next(
|
||||||
|
finder
|
||||||
|
for finder in sys.meta_path
|
||||||
|
if finder.__class__.__name__ == "_ClaudeCodeBypassFinder"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert finder.find_spec("some.other.module") is None
|
||||||
|
found_spec = finder.find_spec(hook_module._TARGET_MODULE)
|
||||||
|
|
||||||
|
assert found_spec is spec
|
||||||
|
assert calls == [hook_module._TARGET_MODULE]
|
||||||
|
|
||||||
|
|
||||||
|
def test_finder_sets_patched_flag_and_stops_repatching(hook_module, monkeypatch):
|
||||||
|
applied = []
|
||||||
|
|
||||||
|
class Loader:
|
||||||
|
def exec_module(self, module):
|
||||||
|
module.loaded = True
|
||||||
|
|
||||||
|
spec = importlib.machinery.ModuleSpec(hook_module._TARGET_MODULE, Loader())
|
||||||
|
|
||||||
|
def fake_find_spec(fullname):
|
||||||
|
return spec if fullname == hook_module._TARGET_MODULE else None
|
||||||
|
|
||||||
|
bypass_module = types.SimpleNamespace(
|
||||||
|
apply_patches=lambda module: applied.append(module.__name__)
|
||||||
|
)
|
||||||
|
|
||||||
|
monkeypatch.setattr(importlib.util, "find_spec", fake_find_spec)
|
||||||
|
monkeypatch.setitem(sys.modules, "anthropic_billing_bypass", bypass_module)
|
||||||
|
|
||||||
|
hook_module._install_hook()
|
||||||
|
finder = next(
|
||||||
|
finder
|
||||||
|
for finder in sys.meta_path
|
||||||
|
if finder.__class__.__name__ == "_ClaudeCodeBypassFinder"
|
||||||
|
)
|
||||||
|
|
||||||
|
found_spec = finder.find_spec(hook_module._TARGET_MODULE)
|
||||||
|
assert found_spec is spec
|
||||||
|
|
||||||
|
module = types.ModuleType(hook_module._TARGET_MODULE)
|
||||||
|
found_spec.loader.exec_module(module)
|
||||||
|
|
||||||
|
assert finder._patched is True
|
||||||
|
assert applied == [hook_module._TARGET_MODULE]
|
||||||
|
assert finder.find_spec(hook_module._TARGET_MODULE) is None
|
||||||
76
tests/test_signing.py
Normal file
76
tests/test_signing.py
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
# pyright: reportPrivateUsage=false, reportUnknownParameterType=false, reportMissingParameterType=false, reportUnknownArgumentType=false, reportUnknownVariableType=false
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
from anthropic_billing_bypass import (
|
||||||
|
_build_billing_header_value,
|
||||||
|
_compute_cch,
|
||||||
|
_compute_version_suffix,
|
||||||
|
_extract_first_user_message_text,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_extract_first_user_message_text_with_string_content(simple_messages):
|
||||||
|
assert _extract_first_user_message_text(simple_messages) == "hello world"
|
||||||
|
|
||||||
|
|
||||||
|
def test_extract_first_user_message_text_with_text_block(complex_messages):
|
||||||
|
assert _extract_first_user_message_text(complex_messages) == "hello world"
|
||||||
|
|
||||||
|
|
||||||
|
def test_extract_first_user_message_text_with_image_block_only_returns_empty_string():
|
||||||
|
messages = [{"role": "user", "content": [{"type": "image", "source": {}}]}]
|
||||||
|
assert _extract_first_user_message_text(messages) == ""
|
||||||
|
|
||||||
|
|
||||||
|
def test_extract_first_user_message_text_with_no_user_message_returns_empty_string():
|
||||||
|
messages = [{"role": "assistant", "content": "hello"}]
|
||||||
|
assert _extract_first_user_message_text(messages) == ""
|
||||||
|
|
||||||
|
|
||||||
|
def test_extract_first_user_message_text_uses_first_user_message_only():
|
||||||
|
messages = [
|
||||||
|
{"role": "user", "content": "first"},
|
||||||
|
{"role": "user", "content": "second"},
|
||||||
|
]
|
||||||
|
assert _extract_first_user_message_text(messages) == "first"
|
||||||
|
|
||||||
|
|
||||||
|
def test_extract_first_user_message_text_with_empty_messages_returns_empty_string():
|
||||||
|
assert _extract_first_user_message_text([]) == ""
|
||||||
|
|
||||||
|
|
||||||
|
def test_compute_cch_known_values():
|
||||||
|
assert _compute_cch("hello world") == "b94d2"
|
||||||
|
assert _compute_cch("") == "e3b0c"
|
||||||
|
|
||||||
|
|
||||||
|
def test_compute_version_suffix_pads_short_text():
|
||||||
|
expected = hashlib.sha256(b"59cf53e54c78e002.1.90").hexdigest()[:3]
|
||||||
|
assert _compute_version_suffix("abcde", "2.1.90") == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_compute_version_suffix_samples_long_enough_text():
|
||||||
|
text = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
sampled = f"{text[4]}{text[7]}{text[20]}"
|
||||||
|
expected = hashlib.sha256(
|
||||||
|
f"59cf53e54c78{sampled}2.1.90".encode("utf-8")
|
||||||
|
).hexdigest()[:3]
|
||||||
|
assert _compute_version_suffix(text, "2.1.90") == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_compute_version_suffix_known_value_for_hello_world():
|
||||||
|
expected = hashlib.sha256(b"59cf53e54c78oo02.1.90").hexdigest()[:3]
|
||||||
|
assert _compute_version_suffix("hello world", "2.1.90") == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_billing_header_value_format(simple_messages):
|
||||||
|
version = "2.1.90"
|
||||||
|
entrypoint = "cli"
|
||||||
|
suffix = _compute_version_suffix("hello world", version)
|
||||||
|
cch = _compute_cch("hello world")
|
||||||
|
|
||||||
|
assert _build_billing_header_value(simple_messages, version, entrypoint) == (
|
||||||
|
f"x-anthropic-billing-header: cc_version={version}.{suffix}; "
|
||||||
|
f"cc_entrypoint={entrypoint}; cch={cch};"
|
||||||
|
)
|
||||||
Loading…
x
Reference in New Issue
Block a user