"""executor.execute_request — direct in-process unit tests (DATA path)."""
import io
import json
import os
import subprocess
import threading
import traceback
import sys
import time
import http.client
import numpy as np
import pytest
import functools
import importlib.util
@functools.lru_cache(maxsize=1)
def _tf_probe_ok():
"""tensorflow 是否能安全 import(子进程隔离 CI 的 C 扩展 segfault,importorskip 捕获不到)。"""
if importlib.util.find_spec("tensorflow") is None:
return False
try:
return subprocess.run([sys.executable, "-c", "import tensorflow"],
capture_output=True, timeout=90).returncode == 0
except Exception:
return False
def _npz(path, **arrs):
np.savez_compressed(str(path),
**{f"a{i}": v for i, v in enumerate(arrs.values())})
return str(path)
def _kw(**over):
base = dict(tenant_sync_dir="", exec_type="api", provider="numpy", api=None,
spec_module=None, spec_class=None, mode=1,
input_schema=[], attrs={}, tmp_in_path=None, input_count=0,
device_id=0, use_device=False, output_dir=None)
base.update(over)
return base
class TestApiData:
def test_numpy_add(self, tmp_path):
from ttk.remote import DATA
from ttk.remote.server import executor
inp = _npz(tmp_path / "in.npz", x1=np.array([1.0, 2.0]), x2=np.array([3.0, 4.0]))
env = executor.execute_request(**_kw(
api="numpy.add", mode=DATA,
input_schema=[{"name": "x1", "index": 0}, {"name": "x2", "index": 1}],
tmp_in_path=inp, input_count=2, output_dir=str(tmp_path)))
assert env["ok"] and env["http_status"] == 200 and env["output_count"] == 1
np.testing.assert_array_equal(np.load(env["output_path"])["a0"],
np.array([4.0, 6.0]))
def test_api_class_is_400(self, tmp_path):
from ttk.remote import DATA
from ttk.remote.server import executor
env = executor.execute_request(**_kw(api="numpy.ndarray", mode=DATA,
output_dir=str(tmp_path)))
assert env["ok"] is False and env["http_status"] == 400
def test_api_missing_module_is_500(self, tmp_path):
from ttk.remote import DATA
from ttk.remote.server import executor
env = executor.execute_request(**_kw(
api="definitely_not_a_module_xyz.fn", mode=DATA, output_dir=str(tmp_path)))
assert env["ok"] is False and env["http_status"] == 500
assert env["missing"] is None
class TestSpecData:
def _write(self, path, body):
path.write_text(body)
def test_mode_b_inputs_in_call(self, tmp_path):
from ttk.remote import DATA
from ttk.remote.server import executor
self._write(tmp_path / "addb.py",
"class AddImpl:\n"
" def __init__(self, **kw): pass\n"
" def __call__(self, x1, x2): return [x1 + x2]\n"
"class AddTestSpec:\n"
" third_party = {'numpy': AddImpl}\n")
inp = _npz(tmp_path / "in.npz", x1=np.array([1.0]), x2=np.array([5.0]))
env = executor.execute_request(**_kw(
exec_type="spec", spec_module="addb", spec_class="AddTestSpec",
mode=DATA, provider="numpy",
input_schema=[{"name": "x1", "index": 0}, {"name": "x2", "index": 1}],
tmp_in_path=inp, input_count=2, tenant_sync_dir=str(tmp_path),
output_dir=str(tmp_path)))
assert env["ok"]
np.testing.assert_array_equal(np.load(env["output_path"])["a0"], np.array([6.0]))
def test_mode_a_inputs_in_init(self, tmp_path):
from ttk.remote import DATA
from ttk.remote.server import executor
self._write(tmp_path / "adda.py",
"class AddImpl:\n"
" def __init__(self, x1, x2, **kw):\n"
" self.x1, self.x2 = x1, x2\n"
" def __call__(self):\n"
" return [self.x1 + self.x2]\n"
"class AddTestSpec:\n"
" third_party = {'numpy': AddImpl}\n")
inp = _npz(tmp_path / "in.npz", x1=np.array([2.0]), x2=np.array([10.0]))
env = executor.execute_request(**_kw(
exec_type="spec", spec_module="adda", spec_class="AddTestSpec",
mode=DATA, provider="numpy",
input_schema=[{"name": "x1", "index": 0}, {"name": "x2", "index": 1}],
tmp_in_path=inp, input_count=2, tenant_sync_dir=str(tmp_path),
output_dir=str(tmp_path)))
assert env["ok"]
np.testing.assert_array_equal(np.load(env["output_path"])["a0"], np.array([12.0]))
def test_missing_spec_module_is_424(self, tmp_path):
from ttk.remote import DATA
from ttk.remote.server import executor
env = executor.execute_request(**_kw(
exec_type="spec", spec_module="no_such_spec", spec_class="X",
mode=DATA, provider="numpy", tenant_sync_dir=str(tmp_path),
output_dir=str(tmp_path)))
assert env["ok"] is False and env["http_status"] == 424
assert env["missing"] == "no_such_spec"
def test_unknown_param_is_400(self, tmp_path):
from ttk.remote import DATA
from ttk.remote.server import executor
self._write(tmp_path / "bad.py",
"class BadImpl:\n"
" def __call__(self, x1, bogus): return [x1]\n"
"class BadTestSpec:\n"
" third_party = {'numpy': BadImpl}\n")
inp = _npz(tmp_path / "in.npz", x1=np.array([1.0]))
env = executor.execute_request(**_kw(
exec_type="spec", spec_module="bad", spec_class="BadTestSpec",
mode=DATA, provider="numpy",
input_schema=[{"name": "x1", "index": 0}],
tmp_in_path=inp, input_count=1, tenant_sync_dir=str(tmp_path),
output_dir=str(tmp_path)))
assert env["ok"] is False and env["http_status"] == 400
assert "bogus" in env["error"]
def test_op_failure_error_is_sanitized_no_traceback(self, tmp_path):
"""Security (OWASP Improper Error Handling): a failing op's client error
is TYPE+MESSAGE only — no traceback, no server FS path leaks over the
wire / into xpu-metrics. Full traceback stays server-side
(logging.exception). _client_error is the single control point."""
from ttk.remote import DATA
from ttk.remote.server import executor
self._write(tmp_path / "boom.py",
"class BoomImpl:\n"
" def __call__(self, x1): raise RuntimeError('op exploded')\n"
"class BoomSpec:\n"
" third_party = {'numpy': BoomImpl}\n")
inp = _npz(tmp_path / "in.npz", x1=np.array([1.0]))
env = executor.execute_request(**_kw(
exec_type="spec", spec_module="boom", spec_class="BoomSpec",
mode=DATA, provider="numpy",
input_schema=[{"name": "x1", "index": 0}],
tmp_in_path=inp, input_count=1, tenant_sync_dir=str(tmp_path),
output_dir=str(tmp_path)))
assert env["ok"] is False and env["http_status"] == 500
assert env["error"] == "RuntimeError: op exploded"
assert "Traceback" not in env["error"]
assert ".py" not in env["error"]
class TestViaSubprocess:
"""_run_in_subprocess: execute_request in a real fresh child process."""
def test_numpy_add_runs_in_child_process(self, tmp_path):
from ttk.remote import DATA
from ttk.remote.server.xpu_server import _run_in_subprocess
inp = _npz(tmp_path / "in.npz", x1=np.array([1.0, 2.0]), x2=np.array([3.0, 4.0]))
out_dir = tmp_path / "out"
out_dir.mkdir()
env = _run_in_subprocess(_kw(
api="numpy.add", mode=DATA,
input_schema=[{"name": "x1", "index": 0}, {"name": "x2", "index": 1}],
tmp_in_path=inp, input_count=2, output_dir=str(out_dir)), deadline=60)
assert env["ok"] and env["output_count"] == 1
np.testing.assert_array_equal(np.load(env["output_path"])["a0"],
np.array([4.0, 6.0]))
def test_child_crash_returns_500(self, tmp_path):
from ttk.remote import DATA
from ttk.remote.server.xpu_server import _run_in_subprocess
(tmp_path / "crashfix.py").write_text(
"import os\n"
"class CrashImpl:\n"
" def __call__(self, x1): os._exit(139)\n"
"class CrashTestSpec:\n"
" third_party = {'numpy': CrashImpl}\n")
inp = _npz(tmp_path / "in.npz", x1=np.array([1.0]))
env = _run_in_subprocess(_kw(
exec_type="spec", spec_module="crashfix",
spec_class="CrashTestSpec", mode=DATA, provider="numpy",
input_schema=[{"name": "x1", "index": 0}],
tmp_in_path=inp, input_count=1, tenant_sync_dir=str(tmp_path),
output_dir=str(tmp_path)), deadline=60)
assert env["ok"] is False and env["http_status"] == 500
assert "139" in env["error"]
class TestPerfPath:
"""PERF timing: CPU NA-fallback + simulated CUDA timing (no GPU needed)."""
def test_data_perf_cpu_marks_na(self, tmp_path):
from ttk.remote import DATA, PERF
from ttk.remote.server import executor
inp = _npz(tmp_path / "in.npz", x1=np.array([1.0, 2.0]), x2=np.array([3.0, 4.0]))
env = executor.execute_request(**_kw(
api="numpy.add", mode=DATA | PERF,
input_schema=[{"name": "x1", "index": 0}, {"name": "x2", "index": 1}],
tmp_in_path=inp, input_count=2, output_dir=str(tmp_path)))
assert env["ok"] and env["output_count"] == 1
perf = env["perf"]
assert perf["device_us"] == "NA" and perf["peak_memory_mb"] == "NA"
def test_bfloat16_via_declared_dtype(self):
import torch
from ttk.remote.server import executor
orig = torch.tensor([1.5, -2.25, 3.0], dtype=torch.bfloat16)
wire = orig.view(torch.int16).numpy()
out = executor._to_vendor_tensor(wire, "torch", "cpu", "bfloat16")
assert out.dtype == torch.bfloat16
assert torch.equal(out, orig)
def test_non_bf16_does_not_get_bf16_view(self):
import torch
from ttk.remote.server import executor
wire = np.array([1, 2, 3], dtype=np.int16)
out = executor._to_vendor_tensor(wire, "torch", "cpu", "int16")
assert out.dtype == torch.int16
assert torch.equal(out, torch.tensor([1, 2, 3], dtype=torch.int16))
def test_tf_input_pinned_to_assigned_device(self, monkeypatch):
"""tf inputs pinned to the assigned device (multi-device correctness).
Verifies tf.device(device_str) is entered for a device and skipped
for cpu."""
if not _tf_probe_ok():
pytest.skip("tensorflow not importable (crashes on import)")
tf = pytest.importorskip("tensorflow")
from ttk.remote.server import executor
recorded = []
class _SpyCtx:
def __init__(self, d): self.d = d
def __enter__(self): recorded.append(self.d); return self
def __exit__(self, *a): return False
monkeypatch.setattr(tf, "device", lambda d: _SpyCtx(d))
executor._to_vendor_tensor(np.array([1.0]), "tf", "/device:GPU:2")
assert "/device:GPU:2" in recorded
recorded.clear()
executor._to_vendor_tensor(np.array([1.0]), "tf", "cpu")
assert recorded == []
def test_bfloat16_output_stored_as_int16_bits(self):
import torch
from ttk.remote.server import executor
orig = torch.tensor([1.5, -2.25, 3.0], dtype=torch.bfloat16)
arr, dt = executor._to_numpy_pair(orig, "torch")
assert dt == "bfloat16"
assert arr.dtype == np.int16
np.testing.assert_array_equal(arr, orig.view(torch.int16).numpy())
def test_bfloat16_output_reinterpret_roundtrip(self):
pytest.importorskip("ml_dtypes")
import torch
from ttk.remote.server import executor
from ttk.remote.dispatcher import _reinterpret_dtype
orig = torch.tensor([1.5, -2.25, 3.0], dtype=torch.bfloat16)
arr, dt = executor._to_numpy_pair(orig, "torch")
back = _reinterpret_dtype(arr, dt)
np.testing.assert_array_equal(
back.astype(np.float32), orig.to(torch.float32).numpy())
class TestOutputSerialization:
"""_outputs_to_numpy nested schema + float8 wire (Task 1: XU server fix).
Locks the new server-side serialization contract that cross_check (3rd-party
comparison) relies on: top-level slots preserved (not flattened), None slots
-> {index:null}, tensor-list slots -> {indices:[...]}, float8 -> uint8 bits.
"""
def test_float8_output_stored_as_uint8_bits(self):
import torch
from ttk.remote.server import executor
orig = torch.tensor([1.0, 2.0, 3.0, 4.0], dtype=torch.float8_e4m3fn)
arr, dt = executor._to_numpy_pair(orig, "torch")
assert dt == "float8_e4m3fn"
assert arr.dtype == np.uint8
np.testing.assert_array_equal(arr, orig.view(torch.uint8).numpy())
def test_float8_e5m2_dtype_name_preserved(self):
import torch
from ttk.remote.server import executor
orig = torch.tensor([1.0, 2.0, 3.0, 4.0], dtype=torch.float8_e5m2)
arr, dt = executor._to_numpy_pair(orig, "torch")
assert dt == "float8_e5m2"
assert arr.dtype == np.uint8
def test_outputs_to_numpy_flat_tensors_schema(self):
import torch
from ttk.remote.server import executor
a = torch.tensor([1.0, 2.0])
b = torch.tensor([3.0, 4.0, 5.0])
schema, arrays = executor._outputs_to_numpy([a, b], "torch")
assert schema == [{"index": 0, "dtype": "float32"},
{"index": 1, "dtype": "float32"}]
assert len(arrays) == 2
np.testing.assert_array_equal(arrays[0], [1.0, 2.0])
def test_outputs_to_numpy_none_slot_index_null(self):
import torch
from ttk.remote.server import executor
a = torch.tensor([1.0, 2.0])
schema, arrays = executor._outputs_to_numpy([a, None], "torch")
assert schema == [{"index": 0, "dtype": "float32"},
{"index": None, "dtype": None}]
assert len(arrays) == 1
def test_outputs_to_numpy_tensor_list_slot_indices(self):
import torch
from ttk.remote.server import executor
single = torch.tensor([1.0])
lst = [torch.tensor([2.0, 3.0]), torch.tensor([4.0])]
schema, arrays = executor._outputs_to_numpy([single, lst], "torch")
assert schema == [{"index": 0, "dtype": "float32"},
{"indices": [1, 2], "dtype": "float32"}]
assert len(arrays) == 3
def test_outputs_to_numpy_single_output_wrapped(self):
from ttk.remote.server import executor
schema, arrays = executor._outputs_to_numpy(
np.array([1.0, 2.0]), "numpy")
assert schema == [{"index": 0, "dtype": "float64"}]
assert len(arrays) == 1
def test_ok_carries_schema_kwarg(self):
from ttk.remote.server import executor
schema = [{"index": 0, "dtype": "float32"}]
env = executor._ok("/p", 1, [[2]], dtypes=None, perf=None,
api="torch.add", schema=schema)
assert env["ok"] is True
assert env["schema"] == schema
def test_ok_schema_defaults_none(self):
from ttk.remote.server import executor
env = executor._ok("/p", 1, [[2]], dtypes=None, perf=None)
assert env["schema"] is None
def test_handle_run_envelope_carries_schema(self, tmp_path):
from ttk.remote import DATA
from ttk.remote.server import executor
inp = _npz(tmp_path / "in.npz", x1=np.array([1.0, 2.0]),
x2=np.array([3.0, 4.0]))
env = executor.execute_request(**_kw(
api="numpy.add", mode=DATA,
input_schema=[{"name": "x1", "index": 0}, {"name": "x2", "index": 1}],
tmp_in_path=inp, input_count=2, output_dir=str(tmp_path)))
assert env["ok"]
assert env["schema"] == [{"index": 0, "dtype": "float64"}]
assert env["output_count"] == 1
npz = np.load(env["output_path"])
assert sorted(npz.files) == ["a0"]
class TestDeviceHelpers:
"""_device_available + _device_time (spec §4.3.2 / §4.3.4)."""
def test_device_available_torch(self, monkeypatch):
"""torch: getattr(torch, torch_lib).is_available() drives availability."""
import torch
from unittest.mock import MagicMock
from ttk.remote.server import executor
fake = MagicMock()
fake.is_available.return_value = True
monkeypatch.setattr(torch, "cuda", fake)
assert executor._device_available("torch", {"torch_lib": "cuda"}) is True
def test_device_available_tf_missing_type(self):
"""tf without tf_device_type -> False (graceful degrade, not KeyError)."""
from ttk.remote.server import executor
assert executor._device_available("tf", {}) is False
def test_device_available_tf_with_type(self, monkeypatch):
"""tf with tf_device_type -> list_physical_devices(type) drives it."""
if not _tf_probe_ok():
pytest.skip("tensorflow crashes on import")
try:
import tensorflow as tf
except ImportError:
pytest.skip("TF not installed")
from ttk.remote.server import executor
monkeypatch.setattr(
tf.config, "list_physical_devices", lambda t: [object()])
assert executor._device_available("tf", {"tf_device_type": "GPU"}) is True
def test_device_time_zero_not_falsy(self):
"""Candidate1=0.0 must NOT be skipped (is not None, not truthiness).
Regression guard: a naive ``or`` fallback would treat 0.0 as missing
and wrongly return candidate2. 0.0 is a valid self_device_time_total.
"""
from types import SimpleNamespace
from ttk.remote.server import executor
evt = SimpleNamespace(self_device_time_total=0.0,
self_cuda_time_total=999.0)
assert executor._device_time(evt, device="cuda") == 0.0
def test_device_time_fallback_to_candidate2(self):
"""Candidate1 None -> candidate2 self_{device}_time_total."""
from types import SimpleNamespace
from ttk.remote.server import executor
evt = SimpleNamespace(self_device_time_total=None,
self_mlu_time_total=42.0)
assert executor._device_time(evt, device="mlu") == 42.0
def test_device_time_missing_both_defaults_zero(self):
"""Both candidates absent -> 0.0 (then filtered to NA upstream)."""
from types import SimpleNamespace
from ttk.remote.server import executor
evt = SimpleNamespace()
assert executor._device_time(evt, device="cuda") == 0.0
def test_profiler_missing_activities_raises(self, monkeypatch):
"""Missing torch_profiler/activities -> RuntimeError (server config error
-> 500), NOT an NA degrade. Config errors must surface, not be masked."""
from ttk.remote.server import executor
monkeypatch.setattr(executor, "_device_available", lambda p, prof: True)
profile = {"torch_lib": "cuda", "torch_profiler": {}}
with pytest.raises(RuntimeError, match="activities"):
executor._run_perf(lambda **kw: None, {}, {}, "torch", 0, True,
profile=profile, runtime=3)
def test_profiler_unknown_activity_raises(self, monkeypatch):
"""Unknown ProfilerActivity name -> RuntimeError (-> 500)."""
import torch
from ttk.remote.server import executor
monkeypatch.setattr(executor, "_device_available", lambda p, prof: True)
from types import SimpleNamespace
monkeypatch.setattr(torch.profiler, "ProfilerActivity",
SimpleNamespace(CUDA="cuda"))
profile = {"torch_lib": "cuda",
"torch_profiler": {"activities": ["BOGUS"]}}
with pytest.raises(RuntimeError, match="unknown ProfilerActivity"):
executor._run_perf(lambda **kw: None, {}, {}, "torch", 0, True,
profile=profile, runtime=3)
class TestPerfMeasurement:
"""v2 perf measurement: profiler-based device_us (μs, 3 sig figs)."""
import torch
_TORCH_PROFILE = {"torch_lib": "cuda",
"torch_profiler": {"activities": ["CUDA"]}}
_TF_PROFILE = {"torch_lib": "cuda", "tf_device_type": "GPU"}
def test_torch_device_us_via_profiler(self, monkeypatch):
"""torch.profiler key_averages -> device_us = total/runtime."""
import torch
from types import SimpleNamespace
from ttk.remote.server import executor
fake_avg = SimpleNamespace(self_device_time_total=450.0,
self_cuda_time_total=450.0)
fake_prof = SimpleNamespace(key_averages=lambda: [fake_avg],
step=lambda: None)
class FakeProfileCtx:
def __enter__(self): return fake_prof
def __exit__(self, *a): return False
monkeypatch.setattr(torch.profiler, "profile", lambda **kw: FakeProfileCtx())
monkeypatch.setattr(torch.profiler, "ProfilerActivity",
SimpleNamespace(CUDA="cuda"))
monkeypatch.setattr(torch.profiler, "schedule", lambda **kw: None)
monkeypatch.setattr(executor, "_device_available", lambda p, prof: True)
noop = lambda **kw: None
outputs, perf = executor._run_perf(
noop, {}, {}, "torch", 0, True, profile=self._TORCH_PROFILE, runtime=3)
assert perf["device_us"] == 150.0
def test_torch_profiler_failure_na(self, monkeypatch):
"""Profiler raises -> device_us=NA."""
import torch
from ttk.remote.server import executor
def boom(**kw): raise AssertionError("No CUDA")
monkeypatch.setattr(torch.profiler, "profile", boom)
monkeypatch.setattr(executor, "_device_available", lambda p, prof: True)
noop = lambda **kw: None
outputs, perf = executor._run_perf(
noop, {}, {}, "torch", 0, True, profile=self._TORCH_PROFILE, runtime=3)
assert perf["device_us"] == "NA"
def test_op_failure_propagates_not_masked_as_na(self, monkeypatch):
"""Op execution failure inside the profiler pass must PROPAGATE (-> FAIL),
not turn into PASS + NA/NA. Uses a fake profiler ctx so the op is reached
without real CUDA.
"""
import torch
from types import SimpleNamespace
from ttk.remote.server import executor
fake_prof = SimpleNamespace(step=lambda: None, key_averages=lambda: [])
class Ctx:
def __enter__(self): return fake_prof
def __exit__(self, *a): return False
monkeypatch.setattr(torch.profiler, "profile", lambda **kw: Ctx())
monkeypatch.setattr(torch.profiler, "ProfilerActivity",
SimpleNamespace(CUDA="cuda"))
monkeypatch.setattr(torch.profiler, "schedule", lambda **kw: None)
monkeypatch.setattr(executor, "_device_available", lambda p, prof: True)
def boom(**kw): raise RuntimeError("op exploded")
with pytest.raises(RuntimeError, match="op exploded"):
executor._run_perf(boom, {}, {}, "torch", 0, True, profile=self._TORCH_PROFILE, runtime=3)
def test_tf_op_failure_propagates_not_masked_as_na(self, monkeypatch):
"""TF op execution failure must PROPAGATE (-> FAIL) — symmetric with the
torch pass. The TF pass has a different shape (warmup outside the
start/stop window), so the contract is locked independently."""
if not _tf_probe_ok():
pytest.skip("tensorflow crashes on import")
try:
import tensorflow as tf
except ImportError:
pytest.skip("TF not installed")
from ttk.remote.server import executor
prof_mod = type("M", (), {})()
prof_mod.start = lambda d: None
prof_mod.stop = lambda: None
monkeypatch.setattr(tf.profiler, "experimental", prof_mod)
monkeypatch.setattr(executor, "_device_available", lambda p, prof: True)
def boom(**kw): raise RuntimeError("op exploded")
with pytest.raises(RuntimeError, match="op exploded"):
executor._run_perf(boom, {}, {}, "tf", 0, True, profile=self._TF_PROFILE, runtime=3)
def test_profiler_start_failure_is_logged(self, monkeypatch, caplog):
"""Profiler-infra failure -> device_us=NA AND a server-side log line
(profiler mechanics only)."""
import torch
import logging as _logging
from ttk.remote.server import executor
def boom(**kw): raise AssertionError("no CUDA")
monkeypatch.setattr(torch.profiler, "profile", boom)
monkeypatch.setattr(executor, "_device_available", lambda p, prof: True)
noop = lambda **kw: None
with caplog.at_level(_logging.ERROR):
outputs, perf = executor._run_perf(
noop, {}, {}, "torch", 0, True, profile=self._TORCH_PROFILE, runtime=3)
assert perf["device_us"] == "NA"
assert any("torch.profiler start failed" in r.message
for r in caplog.records)
def test_profiler_readout_failure_keeps_outputs(self, monkeypatch):
"""Profiler readout (key_averages) failure -> device_us=NA but the op's
OUTPUTS survive. In DATA|PERF mode the op result must not be lost to a
flaky profiler (the 'don't over-fail' half of the error policy)."""
import torch
from types import SimpleNamespace
from ttk.remote.server import executor
marker = object()
fake_prof = SimpleNamespace(
step=lambda: None,
key_averages=lambda: (_ for _ in ()).throw(RuntimeError("readout boom")))
class Ctx:
def __enter__(self): return fake_prof
def __exit__(self, *a): return False
monkeypatch.setattr(torch.profiler, "profile", lambda **kw: Ctx())
monkeypatch.setattr(torch.profiler, "ProfilerActivity",
SimpleNamespace(CUDA="cuda"))
monkeypatch.setattr(torch.profiler, "schedule", lambda **kw: None)
monkeypatch.setattr(executor, "_device_available", lambda p, prof: True)
op = lambda **kw: marker
outputs, perf = executor._run_perf(op, {}, {}, "torch", 0, True, profile=self._TORCH_PROFILE, runtime=3)
assert perf["device_us"] == "NA"
assert outputs is marker
def test_tf_device_us_via_xplane(self, monkeypatch, tmp_path):
"""TF xplane.pb parse -> device_us = sum(duration_ps/1e6)/runtime."""
from ttk.remote.server import executor
if not _tf_probe_ok():
pytest.skip("tensorflow crashes on import")
try:
from tensorflow.core.profiler.protobuf import xplane_pb2
import tensorflow as tf
except ImportError:
pytest.skip("TF not installed")
xs = xplane_pb2.XSpace()
plane = xs.planes.add()
plane.name = "/device:GPU:0"
line = plane.lines.add()
for _ in range(3):
ev = line.events.add()
ev.duration_ps = 13_000_000_000
host_plane = xs.planes.add()
host_plane.name = "/host:CPU"
host_line = host_plane.lines.add()
host_ev = host_line.events.add()
host_ev.duration_ps = 999999999
pb_path = tmp_path / "plugins" / "profile" / "test"
pb_path.mkdir(parents=True)
pb_file = pb_path / "host.xplane.pb"
pb_file.write_bytes(xs.SerializeToString())
prof_mod = type("M", (), {})()
prof_mod.start = lambda d: None
prof_mod.stop = lambda: None
monkeypatch.setattr(tf.profiler, "experimental", prof_mod)
import tempfile as _tempfile
monkeypatch.setattr(_tempfile, "mkdtemp", lambda **kw: str(tmp_path))
monkeypatch.setattr(executor, "_device_available", lambda p, prof: True)
noop = lambda **kw: None
outputs, perf = executor._run_perf(
noop, {}, {}, "tf", 0, True, profile=self._TF_PROFILE, runtime=3)
expected = float(f"{39000.0 / 3:.3g}")
assert perf["device_us"] == expected
assert perf["device_us"] != "NA"
def test_tf_xplane_not_found_na(self, monkeypatch, tmp_path):
"""Empty logdir -> NA."""
if not _tf_probe_ok():
pytest.skip("tensorflow crashes on import")
import tensorflow as tf
from ttk.remote.server import executor
prof_mod = type("M", (), {})()
prof_mod.start = lambda d: None
prof_mod.stop = lambda: None
monkeypatch.setattr(tf.profiler, "experimental", prof_mod)
import tempfile as _tempfile
monkeypatch.setattr(_tempfile, "mkdtemp", lambda **kw: str(tmp_path))
monkeypatch.setattr(executor, "_device_available", lambda p, prof: True)
noop = lambda **kw: None
outputs, perf = executor._run_perf(
noop, {}, {}, "tf", 0, True, profile=self._TF_PROFILE, runtime=3)
assert perf["device_us"] == "NA"
def test_cpu_mode_device_us_na(self):
"""use_device=False -> device_us=NA."""
from ttk.remote.server import executor
noop = lambda **kw: None
outputs, perf = executor._run_perf(
noop, {}, {}, "torch", 0, False, runtime=3)
assert perf["device_us"] == "NA"
def test_sig_figs_3(self):
"""3 significant figures via %.3g."""
assert float(f"{13.4567:.3g}") == 13.5
assert float(f"{0.01234:.3g}") == 0.0123
assert float(f"{999.6:.3g}") == 1000.0
def test_timing_peak_split(self, monkeypatch):
"""Profiler pass: no empty_cache. Peak pass: empty_cache not called
(production never calls empty_cache in either pass)."""
import torch
from types import SimpleNamespace
from ttk.remote.server import executor
calls = []
monkeypatch.setattr(torch.cuda, "empty_cache",
lambda *a, **kw: calls.append("empty_cache"))
fake_prof = SimpleNamespace(
key_averages=lambda: [SimpleNamespace(self_device_time_total=1.0)],
step=lambda: None)
class Ctx:
def __enter__(self): return fake_prof
def __exit__(self, *a): return False
monkeypatch.setattr(torch.profiler, "profile", lambda **kw: Ctx())
monkeypatch.setattr(torch.profiler, "ProfilerActivity",
SimpleNamespace(CUDA="cuda"))
monkeypatch.setattr(torch.profiler, "schedule", lambda **kw: None)
monkeypatch.setattr(executor, "_device_available", lambda p, prof: True)
noop = lambda **kw: None
executor._run_perf(noop, {}, {}, "torch", 0, True, profile=self._TORCH_PROFILE, runtime=3)
assert calls == []
def test_tf_corrupt_xplane_na(self, monkeypatch, tmp_path):
"""TF corrupt .xplane.pb (random bytes) -> NA."""
if not _tf_probe_ok():
pytest.skip("tensorflow crashes on import")
import tensorflow as tf
from ttk.remote.server import executor
pb_path = tmp_path / "junk.xplane.pb"
pb_path.write_bytes(b"\x00\x01\x02not a valid proto\xff\xfe")
prof_mod = type("M", (), {})()
prof_mod.start = lambda d: None
prof_mod.stop = lambda: None
monkeypatch.setattr(tf.profiler, "experimental", prof_mod)
import tempfile as _tempfile
monkeypatch.setattr(_tempfile, "mkdtemp", lambda **kw: str(tmp_path))
monkeypatch.setattr(executor, "_device_available", lambda p, prof: True)
noop = lambda **kw: None
outputs, perf = executor._run_perf(
noop, {}, {}, "tf", 0, True, profile=self._TF_PROFILE, runtime=3)
assert perf["device_us"] == "NA"
def test_tf_start_stop_raise_na(self, monkeypatch, tmp_path):
"""TF start/stop raise -> device_us=NA."""
if not _tf_probe_ok():
pytest.skip("tensorflow crashes on import")
import tensorflow as tf
from ttk.remote.server import executor
prof_mod = type("M", (), {})()
prof_mod.start = lambda d: (_ for _ in ()).throw(RuntimeError("boom"))
prof_mod.stop = lambda: (_ for _ in ()).throw(RuntimeError("boom"))
monkeypatch.setattr(tf.profiler, "experimental", prof_mod)
import tempfile as _tempfile
monkeypatch.setattr(_tempfile, "mkdtemp", lambda **kw: str(tmp_path))
monkeypatch.setattr(executor, "_device_available", lambda p, prof: True)
noop = lambda **kw: None
outputs, perf = executor._run_perf(
noop, {}, {}, "tf", 0, True, profile=self._TF_PROFILE, runtime=3)
assert perf["device_us"] == "NA"
def test_peak_pass_raise_keeps_device_us(self, monkeypatch):
import torch
from types import SimpleNamespace
from ttk.remote.server import executor
fake_prof = SimpleNamespace(
key_averages=lambda: [SimpleNamespace(self_device_time_total=300.0,
self_cuda_time_total=300.0)],
step=lambda: None)
class Ctx:
def __enter__(self): return fake_prof
def __exit__(self, *a): return False
monkeypatch.setattr(torch.profiler, "profile", lambda **kw: Ctx())
monkeypatch.setattr(torch.profiler, "ProfilerActivity",
SimpleNamespace(CUDA="cuda"))
monkeypatch.setattr(torch.profiler, "schedule", lambda **kw: None)
monkeypatch.setattr(executor, "_device_available", lambda p, prof: True)
monkeypatch.setattr(torch.cuda, "reset_peak_memory_stats",
lambda *a, **k: (_ for _ in ()).throw(
RuntimeError("peak boom")))
noop = lambda **kw: None
outputs, perf = executor._run_perf(
noop, {}, {}, "torch", 0, True, profile=self._TORCH_PROFILE, runtime=3)
assert perf["device_us"] == 100.0
assert perf["peak_memory_mb"] == "NA"
def test_tf_logdir_rmtree_on_stop_raise(self, monkeypatch, tmp_path):
"""TF logdir rmtree runs in finally even if stop() raises."""
if not _tf_probe_ok():
pytest.skip("tensorflow crashes on import")
import tensorflow as tf
from ttk.remote.server import executor
import shutil
prof_mod = type("M", (), {})()
prof_mod.start = lambda d: None
prof_mod.stop = lambda: (_ for _ in ()).throw(RuntimeError("stop boom"))
monkeypatch.setattr(tf.profiler, "experimental", prof_mod)
rmtree_calls = []
real_mkdtemp = __import__("tempfile").mkdtemp
created = real_mkdtemp(prefix="tfptest_")
import tempfile as _tempfile
monkeypatch.setattr(_tempfile, "mkdtemp", lambda **kw: created)
monkeypatch.setattr(shutil, "rmtree",
lambda p, **kw: rmtree_calls.append(str(p)))
monkeypatch.setattr(executor, "_device_available", lambda p, prof: True)
noop = lambda **kw: None
executor._run_perf(noop, {}, {}, "tf", 0, True, profile=self._TF_PROFILE, runtime=3)
assert any(created == c for c in rmtree_calls), \
f"rmtree not called with {created}; calls={rmtree_calls}"
class TestRuntimeClamp:
"""Server-side X-Runtime clamp (spec §8 guard). Header is clamped to [1,100];
non-numeric falls back to 3. Tests _clamp_runtime (extracted from _handle_run)."""
def test_over_high_clamps_to_100(self):
from ttk.remote.server.xpu_server import _clamp_runtime
assert _clamp_runtime("200") == 100
def test_zero_clamps_to_1(self):
from ttk.remote.server.xpu_server import _clamp_runtime
assert _clamp_runtime("0") == 1
def test_non_numeric_falls_back_to_default_3(self):
from ttk.remote.server.xpu_server import _clamp_runtime
assert _clamp_runtime("abc") == 3
def test_none_falls_back_to_default_3(self):
from ttk.remote.server.xpu_server import _clamp_runtime
assert _clamp_runtime(None) == 3
def test_in_range_passes_through(self):
from ttk.remote.server.xpu_server import _clamp_runtime
assert _clamp_runtime("50") == 50
def _post_run(port, body, headers, timeout=60):
c = http.client.HTTPConnection("127.0.0.1", port, timeout=timeout)
c.request("POST", "/v1/run", body=body, headers=headers)
r = c.getresponse()
data = r.read()
c.close()
return r.status, data
def _sync_module(port, tenant, rel_path, content):
import base64
import hashlib
body = json.dumps({"files": {
rel_path: {"content": base64.b64encode(content.encode()).decode(),
"hash": hashlib.sha256(content.encode()).hexdigest()}}})
c = http.client.HTTPConnection("127.0.0.1", port, timeout=10)
c.request("POST", "/v1/sync", body=body,
headers={"Content-Type": "application/json", "X-Tenant-ID": tenant})
r = c.getresponse()
r.read()
c.close()
return r.status
class TestServerRunViaSubprocess:
"""End-to-end: real non-dry-run server runs /v1/run in a child process."""
@pytest.fixture(scope="class")
def server(self, tmp_path_factory):
sync = tmp_path_factory.mktemp("sync")
tmp = tmp_path_factory.mktemp("tmp")
import yaml
config_file = tmp_path_factory.mktemp("config") / "xpu_server.yaml"
config_data = {
"storage": {
"sync_dir": str(sync),
"tmp_dir": str(tmp),
},
"server": {
"run_deadline_s": 60,
},
}
with open(config_file, "w") as f:
yaml.dump(config_data, f)
proc = subprocess.Popen(
[sys.executable, "-m", "server.xpu_server",
"--port", "19150", "--devices", "cpu", "--config", str(config_file)],
env=os.environ.copy(),
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
for _ in range(40):
try:
c = http.client.HTTPConnection("127.0.0.1", 19150, timeout=1)
c.request("GET", "/v1/heartbeat")
r = c.getresponse(); c.close()
if r.status == 200:
break
except (ConnectionRefusedError, OSError):
pass
time.sleep(0.5)
yield proc
proc.terminate()
try:
proc.wait(timeout=10)
except subprocess.TimeoutExpired:
proc.kill()
def test_run_numpy_add(self, server):
from ttk.remote import DATA
a0 = np.array([1.0, 2.0])
a1 = np.array([3.0, 4.0])
buf = io.BytesIO()
np.savez_compressed(buf, a0=a0, a1=a1)
c = http.client.HTTPConnection("127.0.0.1", 19150, timeout=60)
c.request("POST", "/v1/run", body=buf.getvalue(), headers={
"X-Execution-Type": "api", "X-Provider": "numpy", "X-API": "numpy.add",
"X-Mode": str(DATA),
"X-Input-Schema": json.dumps([{"name": "x1", "index": 0},
{"name": "x2", "index": 1}]),
"X-Input-Count": "2", "X-Attrs": "{}", "X-Tenant-ID": "e2e1",
"Content-Type": "application/octet-stream"})
r = c.getresponse()
data = r.read()
c.close()
assert r.status == 200
np.testing.assert_array_equal(np.load(io.BytesIO(data))["a0"], a0 + a1)
def test_crash_then_server_keeps_serving(self, server):
from ttk.remote import DATA
_sync_module(19150, "cr", "crashfix.py",
"import os\n"
"class CrashImpl:\n"
" def __call__(self, x1): os._exit(139)\n"
"class CrashTestSpec:\n"
" third_party = {'numpy': CrashImpl}\n")
buf = io.BytesIO()
np.savez_compressed(buf, a0=np.array([1.0]))
h = {"X-Execution-Type": "spec", "X-Provider": "numpy",
"X-Spec-Module": "crashfix", "X-Spec-Class": "CrashTestSpec",
"X-Mode": str(DATA),
"X-Input-Schema": json.dumps([{"name": "x1", "index": 0}]),
"X-Input-Count": "1", "X-Attrs": "{}", "X-Tenant-ID": "cr",
"Content-Type": "application/octet-stream"}
s1, _ = _post_run(19150, buf.getvalue(), h)
assert s1 == 500
addbuf = io.BytesIO()
np.savez_compressed(addbuf, a0=np.array([1.0]), a1=np.array([2.0]))
s2, b2 = _post_run(19150, addbuf.getvalue(), {
"X-Execution-Type": "api", "X-Provider": "numpy", "X-API": "numpy.add",
"X-Mode": str(DATA),
"X-Input-Schema": json.dumps([{"name": "x1", "index": 0},
{"name": "x2", "index": 1}]),
"X-Input-Count": "2", "X-Attrs": "{}", "X-Tenant-ID": "cr2",
"Content-Type": "application/octet-stream"})
assert s2 == 200
np.testing.assert_array_equal(np.load(io.BytesIO(b2))["a0"], np.array([3.0]))
def test_424_then_sync_then_success(self, server):
from ttk.remote import DATA
add_src = ("class AddImpl:\n"
" def __call__(self, x1, x2): return [x1 + x2]\n"
"class AddTestSpec:\n"
" third_party = {'numpy': AddImpl}\n")
buf = io.BytesIO()
np.savez_compressed(buf, a0=np.array([2.0]), a1=np.array([3.0]))
h = {"X-Execution-Type": "spec", "X-Provider": "numpy",
"X-Spec-Module": "addfix", "X-Spec-Class": "AddTestSpec",
"X-Mode": str(DATA),
"X-Input-Schema": json.dumps([{"name": "x1", "index": 0},
{"name": "x2", "index": 1}]),
"X-Input-Count": "2", "X-Attrs": "{}", "X-Tenant-ID": "resync",
"Content-Type": "application/octet-stream"}
s1, b1 = _post_run(19150, buf.getvalue(), h)
assert s1 == 424
assert json.loads(b1).get("missing") in ("addfix", "addfix.py")
assert _sync_module(19150, "resync", "addfix.py", add_src) == 200
s3, b3 = _post_run(19150, buf.getvalue(), h)
assert s3 == 200
np.testing.assert_array_equal(np.load(io.BytesIO(b3))["a0"], np.array([5.0]))
def test_cross_tenant_isolation(self, server):
from ttk.remote import DATA
_sync_module(19150, "ta", "sharedfix.py",
"class AddImpl:\n"
" def __call__(self, x1, x2): return [x1 + x2]\n"
"class AddTestSpec:\n"
" third_party = {'numpy': AddImpl}\n")
_sync_module(19150, "tb", "sharedfix.py",
"class AddImpl:\n"
" def __call__(self, x1, x2): return [x1 * x2]\n"
"class AddTestSpec:\n"
" third_party = {'numpy': AddImpl}\n")
buf = io.BytesIO()
np.savez_compressed(buf, a0=np.array([2.0]), a1=np.array([3.0]))
def hdr(t):
return {"X-Execution-Type": "spec", "X-Provider": "numpy",
"X-Spec-Module": "sharedfix", "X-Spec-Class": "AddTestSpec",
"X-Mode": str(DATA),
"X-Input-Schema": json.dumps([{"name": "x1", "index": 0},
{"name": "x2", "index": 1}]),
"X-Input-Count": "2", "X-Attrs": "{}", "X-Tenant-ID": t,
"Content-Type": "application/octet-stream"}
results = []
errors = []
def fire(t):
try:
results.append((t, _post_run(19150, buf.getvalue(), hdr(t))))
except Exception:
errors.append((t, traceback.format_exc()))
threads = []
for _ in range(8):
threads.append(threading.Thread(target=fire, args=("ta",)))
threads.append(threading.Thread(target=fire, args=("tb",)))
for t in threads:
t.start()
for t in threads:
t.join(timeout=70)
assert not errors, f"fire raised: {errors}"
assert len(results) == 16, f"results={len(results)} errors={errors}"
for tenant, (status, data) in results:
assert status == 200
out = np.load(io.BytesIO(data))["a0"]
expected = np.array([5.0]) if tenant == "ta" else np.array([6.0])
np.testing.assert_array_equal(out, expected)
def test_perf_mode_returns_x_perf_header(self, server):
from ttk.remote import DATA, PERF
buf = io.BytesIO()
np.savez_compressed(buf, a0=np.array([1.0]), a1=np.array([2.0]))
c = http.client.HTTPConnection("127.0.0.1", 19150, timeout=60)
c.request("POST", "/v1/run", body=buf.getvalue(), headers={
"X-Execution-Type": "api", "X-Provider": "numpy", "X-API": "numpy.add",
"X-Mode": str(DATA | PERF),
"X-Input-Schema": json.dumps([{"name": "x1", "index": 0},
{"name": "x2", "index": 1}]),
"X-Input-Count": "2", "X-Attrs": "{}", "X-Tenant-ID": "perf1",
"Content-Type": "application/octet-stream"})
r = c.getresponse()
perf_h = r.getheader("X-Perf")
r.read()
c.close()
assert r.status == 200
assert perf_h is not None
perf = json.loads(perf_h)
class TestBackpressure:
"""MAX_CONCURRENT gate: overflow -> 503; control plane bypasses it."""
@pytest.fixture(scope="class")
def gate_server(self, tmp_path_factory):
sync = tmp_path_factory.mktemp("sync_g")
tmp = tmp_path_factory.mktemp("tmp_g")
import yaml
config_file = tmp_path_factory.mktemp("config") / "xpu_server.yaml"
config_data = {
"storage": {
"sync_dir": str(sync),
"tmp_dir": str(tmp),
},
"server": {
"max_concurrent": 1,
"gate_wait_s": 0.3,
"run_deadline_s": 60,
},
}
with open(config_file, "w") as f:
yaml.dump(config_data, f)
proc = subprocess.Popen(
[sys.executable, "-m", "server.xpu_server",
"--port", "19151", "--devices", "cpu", "--config", str(config_file)],
env=os.environ.copy(),
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
for _ in range(40):
try:
c = http.client.HTTPConnection("127.0.0.1", 19151, timeout=1)
c.request("GET", "/v1/heartbeat")
r = c.getresponse(); c.close()
if r.status == 200:
break
except (ConnectionRefusedError, OSError):
pass
time.sleep(0.5)
yield proc
proc.terminate()
try:
proc.wait(timeout=10)
except subprocess.TimeoutExpired:
proc.kill()
def test_gate_full_returns_503_and_control_plane_ok(self, gate_server):
from ttk.remote import DATA
slow = ("import time\n"
"class SlowImpl:\n"
" def __call__(self, x1):\n"
" time.sleep(2.0)\n"
" return [x1]\n"
"class SlowTestSpec:\n"
" third_party = {'numpy': SlowImpl}\n")
_sync_module(19151, "g", "slowfix.py", slow)
buf = io.BytesIO()
np.savez_compressed(buf, a0=np.array([1.0]))
h = {"X-Execution-Type": "spec", "X-Provider": "numpy",
"X-Spec-Module": "slowfix", "X-Spec-Class": "SlowTestSpec",
"X-Mode": str(DATA),
"X-Input-Schema": json.dumps([{"name": "x1", "index": 0}]),
"X-Input-Count": "1", "X-Attrs": "{}", "X-Tenant-ID": "g",
"Content-Type": "application/octet-stream"}
holder = {}
def fire():
holder["s"] = _post_run(19151, buf.getvalue(), h)[0]
t = threading.Thread(target=fire)
t.start()
time.sleep(0.8)
s2, _ = _post_run(19151, buf.getvalue(), h)
assert s2 == 503
c = http.client.HTTPConnection("127.0.0.1", 19151, timeout=2)
c.request("GET", "/v1/heartbeat")
r = c.getresponse(); r.read(); c.close()
assert r.status == 200
t.join(timeout=15)
assert holder.get("s") == 200