212 lines
7.1 KiB
Python
212 lines
7.1 KiB
Python
import sys
|
||
import unittest
|
||
|
||
import numpy as np
|
||
|
||
sys.path.insert(0, "/home/program/NextAgent/src")
|
||
|
||
from protocol.registry import PROTOCOL_REGISTRY, FMT_NAMES, PARSER_NAMES
|
||
from protocol.codec import CodecAdapter, IdentityCodec, EncodingError, DecodingError
|
||
from protocol.tensor_bus import TensorBus
|
||
from parsers.rule_based import RuleBasedParser
|
||
|
||
|
||
class _TestCodec(CodecAdapter):
|
||
"""测试用编解码器:fmt_id=0 (ref_tensor), parser_id=0 (ref_parser)"""
|
||
def __init__(self):
|
||
super().__init__(subnet_id="core", fmt_id=0, parser_id=0)
|
||
|
||
|
||
class _LaxCodec(CodecAdapter):
|
||
"""宽松编解码器(类似 IdentityCodec 但使用合法 id)"""
|
||
def __init__(self):
|
||
super().__init__(subnet_id="core", fmt_id=0, parser_id=0)
|
||
|
||
def _validate_prefix(self, tensor):
|
||
if tensor.shape[0] < self.prefix_len:
|
||
raise DecodingError(f"张量过短: {tensor.shape[0]} < {self.prefix_len}")
|
||
|
||
def _validate_internal(self, tensor):
|
||
if not isinstance(tensor, np.ndarray):
|
||
raise EncodingError(f"内部类型必须是 np.ndarray, 得到 {type(tensor)}")
|
||
|
||
|
||
class TestProtocolRegistry(unittest.TestCase):
|
||
|
||
def test_validate_fmt_id_valid(self):
|
||
for fid in FMT_NAMES:
|
||
PROTOCOL_REGISTRY.validate_fmt_id(fid)
|
||
|
||
def test_validate_fmt_id_invalid(self):
|
||
with self.assertRaises(ValueError):
|
||
PROTOCOL_REGISTRY.validate_fmt_id(999)
|
||
|
||
def test_validate_parser_id_valid(self):
|
||
for pid in PARSER_NAMES:
|
||
PROTOCOL_REGISTRY.validate_parser_id(pid)
|
||
|
||
def test_validate_parser_id_invalid(self):
|
||
with self.assertRaises(ValueError):
|
||
PROTOCOL_REGISTRY.validate_parser_id(999)
|
||
|
||
def test_validate_subnet_id_valid(self):
|
||
for sid in PROTOCOL_REGISTRY.subnet_ids:
|
||
PROTOCOL_REGISTRY.validate_subnet_id(sid)
|
||
|
||
def test_validate_subnet_id_invalid(self):
|
||
with self.assertRaises(ValueError):
|
||
PROTOCOL_REGISTRY.validate_subnet_id("nonexistent")
|
||
|
||
def test_fmt_name_known(self):
|
||
self.assertEqual(PROTOCOL_REGISTRY.fmt_name(0), "ref_tensor")
|
||
|
||
def test_fmt_name_unknown(self):
|
||
self.assertEqual(PROTOCOL_REGISTRY.fmt_name(999), "unknown_fmt_999")
|
||
|
||
def test_parser_name_known(self):
|
||
self.assertEqual(PROTOCOL_REGISTRY.parser_name(0), "ref_parser")
|
||
|
||
def test_parser_name_unknown(self):
|
||
self.assertEqual(PROTOCOL_REGISTRY.parser_name(999),
|
||
"unknown_parser_999")
|
||
|
||
|
||
class TestCodecAdapter(unittest.TestCase):
|
||
|
||
def test_encode_decode_roundtrip(self):
|
||
codec = _TestCodec()
|
||
payload = np.array([1.0, 2.0, 3.0, 4.0])
|
||
comm = codec.encode(payload, target="routing", reply_req=True)
|
||
decoded = codec.decode(comm)
|
||
np.testing.assert_array_equal(decoded, payload)
|
||
|
||
def test_encode_raises_on_non_ndarray(self):
|
||
codec = _TestCodec()
|
||
with self.assertRaises(EncodingError):
|
||
codec.encode([1, 2, 3], target="routing", reply_req=True)
|
||
|
||
def test_decode_raises_on_short_tensor(self):
|
||
codec = _TestCodec()
|
||
short = np.array([0.0])
|
||
with self.assertRaises(DecodingError):
|
||
codec.decode(short)
|
||
|
||
def test_decode_raises_on_wrong_fmt_id(self):
|
||
codec = _TestCodec()
|
||
wrong = np.array([99.0, 0.0, 1.0, 2.0])
|
||
with self.assertRaises(DecodingError):
|
||
codec.decode(wrong)
|
||
|
||
|
||
class TestLaxCodec(unittest.TestCase):
|
||
|
||
def test_encode_decode_roundtrip(self):
|
||
codec = _LaxCodec()
|
||
payload = np.array([10.0, 20.0, 30.0])
|
||
comm = codec.encode(payload, target="core", reply_req=False)
|
||
decoded = codec.decode(comm)
|
||
np.testing.assert_array_equal(decoded, payload)
|
||
|
||
def test_decode_allows_any_prefix(self):
|
||
codec = _LaxCodec()
|
||
comm = np.array([99.0, 99.0, 42.0])
|
||
decoded = codec.decode(comm)
|
||
np.testing.assert_array_equal(decoded, np.array([42.0]))
|
||
|
||
def test_decode_raises_on_short_tensor(self):
|
||
codec = _LaxCodec()
|
||
with self.assertRaises(DecodingError):
|
||
codec.decode(np.array([0.0]))
|
||
|
||
def test_encode_raises_on_non_ndarray(self):
|
||
codec = _LaxCodec()
|
||
with self.assertRaises(EncodingError):
|
||
codec.encode("bad", target="core", reply_req=True)
|
||
|
||
|
||
class TestRuleBasedParser(unittest.TestCase):
|
||
|
||
def setUp(self):
|
||
self.parser = RuleBasedParser()
|
||
|
||
def test_ref_tensor(self):
|
||
tensor = np.array([0.0, 0.0, 5.0, 1.0, 2.0, 3.0])
|
||
result = self.parser.parse(tensor)
|
||
self.assertEqual(result, "引用张量: 5个标签")
|
||
|
||
def test_memory_result(self):
|
||
tensor = np.array([1.0, 1.0, 3.0, 7.0])
|
||
result = self.parser.parse(tensor)
|
||
self.assertEqual(result, "记忆结果: 3个实体, 7条关系")
|
||
|
||
def test_memory_query(self):
|
||
tensor = np.array([2.0, 2.0, 1.0, 2.0, 3.0])
|
||
result = self.parser.parse(tensor)
|
||
self.assertEqual(result, "记忆查询")
|
||
|
||
def test_memory_update(self):
|
||
tensor = np.array([3.0, 3.0, 2.0, 4.0])
|
||
result = self.parser.parse(tensor)
|
||
self.assertEqual(result, "记忆更新: 2个实体, 4条关系")
|
||
|
||
def test_reasoning_path(self):
|
||
tensor = np.array([4.0, 4.0, 6.0])
|
||
result = self.parser.parse(tensor)
|
||
self.assertEqual(result, "推理路径: 6步")
|
||
|
||
def test_expression_verify(self):
|
||
tensor = np.zeros(2 + 769)
|
||
tensor[0] = 5.0
|
||
tensor[1] = 5.0
|
||
tensor[2 + 768] = 0.85
|
||
result = self.parser.parse(tensor)
|
||
self.assertEqual(result, "表达验证: 意图对齐度=0.85")
|
||
|
||
def test_control(self):
|
||
tensor = np.array([6.0, 6.0])
|
||
result = self.parser.parse(tensor)
|
||
self.assertEqual(result, "控制信号")
|
||
|
||
def test_short_tensor(self):
|
||
tensor = np.array([0.0])
|
||
result = self.parser.parse(tensor)
|
||
self.assertIn("过短", result)
|
||
|
||
|
||
class TestTensorBus(unittest.TestCase):
|
||
|
||
def setUp(self):
|
||
self.bus = TensorBus()
|
||
self.codec_a = _TestCodec()
|
||
self.codec_b = _LaxCodec()
|
||
self.bus.register("routing", self.codec_a)
|
||
self.bus.register("core", self.codec_b)
|
||
|
||
def test_register_and_send(self):
|
||
payload = np.array([7.0, 8.0, 9.0])
|
||
result = self.bus.send(payload, source="routing", target="core")
|
||
np.testing.assert_array_equal(result, payload)
|
||
|
||
def test_recv(self):
|
||
payload = np.array([1.0, 2.0])
|
||
comm = self.codec_a.encode(payload, target="routing", reply_req=True)
|
||
result = self.bus.recv("routing", comm)
|
||
np.testing.assert_array_equal(result, payload)
|
||
|
||
def test_send_unregistered_source(self):
|
||
with self.assertRaises(KeyError):
|
||
self.bus.send(np.array([1.0]), source="nonexistent", target="core")
|
||
|
||
def test_send_unregistered_target(self):
|
||
with self.assertRaises(KeyError):
|
||
self.bus.send(np.array([1.0]), source="routing",
|
||
target="nonexistent")
|
||
|
||
def test_recv_unregistered_source(self):
|
||
with self.assertRaises(KeyError):
|
||
self.bus.recv("nonexistent", np.array([1.0, 2.0]))
|
||
|
||
|
||
if __name__ == "__main__":
|
||
unittest.main()
|