File size: 6,617 Bytes
6172a47 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | """Tests for api/models/responses.py Pydantic response models."""
from api.models.anthropic import (
ContentBlockText,
ContentBlockThinking,
ContentBlockToolUse,
)
from api.models.responses import MessagesResponse, TokenCountResponse, Usage
class TestUsage:
"""Tests for Usage model."""
def test_required_fields(self):
usage = Usage(input_tokens=10, output_tokens=20)
assert usage.input_tokens == 10
assert usage.output_tokens == 20
def test_cache_defaults_zero(self):
usage = Usage(input_tokens=1, output_tokens=2)
assert usage.cache_creation_input_tokens == 0
assert usage.cache_read_input_tokens == 0
def test_cache_fields_set(self):
usage = Usage(
input_tokens=10,
output_tokens=20,
cache_creation_input_tokens=5,
cache_read_input_tokens=3,
)
assert usage.cache_creation_input_tokens == 5
assert usage.cache_read_input_tokens == 3
def test_serialization(self):
usage = Usage(input_tokens=10, output_tokens=20)
data = usage.model_dump()
assert data == {
"input_tokens": 10,
"output_tokens": 20,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
}
class TestTokenCountResponse:
"""Tests for TokenCountResponse model."""
def test_basic(self):
resp = TokenCountResponse(input_tokens=42)
assert resp.input_tokens == 42
def test_serialization(self):
resp = TokenCountResponse(input_tokens=100)
data = resp.model_dump()
assert data == {"input_tokens": 100}
class TestMessagesResponse:
"""Tests for MessagesResponse model."""
def test_minimum_fields(self):
resp = MessagesResponse(
id="msg_001",
model="test-model",
content=[ContentBlockText(type="text", text="Hello")],
usage=Usage(input_tokens=10, output_tokens=5),
)
assert resp.id == "msg_001"
assert resp.model == "test-model"
assert resp.role == "assistant"
assert resp.type == "message"
assert resp.stop_reason is None
assert resp.stop_sequence is None
def test_with_text_content(self):
resp = MessagesResponse(
id="msg_002",
model="model",
content=[ContentBlockText(type="text", text="response")],
usage=Usage(input_tokens=1, output_tokens=1),
)
assert len(resp.content) == 1
block = resp.content[0]
assert isinstance(block, ContentBlockText)
assert block.type == "text"
assert block.text == "response"
def test_with_tool_use_content(self):
resp = MessagesResponse(
id="msg_003",
model="model",
content=[
ContentBlockToolUse(
type="tool_use",
id="tool_1",
name="Read",
input={"path": "test.py"},
)
],
usage=Usage(input_tokens=1, output_tokens=1),
stop_reason="tool_use",
)
block = resp.content[0]
assert isinstance(block, ContentBlockToolUse)
assert block.type == "tool_use"
assert block.name == "Read"
assert resp.stop_reason == "tool_use"
def test_with_thinking_content(self):
resp = MessagesResponse(
id="msg_004",
model="model",
content=[
ContentBlockThinking(type="thinking", thinking="Let me reason..."),
ContentBlockText(type="text", text="Answer"),
],
usage=Usage(input_tokens=5, output_tokens=10),
)
assert len(resp.content) == 2
block0 = resp.content[0]
assert isinstance(block0, ContentBlockThinking)
assert block0.type == "thinking"
assert block0.thinking == "Let me reason..."
block1 = resp.content[1]
assert isinstance(block1, ContentBlockText)
assert block1.type == "text"
def test_with_all_content_types(self):
resp = MessagesResponse(
id="msg_005",
model="model",
content=[
ContentBlockThinking(type="thinking", thinking="hmm"),
ContentBlockText(type="text", text="result"),
ContentBlockToolUse(
type="tool_use", id="t1", name="Bash", input={"command": "ls"}
),
],
usage=Usage(input_tokens=10, output_tokens=20),
stop_reason="tool_use",
)
assert len(resp.content) == 3
def test_with_dict_content(self):
"""Dict content (unknown block type) should be accepted."""
resp = MessagesResponse(
id="msg_006",
model="model",
content=[{"type": "custom", "data": "value"}],
usage=Usage(input_tokens=1, output_tokens=1),
)
block = resp.content[0]
assert isinstance(block, dict)
assert block["type"] == "custom"
def test_stop_reason_values(self):
"""All valid stop_reason values should be accepted."""
from typing import Literal
reasons: list[
Literal["end_turn", "max_tokens", "stop_sequence", "tool_use"]
] = [
"end_turn",
"max_tokens",
"stop_sequence",
"tool_use",
]
for reason in reasons:
resp = MessagesResponse(
id="msg",
model="model",
content=[ContentBlockText(type="text", text="x")],
usage=Usage(input_tokens=1, output_tokens=1),
stop_reason=reason,
)
assert resp.stop_reason == reason
def test_serialization_round_trip(self):
resp = MessagesResponse(
id="msg_rt",
model="model-v1",
content=[ContentBlockText(type="text", text="hello")],
usage=Usage(input_tokens=10, output_tokens=5),
stop_reason="end_turn",
)
data = resp.model_dump()
restored = MessagesResponse(**data)
assert restored.id == resp.id
assert restored.model == resp.model
assert restored.stop_reason == resp.stop_reason
def test_empty_content_list(self):
resp = MessagesResponse(
id="msg_empty",
model="model",
content=[],
usage=Usage(input_tokens=0, output_tokens=0),
)
assert resp.content == []
|