// 小周天/烛照/洛书/河图模块测试。 #include #include #include #include "hunjing/lingtai.h" namespace { struct Engine { HjEngine *ptr = nullptr; Engine() { REQUIRE(hj_engine_new(HJ_ABI_VERSION, &ptr) == HJ_OK); } ~Engine() { hj_engine_free(ptr); } }; std::string buffer_text(HjBuffer *buf) { std::string out(static_cast(hj_buffer_data(buf)), hj_buffer_len(buf)); hj_buffer_free(buf); return out; } } // namespace TEST_CASE("小周天:delta envelope 确定性编码与序号单调") { Engine e; HjStream *stream = nullptr; REQUIRE(hj_stream_new(e.ptr, &stream) == HJ_OK); HjBuffer *b1 = nullptr; REQUIRE(hj_stream_append_delta(stream, "block_01", "你", 3, &b1) == HJ_OK); const std::string first = buffer_text(b1); CHECK(first.find("\"type\":\"content.block.delta\"") != std::string::npos); CHECK(first.find("\"sequence\":0") != std::string::npos); CHECK(first.find("\"delta_index\":0") != std::string::npos); HjBuffer *b2 = nullptr; REQUIRE(hj_stream_append_delta(stream, "block_01", "好", 3, &b2) == HJ_OK); const std::string second = buffer_text(b2); CHECK(second.find("\"sequence\":1") != std::string::npos); CHECK(second.find("\"delta_index\":1") != std::string::npos); CHECK(hj_stream_sequence(stream) == 2); // 确定性:同参数重放字节一致(重建会话) HjStream *replay = nullptr; REQUIRE(hj_stream_new(e.ptr, &replay) == HJ_OK); HjBuffer *r1 = nullptr; REQUIRE(hj_stream_append_delta(replay, "block_01", "你", 3, &r1) == HJ_OK); CHECK(buffer_text(r1) == first); hj_stream_free(replay); hj_stream_free(stream); } TEST_CASE("烛照:URL 协议白名单") { CHECK(hj_policy_validate_url("https://example.com/a") == HJ_OK); CHECK(hj_policy_validate_url("http://example.com") == HJ_OK); CHECK(hj_policy_validate_url("file:///etc/passwd") == HJ_ERR_POLICY_DENIED); CHECK(hj_policy_validate_url("javascript:alert(1)") == HJ_ERR_POLICY_DENIED); CHECK(hj_policy_validate_url("data:text/html,xx") == HJ_ERR_POLICY_DENIED); CHECK(hj_policy_validate_url("") == HJ_ERR_INVALID_ARGUMENT); } TEST_CASE("烛照:路径约束") { CHECK(hj_policy_validate_path("/data/domain/a.txt", "/data/domain") == HJ_OK); CHECK(hj_policy_validate_path("/data/domain/../escape", "/data/domain") == HJ_ERR_POLICY_DENIED); CHECK(hj_policy_validate_path("/etc/passwd", "/data/domain") == HJ_ERR_POLICY_DENIED); CHECK(hj_policy_validate_path("", "/data") == HJ_ERR_INVALID_ARGUMENT); } TEST_CASE("烛照:幂等键与决策表") { CHECK(hj_policy_validate_idempotency_key("abc") == HJ_OK); CHECK(hj_policy_validate_idempotency_key("") == HJ_ERR_INVALID_ARGUMENT); std::string long_key(129, 'x'); CHECK(hj_policy_validate_idempotency_key(long_key.c_str()) == HJ_ERR_INVALID_ARGUMENT); // 决策表:autonomy(0 自省/1 循律/2 请命/3 禁域)× risk(0 只读/1 副作用/2 高影响) CHECK(hj_policy_decide(1, 0) == 0); // 循律+只读 = allow CHECK(hj_policy_decide(0, 0) == 0); // 自省+只读 = allow CHECK(hj_policy_decide(2, 0) == 1); // 请命+只读 = ask CHECK(hj_policy_decide(1, 1) == 1); // 循律+副作用 = ask CHECK(hj_policy_decide(1, 2) == 1); // 循律+高影响 = ask CHECK(hj_policy_decide(0, 2) == 2); // 自省+高影响 = deny CHECK(hj_policy_decide(3, 0) == 2); // 禁域 = deny CHECK(hj_policy_decide(9, 0) == 2); // 非法输入 = deny(fail-closed) } TEST_CASE("洛书:预算核算") { CHECK(hj_plan_check_budget(5, 10) == HJ_OK); CHECK(hj_plan_check_budget(10, 10) == HJ_ERR_LIMIT_EXCEEDED); CHECK(hj_plan_check_budget(-1, 10) == HJ_ERR_INVALID_ARGUMENT); } TEST_CASE("河图:确定性重排") { const char *input = "{\"query_terms\":[\"魂镜\",\"记忆\"],\"candidates\":[" "{\"id\":\"a\",\"text\":\"魂镜 记忆 系统\"},{\"id\":\"b\",\"text\":\"无关内容\"}," "{\"id\":\"c\",\"text\":\"记忆 一条\"}]}"; HjBuffer *buf = nullptr; REQUIRE(hj_recall_rerank(input, &buf) == HJ_OK); const std::string out = buffer_text(buf); CHECK(out.find("{\"id\":\"a\",\"score\":20}") != std::string::npos); CHECK(out.find("{\"id\":\"c\",\"score\":10}") != std::string::npos); CHECK(out.find("{\"id\":\"b\",\"score\":0}") != std::string::npos); CHECK(out.find("\"a\"") < out.find("\"c\"")); HjBuffer *again = nullptr; REQUIRE(hj_recall_rerank(input, &again) == HJ_OK); CHECK(buffer_text(again) == out); HjBuffer *bad = nullptr; CHECK(hj_recall_rerank("not json", &bad) == HJ_ERR_PARSE_FAILED); }