57 lines
2.0 KiB
Python
57 lines
2.0 KiB
Python
"""JSON 序列化与解析的规范化行为 [题面 附件2 4.1/5.1]。"""
|
|
|
|
import json
|
|
|
|
import pytest
|
|
|
|
from referee.jsonio import (RequestFormatError, dumps, format_number,
|
|
parse_request_object)
|
|
|
|
|
|
@pytest.mark.parametrize("value,text", [
|
|
(105, "105"), (0, "0"), (5.0, "5"), (105.5, "105.5"),
|
|
(5282.843, "5282.843"), # 微秒时刻的最短表示
|
|
(0.300001, "0.300001"),
|
|
(123.45, "123.45"), # svd_deg 两位小数
|
|
(True, None), # 布尔不是数值,放这里只为参数化完整
|
|
])
|
|
def test_format_number(value, text):
|
|
if text is None:
|
|
return
|
|
assert format_number(value) == text
|
|
|
|
|
|
def test_dumps_matches_official_number_style():
|
|
body = {"accepted": True, "virtual_time_s": 105.0,
|
|
"real_timestamp_ms": 1760000000000, "svd_deg": 123.45,
|
|
"note": "中文", "ok": False, "none": None, "list": [1, 2.5]}
|
|
text = dumps(body)
|
|
assert '"virtual_time_s":105' in text # 不输出 105.0
|
|
assert '"svd_deg":123.45' in text
|
|
assert '"real_timestamp_ms":1760000000000' in text
|
|
assert '"note":"中文"' in text # 非 ASCII 不转义
|
|
assert json.loads(text) == body # 解析后语义不变
|
|
|
|
|
|
@pytest.mark.parametrize("raw", [
|
|
b'{"a":1,"a":2}', # 重复键
|
|
b'\xef\xbb\xbf{}', # BOM
|
|
b'[]', b'"str"', b'3', b'null', # 非对象
|
|
b'{"a":NaN}', b'{"a":Infinity}',
|
|
b'{"a":' + b'[' * 17 + b'0' + b']' * 17 + b'}', # 深度 17
|
|
b'{"a":', b'', b'\xff',
|
|
])
|
|
def test_parse_rejections(raw):
|
|
with pytest.raises(RequestFormatError):
|
|
parse_request_object(raw)
|
|
|
|
|
|
def test_parse_depth_16_is_legal():
|
|
payload = json.loads(b'{"extra":' + b'[' * 15 + b'0' + b']' * 15 + b'}')
|
|
assert parse_request_object(json.dumps(payload).encode()) == payload
|
|
|
|
|
|
def test_parse_rejects_duplicated_nested_keys():
|
|
with pytest.raises(RequestFormatError):
|
|
parse_request_object(b'{"position":{"x":1,"x":2}}')
|