Files
tsl-devkit/lsp-server/test/test_lsp_any/lsp_any_test.cpp
T
csh 64ec88f0c3 🗑️ 移除test_glaz
 新增测试`test_lsp_any`
2025-11-02 15:47:48 +08:00

690 lines
23 KiB
C++

#include <cmath>
#include <limits>
#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<std::nullptr_t>(), "默认构造应该是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<protocol::decimal>(), "应该是decimal类型");
assertEqual(value, any.Get<protocol::decimal>(), "值应该相等");
// 测试 float 构造
float fValue = 2.5f;
protocol::LSPAny anyFloat(fValue);
assertTrue(anyFloat.Is<protocol::decimal>(), "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<protocol::boolean>(), "应该是boolean类型");
assertTrue(anyFalse.Is<protocol::boolean>(), "应该是boolean类型");
assertEqual(true, anyTrue.Get<protocol::boolean>(), "值应该是true");
assertEqual(false, anyFalse.Get<protocol::boolean>(), "值应该是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<protocol::string>(), "应该是string类型");
assertEqual(value, any.Get<protocol::string>(), "值应该相等");
result.message = "成功";
return result;
}
TestResult LSPAnyTests::testCStringConstructor()
{
TestResult result;
result.passed = true;
const char* value = "C String";
protocol::LSPAny any(value);
assertTrue(any.Is<protocol::string>(), "应该是string类型");
assertEqual(std::string(value), any.Get<protocol::string>(), "值应该相等");
result.message = "成功";
return result;
}
TestResult LSPAnyTests::testNullptrConstructor()
{
TestResult result;
result.passed = true;
protocol::LSPAny any(nullptr);
assertTrue(any.Is<std::nullptr_t>(), "应该是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<protocol::LSPObject>(), "应该是LSPObject类型");
const auto& retrievedObj = any.Get<protocol::LSPObject>();
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<protocol::LSPArray>(), "应该是LSPArray类型");
const auto& retrievedArr = any.Get<protocol::LSPArray>();
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<protocol::integer>(), "拷贝应该保持类型");
assertEqual(42, copy.Get<protocol::integer>(), "拷贝应该保持值");
assertEqual(42, original.Get<protocol::integer>(), "原值不应改变");
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<protocol::string>(), "移动应该保持类型");
assertEqual(std::string("Move me"), moved.Get<protocol::string>(), "移动应该保持值");
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<protocol::integer>(), "赋值应该保持类型");
assertEqual(42, target.Get<protocol::integer>(), "赋值应该保持值");
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<protocol::string>(), "移动赋值应该保持类型");
assertEqual(std::string("Move me"), target.Get<protocol::string>(), "移动赋值应该保持值");
result.message = "成功";
return result;
}
// ==================== 赋值操作符测试 ====================
TestResult LSPAnyTests::testDecimalAssignment()
{
TestResult result;
result.passed = true;
protocol::LSPAny any(nullptr);
any = 2.718;
assertTrue(any.Is<protocol::decimal>(), "赋值后应该是decimal类型");
assertEqual(2.718, any.Get<protocol::decimal>(), "赋值后值应该正确");
result.message = "成功";
return result;
}
TestResult LSPAnyTests::testBooleanAssignment()
{
TestResult result;
result.passed = true;
protocol::LSPAny any(nullptr);
any = true;
assertTrue(any.Is<protocol::boolean>(), "赋值后应该是boolean类型");
assertEqual(true, any.Get<protocol::boolean>(), "赋值后值应该正确");
result.message = "成功";
return result;
}
TestResult LSPAnyTests::testStringAssignment()
{
TestResult result;
result.passed = true;
protocol::LSPAny any(nullptr);
any = protocol::string("Assigned");
assertTrue(any.Is<protocol::string>(), "赋值后应该是string类型");
assertEqual(std::string("Assigned"), any.Get<protocol::string>(), "赋值后值应该正确");
// 测试 C 字符串赋值
any = "C String";
assertEqual(std::string("C String"), any.Get<protocol::string>(), "C字符串赋值应该正确");
result.message = "成功";
return result;
}
TestResult LSPAnyTests::testNullptrAssignment()
{
TestResult result;
result.passed = true;
protocol::LSPAny any(42);
any = nullptr;
assertTrue(any.Is<std::nullptr_t>(), "赋值后应该是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<protocol::LSPObject>(), "赋值后应该是LSPObject类型");
const auto& retrievedObj = any.Get<protocol::LSPObject>();
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<protocol::LSPArray>(), "赋值后应该是LSPArray类型");
const auto& retrievedArr = any.Get<protocol::LSPArray>();
assertTrue(retrievedArr.size() == 2, "数组大小应该是2");
result.message = "成功";
return result;
}
// ==================== 类型检查测试 ====================
TestResult LSPAnyTests::testIsMethod()
{
TestResult result;
result.passed = true;
protocol::LSPAny intAny(42);
assertTrue(intAny.Is<protocol::integer>(), "Is应该正确识别integer");
assertFalse(intAny.Is<protocol::string>(), "Is应该正确排除string");
assertFalse(intAny.Is<protocol::decimal>(), "Is应该正确排除decimal");
protocol::LSPAny strAny(protocol::string("test"));
assertTrue(strAny.Is<protocol::string>(), "Is应该正确识别string");
assertFalse(strAny.Is<protocol::integer>(), "Is应该正确排除integer");
result.message = "成功";
return result;
}
TestResult LSPAnyTests::testGetMethod()
{
TestResult result;
result.passed = true;
protocol::LSPAny any(42);
assertEqual(42, any.Get<protocol::integer>(), "Get应该返回正确的值");
// 修改值
any.Get<protocol::integer>() = 100;
assertEqual(100, any.Get<protocol::integer>(), "Get应该返回可修改的引用");
// const Get 测试
const protocol::LSPAny constAny(200);
assertEqual(200, constAny.Get<protocol::integer>(), "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<decltype(value)>;
if constexpr (std::is_same_v<T, protocol::integer>)
{
return "integer:" + std::to_string(value);
}
else if constexpr (std::is_same_v<T, protocol::string>)
{
return "string:" + value;
}
else if constexpr (std::is_same_v<T, protocol::boolean>)
{
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<int8_t>(-10));
assertTrue(anyInt8.Is<protocol::integer>(), "int8_t应该转为integer");
assertEqual(-10, anyInt8.Get<protocol::integer>(), "int8_t值应该正确");
protocol::LSPAny anyInt16(static_cast<int16_t>(-1000));
assertTrue(anyInt16.Is<protocol::integer>(), "int16_t应该转为integer");
assertEqual(-1000, anyInt16.Get<protocol::integer>(), "int16_t值应该正确");
protocol::LSPAny anyInt64(static_cast<int64_t>(100000));
assertTrue(anyInt64.Is<protocol::integer>(), "int64_t应该转为integer");
assertEqual(100000, anyInt64.Get<protocol::integer>(), "int64_t值应该正确");
result.message = "成功";
return result;
}
TestResult LSPAnyTests::testIntegerTemplateUnsignedTypes()
{
TestResult result;
result.passed = true;
// 测试各种无符号整数类型 - 无符号整数应该存储为uinteger
protocol::LSPAny anyUint8(static_cast<uint8_t>(255));
assertTrue(anyUint8.Is<protocol::uinteger>(), "uint8_t应该转为uinteger");
assertEqual(255u, anyUint8.Get<protocol::uinteger>(), "uint8_t值应该正确");
protocol::LSPAny anyUint16(static_cast<uint16_t>(5000));
assertTrue(anyUint16.Is<protocol::uinteger>(), "uint16_t应该转为uinteger");
assertEqual(5000u, anyUint16.Get<protocol::uinteger>(), "uint16_t值应该正确");
protocol::LSPAny anySize(static_cast<size_t>(12345));
assertTrue(anySize.Is<protocol::uinteger>(), "size_t应该转为uinteger");
assertEqual(12345u, anySize.Get<protocol::uinteger>(), "size_t值应该正确");
result.message = "成功";
return result;
}
TestResult LSPAnyTests::testIntegerTemplateBoundaries()
{
TestResult result;
result.passed = true;
// 测试 int32 边界
protocol::LSPAny anyMax(std::numeric_limits<int32_t>::max());
assertTrue(anyMax.Is<protocol::integer>(), "int32_max应该是integer");
assertEqual(std::numeric_limits<int32_t>::max(), anyMax.Get<protocol::integer>(), "int32_max值应该正确");
protocol::LSPAny anyMin(std::numeric_limits<int32_t>::min());
assertTrue(anyMin.Is<protocol::integer>(), "int32_min应该是integer");
assertEqual(std::numeric_limits<int32_t>::min(), anyMin.Get<protocol::integer>(), "int32_min值应该正确");
// 测试超出 int32 范围的 int64
int64_t largeValue = static_cast<int64_t>(std::numeric_limits<int32_t>::max()) + 1;
protocol::LSPAny anyLarge(largeValue);
assertTrue(anyLarge.Is<protocol::decimal>(), "超出int32范围应该转为decimal");
// 测试 uint32 边界
protocol::LSPAny anyUintMax(std::numeric_limits<uint32_t>::max());
assertTrue(anyUintMax.Is<protocol::uinteger>(), "uint32_max应该是uinteger");
assertEqual(std::numeric_limits<uint32_t>::max(), anyUintMax.Get<protocol::uinteger>(), "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<protocol::LSPObject>(), "应该是LSPObject类型");
const auto& obj = any.Get<protocol::LSPObject>();
assertTrue(obj.count("outer_key") > 0, "应该包含outer_key");
assertTrue(obj.count("name") > 0, "应该包含name");
const auto& inner = obj.at("outer_key");
assertTrue(inner.Is<protocol::LSPObject>(), "嵌套值应该是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<protocol::LSPArray>(), "应该是LSPArray类型");
const auto& arr = any.Get<protocol::LSPArray>();
assertTrue(arr.size() == 2, "外层数组大小应该是2");
assertTrue(arr[0].Is<protocol::LSPArray>(), "第一个元素应该是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<protocol::LSPObject>(), "应该是LSPObject类型");
const auto& retrievedObj = any.Get<protocol::LSPObject>();
assertTrue(retrievedObj.count("array") > 0, "应该包含array");
assertTrue(retrievedObj.at("array").Is<protocol::LSPArray>(), "array应该是LSPArray类型");
const auto& retrievedArr = retrievedObj.at("array").Get<protocol::LSPArray>();
assertTrue(retrievedArr.size() == 3, "数组大小应该是3");
result.message = "成功";
return result;
}
TestResult LSPAnyTests::testTypeConversion()
{
TestResult result;
result.passed = true;
protocol::LSPAny any(42);
assertTrue(any.Is<protocol::integer>(), "初始应该是integer");
// 改变类型
any = protocol::string("now a string");
assertTrue(any.Is<protocol::string>(), "现在应该是string");
assertFalse(any.Is<protocol::integer>(), "不应该再是integer");
// 再次改变
any = 3.14;
assertTrue(any.Is<protocol::decimal>(), "现在应该是decimal");
assertFalse(any.Is<protocol::string>(), "不应该再是string");
result.message = "成功";
return result;
}
// ==================== 边界情况测试 ====================
TestResult LSPAnyTests::testFloatPrecision()
{
TestResult result;
result.passed = true;
float fValue = 1.23456789f;
protocol::LSPAny anyFloat(fValue);
assertTrue(anyFloat.Is<protocol::decimal>(), "float应该转为decimal");
// 注意:float 转为 double 可能有精度变化,这里只是验证类型转换正确
protocol::decimal retrieved = anyFloat.Get<protocol::decimal>();
assertTrue(std::abs(retrieved - static_cast<double>(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<protocol::decimal>(), "大整数应该转为decimal");
protocol::decimal retrieved = anyLarge.Get<protocol::decimal>();
assertTrue(std::abs(retrieved - static_cast<double>(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<protocol::LSPObject>(), "应该是LSPObject类型");
const auto& obj = anyObj.Get<protocol::LSPObject>();
assertTrue(obj.empty(), "对象应该为空");
protocol::LSPArray emptyArr;
protocol::LSPAny anyArr(emptyArr);
assertTrue(anyArr.Is<protocol::LSPArray>(), "应该是LSPArray类型");
const auto& arr = anyArr.Get<protocol::LSPArray>();
assertTrue(arr.empty(), "数组应该为空");
result.message = "成功";
return result;
}
} // namespace lsp::test