#include "icsneo/icsneocpp.h" #include "icsneo/communication/encoder.h" #include "icsneo/communication/packet/a2bpacket.h" #include "icsneo/communication/packetizer.h" #include "icsneo/api/eventmanager.h" #include "gtest/gtest.h" #include using namespace icsneo; class A2BEncoderDecoderTest : public ::testing::Test { protected: void SetUp() override { report = [](APIEvent::Type, APIEvent::Severity) { // Unless caught by the test, the packetizer should not throw errors EXPECT_TRUE(false); }; packetizer.emplace([this](APIEvent::Type t, APIEvent::Severity s) { report(t, s); }); packetEncoder.emplace([this](APIEvent::Type t, APIEvent::Severity s) { report(t, s); }); packetDecoder.emplace([this](APIEvent::Type t, APIEvent::Severity s) { report(t, s); }); A2BPCMSample initialSample = 10 << 8; constructTest( msg1, msg1Encoded, {1,1,0,0,0,0}, 1, true, false, false, false, false, 0, 3, initialSample ); initialSample = (29 << 16) | (10 << 8); constructTest( msg2, msg2Encoded, {1,0,9,0,0,0}, 1, false, true, false, false, true, 0, 1, initialSample ); initialSample = (29 << 16) | (10 << 8); constructTest( msg3, msg3Encoded, {2,0,6,0,0xAA,0xFF}, 2, false, false, true, true, false, 0xFFAA, 3, initialSample ); constructTest( msg4, msg4Encoded, {4,0,6,0,0xAA,0xFF}, 4, false, false, true, true, false, 0xFFAA, 0, initialSample ); } void constructTest( std::shared_ptr& testMsg, std::vector& testMsgEncoded, std::array encodedHeader, uint8_t numChannels, bool channelSize16, bool monitor, bool txmsg, bool errIndicator, bool syncFrame, uint16_t rfu2, uint32_t numFrames, A2BPCMSample initialSample ) { testMsg = std::make_shared( (uint8_t)(channelSize16 ? 16 : 24), (uint8_t)(channelSize16 ? 2 : 4), numChannels ); auto addSample = [&]( uint8_t channel, A2BMessage::A2BDirection dir ) { testMsg->addSample(std::move(initialSample), dir, channel); for(size_t i = 0; i < static_cast(testMsg->getBytesPerSample()); i++) { testMsgEncoded.push_back(static_cast(initialSample >> (i * 8))); } initialSample++; }; testMsg->network = Network(Network::NetID::A2B1); testMsg->channelSize16 = channelSize16; testMsg->monitor = monitor; testMsg->txmsg = txmsg; testMsg->errIndicator = errIndicator; testMsg->syncFrame = syncFrame; testMsg->rfu2 = rfu2; testMsgEncoded.reserve( HardwareA2BPacket::coreMiniMessageHeaderSize + numFrames * static_cast(testMsg->getBytesPerSample()) ); testMsgEncoded.insert( testMsgEncoded.end(), encodedHeader.begin(), encodedHeader.end() ); // Insert header appendCoreMiniHeaderOffset(testMsgEncoded); for(unsigned int frame = 0; frame < numFrames; frame++) { for(uint8_t channel = 0; channel < testMsg->getNumChannels(); channel++) { addSample(channel, A2BMessage::A2BDirection::DownStream); addSample(channel, A2BMessage::A2BDirection::UpStream); } } } void appendCoreMiniHeaderOffset(std::vector& buf) { for( size_t i = 0; i < (HardwareA2BPacket::coreMiniMessageHeaderSize - HardwareA2BPacket::a2bHeaderSize); i++ ) { buf.push_back(0); } } void decrementEncodedMessageSize(std::vector& bytestream) { if(bytestream.size() < 6) return; uint16_t size = (bytestream[3] << 8) | bytestream[2]; if(size == 0) return; size--; bytestream[2] = (uint8_t)size; bytestream[3] = (uint8_t)(size >> 8); } void testMessage(std::shared_ptr& msg, std::vector& msgEncoded) { std::vector bytestream; std::vector rawPacketBytes; std::shared_ptr decodeMsg; std::shared_ptr decodeA2BMsg; EXPECT_TRUE(packetEncoder->encode(*packetizer, bytestream, msg)); rawPacketBytes = std::vector(bytestream.begin() + 6, bytestream.end()); EXPECT_EQ(rawPacketBytes, msgEncoded); decrementEncodedMessageSize(bytestream); EXPECT_TRUE(packetizer->input(bytestream)); auto packets = packetizer->output(); if(packets.empty()) { EXPECT_TRUE(false);} EXPECT_TRUE(packetDecoder->decode(decodeMsg, packets.back())); decodeA2BMsg = std::static_pointer_cast(decodeMsg); EXPECT_EQ(*msg, *decodeA2BMsg); } device_eventhandler_t report; std::optional packetEncoder; std::optional packetizer; std::optional packetDecoder; std::shared_ptr msg1; std::vector msg1Encoded; std::shared_ptr msg2; std::vector msg2Encoded; std::shared_ptr msg3; std::vector msg3Encoded; std::shared_ptr msg4; std::vector msg4Encoded; }; TEST_F(A2BEncoderDecoderTest, ChannelSize16SingleChannel) { testMessage(msg1, msg1Encoded); } TEST_F(A2BEncoderDecoderTest, ChannelSize24MultiChannel) { testMessage(msg2, msg2Encoded); } TEST_F(A2BEncoderDecoderTest, ChannelSize24MultiChannelMultiFrame) { testMessage(msg3, msg3Encoded); } TEST_F(A2BEncoderDecoderTest, NoFrames) { testMessage(msg4, msg4Encoded); }