tsl-devkit/lsp-server/test/test_lsp_any/lsp_any_test.cpp

690 lines
23 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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