339 lines
13 KiB
Python
339 lines
13 KiB
Python
import t, c
|
||
from stdint import *
|
||
from stdio import printf
|
||
import mpool
|
||
import json
|
||
import string
|
||
import w32.win32memory as win32mem
|
||
|
||
# ============================================================
|
||
# 测试计数器
|
||
# ============================================================
|
||
_pass_count: t.CInt = 0
|
||
_fail_count: t.CInt = 0
|
||
|
||
def check(name: t.CChar | t.CPtr, condition: bool):
|
||
global _pass_count, _fail_count
|
||
if condition:
|
||
_pass_count += 1
|
||
printf(" [PASS] %s\n", name)
|
||
else:
|
||
_fail_count += 1
|
||
printf(" [FAIL] %s\n", name)
|
||
|
||
|
||
# ============================================================
|
||
# 测试 1:构造 JSON 值(使用 mpool)
|
||
# ============================================================
|
||
def test_construct(pool: mpool.MPool | t.CPtr):
|
||
printf("\n+-- Construct JsonValue (with mpool) --+\n")
|
||
|
||
# null
|
||
v1: json.JsonValue | t.CPtr = json.null(pool)
|
||
check("null is_null", v1.is_null())
|
||
|
||
# bool
|
||
v2: json.JsonValue | t.CPtr = json.bool_val(pool, True)
|
||
check("bool true is_bool", v2.is_bool())
|
||
check("bool true as_bool", v2.as_bool())
|
||
|
||
v3: json.JsonValue | t.CPtr = json.bool_val(pool, False)
|
||
check("bool false !as_bool", not v3.as_bool())
|
||
|
||
# int
|
||
v4: json.JsonValue | t.CPtr = json.int_val(pool, 42)
|
||
check("int is_int", v4.is_int())
|
||
check("int 42 == 42", v4.as_int() == 42)
|
||
|
||
v5: json.JsonValue | t.CPtr = json.int_val(pool, -100)
|
||
check("int -100 == -100", v5.as_int() == -100)
|
||
|
||
# float
|
||
v6: json.JsonValue | t.CPtr = json.float_val(pool, 3.14)
|
||
check("float is_float", v6.is_float())
|
||
check("float 3.14 ~= 3.14", v6.as_float() > 3.13 and v6.as_float() < 3.15)
|
||
|
||
# string
|
||
v7: json.JsonValue | t.CPtr = json.string_val(pool, "hello")
|
||
check("string is_string", v7.is_string())
|
||
check("string == hello", string.strcmp(v7.as_string(), "hello") == 0)
|
||
|
||
# array
|
||
v8: json.JsonValue | t.CPtr = json.array(pool)
|
||
check("array is_array", v8.is_array())
|
||
check("array empty len()==0", len(v8) == 0)
|
||
|
||
# object
|
||
v9: json.JsonValue | t.CPtr = json.object(pool)
|
||
check("object is_object", v9.is_object())
|
||
check("object empty len()==0", len(v9) == 0)
|
||
|
||
printf("+--------------------------------------------+\n")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 2:构造数组和对象(Python风格API)
|
||
# ============================================================
|
||
def test_build_structures(pool: mpool.MPool | t.CPtr):
|
||
printf("\n+-- Build Arrays and Objects (Pythonic API) --+\n")
|
||
|
||
# 构建数组 [1, 2, 3]
|
||
arr: json.JsonValue | t.CPtr = json.array(pool)
|
||
json.array_append(pool, arr, json.int_val(pool, 1))
|
||
json.array_append(pool, arr, json.int_val(pool, 2))
|
||
json.array_append(pool, arr, json.int_val(pool, 3))
|
||
check("array [1,2,3] len()==3", len(arr) == 3)
|
||
check("array get_item(0)==1", arr.get_item(0).as_int() == 1)
|
||
check("array get_item(1)==2", arr.get_item(1).as_int() == 2)
|
||
check("array get_item(2)==3", arr.get_item(2).as_int() == 3)
|
||
|
||
# 构建对象 {"name": "Viper", "version": 1}
|
||
obj: json.JsonValue | t.CPtr = json.object(pool)
|
||
json.object_set(pool, obj, "name", json.string_val(pool, "Viper"))
|
||
json.object_set(pool, obj, "version", json.int_val(pool, 1))
|
||
check("object len()==2", len(obj) == 2)
|
||
|
||
# Python风格取值:obj["key"]
|
||
name_val: json.JsonValue | t.CPtr = obj["name"]
|
||
check("obj['name']==Viper", name_val != None and string.strcmp(name_val.as_string(), "Viper") == 0)
|
||
ver_val: json.JsonValue | t.CPtr = obj["version"]
|
||
check("obj['version']==1", ver_val != None and ver_val.as_int() == 1)
|
||
missing: json.JsonValue | t.CPtr = obj["missing"]
|
||
check("obj['missing']==None", missing == None)
|
||
|
||
printf("+--------------------------------------------+\n")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 3:JSON 解析
|
||
# ============================================================
|
||
def test_parse(pool: mpool.MPool | t.CPtr):
|
||
printf("\n+-- Parse JSON --+\n")
|
||
|
||
# 解析整数
|
||
v1: json.JsonValue | t.CPtr = json.parse(pool, "42")
|
||
check("parse int is_int", v1.is_int())
|
||
check("parse int == 42", v1.as_int() == 42)
|
||
|
||
# 解析负数
|
||
v2: json.JsonValue | t.CPtr = json.parse(pool, "-7")
|
||
check("parse neg int == -7", v2.as_int() == -7)
|
||
|
||
# 解析浮点数
|
||
v3: json.JsonValue | t.CPtr = json.parse(pool, "3.14")
|
||
check("parse float is_float", v3.is_float())
|
||
check("parse float ~= 3.14", v3.as_float() > 3.13 and v3.as_float() < 3.15)
|
||
|
||
# 解析字符串
|
||
v4: json.JsonValue | t.CPtr = json.parse(pool, '"hello world"')
|
||
check("parse string is_string", v4.is_string())
|
||
check("parse string == hello world", string.strcmp(v4.as_string(), "hello world") == 0)
|
||
|
||
# 解析布尔
|
||
v5: json.JsonValue | t.CPtr = json.parse(pool, "true")
|
||
check("parse true is_bool", v5.is_bool())
|
||
check("parse true as_bool", v5.as_bool())
|
||
|
||
v6: json.JsonValue | t.CPtr = json.parse(pool, "false")
|
||
check("parse false !as_bool", not v6.as_bool())
|
||
|
||
# 解析 null
|
||
v7: json.JsonValue | t.CPtr = json.parse(pool, "null")
|
||
check("parse null is_null", v7.is_null())
|
||
|
||
# 解析数组
|
||
v8: json.JsonValue | t.CPtr = json.parse(pool, "[1, 2, 3]")
|
||
check("parse array is_array", v8.is_array())
|
||
check("parse array len()==3", len(v8) == 3)
|
||
check("parse array get_item(0)==1", v8.get_item(0).as_int() == 1)
|
||
check("parse array get_item(2)==3", v8.get_item(2).as_int() == 3)
|
||
|
||
# 解析对象(Python风格取值)
|
||
v9: json.JsonValue | t.CPtr = json.parse(pool, '{"x": 10, "y": 20}')
|
||
check("parse object is_object", v9.is_object())
|
||
check("parse object len()==2", len(v9) == 2)
|
||
x_val: json.JsonValue | t.CPtr = v9["x"]
|
||
check("parse obj['x']==10", x_val != None and x_val.as_int() == 10)
|
||
y_val: json.JsonValue | t.CPtr = v9["y"]
|
||
check("parse obj['y']==20", y_val != None and y_val.as_int() == 20)
|
||
|
||
printf("+--------------------------------------------+\n")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 4:JSON 序列化
|
||
# ============================================================
|
||
def test_write(pool: mpool.MPool | t.CPtr):
|
||
printf("\n+-- Write JSON --+\n")
|
||
|
||
# 写整数
|
||
v1: json.JsonValue | t.CPtr = json.int_val(pool, 42)
|
||
s1: t.CChar | t.CPtr = json.write(pool, v1, False)
|
||
check("write int 42", string.strcmp(s1, "42") == 0)
|
||
|
||
# 写字符串
|
||
v2: json.JsonValue | t.CPtr = json.string_val(pool, "hello")
|
||
s2: t.CChar | t.CPtr = json.write(pool, v2, False)
|
||
check("write string hello", string.strcmp(s2, '"hello"') == 0)
|
||
|
||
# 写布尔
|
||
v3: json.JsonValue | t.CPtr = json.bool_val(pool, True)
|
||
s3: t.CChar | t.CPtr = json.write(pool, v3, False)
|
||
check("write bool true", string.strcmp(s3, "true") == 0)
|
||
|
||
v4: json.JsonValue | t.CPtr = json.bool_val(pool, False)
|
||
s4: t.CChar | t.CPtr = json.write(pool, v4, False)
|
||
check("write bool false", string.strcmp(s4, "false") == 0)
|
||
|
||
# 写 null
|
||
v5: json.JsonValue | t.CPtr = json.null(pool)
|
||
s5: t.CChar | t.CPtr = json.write(pool, v5, False)
|
||
check("write null", string.strcmp(s5, "null") == 0)
|
||
|
||
# 写数组
|
||
arr: json.JsonValue | t.CPtr = json.array(pool)
|
||
json.array_append(pool, arr, json.int_val(pool, 1))
|
||
json.array_append(pool, arr, json.int_val(pool, 2))
|
||
json.array_append(pool, arr, json.int_val(pool, 3))
|
||
s6: t.CChar | t.CPtr = json.write(pool, arr, False)
|
||
check("write array [1,2,3]", string.strcmp(s6, "[1,2,3]") == 0)
|
||
|
||
# 写对象
|
||
obj: json.JsonValue | t.CPtr = json.object(pool)
|
||
json.object_set(pool, obj, "a", json.int_val(pool, 1))
|
||
json.object_set(pool, obj, "b", json.string_val(pool, "x"))
|
||
s7: t.CChar | t.CPtr = json.write(pool, obj, False)
|
||
check("write object non-null", s7 != None)
|
||
|
||
printf("+--------------------------------------------+\n")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 5:解析复杂嵌套 JSON(Python风格API)
|
||
# ============================================================
|
||
def test_nested(pool: mpool.MPool | t.CPtr):
|
||
printf("\n+-- Parse Nested JSON (Pythonic API) --+\n")
|
||
|
||
src: t.CChar | t.CPtr = '{"name": "Viper", "version": 1, "features": ["fast", "safe", "portable"], "nested": {"key": "value", "num": 99}}'
|
||
root: json.JsonValue | t.CPtr = json.parse(pool, src)
|
||
check("nested is_object", root.is_object())
|
||
check("nested len()==4", len(root) == 4)
|
||
|
||
# Python风格取值:root["name"]
|
||
name: json.JsonValue | t.CPtr = root["name"]
|
||
check("root['name']==Viper", name != None and string.strcmp(name.as_string(), "Viper") == 0)
|
||
|
||
# root["version"]
|
||
ver: json.JsonValue | t.CPtr = root["version"]
|
||
check("root['version']==1", ver != None and ver.as_int() == 1)
|
||
|
||
# root["features"] 数组
|
||
feat: json.JsonValue | t.CPtr = root["features"]
|
||
check("root['features'] is_array", feat != None and feat.is_array())
|
||
check("root['features'] len()==3", feat != None and len(feat) == 3)
|
||
check("root['features'][0]==fast", feat != None and string.strcmp(feat.get_item(0).as_string(), "fast") == 0)
|
||
check("root['features'][2]==portable", feat != None and string.strcmp(feat.get_item(2).as_string(), "portable") == 0)
|
||
|
||
# root["nested"] 对象
|
||
nested: json.JsonValue | t.CPtr = root["nested"]
|
||
check("root['nested'] is_object", nested != None and nested.is_object())
|
||
nk: json.JsonValue | t.CPtr = nested["key"] if nested != None else None
|
||
check("root['nested']['key']==value", nk != None and string.strcmp(nk.as_string(), "value") == 0)
|
||
nn: json.JsonValue | t.CPtr = nested["num"] if nested != None else None
|
||
check("root['nested']['num']==99", nn != None and nn.as_int() == 99)
|
||
|
||
printf("+--------------------------------------------+\n")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 6:mpool 重置后重新使用
|
||
# ============================================================
|
||
def test_mpool_reuse():
|
||
printf("\n+-- MPool Reuse --+\n")
|
||
|
||
# 分配内存
|
||
mem: t.CVoid | t.CPtr = win32mem.VirtualAlloc(t.CVoid(0, t.CPtr), 8192, 0x3000, 0x04)
|
||
check("VirtualAlloc ok", mem != None)
|
||
|
||
pool: mpool.MPool | t.CPtr = mpool.MPool(mem, 8192, 0)
|
||
|
||
# 第一次使用
|
||
v1: json.JsonValue | t.CPtr = json.int_val(pool, 100)
|
||
check("reuse round1 int==100", v1.as_int() == 100)
|
||
|
||
# 重置 mpool
|
||
pool.reset()
|
||
|
||
# 第二次使用(内存复用)
|
||
v2: json.JsonValue | t.CPtr = json.string_val(pool, "reused")
|
||
check("reuse round2 string==reused", string.strcmp(v2.as_string(), "reused") == 0)
|
||
|
||
# 重置后再解析
|
||
pool.reset()
|
||
v3: json.JsonValue | t.CPtr = json.parse(pool, '{"test": true}')
|
||
check("reuse round3 parse ok", v3.is_object())
|
||
tv: json.JsonValue | t.CPtr = v3["test"]
|
||
check("reuse round3 obj['test']==true", tv != None and tv.as_bool())
|
||
|
||
win32mem.VirtualFree(mem, 0, 0x8000)
|
||
printf("+--------------------------------------------+\n")
|
||
|
||
|
||
# ============================================================
|
||
# 测试 7:转义字符解析
|
||
# ============================================================
|
||
def test_escape(pool: mpool.MPool | t.CPtr):
|
||
printf("\n+-- Escape Characters --+\n")
|
||
|
||
# 解析含转义字符的字符串
|
||
v1: json.JsonValue | t.CPtr = json.parse(pool, '"hello\\nworld"')
|
||
check("escape \\n is_string", v1.is_string())
|
||
sv1: t.CChar | t.CPtr = v1.as_string()
|
||
check("escape \\n contains newline", sv1 != None and sv1[5] == '\n')
|
||
|
||
v2: json.JsonValue | t.CPtr = json.parse(pool, '"tab\\there"')
|
||
check("escape \\t is_string", v2.is_string())
|
||
sv2: t.CChar | t.CPtr = v2.as_string()
|
||
check("escape \\t contains tab", sv2 != None and sv2[3] == '\t')
|
||
|
||
v3: json.JsonValue | t.CPtr = json.parse(pool, '"quote\\""')
|
||
check("escape \\\" is_string", v3.is_string())
|
||
|
||
printf("+--------------------------------------------+\n")
|
||
|
||
|
||
# ============================================================
|
||
# 主函数
|
||
# ============================================================
|
||
def main() -> t.CInt | t.CExport:
|
||
printf("=== JSON Library Test (Pythonic API) ===\n")
|
||
|
||
# 使用 mpool 的 bump 分配器
|
||
mem: t.CVoid | t.CPtr = win32mem.VirtualAlloc(t.CVoid(0, t.CPtr), 65536, 0x3000, 0x04)
|
||
pool: mpool.MPool | t.CPtr = mpool.MPool(mem, 65536, 0)
|
||
|
||
test_construct(pool)
|
||
pool.reset()
|
||
|
||
test_build_structures(pool)
|
||
pool.reset()
|
||
|
||
test_parse(pool)
|
||
pool.reset()
|
||
|
||
test_write(pool)
|
||
pool.reset()
|
||
|
||
test_nested(pool)
|
||
pool.reset()
|
||
|
||
test_escape(pool)
|
||
pool.reset()
|
||
|
||
test_mpool_reuse()
|
||
|
||
win32mem.VirtualFree(mem, 0, 0x8000)
|
||
|
||
printf("\n=== Results: %d passed, %d failed ===\n", _pass_count, _fail_count)
|
||
return 0
|