385 lines
12 KiB
C++
385 lines
12 KiB
C++
#include <glaze/glaze.hpp>
|
|
#include "facade_test.hpp"
|
|
#include "../../src/protocol/transform/facade.hpp"
|
|
#include "../../src/protocol/detail/basic_types.hpp"
|
|
|
|
namespace lsp::test
|
|
{
|
|
// 测试用结构体
|
|
struct TestPerson
|
|
{
|
|
std::string name;
|
|
int age;
|
|
};
|
|
|
|
struct TestConfig
|
|
{
|
|
std::string version;
|
|
bool enabled;
|
|
std::vector<int> ports;
|
|
};
|
|
}
|
|
|
|
// Glaze 元数据
|
|
template<>
|
|
struct glz::meta<lsp::test::TestPerson>
|
|
{
|
|
using T = lsp::test::TestPerson;
|
|
static constexpr auto value = object(
|
|
"name",
|
|
&T::name,
|
|
"age",
|
|
&T::age);
|
|
};
|
|
|
|
template<>
|
|
struct glz::meta<lsp::test::TestConfig>
|
|
{
|
|
using T = lsp::test::TestConfig;
|
|
static constexpr auto value = object(
|
|
"version",
|
|
&T::version,
|
|
"enabled",
|
|
&T::enabled,
|
|
"ports",
|
|
&T::ports);
|
|
};
|
|
|
|
namespace lsp::test
|
|
{
|
|
void FacadeTests::registerTests(TestRunner& runner)
|
|
{
|
|
// Serialize/Deserialize 测试
|
|
runner.addTest("Facade - 序列化简单结构体", testSerializeSimpleStruct);
|
|
runner.addTest("Facade - 序列化复杂结构体", testSerializeComplexStruct);
|
|
runner.addTest("Facade - 序列化LSPAny", testSerializeLSPAny);
|
|
runner.addTest("Facade - 反序列化简单结构体", testDeserializeSimpleStruct);
|
|
runner.addTest("Facade - 反序列化复杂结构体", testDeserializeComplexStruct);
|
|
runner.addTest("Facade - 反序列化无效JSON", testDeserializeInvalidJSON);
|
|
runner.addTest("Facade - 序列化反序列化往返", testSerializeDeserializeRoundtrip);
|
|
|
|
// check 命名空间测试
|
|
runner.addTest("Facade - Check IsObject", testCheckIsObject);
|
|
runner.addTest("Facade - Check IsArray", testCheckIsArray);
|
|
runner.addTest("Facade - Check IsString", testCheckIsString);
|
|
runner.addTest("Facade - Check IsNumber", testCheckIsNumber);
|
|
runner.addTest("Facade - Check IsBool", testCheckIsBool);
|
|
runner.addTest("Facade - Check IsNull", testCheckIsNull);
|
|
runner.addTest("Facade - Check 多类型检查", testCheckMultipleTypes);
|
|
|
|
// debug 命名空间测试
|
|
runner.addTest("Facade - Debug GetTypeName", testDebugGetTypeName);
|
|
runner.addTest("Facade - Debug GetIdString (int)", testDebugGetIdStringInt);
|
|
runner.addTest("Facade - Debug GetIdString (string)", testDebugGetIdStringString);
|
|
}
|
|
|
|
// ==================== Serialize/Deserialize 测试 ====================
|
|
|
|
TestResult FacadeTests::testSerializeSimpleStruct()
|
|
{
|
|
TestResult result;
|
|
result.passed = true;
|
|
|
|
TestPerson person{ "Alice", 30 };
|
|
auto json_opt = transform::Serialize(person);
|
|
|
|
assertTrue(json_opt.has_value(), "序列化应该成功");
|
|
const auto& json = json_opt.value();
|
|
assertTrue(json.find("Alice") != std::string::npos, "JSON应该包含'Alice'");
|
|
assertTrue(json.find("30") != std::string::npos, "JSON应该包含'30'");
|
|
|
|
result.message = "成功";
|
|
return result;
|
|
}
|
|
|
|
TestResult FacadeTests::testSerializeComplexStruct()
|
|
{
|
|
TestResult result;
|
|
result.passed = true;
|
|
|
|
TestConfig config{ "1.0.0", true, { 8080, 8081, 8082 } };
|
|
auto json_opt = transform::Serialize(config);
|
|
|
|
assertTrue(json_opt.has_value(), "序列化应该成功");
|
|
const auto& json = json_opt.value();
|
|
assertTrue(json.find("1.0.0") != std::string::npos, "JSON应该包含版本号");
|
|
assertTrue(json.find("true") != std::string::npos, "JSON应该包含enabled");
|
|
assertTrue(json.find("8080") != std::string::npos, "JSON应该包含端口");
|
|
|
|
result.message = "成功";
|
|
return result;
|
|
}
|
|
|
|
TestResult FacadeTests::testSerializeLSPAny()
|
|
{
|
|
TestResult result;
|
|
result.passed = true;
|
|
|
|
protocol::LSPObject obj;
|
|
obj["key"] = protocol::LSPAny(42);
|
|
obj["name"] = protocol::LSPAny("test");
|
|
protocol::LSPAny any(obj);
|
|
|
|
auto json_opt = transform::Serialize(any);
|
|
assertTrue(json_opt.has_value(), "序列化LSPAny应该成功");
|
|
|
|
result.message = "成功";
|
|
return result;
|
|
}
|
|
|
|
TestResult FacadeTests::testDeserializeSimpleStruct()
|
|
{
|
|
TestResult result;
|
|
result.passed = true;
|
|
|
|
std::string json = R"({"name":"Bob","age":25})";
|
|
auto person_opt = transform::Deserialize<TestPerson>(json);
|
|
|
|
assertTrue(person_opt.has_value(), "反序列化应该成功");
|
|
const auto& person = person_opt.value();
|
|
assertEqual(std::string("Bob"), person.name, "名字应该为'Bob'");
|
|
assertEqual(25, person.age, "年龄应该为25");
|
|
|
|
result.message = "成功";
|
|
return result;
|
|
}
|
|
|
|
TestResult FacadeTests::testDeserializeComplexStruct()
|
|
{
|
|
TestResult result;
|
|
result.passed = true;
|
|
|
|
std::string json = R"({"version":"2.0.0","enabled":false,"ports":[9000,9001,9002]})";
|
|
auto config_opt = transform::Deserialize<TestConfig>(json);
|
|
|
|
assertTrue(config_opt.has_value(), "反序列化应该成功");
|
|
const auto& config = config_opt.value();
|
|
assertEqual(std::string("2.0.0"), config.version, "版本应该为'2.0.0'");
|
|
assertEqual(false, config.enabled, "enabled应该为false");
|
|
assertEqual(size_t(3), config.ports.size(), "应该有3个端口");
|
|
assertEqual(9000, config.ports[0], "第一个端口应该为9000");
|
|
|
|
result.message = "成功";
|
|
return result;
|
|
}
|
|
|
|
TestResult FacadeTests::testDeserializeInvalidJSON()
|
|
{
|
|
TestResult result;
|
|
result.passed = true;
|
|
|
|
std::string json = R"({"invalid json syntax)";
|
|
auto person_opt = transform::Deserialize<TestPerson>(json);
|
|
|
|
assertFalse(person_opt.has_value(), "反序列化无效JSON应该失败");
|
|
|
|
result.message = "成功";
|
|
return result;
|
|
}
|
|
|
|
TestResult FacadeTests::testSerializeDeserializeRoundtrip()
|
|
{
|
|
TestResult result;
|
|
result.passed = true;
|
|
|
|
TestPerson original{ "Charlie", 35 };
|
|
|
|
auto json_opt = transform::Serialize(original);
|
|
assertTrue(json_opt.has_value(), "序列化应该成功");
|
|
|
|
auto person_opt = transform::Deserialize<TestPerson>(json_opt.value());
|
|
assertTrue(person_opt.has_value(), "反序列化应该成功");
|
|
|
|
const auto& restored = person_opt.value();
|
|
assertEqual(original.name, restored.name, "名字应该保持一致");
|
|
assertEqual(original.age, restored.age, "年龄应该保持一致");
|
|
|
|
result.message = "成功";
|
|
return result;
|
|
}
|
|
|
|
// ==================== check 命名空间测试 ====================
|
|
|
|
TestResult FacadeTests::testCheckIsObject()
|
|
{
|
|
TestResult result;
|
|
result.passed = true;
|
|
|
|
protocol::LSPObject obj;
|
|
obj["key"] = protocol::LSPAny(1);
|
|
protocol::LSPAny any(obj);
|
|
|
|
assertTrue(transform::check::IsObject(any), "应该识别为object");
|
|
|
|
protocol::LSPAny not_obj(42);
|
|
assertFalse(transform::check::IsObject(not_obj), "integer不应该识别为object");
|
|
|
|
result.message = "成功";
|
|
return result;
|
|
}
|
|
|
|
TestResult FacadeTests::testCheckIsArray()
|
|
{
|
|
TestResult result;
|
|
result.passed = true;
|
|
|
|
protocol::LSPArray arr;
|
|
arr.push_back(protocol::LSPAny(1));
|
|
protocol::LSPAny any(arr);
|
|
|
|
assertTrue(transform::check::IsArray(any), "应该识别为array");
|
|
|
|
protocol::LSPAny not_arr("string");
|
|
assertFalse(transform::check::IsArray(not_arr), "string不应该识别为array");
|
|
|
|
result.message = "成功";
|
|
return result;
|
|
}
|
|
|
|
TestResult FacadeTests::testCheckIsString()
|
|
{
|
|
TestResult result;
|
|
result.passed = true;
|
|
|
|
protocol::LSPAny any("hello");
|
|
assertTrue(transform::check::IsString(any), "应该识别为string");
|
|
|
|
protocol::LSPAny not_str(42);
|
|
assertFalse(transform::check::IsString(not_str), "integer不应该识别为string");
|
|
|
|
result.message = "成功";
|
|
return result;
|
|
}
|
|
|
|
TestResult FacadeTests::testCheckIsNumber()
|
|
{
|
|
TestResult result;
|
|
result.passed = true;
|
|
|
|
protocol::LSPAny int_any(42);
|
|
assertTrue(transform::check::IsNumber(int_any), "integer应该是数字");
|
|
|
|
protocol::LSPAny uint_any(100u);
|
|
assertTrue(transform::check::IsNumber(uint_any), "uinteger应该是数字");
|
|
|
|
protocol::LSPAny decimal_any(3.14);
|
|
assertTrue(transform::check::IsNumber(decimal_any), "decimal应该是数字");
|
|
|
|
protocol::LSPAny not_num("string");
|
|
assertFalse(transform::check::IsNumber(not_num), "string不应该是数字");
|
|
|
|
result.message = "成功";
|
|
return result;
|
|
}
|
|
|
|
TestResult FacadeTests::testCheckIsBool()
|
|
{
|
|
TestResult result;
|
|
result.passed = true;
|
|
|
|
protocol::LSPAny any(true);
|
|
assertTrue(transform::check::IsBool(any), "应该识别为bool");
|
|
|
|
protocol::LSPAny not_bool(42);
|
|
assertFalse(transform::check::IsBool(not_bool), "integer不应该识别为bool");
|
|
|
|
result.message = "成功";
|
|
return result;
|
|
}
|
|
|
|
TestResult FacadeTests::testCheckIsNull()
|
|
{
|
|
TestResult result;
|
|
result.passed = true;
|
|
|
|
protocol::LSPAny any(nullptr);
|
|
assertTrue(transform::check::IsNull(any), "应该识别为null");
|
|
|
|
protocol::LSPAny not_null(42);
|
|
assertFalse(transform::check::IsNull(not_null), "integer不应该识别为null");
|
|
|
|
result.message = "成功";
|
|
return result;
|
|
}
|
|
|
|
TestResult FacadeTests::testCheckMultipleTypes()
|
|
{
|
|
TestResult result;
|
|
result.passed = true;
|
|
|
|
// 测试一个值不能同时是多种类型
|
|
protocol::LSPAny any(42);
|
|
assertTrue(transform::check::IsNumber(any), "应该是数字");
|
|
assertFalse(transform::check::IsString(any), "不应该是字符串");
|
|
assertFalse(transform::check::IsBool(any), "不应该是布尔值");
|
|
assertFalse(transform::check::IsNull(any), "不应该是null");
|
|
assertFalse(transform::check::IsArray(any), "不应该是数组");
|
|
assertFalse(transform::check::IsObject(any), "不应该是对象");
|
|
|
|
result.message = "成功";
|
|
return result;
|
|
}
|
|
|
|
// ==================== debug 命名空间测试 ====================
|
|
|
|
TestResult FacadeTests::testDebugGetTypeName()
|
|
{
|
|
TestResult result;
|
|
result.passed = true;
|
|
|
|
protocol::LSPAny obj_any(protocol::LSPObject{});
|
|
assertEqual(std::string("LSPObject"), transform::debug::GetTypeName(obj_any), "类型名应该为'LSPObject'");
|
|
|
|
protocol::LSPAny arr_any(protocol::LSPArray{});
|
|
assertEqual(std::string("LSPArray"), transform::debug::GetTypeName(arr_any), "类型名应该为'LSPArray'");
|
|
|
|
protocol::LSPAny str_any("test");
|
|
assertEqual(std::string("string"), transform::debug::GetTypeName(str_any), "类型名应该为'string'");
|
|
|
|
protocol::LSPAny int_any(42);
|
|
assertEqual(std::string("integer"), transform::debug::GetTypeName(int_any), "类型名应该为'integer'");
|
|
|
|
protocol::LSPAny uint_any(100u);
|
|
assertEqual(std::string("uinteger"), transform::debug::GetTypeName(uint_any), "类型名应该为'uinteger'");
|
|
|
|
protocol::LSPAny decimal_any(3.14);
|
|
assertEqual(std::string("decimal"), transform::debug::GetTypeName(decimal_any), "类型名应该为'decimal'");
|
|
|
|
protocol::LSPAny bool_any(true);
|
|
assertEqual(std::string("boolean"), transform::debug::GetTypeName(bool_any), "类型名应该为'boolean'");
|
|
|
|
protocol::LSPAny null_any(nullptr);
|
|
assertEqual(std::string("null"), transform::debug::GetTypeName(null_any), "类型名应该为'null'");
|
|
|
|
result.message = "成功";
|
|
return result;
|
|
}
|
|
|
|
TestResult FacadeTests::testDebugGetIdStringInt()
|
|
{
|
|
TestResult result;
|
|
result.passed = true;
|
|
|
|
std::variant<int, std::string> id = 123;
|
|
std::string id_str = transform::debug::GetIdString(id);
|
|
assertEqual(std::string("123"), id_str, "int id应该转换为'123'");
|
|
|
|
result.message = "成功";
|
|
return result;
|
|
}
|
|
|
|
TestResult FacadeTests::testDebugGetIdStringString()
|
|
{
|
|
TestResult result;
|
|
result.passed = true;
|
|
|
|
std::variant<int, std::string> id = std::string("abc-123-def");
|
|
std::string id_str = transform::debug::GetIdString(id);
|
|
assertEqual(std::string("abc-123-def"), id_str, "string id应该保持为'abc-123-def'");
|
|
|
|
result.message = "成功";
|
|
return result;
|
|
}
|
|
|
|
} // namespace lsp::test
|