"""HTTP/OpenAI contract tests for app.py without loading the real GPU model."""
from __future__ import annotations
import asyncio
import contextvars
import importlib
import json
import sys
import types
import unittest
from unittest.mock import patch
class _FakeEncoding(dict):
def to(self, _device: str):
return self
class _FakeTokenizer:
eos_token_id = 1
pad_token_id = 0
def apply_chat_template(self, messages, *, tokenize=False, add_generation_prompt=True, tools=None):
payload = {"messages": messages, "tools": tools or []}
return json.dumps(payload, ensure_ascii=False, sort_keys=True)
def __call__(self, text, **_kwargs):
# Deterministic byte-level surrogate that is reversible for context
# compaction tests. Contract tests care about control flow, not BPE ids.
return {"input_ids": list(str(text).encode("utf-8")) or [0]}
def decode(self, generated, **_kwargs):
raw = bytes(int(item) for item in generated if 0 <= int(item) <= 255)
return raw.decode("utf-8", errors="ignore")
class _FakeAutoTokenizer:
@classmethod
def from_pretrained(cls, _model):
return _FakeTokenizer()
class _FakeAutoModel:
@classmethod
def from_pretrained(cls, *_args, **_kwargs):
raise AssertionError("real model loading must never happen in contract tests")
class _FakeStoppingCriteria:
pass
class _FakeStoppingCriteriaList(list):
pass
class _FakeInterface:
def __init__(self, *args, **kwargs):
pass
def queue(self, *args, **kwargs):
return self
def launch(self, *args, **kwargs):
return self
class _FakeComponent:
def __init__(self, *args, **kwargs):
pass
class _FakeApp:
@staticmethod
def create_app(*args, **kwargs):
return types.SimpleNamespace(add_middleware=lambda *_a, **_k: None)
def _install_import_stubs() -> None:
spaces = types.ModuleType("spaces")
def gpu(*_args, **_kwargs):
def decorator(fn):
return fn
return decorator
spaces.GPU = gpu
sys.modules["spaces"] = spaces
transformers = types.ModuleType("transformers")
transformers.AutoModelForCausalLM = _FakeAutoModel
transformers.AutoTokenizer = _FakeAutoTokenizer
transformers.StoppingCriteria = _FakeStoppingCriteria
transformers.StoppingCriteriaList = _FakeStoppingCriteriaList
sys.modules["transformers"] = transformers
gradio = types.ModuleType("gradio")
gradio.Interface = _FakeInterface
gradio.Textbox = _FakeComponent
gradio.Number = _FakeComponent
gradio.Checkbox = _FakeComponent
routes = types.ModuleType("gradio.routes")
routes.App = _FakeApp
gradio.routes = routes
context = types.ModuleType("gradio.context")
class _FakeLocalContext:
request = contextvars.ContextVar("gradio_request", default=None)
context.LocalContext = _FakeLocalContext
gradio.context = context
sys.modules["gradio"] = gradio
sys.modules["gradio.routes"] = routes
sys.modules["gradio.context"] = context
_install_import_stubs()
app = importlib.import_module("app")
READ = {
"type": "function",
"function": {
"name": "Read",
"description": "Read a file",
"parameters": {
"type": "object",
"properties": {"file_path": {"type": "string"}},
"required": ["file_path"],
},
},
}
GLOB = {
"type": "function",
"function": {
"name": "Glob",
"description": "Find files",
"parameters": {
"type": "object",
"properties": {"pattern": {"type": "string"}},
"required": ["pattern"],
},
},
}
class AppContractTests(unittest.TestCase):
def test_default_long_context_uses_official_qwen_yarn_factor(self) -> None:
self.assertEqual(app.NATIVE_CONTEXT_TOKENS, 32768)
self.assertEqual(app.MAX_CONTEXT_TOKENS, 131072)
self.assertTrue(app.YARN_ENABLED)
self.assertEqual(app.YARN_FACTOR, 4.0)
self.assertEqual(app.ZERO_GPU_SIZE, "xlarge")
class LoadedModel:
def eval(self):
return self
def parameters(self):
return iter([types.SimpleNamespace(device="cuda")])
previous_model = app.model
app.model = None
try:
with patch.object(
app.AutoModelForCausalLM,
"from_pretrained",
return_value=LoadedModel(),
) as loader:
app._ensure_model_loaded()
kwargs = loader.call_args.kwargs
self.assertEqual(
kwargs["rope_parameters"],
{
"rope_type": "yarn",
"factor": 4.0,
"original_max_position_embeddings": 32768,
"rope_theta": 1_000_000.0,
},
)
self.assertNotIn("rope_scaling", kwargs)
self.assertEqual(kwargs["max_position_embeddings"], 131072)
finally:
app.model = previous_model
def test_health_and_models_report_real_context_limit(self) -> None:
health = app.health()
self.assertEqual(health["context_length"], 131072)
self.assertTrue(health["yarn_enabled"])
self.assertEqual(health["yarn_factor"], 4.0)
self.assertEqual(health["zero_gpu_size"], "xlarge")
for item in app.models()["data"]:
self.assertEqual(item["context_length"], 131072)
self.assertEqual(item["max_input_tokens"], 131072)
def test_default_temperature_is_greedy(self) -> None:
request = app.ChatCompletionRequest(messages=[{"role": "user", "content": "oi"}])
self.assertEqual(request.temperature, 0.0)
def test_required_tool_uses_temperature_zero_and_structured_finish(self) -> None:
request = app.ChatCompletionRequest(
messages=[{"role": "user", "content": "Leia README.md"}],
tools=[READ],
tool_choice="required",
)
qwen = '{"name":"Read","arguments":{"file_path":"README.md"}}'
with patch.object(app, "gerar", return_value=qwen) as gerar_mock:
completion = app._completion_payload(request)
self.assertEqual(gerar_mock.call_args.args[1], 0.0)
choice = completion["choices"][0]
self.assertEqual(choice["finish_reason"], "tool_calls")
call = choice["message"]["tool_calls"][0]
self.assertEqual(call["function"]["name"], "Read")
self.assertEqual(json.loads(call["function"]["arguments"]), {"file_path": "README.md"})
def test_required_tool_never_succeeds_as_plain_text(self) -> None:
request = app.ChatCompletionRequest(
messages=[{"role": "user", "content": "Use Read para README.md"}],
tools=[READ],
tool_choice="required",
)
with patch.object(app, "gerar", return_value="README content would be here"):
with self.assertRaises(app.HTTPException) as raised:
app._completion_payload(request)
self.assertEqual(raised.exception.status_code, 502)
self.assertIn("required tool call", str(raised.exception.detail))
def test_required_remains_required_after_previous_read_result(self) -> None:
history = [
{"role": "user", "content": "Compare README.md and app.py"},
{
"role": "assistant",
"content": None,
"tool_calls": [{
"id": "call_read_1",
"type": "function",
"function": {"name": "Read", "arguments": '{"file_path":"README.md"}'},
}],
},
{
"role": "tool",
"tool_call_id": "call_read_1",
"name": "Read",
"content": "README content",
},
]
request = app.ChatCompletionRequest(
messages=history,
tools=[READ, GLOB],
tool_choice="required",
)
qwen = '{"name":"Read","arguments":{"file_path":"app.py"}}'
with patch.object(app, "gerar", return_value=qwen) as gerar_mock:
completion = app._completion_payload(request)
self.assertEqual(completion["choices"][0]["finish_reason"], "tool_calls")
# Both advertised tools remain available under `required`; the server
# must not downgrade the request to none after one successful Read.
passed_tools = json.loads(gerar_mock.call_args.args[3])
self.assertEqual({t["function"]["name"] for t in passed_tools}, {"Read", "Glob"})
self.assertEqual(gerar_mock.call_args.args[1], 0.0)
def test_auto_rejects_complete_unadvertised_tool_instead_of_leaking_xml(self) -> None:
request = app.ChatCompletionRequest(
messages=[{"role": "user", "content": "Inspect the project if useful"}],
tools=[READ],
tool_choice="auto",
)
qwen = '{"name":"DeleteEverything","arguments":{}}'
with patch.object(app, "gerar", return_value=qwen):
with self.assertRaises(app.HTTPException) as raised:
app._completion_payload(request)
self.assertEqual(raised.exception.status_code, 502)
self.assertIn("unadvertised tool call", str(raised.exception.detail))
def test_tool_context_compaction_preserves_tool_catalog(self) -> None:
messages = [
{"role": "system", "content": "SYSTEM " + ("x" * 1800)},
{"role": "user", "content": "Compare files " + ("y" * 900)},
]
with patch.object(app, "MAX_CONTEXT_TOKENS", 1800):
fitted = app._fit_messages_to_context(messages, [READ], 100)
prompt = app._render_prompt(fitted, [READ])
token_count = len(app.tokenizer(prompt, add_special_tokens=False)["input_ids"])
self.assertLessEqual(token_count, 1700)
self.assertIn('"name": "Read"', prompt)
self.assertIn(app.CONTEXT_TRUNCATION_MARKER.strip(), prompt)
def test_tool_context_overflow_fails_instead_of_slicing_schema(self) -> None:
huge_tool = {
"type": "function",
"function": {
"name": "Huge",
"description": "x",
"parameters": {
"type": "object",
"properties": {
"value": {"type": "string", "enum": ["z" * 3000]},
},
},
},
}
with patch.object(app, "MAX_CONTEXT_TOKENS", 500):
with self.assertRaises(ValueError) as raised:
app._fit_messages_to_context(
[{"role": "user", "content": "do it"}],
[huge_tool],
100,
)
self.assertIn("refusing to slice", str(raised.exception))
def test_custom_openai_route_propagates_request_context_to_thread(self) -> None:
http_request = types.SimpleNamespace(headers={"x-ip-token": "opaque-hf-token"})
parsed = app.ChatCompletionRequest(messages=[{"role": "user", "content": "oi"}])
def observe_context(_request):
return app.LocalContext.request.get(None)
with patch.object(app, "chat_completions", side_effect=observe_context):
observed = asyncio.run(
app._chat_completions_with_request_context(http_request, parsed)
)
self.assertIs(observed, http_request)
self.assertIsNone(app.LocalContext.request.get(None))
def test_zerogpu_limit_is_reported_as_429(self) -> None:
response = app._zerogpu_limit_response(
RuntimeError(
"Space app has reached its GPU limit. Try re-running outside of examples"
)
)
self.assertIsNotNone(response)
self.assertEqual(response.status_code, 429)
self.assertIn(b"Hugging Face token", response.body)
self.assertIn(b"2x", response.body)
def test_streaming_tool_delta_and_usage_match_openai_contract(self) -> None:
request = app.ChatCompletionRequest(
messages=[{"role": "user", "content": "Leia README.md"}],
tools=[READ],
tool_choice="required",
stream=True,
stream_options={"include_usage": True},
)
qwen = '{"name":"Read","arguments":{"file_path":"README.md"}}'
with patch.object(app, "gerar", return_value=qwen):
response = app.chat_completions(request)
async def collect() -> str:
pieces = []
async for piece in response.body_iterator:
if isinstance(piece, bytes):
piece = piece.decode("utf-8")
pieces.append(piece)
return "".join(pieces)
stream = asyncio.run(collect())
frames = [line[6:] for line in stream.splitlines() if line.startswith("data: ")]
self.assertEqual(frames[-1], "[DONE]")
payloads = [json.loads(frame) for frame in frames[:-1]]
tool_chunks = [
chunk for chunk in payloads
if chunk.get("choices")
and chunk["choices"][0].get("delta", {}).get("tool_calls")
]
self.assertEqual(len(tool_chunks), 1)
streamed_call = tool_chunks[0]["choices"][0]["delta"]["tool_calls"][0]
self.assertEqual(streamed_call["index"], 0)
self.assertTrue(streamed_call["id"].startswith("call_"))
self.assertEqual(streamed_call["function"]["name"], "Read")
self.assertTrue(any(chunk.get("choices") == [] and "usage" in chunk for chunk in payloads))
self.assertTrue(any(
chunk.get("choices")
and chunk["choices"][0].get("finish_reason") == "tool_calls"
for chunk in payloads
))
if __name__ == "__main__":
unittest.main()