去敏感提交
This commit is contained in:
@@ -11,11 +11,11 @@ const REPO = process.env.REPO;
|
||||
if (!REPO) throw new Error("REPO env required");
|
||||
|
||||
// ---- 构造一局日志:复刻"原点换频道"致病模式(第一步原地检测且换频道) ----
|
||||
function base(id) { return { arena_id: "default", robot_id: "2026001", request_id: id }; }
|
||||
function base(id) { return { arena_id: "default", robot_id: "TEAM-0001", request_id: id }; }
|
||||
const sources = [{ channel: 4, x: 100, y: 0, r_eff_m: 1200, directional: false, heading_deg: 0 }];
|
||||
const refereeLog = [
|
||||
JSON.stringify({ event: "session_start", case_code: "TEST-CASE-0001", module: "q3_practice",
|
||||
robot_id: "2026001", seed: 9, truth: sources }),
|
||||
robot_id: "TEAM-0001", seed: 9, truth: sources }),
|
||||
JSON.stringify({ event: "action", seq: 1, method: "POST", path: "/enter", status: 200,
|
||||
request: base("e1"), response: { accepted: true, virtual_time_s: 0,
|
||||
remaining_real_duration_s: 1200 } }),
|
||||
@@ -99,10 +99,10 @@ const replayEvents = refereeLog.split("\n").map((l) => JSON.parse(l));
|
||||
globalThis.fetch = async (url) => {
|
||||
const json = async () => {
|
||||
if (url.startsWith("/ui/api/sessions"))
|
||||
return { sessions: [{ case_code: "TEST-CASE-0001", module: "q3_practice", robot_id: "2026001" }] };
|
||||
return { sessions: [{ case_code: "TEST-CASE-0001", module: "q3_practice", robot_id: "TEAM-0001" }] };
|
||||
if (url.startsWith("/ui/api/replay"))
|
||||
return { case_code: "TEST-CASE-0001", module: "q3_practice",
|
||||
meta: { module: "q3_practice", robot_id: "2026001", truth: sources }, events: replayEvents };
|
||||
meta: { module: "q3_practice", robot_id: "TEAM-0001", truth: sources }, events: replayEvents };
|
||||
if (url.startsWith("/ui/api/state"))
|
||||
return { phase: "idle", action_port: 2026, display_limit: 1000, modules: {}, attempts: {} };
|
||||
throw new Error("unexpected fetch " + url);
|
||||
|
||||
@@ -46,12 +46,12 @@ def post(port, path, obj=None, *, headers=None, method="POST", raw=None):
|
||||
|
||||
|
||||
def payload(request_id="e", **extra):
|
||||
return dict(arena_id="default", robot_id="2026001", request_id=request_id, **extra)
|
||||
return dict(arena_id="default", robot_id="TEAM-0001", request_id=request_id, **extra)
|
||||
|
||||
|
||||
def start_open_session(local_referee, **opts):
|
||||
opts.setdefault("countdown_s", 0.05)
|
||||
session = local_referee.start("q3_practice", "2026001", **opts)
|
||||
session = local_referee.start("q3_practice", "TEAM-0001", **opts)
|
||||
assert wait_until(lambda: session.phase == "open")
|
||||
return session
|
||||
|
||||
@@ -67,7 +67,7 @@ def test_binding_is_loopback_only(local_referee):
|
||||
|
||||
|
||||
def test_interface_refuses_connections_outside_window(local_referee):
|
||||
session = local_referee.start("q3_practice", "2026001", countdown_s=5)
|
||||
session = local_referee.start("q3_practice", "TEAM-0001", countdown_s=5)
|
||||
server = local_referee._open_interface.__self__
|
||||
assert server.is_open is False # 倒计时期间未监听
|
||||
assert wait_until(lambda: session.phase == "open", timeout=6)
|
||||
|
||||
@@ -12,7 +12,7 @@ from referee.interface import handle_raw
|
||||
|
||||
|
||||
def payload(request_id="e", **extra):
|
||||
return dict(arena_id="default", robot_id="2026001", request_id=request_id, **extra)
|
||||
return dict(arena_id="default", robot_id="TEAM-0001", request_id=request_id, **extra)
|
||||
|
||||
|
||||
def post(sim, path, body=None, headers=None, method="POST", target=None):
|
||||
@@ -22,7 +22,7 @@ def post(sim, path, body=None, headers=None, method="POST", target=None):
|
||||
|
||||
|
||||
def test_raw_json_format_errors():
|
||||
sim = LocalSimulator([])
|
||||
sim = LocalSimulator([], robot_id="TEAM-0001")
|
||||
cases = [
|
||||
(b'{"request_id":"a","request_id":"b"}', 400), # 重复键
|
||||
(b'{"position":{"x":1,"x":2}}', 400), # 嵌套重复键
|
||||
@@ -41,7 +41,7 @@ def test_raw_json_format_errors():
|
||||
|
||||
|
||||
def test_raw_size_and_depth_boundaries_are_inclusive():
|
||||
sim = LocalSimulator([])
|
||||
sim = LocalSimulator([], robot_id="TEAM-0001")
|
||||
headers = [("Content-Type", "application/json")]
|
||||
deep = b'{"extra":' + b'[' * 15 + b'0' + b']' * 15 + b'}' # 深度 16 合法
|
||||
body = json.dumps({**payload(), **json.loads(deep)}).encode()
|
||||
@@ -67,21 +67,21 @@ def test_raw_size_and_depth_boundaries_are_inclusive():
|
||||
("POST", "/enter", [("content-type", 'application/json;charset="utf-8"')], 200),
|
||||
])
|
||||
def test_http_boundary(method, path, headers, status):
|
||||
sim = LocalSimulator([])
|
||||
sim = LocalSimulator([], robot_id="TEAM-0001")
|
||||
raw = json.dumps(payload()).encode()
|
||||
result = handle_raw(sim, method, path, headers or [("Content-Type", "application/json")], raw)
|
||||
assert result.status == status
|
||||
|
||||
|
||||
def test_closed_simulator_raises_connection_level_error():
|
||||
sim = LocalSimulator([], clock=lambda: 9999, window_started_at=0)
|
||||
sim = LocalSimulator([], clock=lambda: 9999, window_started_at=0, robot_id="TEAM-0001")
|
||||
with pytest.raises(SimulatorClosed):
|
||||
handle_raw(sim, "POST", "/enter",
|
||||
[("Content-Type", "application/json")], json.dumps(payload()).encode())
|
||||
|
||||
|
||||
def test_on_request_callback_receives_parsed_payload():
|
||||
sim = LocalSimulator([])
|
||||
sim = LocalSimulator([], robot_id="TEAM-0001")
|
||||
seen = []
|
||||
raw = json.dumps(payload("enter-1")).encode()
|
||||
handle_raw(sim, "POST", "/enter", [("Content-Type", "application/json")], raw,
|
||||
|
||||
@@ -28,7 +28,7 @@ def test_countdown_then_open_then_window_timeout(tmp_path):
|
||||
referee = Referee(action_port=0, data_dir=tmp_path)
|
||||
opened = []
|
||||
referee.set_interface_callbacks(lambda s: opened.append(1), lambda s: None)
|
||||
session = referee.start("q3_practice", "2026001", countdown_s=0.05, window_s=0.3)
|
||||
session = referee.start("q3_practice", "TEAM-0001", countdown_s=0.05, window_s=0.3)
|
||||
assert session.phase == "countdown"
|
||||
assert wait_until(lambda: session.phase == "open")
|
||||
assert opened == [1]
|
||||
@@ -39,11 +39,11 @@ def test_countdown_then_open_then_window_timeout(tmp_path):
|
||||
|
||||
def test_abort_during_countdown_and_running(tmp_path):
|
||||
referee = Referee(action_port=0, data_dir=tmp_path)
|
||||
session = referee.start("q3_practice", "2026001", countdown_s=5)
|
||||
session = referee.start("q3_practice", "TEAM-0001", countdown_s=5)
|
||||
assert referee.abort() is True
|
||||
assert session.phase == "finished" and session.end_reason == "manual_abort"
|
||||
assert referee.abort() is False # 已结束,不能重复中止
|
||||
session = referee.start("q3_practice", "2026001", countdown_s=0.05, window_s=30)
|
||||
session = referee.start("q3_practice", "TEAM-0001", countdown_s=0.05, window_s=30)
|
||||
assert wait_until(lambda: session.phase == "open")
|
||||
assert referee.abort() is True
|
||||
assert session.end_reason == "manual_abort"
|
||||
@@ -51,11 +51,11 @@ def test_abort_during_countdown_and_running(tmp_path):
|
||||
|
||||
def test_cannot_start_while_running_and_restart_after_finish(tmp_path):
|
||||
referee = Referee(action_port=0, data_dir=tmp_path)
|
||||
first = referee.start("q3_practice", "2026001", countdown_s=5)
|
||||
first = referee.start("q3_practice", "TEAM-0001", countdown_s=5)
|
||||
with pytest.raises(RefereeError):
|
||||
referee.start("q3_practice", "2026001", countdown_s=0.05)
|
||||
referee.start("q3_practice", "TEAM-0001", countdown_s=0.05)
|
||||
assert referee.abort()
|
||||
second = referee.start("q3_practice", "2026001", countdown_s=0.05, window_s=1)
|
||||
second = referee.start("q3_practice", "TEAM-0001", countdown_s=0.05, window_s=1)
|
||||
assert second.case_code != first.case_code # 新的一局、新的案例编码
|
||||
referee.abort()
|
||||
# 结束后不能复位继续原测试,只能开始新的一局 [题面 4.5]
|
||||
@@ -65,19 +65,19 @@ def test_cannot_start_while_running_and_restart_after_finish(tmp_path):
|
||||
def test_formal_attempts_accounting(tmp_path):
|
||||
referee = Referee(action_port=0, data_dir=tmp_path)
|
||||
for _ in range(FORMAL_ATTEMPTS):
|
||||
_session = referee.start("q3_formal", "2026001", countdown_s=0.05)
|
||||
_session = referee.start("q3_formal", "TEAM-0001", countdown_s=0.05)
|
||||
referee.abort() # 正式中止仍占用机会 [题面 4.5]
|
||||
with pytest.raises(RefereeError):
|
||||
referee.start("q3_formal", "2026001", countdown_s=0.05)
|
||||
referee.start("q3_formal", "TEAM-0001", countdown_s=0.05)
|
||||
# 演练不限次数
|
||||
for _ in range(FORMAL_ATTEMPTS + 2):
|
||||
referee.start("q3_practice", "2026001", countdown_s=0.05)
|
||||
referee.start("q3_practice", "TEAM-0001", countdown_s=0.05)
|
||||
referee.abort()
|
||||
|
||||
|
||||
def test_truth_policy_practice_vs_formal(tmp_path):
|
||||
referee = Referee(action_port=0, data_dir=tmp_path)
|
||||
practice = referee.start("q3_practice", "2026001", countdown_s=0.05, window_s=5,
|
||||
practice = referee.start("q3_practice", "TEAM-0001", countdown_s=0.05, window_s=5,
|
||||
seed=42, source_count=12)
|
||||
assert wait_until(lambda: practice.phase == "open")
|
||||
referee.abort()
|
||||
@@ -86,7 +86,7 @@ def test_truth_policy_practice_vs_formal(tmp_path):
|
||||
assert state["truth"]["source_count"] == 12
|
||||
assert {"omni_count", "directional_count"} <= set(state["truth"])
|
||||
|
||||
formal = referee.start("q4_formal", "2026001", countdown_s=0.05, seed=42)
|
||||
formal = referee.start("q4_formal", "TEAM-0001", countdown_s=0.05, seed=42)
|
||||
assert wait_until(lambda: formal.phase == "open")
|
||||
# 运行中考官视图也不显示 [题面 4.6:正式测试任何界面不显示真值]
|
||||
assert referee.snapshot(examiner=True)["truth"]["revealed"] is False
|
||||
@@ -97,9 +97,9 @@ def test_truth_policy_practice_vs_formal(tmp_path):
|
||||
|
||||
def test_exit_finishes_session_with_user_exit(tmp_path):
|
||||
referee = Referee(action_port=0, data_dir=tmp_path)
|
||||
session = referee.start("q3_practice", "2026001", countdown_s=0.05, window_s=20)
|
||||
session = referee.start("q3_practice", "TEAM-0001", countdown_s=0.05, window_s=20)
|
||||
assert wait_until(lambda: session.phase == "open")
|
||||
payload = dict(arena_id="default", robot_id="2026001", request_id="enter")
|
||||
payload = dict(arena_id="default", robot_id="TEAM-0001", request_id="enter")
|
||||
session.simulator.handle("/enter", payload)
|
||||
session.simulator.handle("/exit", {**payload, "request_id": "exit"})
|
||||
assert wait_until(lambda: session.phase == "finished")
|
||||
@@ -109,9 +109,9 @@ def test_exit_finishes_session_with_user_exit(tmp_path):
|
||||
def test_program_timeout_after_enter(tmp_path):
|
||||
spec = Spec(field=FieldSpec(max_real_duration_s=0.3))
|
||||
referee = Referee(action_port=0, data_dir=tmp_path, spec=spec)
|
||||
session = referee.start("q3_practice", "2026001", countdown_s=0.05, window_s=10)
|
||||
session = referee.start("q3_practice", "TEAM-0001", countdown_s=0.05, window_s=10)
|
||||
assert wait_until(lambda: session.phase == "open")
|
||||
session.simulator.handle("/enter", dict(arena_id="default", robot_id="2026001",
|
||||
session.simulator.handle("/enter", dict(arena_id="default", robot_id="TEAM-0001",
|
||||
request_id="enter"))
|
||||
assert wait_until(lambda: session.phase == "finished", timeout=5)
|
||||
assert session.end_reason == "program_timeout"
|
||||
@@ -119,7 +119,7 @@ def test_program_timeout_after_enter(tmp_path):
|
||||
|
||||
def test_record_action_updates_feed_trail_and_counts(tmp_path):
|
||||
referee = Referee(action_port=0, data_dir=tmp_path)
|
||||
session = referee.start("q3_practice", "2026001", countdown_s=0.05, window_s=5)
|
||||
session = referee.start("q3_practice", "TEAM-0001", countdown_s=0.05, window_s=5)
|
||||
assert wait_until(lambda: session.phase == "open")
|
||||
_sim = session.simulator
|
||||
referee.record_action(session, "POST", "/measure",
|
||||
@@ -142,7 +142,7 @@ def test_record_action_updates_feed_trail_and_counts(tmp_path):
|
||||
|
||||
def test_behavior_log_and_meta_written(tmp_path):
|
||||
referee = Referee(action_port=0, data_dir=tmp_path)
|
||||
session = referee.start("q3_practice", "2026001", countdown_s=0.05, window_s=1,
|
||||
session = referee.start("q3_practice", "TEAM-0001", countdown_s=0.05, window_s=1,
|
||||
seed=7, source_count=10)
|
||||
assert wait_until(lambda: session.phase == "open")
|
||||
referee.record_action(session, "POST", "/measure",
|
||||
@@ -168,7 +168,7 @@ def test_display_limit_and_port_settings(tmp_path):
|
||||
referee.set_display_limit(50)
|
||||
with pytest.raises(RefereeError):
|
||||
referee.set_display_limit(5001)
|
||||
_session = referee.start("q3_practice", "2026001", countdown_s=5)
|
||||
_session = referee.start("q3_practice", "TEAM-0001", countdown_s=5)
|
||||
with pytest.raises(RefereeError):
|
||||
referee.set_action_port(8080) # 测试进行中不能改端口
|
||||
referee.abort()
|
||||
|
||||
@@ -9,7 +9,7 @@ from referee import FieldSpec, LocalSimulator, SimulatorClosed, Source, Spec
|
||||
|
||||
|
||||
def payload(request_id="e", **extra):
|
||||
return dict(arena_id="default", robot_id="2026001", request_id=request_id, **extra)
|
||||
return dict(arena_id="default", robot_id="TEAM-0001", request_id=request_id, **extra)
|
||||
|
||||
|
||||
def measure(request_id="m", x=0, y=0, channel=1):
|
||||
@@ -20,7 +20,7 @@ def measure(request_id="m", x=0, y=0, channel=1):
|
||||
def test_late_enter_and_deadline():
|
||||
now = [1400.25]
|
||||
sim = LocalSimulator([], clock=lambda: now[0], wall_clock=lambda: 1234.5,
|
||||
window_started_at=0)
|
||||
window_started_at=0, robot_id="TEAM-0001")
|
||||
response = sim.handle("/enter", payload())[1]
|
||||
assert response["remaining_real_duration_s"] == 99 # 窗口剩余取早
|
||||
assert response["real_timestamp_ms"] == 1234500
|
||||
@@ -35,28 +35,28 @@ def test_late_enter_and_deadline():
|
||||
|
||||
def test_program_deadline_and_subsecond_enter():
|
||||
now = [100]
|
||||
sim = LocalSimulator([], clock=lambda: now[0], window_started_at=0)
|
||||
sim = LocalSimulator([], clock=lambda: now[0], window_started_at=0, robot_id="TEAM-0001")
|
||||
assert sim.handle("/enter", payload())[1]["remaining_real_duration_s"] == 1200
|
||||
now[0] = 1300
|
||||
with pytest.raises(SimulatorClosed):
|
||||
sim.handle("/measure", measure())
|
||||
late = LocalSimulator([], clock=lambda: 1499.5, window_started_at=0)
|
||||
late = LocalSimulator([], clock=lambda: 1499.5, window_started_at=0, robot_id="TEAM-0001")
|
||||
assert late.handle("/enter", payload())[1]["remaining_real_duration_s"] == 0
|
||||
expired = LocalSimulator([], clock=lambda: 1500, window_started_at=0)
|
||||
expired = LocalSimulator([], clock=lambda: 1500, window_started_at=0, robot_id="TEAM-0001")
|
||||
with pytest.raises(SimulatorClosed):
|
||||
expired.handle("/enter", payload())
|
||||
|
||||
|
||||
def test_stress_mode_is_explicit():
|
||||
spec = Spec(field=FieldSpec(max_real_duration_s=1800))
|
||||
official = LocalSimulator([], spec=spec, clock=lambda: 0)
|
||||
stress = LocalSimulator([], spec=spec, clock=lambda: 0, stress_mode=True)
|
||||
official = LocalSimulator([], spec=spec, clock=lambda: 0, robot_id="TEAM-0001")
|
||||
stress = LocalSimulator([], spec=spec, clock=lambda: 0, stress_mode=True, robot_id="TEAM-0001")
|
||||
assert official.handle("/enter", payload())[1]["remaining_real_duration_s"] == 1200
|
||||
assert stress.handle("/enter", payload())[1]["remaining_real_duration_s"] == 1800
|
||||
|
||||
|
||||
def test_virtual_crossing_action_finishes_then_connection_closes():
|
||||
sim = LocalSimulator([])
|
||||
sim = LocalSimulator([], robot_id="TEAM-0001")
|
||||
sim.handle("/enter", payload())
|
||||
assert sim.handle("/measure", measure(x=1_800_000))[1]["virtual_time_s"] == 360005
|
||||
for path, body in [("/measure", measure("m2")), ("/exit", payload("x"))]:
|
||||
@@ -66,7 +66,7 @@ def test_virtual_crossing_action_finishes_then_connection_closes():
|
||||
|
||||
|
||||
def test_explicit_exit_closes_new_requests():
|
||||
sim = LocalSimulator([])
|
||||
sim = LocalSimulator([], robot_id="TEAM-0001")
|
||||
sim.handle("/enter", payload())
|
||||
assert sim.handle("/exit", payload("exit"))[1]["exit_reason"] == "user_exit"
|
||||
assert sim.closed_reason == "user_exit"
|
||||
@@ -76,7 +76,7 @@ def test_explicit_exit_closes_new_requests():
|
||||
|
||||
# ---------------------------------------------------------------- 量化与幂等
|
||||
def test_microseconds_accumulate_and_signed_zero_is_same_location():
|
||||
sim = LocalSimulator([Source(1, 1000, 0, 1500)])
|
||||
sim = LocalSimulator([Source(1, 1000, 0, 1500)], robot_id="TEAM-0001")
|
||||
sim.handle("/enter", payload())
|
||||
a = sim.handle("/measure", measure("a", 0.0))[1]
|
||||
b = sim.handle("/measure", measure("b", -0.0))[1]
|
||||
@@ -88,7 +88,7 @@ def test_microseconds_accumulate_and_signed_zero_is_same_location():
|
||||
|
||||
|
||||
def test_error_rejection_does_not_consume_id():
|
||||
sim = LocalSimulator([])
|
||||
sim = LocalSimulator([], robot_id="TEAM-0001")
|
||||
for bad in ["e\n", "e\u200b", "e\u0085", "e\ud800"]:
|
||||
assert sim.handle("/enter", payload(bad))[0] == 400
|
||||
assert not sim._idempotency
|
||||
@@ -96,7 +96,7 @@ def test_error_rejection_does_not_consume_id():
|
||||
|
||||
|
||||
def test_idempotent_replay_and_conflict():
|
||||
sim = LocalSimulator([])
|
||||
sim = LocalSimulator([], robot_id="TEAM-0001")
|
||||
sim.handle("/enter", payload("enter"))
|
||||
first = sim.handle("/measure", measure("m1", 100, 0))[1]
|
||||
replay = sim.handle("/measure", measure("m1", 100, 0))[1]
|
||||
@@ -108,7 +108,7 @@ def test_idempotent_replay_and_conflict():
|
||||
|
||||
|
||||
def test_idempotency_only_accepted_actions_occupy_id():
|
||||
sim = LocalSimulator([])
|
||||
sim = LocalSimulator([], robot_id="TEAM-0001")
|
||||
sim.handle("/enter", payload("enter"))
|
||||
# 未知字段:200 accepted=false,不占用 ID [题面 附件2 5.3]
|
||||
rejected = payload("m1", extra=1, position=dict(x=0, y=0), channel=1)
|
||||
@@ -118,7 +118,7 @@ def test_idempotency_only_accepted_actions_occupy_id():
|
||||
|
||||
def test_concurrent_registration_and_action_finishing_after_deadline():
|
||||
now = [0]
|
||||
sim = LocalSimulator([], clock=lambda: now[0])
|
||||
sim = LocalSimulator([], clock=lambda: now[0], robot_id="TEAM-0001")
|
||||
sim.handle("/enter", payload())
|
||||
started, release = Event(), Event()
|
||||
observe = sim._observe
|
||||
@@ -165,7 +165,7 @@ def test_concurrent_registration_and_action_finishing_after_deadline():
|
||||
|
||||
# ---------------------------------------------------------------- 校验与业务拒绝
|
||||
def test_huge_numeric_fields_return_bad_request():
|
||||
sim = LocalSimulator([])
|
||||
sim = LocalSimulator([], robot_id="TEAM-0001")
|
||||
sim.handle("/enter", payload())
|
||||
huge = 10 ** 400
|
||||
assert sim.handle("/measure", measure(x=huge))[0] == 400
|
||||
@@ -176,21 +176,21 @@ def test_huge_numeric_fields_return_bad_request():
|
||||
|
||||
|
||||
@pytest.mark.parametrize("body,expect", [
|
||||
(dict(arena_id="default", robot_id="2026001", request_id="e", extra=1), False),
|
||||
(dict(arena_id="other", robot_id="2026001", request_id="e"), False),
|
||||
(dict(arena_id="default", robot_id="TEAM-0001", request_id="e", extra=1), False),
|
||||
(dict(arena_id="other", robot_id="TEAM-0001", request_id="e"), False),
|
||||
(dict(arena_id="default", robot_id="someone-else", request_id="e"), False),
|
||||
])
|
||||
# pytest 参数化保留 expect 列(用例矩阵可读性),当前断言恒为 False,故不参与断言
|
||||
# pylint: disable-next=unused-argument
|
||||
def test_unknown_fields_and_mismatch_are_business_rejected(body, expect):
|
||||
sim = LocalSimulator([])
|
||||
sim = LocalSimulator([], robot_id="TEAM-0001")
|
||||
status, response = sim.handle("/enter", body)
|
||||
assert status == 200 and response["accepted"] is False
|
||||
assert response["virtual_time_s"] == 0
|
||||
|
||||
|
||||
def test_channel_and_position_validation():
|
||||
sim = LocalSimulator([])
|
||||
sim = LocalSimulator([], robot_id="TEAM-0001")
|
||||
sim.handle("/enter", payload())
|
||||
cases = [
|
||||
dict(position=dict(x=0, y=0), channel=0),
|
||||
@@ -210,7 +210,7 @@ def test_channel_and_position_validation():
|
||||
|
||||
|
||||
def test_actions_before_enter_are_business_rejected():
|
||||
sim = LocalSimulator([])
|
||||
sim = LocalSimulator([], robot_id="TEAM-0001")
|
||||
for path, body in [("/measure", measure()),
|
||||
("/clear", payload("c", position=dict(x=0, y=0), channel=1)),
|
||||
("/exit", payload("x"))]:
|
||||
@@ -220,7 +220,7 @@ def test_actions_before_enter_are_business_rejected():
|
||||
|
||||
def test_clear_rules():
|
||||
sim = LocalSimulator([Source(5, 10, 0, 1500), Source(6, 15, 0, 1500, directional=True,
|
||||
heading_deg=180)])
|
||||
heading_deg=180)], robot_id="TEAM-0001")
|
||||
sim.handle("/enter", payload())
|
||||
# 20m 内清除成功,且与定向朝向无关(源6 朝向 180°,机器人从西侧接近仍可清除)
|
||||
ok = sim.handle("/clear", payload("c5", position=dict(x=25, y=0), channel=5))[1]
|
||||
@@ -239,7 +239,7 @@ def test_measure_observation_matrix():
|
||||
sources = [Source(1, 1000, 0, 1500), # 全向,r_eff=1500
|
||||
Source(2, 100, 0, 1500, directional=True, heading_deg=0), # 定向朝东
|
||||
Source(3, 5000, 0, 1500)]
|
||||
sim = LocalSimulator(sources, error_half_deg=0.0)
|
||||
sim = LocalSimulator(sources, error_half_deg=0.0, robot_id="TEAM-0001")
|
||||
sim.handle("/enter", payload("enter"))
|
||||
# 超出有效接收半径
|
||||
assert sim.handle("/measure",
|
||||
@@ -264,7 +264,7 @@ def test_measure_observation_matrix():
|
||||
|
||||
|
||||
def test_svd_decimals_and_normalization():
|
||||
sim = LocalSimulator([Source(1, -10, 0, 1500)], error_half_deg=0.0)
|
||||
sim = LocalSimulator([Source(1, -10, 0, 1500)], error_half_deg=0.0, robot_id="TEAM-0001")
|
||||
sim.handle("/enter", payload())
|
||||
response = sim.handle("/measure", measure("m", 10, 0))[1]
|
||||
assert response["measure_result"] == "direction"
|
||||
@@ -272,7 +272,7 @@ def test_svd_decimals_and_normalization():
|
||||
|
||||
|
||||
def test_error_field_is_fixed_per_location():
|
||||
sim = LocalSimulator([Source(1, 1000, 0, 1500)], error_seed=7)
|
||||
sim = LocalSimulator([Source(1, 1000, 0, 1500)], error_seed=7, robot_id="TEAM-0001")
|
||||
sim.handle("/enter", payload())
|
||||
first = sim.handle("/measure", measure("m1", 500, 0))[1]["svd_deg"]
|
||||
sim.handle("/measure", measure("away", 300, 300))
|
||||
|
||||
@@ -5,7 +5,7 @@ from referee.timing import move_time
|
||||
|
||||
|
||||
def payload(request_id="e", **extra):
|
||||
return dict(arena_id="default", robot_id="2026001", request_id=request_id, **extra)
|
||||
return dict(arena_id="default", robot_id="TEAM-0001", request_id=request_id, **extra)
|
||||
|
||||
|
||||
def measure(request_id="m", x=0, y=0, channel=1):
|
||||
@@ -15,7 +15,7 @@ def measure(request_id="m", x=0, y=0, channel=1):
|
||||
def test_attachment_timing_example():
|
||||
"""附件2 第10节:(0,0)→(300,400) 检测ch1 → 原地检测ch2 → (300,0)清除ch3(未发现)
|
||||
→ 原地检测ch2 → /exit,虚拟时刻 105/111/194/199。"""
|
||||
sim = LocalSimulator([Source(3, 10_000, 10_000, 1500)]) # 远源,保证"未发现"
|
||||
sim = LocalSimulator([Source(3, 10_000, 10_000, 1500)], robot_id="TEAM-0001") # 远源,保证"未发现"
|
||||
sim.handle("/enter", payload())
|
||||
assert sim.handle("/measure", measure("m1", 300, 400))[1]["virtual_time_s"] == 105
|
||||
assert sim.handle("/measure", measure("m2", 300, 400, channel=2))[1]["virtual_time_s"] == 111
|
||||
|
||||
@@ -58,12 +58,12 @@ def test_state_idle_snapshot(webui):
|
||||
def test_start_countdown_open_abort_cycle(webui):
|
||||
referee, port = webui
|
||||
status, body = call(port, "POST", "/ui/api/start",
|
||||
{"module": "q3_practice", "robot_id": "2026001",
|
||||
{"module": "q3_practice", "robot_id": "TEAM-0001",
|
||||
"countdown_s": 0.05, "window_s": 5})
|
||||
assert status == 200 and body["started"] is True
|
||||
assert wait_until(lambda: referee.session.phase == "open")
|
||||
status, state = call(port, "GET", "/ui/api/state")
|
||||
assert state["phase"] == "open" and state["robot_id"] == "2026001"
|
||||
assert state["phase"] == "open" and state["robot_id"] == "TEAM-0001"
|
||||
assert "virtual_time_s" in state and "window_remaining_s" in state
|
||||
status, body = call(port, "POST", "/ui/api/abort", {})
|
||||
assert body["aborted"] is True
|
||||
@@ -75,12 +75,12 @@ def test_start_countdown_open_abort_cycle(webui):
|
||||
def test_start_rejects_running_session_and_bad_module(webui):
|
||||
_referee, port = webui
|
||||
call(port, "POST", "/ui/api/start",
|
||||
{"module": "q3_practice", "robot_id": "2026001", "countdown_s": 5})
|
||||
{"module": "q3_practice", "robot_id": "TEAM-0001", "countdown_s": 5})
|
||||
status, _body = call(port, "POST", "/ui/api/start",
|
||||
{"module": "q3_practice", "robot_id": "2026001"})
|
||||
{"module": "q3_practice", "robot_id": "TEAM-0001"})
|
||||
assert status == 409
|
||||
status, _body = call(port, "POST", "/ui/api/start",
|
||||
{"module": "nope", "robot_id": "2026001"})
|
||||
{"module": "nope", "robot_id": "TEAM-0001"})
|
||||
assert status == 409
|
||||
call(port, "POST", "/ui/api/abort", {})
|
||||
|
||||
@@ -98,7 +98,7 @@ def test_config_endpoints(webui):
|
||||
def test_sessions_list_and_replay_source(webui):
|
||||
referee, port = webui
|
||||
call(port, "POST", "/ui/api/start",
|
||||
{"module": "q3_practice", "robot_id": "2026001",
|
||||
{"module": "q3_practice", "robot_id": "TEAM-0001",
|
||||
"countdown_s": 0.05, "window_s": 5, "seed": 11, "source_count": 10})
|
||||
assert wait_until(lambda: referee.session.phase == "open")
|
||||
session = referee.session
|
||||
@@ -115,7 +115,7 @@ def test_sessions_list_and_replay_source(webui):
|
||||
status, data = call(port, "GET", "/ui/api/sessions")
|
||||
assert status == 200 and len(data["sessions"]) == 1
|
||||
case = data["sessions"][0]["case_code"]
|
||||
assert data["sessions"][0]["robot_id"] == "2026001"
|
||||
assert data["sessions"][0]["robot_id"] == "TEAM-0001"
|
||||
status, replay = call(port, "GET", f"/ui/api/replay?case={case}")
|
||||
assert status == 200
|
||||
kinds = [event["event"] for event in replay["events"]]
|
||||
|
||||
Reference in New Issue
Block a user