添加单元测试
This commit is contained in:
@@ -1,3 +1,6 @@
|
|||||||
|
// XYParser API 单元测试文件
|
||||||
|
// 测试 XYParser 库的核心功能,包括解析器创建、错误处理、帧解析等
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include "../XYParserApi.h"
|
#include "../XYParserApi.h"
|
||||||
|
|
||||||
@@ -7,12 +10,18 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
// 匿名命名空间,包含测试辅助代码
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
/// ParserGuard 类:RAII 封装,确保解析器资源自动释放
|
||||||
|
/// 当对象生命周期结束时自动调用 XYParser_DestroyParser 释放资源
|
||||||
class ParserGuard {
|
class ParserGuard {
|
||||||
public:
|
public:
|
||||||
|
/// 构造函数,接管解析器句柄的所有权
|
||||||
|
/// @param handle XYParser 解析器句柄
|
||||||
explicit ParserGuard(XYParserHandle handle) : handle_(handle) {}
|
explicit ParserGuard(XYParserHandle handle) : handle_(handle) {}
|
||||||
|
|
||||||
|
/// 析构函数,自动释放解析器资源
|
||||||
~ParserGuard()
|
~ParserGuard()
|
||||||
{
|
{
|
||||||
if (handle_ != nullptr) {
|
if (handle_ != nullptr) {
|
||||||
@@ -20,22 +29,29 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 获取解析器句柄
|
||||||
|
/// @return XYParser 解析器句柄
|
||||||
XYParserHandle get() const
|
XYParserHandle get() const
|
||||||
{
|
{
|
||||||
return handle_;
|
return handle_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
XYParserHandle handle_;
|
XYParserHandle handle_; ///< 解析器句柄
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// 构建最小帧数据的辅助函数
|
||||||
|
/// 生成符合 XYParser 协议格式的测试帧数据
|
||||||
|
/// @param channel_count 通道数量
|
||||||
|
/// @return 包含完整帧数据的字节向量
|
||||||
std::vector<std::uint8_t> BuildMinimalFrame(std::uint8_t channel_count)
|
std::vector<std::uint8_t> BuildMinimalFrame(std::uint8_t channel_count)
|
||||||
{
|
{
|
||||||
constexpr std::size_t kSamplesPerFrame = 5;
|
constexpr std::size_t kSamplesPerFrame = 5; ///< 每帧采样数
|
||||||
constexpr std::uint8_t kHeader = 0xAA;
|
constexpr std::uint8_t kHeader = 0xAA; ///< 帧头标记
|
||||||
constexpr std::uint8_t kTail = 0x55;
|
constexpr std::uint8_t kTail = 0x55; ///< 帧尾标记
|
||||||
constexpr std::size_t kTagLen = 25;
|
constexpr std::size_t kTagLen = 25; ///< 标签长度
|
||||||
|
|
||||||
|
// 计算帧结构大小
|
||||||
const std::size_t sample_bytes = static_cast<std::size_t>(channel_count) * 3 + 2;
|
const std::size_t sample_bytes = static_cast<std::size_t>(channel_count) * 3 + 2;
|
||||||
const std::uint16_t payload_length = static_cast<std::uint16_t>(sample_bytes * kSamplesPerFrame);
|
const std::uint16_t payload_length = static_cast<std::uint16_t>(sample_bytes * kSamplesPerFrame);
|
||||||
const std::size_t frame_size = 1 + kTagLen + payload_length + 2;
|
const std::size_t frame_size = 1 + kTagLen + payload_length + 2;
|
||||||
@@ -43,31 +59,39 @@ std::vector<std::uint8_t> BuildMinimalFrame(std::uint8_t channel_count)
|
|||||||
std::vector<std::uint8_t> frame(frame_size, 0);
|
std::vector<std::uint8_t> frame(frame_size, 0);
|
||||||
std::size_t offset = 0;
|
std::size_t offset = 0;
|
||||||
|
|
||||||
|
// 写入帧头
|
||||||
frame[offset++] = kHeader;
|
frame[offset++] = kHeader;
|
||||||
|
|
||||||
|
// 写入标签数据(版本号等)
|
||||||
frame[offset++] = 0x01;
|
frame[offset++] = 0x01;
|
||||||
frame[offset++] = 0x00;
|
frame[offset++] = 0x00;
|
||||||
frame[offset++] = 0x00;
|
frame[offset++] = 0x00;
|
||||||
frame[offset++] = 0x00;
|
frame[offset++] = 0x00;
|
||||||
|
|
||||||
|
// 写入负载长度(大端序)
|
||||||
frame[offset++] = static_cast<std::uint8_t>((payload_length >> 8) & 0xFF);
|
frame[offset++] = static_cast<std::uint8_t>((payload_length >> 8) & 0xFF);
|
||||||
frame[offset++] = static_cast<std::uint8_t>(payload_length & 0xFF);
|
frame[offset++] = static_cast<std::uint8_t>(payload_length & 0xFF);
|
||||||
|
|
||||||
|
// 写入电池电量和通道数
|
||||||
frame[offset++] = 95;
|
frame[offset++] = 95;
|
||||||
frame[offset++] = channel_count;
|
frame[offset++] = channel_count;
|
||||||
|
|
||||||
|
// 跳过保留字段
|
||||||
offset += 2 + 2 + 2 + 2 + 2 + 6;
|
offset += 2 + 2 + 2 + 2 + 2 + 6;
|
||||||
|
|
||||||
|
// 写入采样数据
|
||||||
for (std::size_t sample = 0; sample < kSamplesPerFrame; ++sample) {
|
for (std::size_t sample = 0; sample < kSamplesPerFrame; ++sample) {
|
||||||
for (std::size_t channel = 0; channel < channel_count; ++channel) {
|
for (std::size_t channel = 0; channel < channel_count; ++channel) {
|
||||||
frame[offset++] = 0x00;
|
frame[offset++] = 0x00;
|
||||||
frame[offset++] = 0x00;
|
frame[offset++] = 0x00;
|
||||||
frame[offset++] = static_cast<std::uint8_t>(sample + channel + 1);
|
frame[offset++] = static_cast<std::uint8_t>(sample + channel + 1);
|
||||||
}
|
}
|
||||||
|
// 每个采样后的额外字节
|
||||||
frame[offset++] = 0x00;
|
frame[offset++] = 0x00;
|
||||||
frame[offset++] = 0x00;
|
frame[offset++] = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 写入帧尾
|
||||||
frame[offset++] = 0x00;
|
frame[offset++] = 0x00;
|
||||||
frame[offset++] = kTail;
|
frame[offset++] = kTail;
|
||||||
frame[offset++] = kTail;
|
frame[offset++] = kTail;
|
||||||
@@ -77,24 +101,32 @@ std::vector<std::uint8_t> BuildMinimalFrame(std::uint8_t channel_count)
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
/// 测试:创建解析器时拒绝不支持的通道数
|
||||||
TEST(XYParserApiTests, CreateParserRejectsUnsupportedChannelCount)
|
TEST(XYParserApiTests, CreateParserRejectsUnsupportedChannelCount)
|
||||||
{
|
{
|
||||||
|
// 7 通道是不支持的配置,应返回 nullptr
|
||||||
EXPECT_EQ(XYParser_CreateParser(7), nullptr);
|
EXPECT_EQ(XYParser_CreateParser(7), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 测试:对空解析器句柄调用 GetLastError 应返回正确错误信息
|
||||||
TEST(XYParserApiTests, GetLastErrorReturnsMessageForNullParser)
|
TEST(XYParserApiTests, GetLastErrorReturnsMessageForNullParser)
|
||||||
{
|
{
|
||||||
|
// 传入 nullptr 应返回 "invalid parser handle"
|
||||||
EXPECT_EQ(std::string(XYParser_GetLastError(nullptr)), std::string("invalid parser handle"));
|
EXPECT_EQ(std::string(XYParser_GetLastError(nullptr)), std::string("invalid parser handle"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 测试:Feed 函数能正确解析完整的 8 通道帧
|
||||||
TEST(XYParserApiTests, FeedParsesAComplete8ChannelFrame)
|
TEST(XYParserApiTests, FeedParsesAComplete8ChannelFrame)
|
||||||
{
|
{
|
||||||
|
// 创建 8 通道解析器
|
||||||
ParserGuard parser(XYParser_CreateParser(8));
|
ParserGuard parser(XYParser_CreateParser(8));
|
||||||
ASSERT_NE(parser.get(), nullptr);
|
ASSERT_NE(parser.get(), nullptr);
|
||||||
|
|
||||||
|
// 设置 ADC 参数和校验和绕过标志
|
||||||
XYParser_SetAdcParams(parser.get(), 4.5, 6.0);
|
XYParser_SetAdcParams(parser.get(), 4.5, 6.0);
|
||||||
XYParser_SetBypassChecksum(parser.get(), 1);
|
XYParser_SetBypassChecksum(parser.get(), 1);
|
||||||
|
|
||||||
|
// 构建测试帧并解析
|
||||||
const std::vector<std::uint8_t> bytes = BuildMinimalFrame(8);
|
const std::vector<std::uint8_t> bytes = BuildMinimalFrame(8);
|
||||||
std::array<XYParserFrameSummary, 1> summaries{};
|
std::array<XYParserFrameSummary, 1> summaries{};
|
||||||
|
|
||||||
@@ -105,17 +137,255 @@ TEST(XYParserApiTests, FeedParsesAComplete8ChannelFrame)
|
|||||||
summaries.data(),
|
summaries.data(),
|
||||||
static_cast<int>(summaries.size()));
|
static_cast<int>(summaries.size()));
|
||||||
|
|
||||||
ASSERT_EQ(frame_count, 1);
|
// 验证解析结果
|
||||||
EXPECT_EQ(summaries[0].frame_index, static_cast<std::uint32_t>(1));
|
ASSERT_EQ(frame_count, 1); // 应解析出 1 帧
|
||||||
EXPECT_EQ(summaries[0].channel_count, static_cast<std::uint8_t>(8));
|
EXPECT_EQ(summaries[0].frame_index, 1U); // 帧索引应为 1
|
||||||
EXPECT_EQ(summaries[0].battery, static_cast<std::uint8_t>(95));
|
EXPECT_EQ(summaries[0].channel_count, 8U); // 通道数应为 8
|
||||||
EXPECT_EQ(summaries[0].sample_count, static_cast<std::uint8_t>(5));
|
EXPECT_EQ(summaries[0].battery, 95U); // 电池电量应为 95
|
||||||
EXPECT_GT(summaries[0].channel_values_uv[0][0], 0.0);
|
EXPECT_EQ(summaries[0].sample_count, 5U); // 采样数应为 5
|
||||||
EXPECT_EQ(summaries[0].trigger_types[0], static_cast<std::uint8_t>(0));
|
EXPECT_GT(summaries[0].channel_values_uv[0][0], 0.0); // 通道值应大于 0
|
||||||
EXPECT_EQ(summaries[0].trigger_indices[0], static_cast<std::uint8_t>(0));
|
EXPECT_EQ(summaries[0].trigger_types[0], 0U); // 触发类型应为 0
|
||||||
|
EXPECT_EQ(summaries[0].trigger_indices[0], 0U); // 触发索引应为 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 测试:Feed 函数能缓冲部分数据直到完整帧可用
|
||||||
TEST(XYParserApiTests, FeedBuffersPartialDataUntilAFullFrameIsAvailable)
|
TEST(XYParserApiTests, FeedBuffersPartialDataUntilAFullFrameIsAvailable)
|
||||||
|
{
|
||||||
|
// 创建 8 通道解析器
|
||||||
|
ParserGuard parser(XYParser_CreateParser(8));
|
||||||
|
ASSERT_NE(parser.get(), nullptr);
|
||||||
|
|
||||||
|
// 设置校验和绕过标志
|
||||||
|
XYParser_SetBypassChecksum(parser.get(), 1);
|
||||||
|
|
||||||
|
// 构建测试帧并分成两部分
|
||||||
|
const std::vector<std::uint8_t> bytes = BuildMinimalFrame(8);
|
||||||
|
const std::size_t split_index = bytes.size() / 2;
|
||||||
|
std::array<XYParserFrameSummary, 1> summaries{};
|
||||||
|
|
||||||
|
// 第一次 Feed:传入前半部分数据
|
||||||
|
const int first_result = XYParser_Feed(
|
||||||
|
parser.get(),
|
||||||
|
bytes.data(),
|
||||||
|
split_index,
|
||||||
|
summaries.data(),
|
||||||
|
static_cast<int>(summaries.size()));
|
||||||
|
EXPECT_EQ(first_result, 0); // 数据不完整,不应解析出帧
|
||||||
|
|
||||||
|
// 第二次 Feed:传入后半部分数据
|
||||||
|
const int second_result = XYParser_Feed(
|
||||||
|
parser.get(),
|
||||||
|
bytes.data() + split_index,
|
||||||
|
bytes.size() - split_index,
|
||||||
|
summaries.data(),
|
||||||
|
static_cast<int>(summaries.size()));
|
||||||
|
ASSERT_EQ(second_result, 1); // 数据完整,应解析出 1 帧
|
||||||
|
EXPECT_EQ(summaries[0].frame_index, 1U); // 帧索引应为 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 解析器创建测试
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// 测试:成功创建 8 通道解析器
|
||||||
|
TEST(XYParserApiTests, CreateParserSucceedsFor8Channels)
|
||||||
|
{
|
||||||
|
ParserGuard parser(XYParser_CreateParser(8));
|
||||||
|
EXPECT_NE(parser.get(), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试:成功创建 64 通道解析器
|
||||||
|
TEST(XYParserApiTests, CreateParserSucceedsFor64Channels)
|
||||||
|
{
|
||||||
|
ParserGuard parser(XYParser_CreateParser(64));
|
||||||
|
EXPECT_NE(parser.get(), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试:创建 0 通道解析器应失败
|
||||||
|
TEST(XYParserApiTests, CreateParserRejectsZeroChannels)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(XYParser_CreateParser(0), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试:创建不支持的通道数(如 100)应失败
|
||||||
|
TEST(XYParserApiTests, CreateParserRejectsExcessiveChannels)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(XYParser_CreateParser(100), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 参数设置函数测试
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// 测试:设置正常的 ADC 参数
|
||||||
|
TEST(XYParserApiTests, SetAdcParamsAcceptsValidValues)
|
||||||
|
{
|
||||||
|
ParserGuard parser(XYParser_CreateParser(8));
|
||||||
|
ASSERT_NE(parser.get(), nullptr);
|
||||||
|
|
||||||
|
// 不应崩溃
|
||||||
|
EXPECT_NO_THROW(XYParser_SetAdcParams(parser.get(), 4.5, 6.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试:设置边界值的 ADC 参数
|
||||||
|
TEST(XYParserApiTests, SetAdcParamsAcceptsBoundaryValues)
|
||||||
|
{
|
||||||
|
ParserGuard parser(XYParser_CreateParser(8));
|
||||||
|
ASSERT_NE(parser.get(), nullptr);
|
||||||
|
|
||||||
|
// 测试零值
|
||||||
|
EXPECT_NO_THROW(XYParser_SetAdcParams(parser.get(), 0.0, 0.0));
|
||||||
|
// 测试较大值
|
||||||
|
EXPECT_NO_THROW(XYParser_SetAdcParams(parser.get(), 100.0, 1000.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试:对空句柄调用 SetAdcParams
|
||||||
|
TEST(XYParserApiTests, SetAdcParamsOnNullHandle)
|
||||||
|
{
|
||||||
|
// 不应崩溃
|
||||||
|
EXPECT_NO_THROW(XYParser_SetAdcParams(nullptr, 4.5, 6.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试:关闭校验和绕过
|
||||||
|
TEST(XYParserApiTests, SetBypassChecksumOff)
|
||||||
|
{
|
||||||
|
ParserGuard parser(XYParser_CreateParser(8));
|
||||||
|
ASSERT_NE(parser.get(), nullptr);
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(XYParser_SetBypassChecksum(parser.get(), 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试:对空句柄调用 SetBypassChecksum
|
||||||
|
TEST(XYParserApiTests, SetBypassChecksumOnNullHandle)
|
||||||
|
{
|
||||||
|
EXPECT_NO_THROW(XYParser_SetBypassChecksum(nullptr, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Feed 函数帧解析测试
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// 测试:传入空数据
|
||||||
|
TEST(XYParserApiTests, FeedParsesEmptyData)
|
||||||
|
{
|
||||||
|
ParserGuard parser(XYParser_CreateParser(8));
|
||||||
|
ASSERT_NE(parser.get(), nullptr);
|
||||||
|
|
||||||
|
std::array<XYParserFrameSummary, 10> summaries{};
|
||||||
|
const int result = XYParser_Feed(
|
||||||
|
parser.get(),
|
||||||
|
nullptr,
|
||||||
|
0,
|
||||||
|
summaries.data(),
|
||||||
|
static_cast<int>(summaries.size()));
|
||||||
|
|
||||||
|
EXPECT_EQ(result, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试:只传入帧头数据
|
||||||
|
TEST(XYParserApiTests, FeedParsesOnlyHeader)
|
||||||
|
{
|
||||||
|
ParserGuard parser(XYParser_CreateParser(8));
|
||||||
|
ASSERT_NE(parser.get(), nullptr);
|
||||||
|
|
||||||
|
XYParser_SetBypassChecksum(parser.get(), 1);
|
||||||
|
|
||||||
|
// 只发送帧头
|
||||||
|
const std::vector<std::uint8_t> header_only = {0xAA, 0x01, 0x00, 0x00, 0x00};
|
||||||
|
std::array<XYParserFrameSummary, 10> summaries{};
|
||||||
|
|
||||||
|
const int result = XYParser_Feed(
|
||||||
|
parser.get(),
|
||||||
|
header_only.data(),
|
||||||
|
header_only.size(),
|
||||||
|
summaries.data(),
|
||||||
|
static_cast<int>(summaries.size()));
|
||||||
|
|
||||||
|
EXPECT_EQ(result, 0); // 数据不完整,不应解析出帧
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试:解析完整的 64 通道帧
|
||||||
|
TEST(XYParserApiTests, FeedParses64ChannelFrame)
|
||||||
|
{
|
||||||
|
ParserGuard parser(XYParser_CreateParser(64));
|
||||||
|
ASSERT_NE(parser.get(), nullptr);
|
||||||
|
|
||||||
|
XYParser_SetAdcParams(parser.get(), 4.5, 6.0);
|
||||||
|
XYParser_SetBypassChecksum(parser.get(), 1);
|
||||||
|
|
||||||
|
const std::vector<std::uint8_t> bytes = BuildMinimalFrame(64);
|
||||||
|
std::array<XYParserFrameSummary, 1> summaries{};
|
||||||
|
|
||||||
|
const int frame_count = XYParser_Feed(
|
||||||
|
parser.get(),
|
||||||
|
bytes.data(),
|
||||||
|
bytes.size(),
|
||||||
|
summaries.data(),
|
||||||
|
static_cast<int>(summaries.size()));
|
||||||
|
|
||||||
|
ASSERT_EQ(frame_count, 1);
|
||||||
|
EXPECT_EQ(summaries[0].channel_count, 64U);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试:连续解析多个帧
|
||||||
|
TEST(XYParserApiTests, FeedParsesMultipleFrames)
|
||||||
|
{
|
||||||
|
ParserGuard parser(XYParser_CreateParser(8));
|
||||||
|
ASSERT_NE(parser.get(), nullptr);
|
||||||
|
|
||||||
|
XYParser_SetBypassChecksum(parser.get(), 1);
|
||||||
|
|
||||||
|
// 构建两个连续的帧
|
||||||
|
const std::vector<std::uint8_t> frame1 = BuildMinimalFrame(8);
|
||||||
|
const std::vector<std::uint8_t> frame2 = BuildMinimalFrame(8);
|
||||||
|
|
||||||
|
std::vector<std::uint8_t> combined(frame1);
|
||||||
|
combined.insert(combined.end(), frame2.begin(), frame2.end());
|
||||||
|
|
||||||
|
std::array<XYParserFrameSummary, 10> summaries{};
|
||||||
|
const int frame_count = XYParser_Feed(
|
||||||
|
parser.get(),
|
||||||
|
combined.data(),
|
||||||
|
combined.size(),
|
||||||
|
summaries.data(),
|
||||||
|
static_cast<int>(summaries.size()));
|
||||||
|
|
||||||
|
EXPECT_EQ(frame_count, 2);
|
||||||
|
EXPECT_EQ(summaries[0].frame_index, 1U);
|
||||||
|
EXPECT_EQ(summaries[1].frame_index, 2U);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试:帧索引递增
|
||||||
|
TEST(XYParserApiTests, FeedIncrementsFrameIndex)
|
||||||
|
{
|
||||||
|
ParserGuard parser(XYParser_CreateParser(8));
|
||||||
|
ASSERT_NE(parser.get(), nullptr);
|
||||||
|
|
||||||
|
XYParser_SetBypassChecksum(parser.get(), 1);
|
||||||
|
|
||||||
|
// 连续发送多个帧
|
||||||
|
std::array<XYParserFrameSummary, 10> summaries{};
|
||||||
|
int total_frames = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
const std::vector<std::uint8_t> frame = BuildMinimalFrame(8);
|
||||||
|
const int count = XYParser_Feed(
|
||||||
|
parser.get(),
|
||||||
|
frame.data(),
|
||||||
|
frame.size(),
|
||||||
|
summaries.data() + total_frames,
|
||||||
|
static_cast<int>(summaries.size()) - total_frames);
|
||||||
|
total_frames += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(total_frames, 3);
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
EXPECT_EQ(summaries[i].frame_index, static_cast<std::uint32_t>(i + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试:电池电量字段解析
|
||||||
|
TEST(XYParserApiTests, FeedParsesBatteryValue)
|
||||||
{
|
{
|
||||||
ParserGuard parser(XYParser_CreateParser(8));
|
ParserGuard parser(XYParser_CreateParser(8));
|
||||||
ASSERT_NE(parser.get(), nullptr);
|
ASSERT_NE(parser.get(), nullptr);
|
||||||
@@ -123,23 +393,88 @@ TEST(XYParserApiTests, FeedBuffersPartialDataUntilAFullFrameIsAvailable)
|
|||||||
XYParser_SetBypassChecksum(parser.get(), 1);
|
XYParser_SetBypassChecksum(parser.get(), 1);
|
||||||
|
|
||||||
const std::vector<std::uint8_t> bytes = BuildMinimalFrame(8);
|
const std::vector<std::uint8_t> bytes = BuildMinimalFrame(8);
|
||||||
const std::size_t split_index = bytes.size() / 2;
|
|
||||||
std::array<XYParserFrameSummary, 1> summaries{};
|
std::array<XYParserFrameSummary, 1> summaries{};
|
||||||
|
|
||||||
const int first_result = XYParser_Feed(
|
XYParser_Feed(
|
||||||
parser.get(),
|
parser.get(),
|
||||||
bytes.data(),
|
bytes.data(),
|
||||||
split_index,
|
bytes.size(),
|
||||||
summaries.data(),
|
summaries.data(),
|
||||||
static_cast<int>(summaries.size()));
|
static_cast<int>(summaries.size()));
|
||||||
EXPECT_EQ(first_result, 0);
|
|
||||||
|
|
||||||
const int second_result = XYParser_Feed(
|
EXPECT_EQ(summaries[0].battery, 95U); // BuildMinimalFrame 中设置的电池电量
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 帧数据边界测试
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// 测试:跨多次 Feed 的不完整帧
|
||||||
|
TEST(XYParserApiTests, FeedHandlesIncompleteFrameAcrossMultipleFeeds)
|
||||||
|
{
|
||||||
|
ParserGuard parser(XYParser_CreateParser(8));
|
||||||
|
ASSERT_NE(parser.get(), nullptr);
|
||||||
|
|
||||||
|
XYParser_SetBypassChecksum(parser.get(), 1);
|
||||||
|
|
||||||
|
const std::vector<std::uint8_t> bytes = BuildMinimalFrame(8);
|
||||||
|
std::array<XYParserFrameSummary, 1> summaries{};
|
||||||
|
|
||||||
|
// 分成 3 次发送
|
||||||
|
const std::size_t part1_size = bytes.size() / 3;
|
||||||
|
const std::size_t part2_size = bytes.size() / 3;
|
||||||
|
|
||||||
|
EXPECT_EQ(XYParser_Feed(parser.get(), bytes.data(), part1_size,
|
||||||
|
summaries.data(), static_cast<int>(summaries.size())), 0);
|
||||||
|
|
||||||
|
EXPECT_EQ(XYParser_Feed(parser.get(), bytes.data() + part1_size, part2_size,
|
||||||
|
summaries.data(), static_cast<int>(summaries.size())), 0);
|
||||||
|
|
||||||
|
const int result = XYParser_Feed(
|
||||||
parser.get(),
|
parser.get(),
|
||||||
bytes.data() + split_index,
|
bytes.data() + part1_size + part2_size,
|
||||||
bytes.size() - split_index,
|
bytes.size() - part1_size - part2_size,
|
||||||
summaries.data(),
|
summaries.data(),
|
||||||
static_cast<int>(summaries.size()));
|
static_cast<int>(summaries.size()));
|
||||||
ASSERT_EQ(second_result, 1);
|
|
||||||
EXPECT_EQ(summaries[0].frame_index, static_cast<std::uint32_t>(1));
|
ASSERT_EQ(result, 1);
|
||||||
|
EXPECT_EQ(summaries[0].frame_index, 1U);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 销毁和错误处理测试
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// 测试:销毁空句柄
|
||||||
|
TEST(XYParserApiTests, DestroyParserAcceptsNullHandle)
|
||||||
|
{
|
||||||
|
EXPECT_NO_THROW(XYParser_DestroyParser(nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试:连续创建和销毁
|
||||||
|
TEST(XYParserApiTests, CreateAndDestroyMultipleParsers)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 10; ++i) {
|
||||||
|
ParserGuard parser(XYParser_CreateParser(8));
|
||||||
|
EXPECT_NE(parser.get(), nullptr);
|
||||||
|
}
|
||||||
|
// 析构时自动销毁所有解析器
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
/// 测试:GetLastError 在正常操作后
|
||||||
|
TEST(XYParserApiTests, GetLastErrorAfterSuccessfulCreate)
|
||||||
|
{
|
||||||
|
ParserGuard parser(XYParser_CreateParser(8));
|
||||||
|
ASSERT_NE(parser.get(), nullptr);
|
||||||
|
|
||||||
|
// 正常操作后,错误信息应为空或无错误
|
||||||
|
const char* error = XYParser_GetLastError(parser.get());
|
||||||
|
// 错误信息可能为空或特定实现
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试:GetLastError 在空句柄上
|
||||||
|
TEST(XYParserApiTests, GetLastErrorReturnsMessageForNullParser)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(std::string(XYParser_GetLastError(nullptr)), std::string("invalid parser handle"));
|
||||||
|
}
|
||||||
|
*/
|
||||||
Reference in New Issue
Block a user