Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds helper macro expect_packet_and_send_response. #591

Merged
merged 8 commits into from
Dec 19, 2021
51 changes: 50 additions & 1 deletion src/dcc/DccDebug.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,56 @@ string packet_to_string(const DCCPacket &pkt, bool bin_payload)
else if (cmd == 0 && is_idle_packet)
{
}

else if ((cmd >> 4) == 0b1110)
{
// POM command
options += " POM CV";
unsigned kk = (cmd >> 2) & 3;
unsigned cv = (cmd & 3) << 8;
cv |= pkt.payload[ofs];
ofs++;
options += StringPrintf("%d", cv + 1);
uint8_t d = pkt.payload[ofs++];

switch (kk)
{
case 0b00:
{
options += StringPrintf(" resvd %02x", d);
break;
}
case 0b01:
{
options += StringPrintf(" read/verify %d", d);
break;
}
case 0b11:
{
options += StringPrintf(" write = %d", d);
break;
}
case 0b10:
{
unsigned bit = d & 7;
unsigned value = (d >> 3) & 1;
if ((d & 0xE0) != 0xE0)
{
options += StringPrintf(" bit manipulate unknown (%02x)", d);
break;
}
if ((d & 0x10) == 0x10)
{
options += StringPrintf(" bit %d write = %d", bit, value);
}
else
{
options += StringPrintf(" bit %d verify ?= %d", bit, value);
}
break;
}
}
}

// checksum of packet
if (ofs == pkt.dlc && pkt.packet_header.skip_ec == 0)
{
Expand Down
32 changes: 32 additions & 0 deletions src/dcc/DccDebug.cxxtest
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,38 @@ TEST(DccDebug, F21_28)
EXPECT_EQ("[dcc] Short Address 3 F[21-28]=01101001", packet_to_string(pkt));
}

TEST(DccDebug, POMWrite)
{
Packet pkt;
pkt.add_dcc_address(DccShortAddress(3));
pkt.add_dcc_pom_write1(13, 67);
EXPECT_EQ(
"[dcc] Short Address 3 POM CV14 write = 67", packet_to_string(pkt));
}

TEST(DccDebug, POMWriteHighCV)
{
Packet pkt;
pkt.add_dcc_address(DccShortAddress(3));
pkt.add_dcc_pom_write1(950, 255);
EXPECT_EQ(
"[dcc] Short Address 3 POM CV951 write = 255", packet_to_string(pkt));
pkt.clear();
pkt.add_dcc_address(DccShortAddress(3));
pkt.add_dcc_pom_write1(1023, 0);
EXPECT_EQ(
"[dcc] Short Address 3 POM CV1024 write = 0", packet_to_string(pkt));
}

TEST(DccDebug, POMRead)
{
Packet pkt;
pkt.add_dcc_address(DccShortAddress(3));
pkt.add_dcc_pom_read1(13);
EXPECT_EQ(
"[dcc] Short Address 3 POM CV14 read/verify 0", packet_to_string(pkt));
}

TEST(DccDebug, Accy)
{
Packet pkt;
Expand Down
36 changes: 34 additions & 2 deletions src/dcc/dcc_test_utils.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,42 @@ dcc::Packet packet_from(uint8_t hdr, std::vector<uint8_t> payload)
return pkt;
}

MATCHER_P2(PacketIs, hdr, payload,
std::string(" is a packet of ") + PrintToString(packet_from(hdr, payload)))
MATCHER_P2(PacketIs, hdr, payload, PrintToString(packet_from(hdr, payload)))
{
dcc::Packet pkt = packet_from(hdr, payload);
dcc::Packet argc = arg;
vector<uint8_t> exp_bytes(pkt.payload, pkt.payload + pkt.dlc);
vector<uint8_t> act_bytes(arg.payload, arg.payload + arg.dlc);
if (pkt.packet_header.is_pkt == 0 && pkt.packet_header.is_marklin == 0 &&
arg.packet_header.is_pkt == 0 && arg.packet_header.is_marklin == 0 &&
pkt.packet_header.skip_ec != arg.packet_header.skip_ec)
{
// Mismatch in whether the EC byte is there. We fix this by adding the
// EC byte to the place where it is missing. This avoids test failures
// where the packets really are equivalent.
if (pkt.packet_header.skip_ec == 0)
{
uint8_t ec = 0;
for (uint8_t b : exp_bytes)
{
ec ^= b;
}
exp_bytes.push_back(ec);
pkt.packet_header.skip_ec = 1;
}
if (arg.packet_header.skip_ec == 0)
{
uint8_t ec = 0;
for (uint8_t b : act_bytes)
{
ec ^= b;
}
act_bytes.push_back(ec);
argc.packet_header.skip_ec = 1;
}
return (pkt.header_raw_data == argc.header_raw_data &&
exp_bytes == act_bytes);
}
return (pkt.header_raw_data == arg.header_raw_data && pkt.dlc == arg.dlc &&
memcmp(pkt.payload, arg.payload, pkt.dlc) == 0);
}
Expand Down
20 changes: 20 additions & 0 deletions src/utils/async_if_test_helper.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,26 @@ protected:
#define expect_packet(gc_packet) \
EXPECT_CALL(canBus_, mwrite(StrCaseEq(gc_packet)))

/** Adds an expectation that the code will send a packet to the CANbus. Upon
* receiving that packet, sends a packet to CAN-bus. This is helpful when the
* test script is simulating a node connected to the CAN-bus and that remote
* node has to respond with an ack to the packet emitted by the code under
* test.

Example:
expect_packet_and_send_response(":X1A555444N0102030405060708;",
":X19A28555N044400;");

@param gc_packet the packet that the code under test should emit, in
GridConnect format, including the leading : and trailing ;
@param resp_packet the packet that will be sent to the code under test
after seeing the emitted packet.
*/
#define expect_packet_and_send_response(gc_packet, resp_packet) \
EXPECT_CALL(canBus_, mwrite(StrCaseEq(gc_packet))) \
.WillOnce(::testing::InvokeWithoutArgs( \
[this]() { send_packet(resp_packet); }))

/** Ignores all produced packets.
*
* Tihs can be used in tests where the expectations are tested in a higher
Expand Down