#include #include #include "../../src/protocol/detail/basic_types.hpp" #include "./lsp_any_test.hpp" namespace lsp::test { // ==================== LSPAnyTests 实现 ==================== void LSPAnyTests::registerTests(TestRunner& runner) { // 构造函数测试 runner.addTest("默认构造函数", testDefaultConstructor); runner.addTest("浮点数构造函数", testDecimalConstructor); runner.addTest("布尔构造函数", testBooleanConstructor); runner.addTest("字符串构造函数", testStringConstructor); runner.addTest("C字符串构造函数", testCStringConstructor); runner.addTest("空指针构造函数", testNullptrConstructor); runner.addTest("LSPObject构造函数", testLSPObjectConstructor); runner.addTest("LSPArray构造函数", testLSPArrayConstructor); // 拷贝和移动测试 runner.addTest("拷贝构造函数", testCopyConstructor); runner.addTest("移动构造函数", testMoveConstructor); runner.addTest("拷贝赋值", testCopyAssignment); runner.addTest("移动赋值", testMoveAssignment); // 赋值操作符测试 runner.addTest("浮点数赋值", testDecimalAssignment); runner.addTest("布尔赋值", testBooleanAssignment); runner.addTest("字符串赋值", testStringAssignment); runner.addTest("空指针赋值", testNullptrAssignment); runner.addTest("LSPObject赋值", testLSPObjectAssignment); runner.addTest("LSPArray赋值", testLSPArrayAssignment); // 类型检查测试 runner.addTest("Is类型检查", testIsMethod); runner.addTest("Get获取值", testGetMethod); // 访问者模式测试 runner.addTest("Visit访问者", testVisitMethod); // 整数模板测试 runner.addTest("有符号整数模板", testIntegerTemplateSignedTypes); runner.addTest("无符号整数模板", testIntegerTemplateUnsignedTypes); runner.addTest("整数边界测试", testIntegerTemplateBoundaries); // 复杂场景测试 runner.addTest("嵌套LSPObject", testNestedLSPObject); runner.addTest("嵌套LSPArray", testNestedLSPArray); runner.addTest("混合嵌套", testMixedNesting); runner.addTest("类型转换", testTypeConversion); // 边界情况测试 runner.addTest("浮点精度", testFloatPrecision); runner.addTest("大数字", testLargeNumbers); runner.addTest("空容器", testEmptyContainers); } // ==================== 构造函数测试 ==================== TestResult LSPAnyTests::testDefaultConstructor() { TestResult result; result.passed = true; protocol::LSPAny any; assertTrue(any.Is(), "默认构造应该是nullptr类型"); result.message = "成功"; return result; } TestResult LSPAnyTests::testDecimalConstructor() { TestResult result; result.passed = true; protocol::decimal value = 3.14; protocol::LSPAny any(value); assertTrue(any.Is(), "应该是decimal类型"); assertEqual(value, any.Get(), "值应该相等"); // 测试 float 构造 float fValue = 2.5f; protocol::LSPAny anyFloat(fValue); assertTrue(anyFloat.Is(), "float应该转为decimal类型"); result.message = "成功"; return result; } TestResult LSPAnyTests::testBooleanConstructor() { TestResult result; result.passed = true; protocol::LSPAny anyTrue(true); protocol::LSPAny anyFalse(false); assertTrue(anyTrue.Is(), "应该是boolean类型"); assertTrue(anyFalse.Is(), "应该是boolean类型"); assertEqual(true, anyTrue.Get(), "值应该是true"); assertEqual(false, anyFalse.Get(), "值应该是false"); result.message = "成功"; return result; } TestResult LSPAnyTests::testStringConstructor() { TestResult result; result.passed = true; protocol::string value = "Hello, LSP!"; protocol::LSPAny any(value); assertTrue(any.Is(), "应该是string类型"); assertEqual(value, any.Get(), "值应该相等"); result.message = "成功"; return result; } TestResult LSPAnyTests::testCStringConstructor() { TestResult result; result.passed = true; const char* value = "C String"; protocol::LSPAny any(value); assertTrue(any.Is(), "应该是string类型"); assertEqual(std::string(value), any.Get(), "值应该相等"); result.message = "成功"; return result; } TestResult LSPAnyTests::testNullptrConstructor() { TestResult result; result.passed = true; protocol::LSPAny any(nullptr); assertTrue(any.Is(), "应该是nullptr类型"); result.message = "成功"; return result; } TestResult LSPAnyTests::testLSPObjectConstructor() { TestResult result; result.passed = true; protocol::LSPObject obj; obj["key1"] = protocol::LSPAny(42); obj["key2"] = protocol::LSPAny("value"); protocol::LSPAny any(obj); assertTrue(any.Is(), "应该是LSPObject类型"); const auto& retrievedObj = any.Get(); assertTrue(retrievedObj.count("key1") > 0, "应该包含key1"); assertTrue(retrievedObj.count("key2") > 0, "应该包含key2"); result.message = "成功"; return result; } TestResult LSPAnyTests::testLSPArrayConstructor() { TestResult result; result.passed = true; protocol::LSPArray arr; arr.push_back(protocol::LSPAny(1)); arr.push_back(protocol::LSPAny(2)); arr.push_back(protocol::LSPAny(3)); protocol::LSPAny any(arr); assertTrue(any.Is(), "应该是LSPArray类型"); const auto& retrievedArr = any.Get(); assertTrue(retrievedArr.size() == 3, "数组大小应该是3"); result.message = "成功"; return result; } // ==================== 拷贝和移动测试 ==================== TestResult LSPAnyTests::testCopyConstructor() { TestResult result; result.passed = true; protocol::LSPAny original(42); protocol::LSPAny copy(original); assertTrue(copy.Is(), "拷贝应该保持类型"); assertEqual(42, copy.Get(), "拷贝应该保持值"); assertEqual(42, original.Get(), "原值不应改变"); result.message = "成功"; return result; } TestResult LSPAnyTests::testMoveConstructor() { TestResult result; result.passed = true; protocol::LSPAny original(protocol::string("Move me")); protocol::LSPAny moved(std::move(original)); assertTrue(moved.Is(), "移动应该保持类型"); assertEqual(std::string("Move me"), moved.Get(), "移动应该保持值"); result.message = "成功"; return result; } TestResult LSPAnyTests::testCopyAssignment() { TestResult result; result.passed = true; protocol::LSPAny original(42); protocol::LSPAny target(nullptr); target = original; assertTrue(target.Is(), "赋值应该保持类型"); assertEqual(42, target.Get(), "赋值应该保持值"); result.message = "成功"; return result; } TestResult LSPAnyTests::testMoveAssignment() { TestResult result; result.passed = true; protocol::LSPAny original(protocol::string("Move me")); protocol::LSPAny target(nullptr); target = std::move(original); assertTrue(target.Is(), "移动赋值应该保持类型"); assertEqual(std::string("Move me"), target.Get(), "移动赋值应该保持值"); result.message = "成功"; return result; } // ==================== 赋值操作符测试 ==================== TestResult LSPAnyTests::testDecimalAssignment() { TestResult result; result.passed = true; protocol::LSPAny any(nullptr); any = 2.718; assertTrue(any.Is(), "赋值后应该是decimal类型"); assertEqual(2.718, any.Get(), "赋值后值应该正确"); result.message = "成功"; return result; } TestResult LSPAnyTests::testBooleanAssignment() { TestResult result; result.passed = true; protocol::LSPAny any(nullptr); any = true; assertTrue(any.Is(), "赋值后应该是boolean类型"); assertEqual(true, any.Get(), "赋值后值应该正确"); result.message = "成功"; return result; } TestResult LSPAnyTests::testStringAssignment() { TestResult result; result.passed = true; protocol::LSPAny any(nullptr); any = protocol::string("Assigned"); assertTrue(any.Is(), "赋值后应该是string类型"); assertEqual(std::string("Assigned"), any.Get(), "赋值后值应该正确"); // 测试 C 字符串赋值 any = "C String"; assertEqual(std::string("C String"), any.Get(), "C字符串赋值应该正确"); result.message = "成功"; return result; } TestResult LSPAnyTests::testNullptrAssignment() { TestResult result; result.passed = true; protocol::LSPAny any(42); any = nullptr; assertTrue(any.Is(), "赋值后应该是nullptr类型"); result.message = "成功"; return result; } TestResult LSPAnyTests::testLSPObjectAssignment() { TestResult result; result.passed = true; protocol::LSPObject obj; obj["test"] = protocol::LSPAny(999); protocol::LSPAny any(nullptr); any = obj; assertTrue(any.Is(), "赋值后应该是LSPObject类型"); const auto& retrievedObj = any.Get(); assertTrue(retrievedObj.count("test") > 0, "应该包含test键"); result.message = "成功"; return result; } TestResult LSPAnyTests::testLSPArrayAssignment() { TestResult result; result.passed = true; protocol::LSPArray arr; arr.push_back(protocol::LSPAny(10)); arr.push_back(protocol::LSPAny(20)); protocol::LSPAny any(nullptr); any = arr; assertTrue(any.Is(), "赋值后应该是LSPArray类型"); const auto& retrievedArr = any.Get(); assertTrue(retrievedArr.size() == 2, "数组大小应该是2"); result.message = "成功"; return result; } // ==================== 类型检查测试 ==================== TestResult LSPAnyTests::testIsMethod() { TestResult result; result.passed = true; protocol::LSPAny intAny(42); assertTrue(intAny.Is(), "Is应该正确识别integer"); assertFalse(intAny.Is(), "Is应该正确排除string"); assertFalse(intAny.Is(), "Is应该正确排除decimal"); protocol::LSPAny strAny(protocol::string("test")); assertTrue(strAny.Is(), "Is应该正确识别string"); assertFalse(strAny.Is(), "Is应该正确排除integer"); result.message = "成功"; return result; } TestResult LSPAnyTests::testGetMethod() { TestResult result; result.passed = true; protocol::LSPAny any(42); assertEqual(42, any.Get(), "Get应该返回正确的值"); // 修改值 any.Get() = 100; assertEqual(100, any.Get(), "Get应该返回可修改的引用"); // const Get 测试 const protocol::LSPAny constAny(200); assertEqual(200, constAny.Get(), "const Get应该正常工作"); result.message = "成功"; return result; } // ==================== 访问者模式测试 ==================== TestResult LSPAnyTests::testVisitMethod() { TestResult result; result.passed = true; protocol::LSPAny intAny(42); protocol::LSPAny strAny(protocol::string("hello")); protocol::LSPAny boolAny(true); // 测试 const Visit auto visitor = [](const auto& value) -> std::string { using T = std::decay_t; if constexpr (std::is_same_v) { return "integer:" + std::to_string(value); } else if constexpr (std::is_same_v) { return "string:" + value; } else if constexpr (std::is_same_v) { return value ? "bool:true" : "bool:false"; } else { return "other"; } }; std::string result1 = intAny.Visit(visitor); assertEqual(std::string("integer:42"), result1, "Visit应该正确访问integer"); std::string result2 = strAny.Visit(visitor); assertEqual(std::string("string:hello"), result2, "Visit应该正确访问string"); std::string result3 = boolAny.Visit(visitor); assertEqual(std::string("bool:true"), result3, "Visit应该正确访问boolean"); result.message = "成功"; return result; } // ==================== 整数模板测试 ==================== TestResult LSPAnyTests::testIntegerTemplateSignedTypes() { TestResult result; result.passed = true; // 测试各种有符号整数类型 protocol::LSPAny anyInt8(static_cast(-10)); assertTrue(anyInt8.Is(), "int8_t应该转为integer"); assertEqual(-10, anyInt8.Get(), "int8_t值应该正确"); protocol::LSPAny anyInt16(static_cast(-1000)); assertTrue(anyInt16.Is(), "int16_t应该转为integer"); assertEqual(-1000, anyInt16.Get(), "int16_t值应该正确"); protocol::LSPAny anyInt64(static_cast(100000)); assertTrue(anyInt64.Is(), "int64_t应该转为integer"); assertEqual(100000, anyInt64.Get(), "int64_t值应该正确"); result.message = "成功"; return result; } TestResult LSPAnyTests::testIntegerTemplateUnsignedTypes() { TestResult result; result.passed = true; // 测试各种无符号整数类型 - 无符号整数应该存储为uinteger protocol::LSPAny anyUint8(static_cast(255)); assertTrue(anyUint8.Is(), "uint8_t应该转为uinteger"); assertEqual(255u, anyUint8.Get(), "uint8_t值应该正确"); protocol::LSPAny anyUint16(static_cast(5000)); assertTrue(anyUint16.Is(), "uint16_t应该转为uinteger"); assertEqual(5000u, anyUint16.Get(), "uint16_t值应该正确"); protocol::LSPAny anySize(static_cast(12345)); assertTrue(anySize.Is(), "size_t应该转为uinteger"); assertEqual(12345u, anySize.Get(), "size_t值应该正确"); result.message = "成功"; return result; } TestResult LSPAnyTests::testIntegerTemplateBoundaries() { TestResult result; result.passed = true; // 测试 int32 边界 protocol::LSPAny anyMax(std::numeric_limits::max()); assertTrue(anyMax.Is(), "int32_max应该是integer"); assertEqual(std::numeric_limits::max(), anyMax.Get(), "int32_max值应该正确"); protocol::LSPAny anyMin(std::numeric_limits::min()); assertTrue(anyMin.Is(), "int32_min应该是integer"); assertEqual(std::numeric_limits::min(), anyMin.Get(), "int32_min值应该正确"); // 测试超出 int32 范围的 int64 int64_t largeValue = static_cast(std::numeric_limits::max()) + 1; protocol::LSPAny anyLarge(largeValue); assertTrue(anyLarge.Is(), "超出int32范围应该转为decimal"); // 测试 uint32 边界 protocol::LSPAny anyUintMax(std::numeric_limits::max()); assertTrue(anyUintMax.Is(), "uint32_max应该是uinteger"); assertEqual(std::numeric_limits::max(), anyUintMax.Get(), "uint32_max值应该正确"); result.message = "成功"; return result; } // ==================== 复杂场景测试 ==================== TestResult LSPAnyTests::testNestedLSPObject() { TestResult result; result.passed = true; protocol::LSPObject innerObj; innerObj["inner_key"] = protocol::LSPAny(42); protocol::LSPObject outerObj; outerObj["outer_key"] = protocol::LSPAny(innerObj); outerObj["name"] = protocol::LSPAny(protocol::string("test")); protocol::LSPAny any(outerObj); assertTrue(any.Is(), "应该是LSPObject类型"); const auto& obj = any.Get(); assertTrue(obj.count("outer_key") > 0, "应该包含outer_key"); assertTrue(obj.count("name") > 0, "应该包含name"); const auto& inner = obj.at("outer_key"); assertTrue(inner.Is(), "嵌套值应该是LSPObject"); result.message = "成功"; return result; } TestResult LSPAnyTests::testNestedLSPArray() { TestResult result; result.passed = true; protocol::LSPArray innerArr; innerArr.push_back(protocol::LSPAny(1)); innerArr.push_back(protocol::LSPAny(2)); protocol::LSPArray outerArr; outerArr.push_back(protocol::LSPAny(innerArr)); outerArr.push_back(protocol::LSPAny(protocol::string("text"))); protocol::LSPAny any(outerArr); assertTrue(any.Is(), "应该是LSPArray类型"); const auto& arr = any.Get(); assertTrue(arr.size() == 2, "外层数组大小应该是2"); assertTrue(arr[0].Is(), "第一个元素应该是LSPArray"); result.message = "成功"; return result; } TestResult LSPAnyTests::testMixedNesting() { TestResult result; result.passed = true; protocol::LSPArray arr; arr.push_back(protocol::LSPAny(1)); arr.push_back(protocol::LSPAny(protocol::string("two"))); arr.push_back(protocol::LSPAny(3.0)); protocol::LSPObject obj; obj["array"] = protocol::LSPAny(arr); obj["number"] = protocol::LSPAny(42); obj["flag"] = protocol::LSPAny(true); protocol::LSPAny any(obj); assertTrue(any.Is(), "应该是LSPObject类型"); const auto& retrievedObj = any.Get(); assertTrue(retrievedObj.count("array") > 0, "应该包含array"); assertTrue(retrievedObj.at("array").Is(), "array应该是LSPArray类型"); const auto& retrievedArr = retrievedObj.at("array").Get(); assertTrue(retrievedArr.size() == 3, "数组大小应该是3"); result.message = "成功"; return result; } TestResult LSPAnyTests::testTypeConversion() { TestResult result; result.passed = true; protocol::LSPAny any(42); assertTrue(any.Is(), "初始应该是integer"); // 改变类型 any = protocol::string("now a string"); assertTrue(any.Is(), "现在应该是string"); assertFalse(any.Is(), "不应该再是integer"); // 再次改变 any = 3.14; assertTrue(any.Is(), "现在应该是decimal"); assertFalse(any.Is(), "不应该再是string"); result.message = "成功"; return result; } // ==================== 边界情况测试 ==================== TestResult LSPAnyTests::testFloatPrecision() { TestResult result; result.passed = true; float fValue = 1.23456789f; protocol::LSPAny anyFloat(fValue); assertTrue(anyFloat.Is(), "float应该转为decimal"); // 注意:float 转为 double 可能有精度变化,这里只是验证类型转换正确 protocol::decimal retrieved = anyFloat.Get(); assertTrue(std::abs(retrieved - static_cast(fValue)) < 1e-6, "转换后的值应该接近原值"); result.message = "成功"; return result; } TestResult LSPAnyTests::testLargeNumbers() { TestResult result; result.passed = true; // 测试大的 uint64 值转为 decimal uint64_t largeUint = 10000000000ULL; // 超出 uint32 范围 protocol::LSPAny anyLarge(largeUint); assertTrue(anyLarge.Is(), "大整数应该转为decimal"); protocol::decimal retrieved = anyLarge.Get(); assertTrue(std::abs(retrieved - static_cast(largeUint)) < 1.0, "转换后的值应该接近原值"); result.message = "成功"; return result; } TestResult LSPAnyTests::testEmptyContainers() { TestResult result; result.passed = true; protocol::LSPObject emptyObj; protocol::LSPAny anyObj(emptyObj); assertTrue(anyObj.Is(), "应该是LSPObject类型"); const auto& obj = anyObj.Get(); assertTrue(obj.empty(), "对象应该为空"); protocol::LSPArray emptyArr; protocol::LSPAny anyArr(emptyArr); assertTrue(anyArr.Is(), "应该是LSPArray类型"); const auto& arr = anyArr.Get(); assertTrue(arr.empty(), "数组应该为空"); result.message = "成功"; return result; } } // namespace lsp::test