146 lines
4.2 KiB
C++
146 lines
4.2 KiB
C++
#include <gtest/gtest.h>
|
|
#include "../XYParserApi.h"
|
|
|
|
#include <array>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
|
|
class ParserGuard {
|
|
public:
|
|
explicit ParserGuard(XYParserHandle handle) : handle_(handle) {}
|
|
|
|
~ParserGuard()
|
|
{
|
|
if (handle_ != nullptr) {
|
|
XYParser_DestroyParser(handle_);
|
|
}
|
|
}
|
|
|
|
XYParserHandle get() const
|
|
{
|
|
return handle_;
|
|
}
|
|
|
|
private:
|
|
XYParserHandle handle_;
|
|
};
|
|
|
|
std::vector<std::uint8_t> BuildMinimalFrame(std::uint8_t channel_count)
|
|
{
|
|
constexpr std::size_t kSamplesPerFrame = 5;
|
|
constexpr std::uint8_t kHeader = 0xAA;
|
|
constexpr std::uint8_t kTail = 0x55;
|
|
constexpr std::size_t kTagLen = 25;
|
|
|
|
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::size_t frame_size = 1 + kTagLen + payload_length + 2;
|
|
|
|
std::vector<std::uint8_t> frame(frame_size, 0);
|
|
std::size_t offset = 0;
|
|
|
|
frame[offset++] = kHeader;
|
|
|
|
frame[offset++] = 0x01;
|
|
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 & 0xFF);
|
|
|
|
frame[offset++] = 95;
|
|
frame[offset++] = channel_count;
|
|
|
|
offset += 2 + 2 + 2 + 2 + 2 + 6;
|
|
|
|
for (std::size_t sample = 0; sample < kSamplesPerFrame; ++sample) {
|
|
for (std::size_t channel = 0; channel < channel_count; ++channel) {
|
|
frame[offset++] = 0x00;
|
|
frame[offset++] = 0x00;
|
|
frame[offset++] = static_cast<std::uint8_t>(sample + channel + 1);
|
|
}
|
|
frame[offset++] = 0x00;
|
|
frame[offset++] = 0x00;
|
|
}
|
|
|
|
frame[offset++] = 0x00;
|
|
frame[offset++] = kTail;
|
|
frame[offset++] = kTail;
|
|
|
|
return frame;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TEST(XYParserApiTests, CreateParserRejectsUnsupportedChannelCount)
|
|
{
|
|
EXPECT_EQ(XYParser_CreateParser(7), nullptr);
|
|
}
|
|
|
|
TEST(XYParserApiTests, GetLastErrorReturnsMessageForNullParser)
|
|
{
|
|
EXPECT_EQ(std::string(XYParser_GetLastError(nullptr)), std::string("invalid parser handle"));
|
|
}
|
|
|
|
TEST(XYParserApiTests, FeedParsesAComplete8ChannelFrame)
|
|
{
|
|
ParserGuard parser(XYParser_CreateParser(8));
|
|
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(8);
|
|
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].frame_index, static_cast<std::uint32_t>(1));
|
|
EXPECT_EQ(summaries[0].channel_count, static_cast<std::uint8_t>(8));
|
|
EXPECT_EQ(summaries[0].battery, static_cast<std::uint8_t>(95));
|
|
EXPECT_EQ(summaries[0].sample_count, static_cast<std::uint8_t>(5));
|
|
EXPECT_GT(summaries[0].channel_values_uv[0][0], 0.0);
|
|
EXPECT_EQ(summaries[0].trigger_types[0], static_cast<std::uint8_t>(0));
|
|
EXPECT_EQ(summaries[0].trigger_indices[0], static_cast<std::uint8_t>(0));
|
|
}
|
|
|
|
TEST(XYParserApiTests, FeedBuffersPartialDataUntilAFullFrameIsAvailable)
|
|
{
|
|
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{};
|
|
|
|
const int first_result = XYParser_Feed(
|
|
parser.get(),
|
|
bytes.data(),
|
|
split_index,
|
|
summaries.data(),
|
|
static_cast<int>(summaries.size()));
|
|
EXPECT_EQ(first_result, 0);
|
|
|
|
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);
|
|
EXPECT_EQ(summaries[0].frame_index, static_cast<std::uint32_t>(1));
|
|
}
|