GCC Code Coverage Report


Directory: ./
File: tests/packetmanager/test_packetmanager.cpp
Date: 2025-09-29 13:19:55
Exec Total Coverage
Lines: 388 408 95.1%
Functions: 39 39 100.0%
Branches: 352 746 47.2%

Line Branch Exec Source
1 /*
2 ** EPITECH PROJECT, 2025
3 ** rtype
4 ** File description:
5 ** TODO: add description
6 */
7
8 #include <iostream>
9 #include <memory>
10 #include <functional>
11 #include <vector>
12 #include <cstring>
13 #include <cstdlib>
14 #include "packetmanager.h"
15
16 #define COLOR_RED "\033[31m"
17 #define COLOR_GREEN "\033[32m"
18 #define COLOR_YELLOW "\033[33m"
19 #define COLOR_BLUE "\033[34m"
20 #define COLOR_RESET "\033[0m"
21
22 // Test Framework Classes
23 class TestResult {
24 public:
25 int passed = 0;
26 int failed = 0;
27 int crashed = 0;
28
29 1 int total() const { return passed + failed + crashed; }
30
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 bool hasFailures() const { return failed > 0 || crashed > 0; }
31
32 1 void printSummary() const {
33 1 std::cout << "\n" << COLOR_BLUE << "=== Test Summary ===" << COLOR_RESET << std::endl;
34 1 std::cout << COLOR_GREEN << "Passed: " << passed << COLOR_RESET << std::endl;
35 1 std::cout << COLOR_RED << "Failed: " << failed << COLOR_RESET << std::endl;
36 1 std::cout << COLOR_YELLOW << "Crashed: " << crashed << COLOR_RESET << std::endl;
37 1 std::cout << COLOR_BLUE << "Total: " << total() << COLOR_RESET << std::endl;
38
39
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!hasFailures()) {
40 1 std::cout << COLOR_GREEN << "All tests passed! ✓" << COLOR_RESET << std::endl;
41 } else {
42 std::cout << COLOR_RED << "Some tests failed! ✗" << COLOR_RESET << std::endl;
43 }
44 1 }
45 };
46
47 class TestRunner {
48 private:
49 TestResult result;
50
51 55 void log(const std::string& level, const std::string& message, const std::string& color) {
52 55 std::cout << "[" << color << level << COLOR_RESET << "] " << message << std::endl;
53 55 }
54
55 public:
56 template<typename T>
57 82 void assertEqual(const std::string& testName, const T& expected, const T& actual, const std::string& description = "") {
58
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
82 if (expected == actual) {
59 82 result.passed++;
60
3/6
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 41 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 41 times.
✗ Branch 8 not taken.
328 log("PASS", testName, COLOR_GREEN);
61 } else {
62 result.failed++;
63 log("FAIL", testName, COLOR_RED);
64 std::cout << COLOR_RED << "-> " << description << " Expected: " << expected
65 << ", Actual: " << actual << COLOR_RESET << std::endl;
66 }
67 82 }
68
69 3 void assertStringEqual(const std::string& testName, const char* expected, const char* actual, const std::string& description = "") {
70
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (strcmp(expected, actual) == 0) {
71 3 result.passed++;
72
3/6
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
12 log("PASS", testName, COLOR_GREEN);
73 } else {
74 result.failed++;
75 log("FAIL", testName, COLOR_RED);
76 std::cout << COLOR_RED << "-> " << description << " Expected: '" << expected
77 << "', Actual: '" << actual << "'" << COLOR_RESET << std::endl;
78 }
79 3 }
80
81 11 void assertTrue(const std::string& testName, bool condition, const std::string& description = "") {
82
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (condition) {
83 11 result.passed++;
84
3/6
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 8 not taken.
44 log("PASS", testName, COLOR_GREEN);
85 } else {
86 result.failed++;
87 log("FAIL", testName, COLOR_RED);
88 std::cout << COLOR_RED << "-> " << description << COLOR_RESET << std::endl;
89 }
90 11 }
91
92 5 void runTest(const std::string& testName, std::function<void()> testFunction) {
93 try {
94
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 testFunction();
95 } catch (const std::exception& e) {
96 result.crashed++;
97 log("CRASH", testName + " - Exception: " + e.what(), COLOR_RED);
98 } catch (...) {
99 result.crashed++;
100 log("CRASH", testName + " - Unknown exception", COLOR_RED);
101 }
102 5 }
103
104 1 TestResult getResult() const { return result; }
105
106 void printProgress() const {
107 std::cout << COLOR_BLUE << "Progress: " << result.total() << " tests completed" << COLOR_RESET << std::endl;
108 }
109 };
110
111 // Test Data Structure
112 typedef struct super_packet_s {
113 int my_age;
114 bool im_gay;
115 char my_name[50];
116 } super_packet_t;
117
118 // Test Helper Functions
119 class PacketTestHelper {
120 public:
121 35 static super_packet_t createTestPacket(int age = 25, bool gay = true, const char* name = "John Doe") {
122 super_packet_t packet;
123 35 packet.my_age = age;
124 35 packet.im_gay = gay;
125 35 strncpy(packet.my_name, name, sizeof(packet.my_name) - 1);
126 35 packet.my_name[sizeof(packet.my_name) - 1] = '\0';
127 35 return packet;
128 }
129
130 36 static void* createPacketData(const super_packet_t& packet) {
131 36 void* data = malloc(sizeof(super_packet_t));
132 36 memcpy(data, &packet, sizeof(super_packet_t));
133 36 return data;
134 }
135
136 3 static void transferPacket(PacketManager& sender, PacketManager& receiver) {
137
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 std::vector<std::unique_ptr<packet_t>> to_send = sender.fetchPacketsToSend();
138
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 if (!to_send.empty()) {
139 3 packet_t* packet = to_send[0].get();
140
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 std::vector<uint8_t> raw_packet = PacketManager::serializePacket(*packet);
141
1/2
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
3 receiver.handlePacketBytes(raw_packet.data(), raw_packet.size());
142 3 }
143 3 }
144 };
145
146 // Test Functions
147 1 void testPacketSending(TestRunner& runner) {
148
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 PacketManager manager;
149 1 super_packet_t testPacket = PacketTestHelper::createTestPacket();
150 1 void* data = PacketTestHelper::createPacketData(testPacket);
151 1 size_t data_size = sizeof(super_packet_t);
152 size_t output_size;
153
154
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto packet_data = manager.sendPacketBytesSafe(data, data_size, 1, &output_size, true);
155
156
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
4 runner.assertEqual("Send buffer size check", 1UL, manager._get_buffer_send()->size(), "Buffer should contain 1 packet");
157
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertEqual("Send sequence ID check", 1U, manager._get_send_seqid(), "Sequence ID should be 1");
158
159 1 free(data);
160 1 }
161
162 1 void testPacketTransfer(TestRunner& runner) {
163
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 PacketManager sender, receiver;
164 1 super_packet_t testPacket = PacketTestHelper::createTestPacket();
165 1 void* data = PacketTestHelper::createPacketData(testPacket);
166 1 size_t data_size = sizeof(super_packet_t);
167 size_t output_size;
168
169
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto packet_data = sender.sendPacketBytesSafe(data, data_size, 1, &output_size, true);
170
171
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
3 runner.runTest("Packet transfer", [&]() {
172 1 PacketTestHelper::transferPacket(sender, receiver);
173 1 });
174
175 1 free(data);
176 1 }
177
178 1 void testPacketReception(TestRunner& runner) {
179
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 PacketManager sender, receiver;
180 1 super_packet_t testPacket = PacketTestHelper::createTestPacket();
181 1 void* data = PacketTestHelper::createPacketData(testPacket);
182 1 size_t data_size = sizeof(super_packet_t);
183 size_t output_size;
184
185 // Send and transfer packet
186
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto packet_data = sender.sendPacketBytesSafe(data, data_size, 1, &output_size, true);
187
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 PacketTestHelper::transferPacket(sender, receiver);
188
189 // Test reception
190
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertEqual("Receive sequence ID", 1U, receiver._get_recv_seqid(), "Received sequence ID should be 1");
191
192
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> mailbox = receiver.fetchReceivedPackets();
193
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
4 runner.assertEqual("Received packets count", 1UL, mailbox.size(), "Should receive exactly 1 packet");
194
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
3 runner.assertEqual("Buffer cleared after fetch", 0UL, receiver._get_buffer_received()->size(), "Buffer should be empty after fetch");
195
196 1 free(data);
197 1 }
198
199 1 void testPacketData(TestRunner& runner) {
200
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 PacketManager sender, receiver;
201 1 super_packet_t testPacket = PacketTestHelper::createTestPacket(25, true, "John Doe");
202 1 void* data = PacketTestHelper::createPacketData(testPacket);
203 1 size_t data_size = sizeof(super_packet_t);
204 size_t output_size;
205
206 // Send, transfer, and receive packet
207
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto packet_data = sender.sendPacketBytesSafe(data, data_size, 1, &output_size, true);
208
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 PacketTestHelper::transferPacket(sender, receiver);
209
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> mailbox = receiver.fetchReceivedPackets();
210
211
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!mailbox.empty()) {
212 1 packet_t* packet = mailbox[0].get();
213
214 // Test header
215
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
4 runner.assertEqual("Packet type", (uint8_t)1, packet->header.type, "Packet type should be 1");
216
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
4 runner.assertEqual("Packet sequence ID", 1U, packet->header.seqid, "Packet sequence ID should be 1");
217
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
4 runner.assertEqual("Packet ACK", 0U, packet->header.ack, "Packet ACK should be 0");
218
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
3 runner.assertEqual("Packet data size", (uint32_t)sizeof(super_packet_t), packet->header.data_size, "Data size should match");
219
220 // Test data
221 1 super_packet_t* received_data = (super_packet_t*)packet->data;
222
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
4 runner.assertEqual("Data age", 25, received_data->my_age, "Age should be 25");
223
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
4 runner.assertEqual("Data boolean flag", true, received_data->im_gay, "Boolean flag should be true");
224
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
4 runner.assertStringEqual("Data name", "John Doe", received_data->my_name, "Name should be 'John Doe'");
225 } else {
226 runner.assertTrue("Packet data validation", false, "No packet received for data validation");
227 }
228
229 1 free(data);
230 1 }
231
232 1 void testMissingPacketsAndAck(TestRunner& runner) {
233
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 PacketManager sender, receiver;
234
235 // Create test packets
236 1 super_packet_t packet1 = PacketTestHelper::createTestPacket(25, true, "Packet 1");
237 1 super_packet_t packet2 = PacketTestHelper::createTestPacket(30, false, "Packet 2");
238 1 super_packet_t packet3 = PacketTestHelper::createTestPacket(35, true, "Packet 3");
239
240 1 void* data1 = PacketTestHelper::createPacketData(packet1);
241 1 void* data2 = PacketTestHelper::createPacketData(packet2);
242 1 void* data3 = PacketTestHelper::createPacketData(packet3);
243 1 size_t data_size1 = sizeof(super_packet_t);
244 1 size_t data_size2 = sizeof(super_packet_t);
245 1 size_t data_size3 = sizeof(super_packet_t);
246 size_t output_size1, output_size2, output_size3;
247
248 // Send 3 packets using the safer method
249
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto packet_data1 = sender.sendPacketBytesSafe(data1, data_size1, 1, &output_size1, true);
250
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto packet_data2 = sender.sendPacketBytesSafe(data2, data_size2, 1, &output_size2, true);
251
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto packet_data3 = sender.sendPacketBytesSafe(data3, data_size3, 1, &output_size3, true);
252
253 // Get packets to send
254
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> packets_to_send = sender.fetchPacketsToSend();
255
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertEqual("Sender prepared 3 packets", 3UL, packets_to_send.size(), "Should have 3 packets to send");
256
257 // Transfer packet 1 (seqid=1) - normal delivery
258
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (packets_to_send.size() > 0) {
259
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 std::vector<uint8_t> raw_packet1 = PacketManager::serializePacket(*packets_to_send[0]);
260
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 receiver.handlePacketBytes(raw_packet1.data(), raw_packet1.size());
261 1 }
262
263 // Skip packet 2 (seqid=2) - simulate packet loss
264
265 // Transfer packet 3 (seqid=3) - this should trigger missing packet detection
266
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (packets_to_send.size() > 2) {
267
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 std::vector<uint8_t> raw_packet3 = PacketManager::serializePacket(*packets_to_send[2]);
268
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 receiver.handlePacketBytes(raw_packet3.data(), raw_packet3.size());
269 1 }
270
271 // Check receiver state
272
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertEqual("Receiver seqid after gap", 3U, receiver._get_recv_seqid(), "Should have seqid=3 after receiving packet 3");
273
274 // Check missed packets list
275 1 const std::vector<uint32_t>* missed_packets = receiver._get_missed_packets();
276
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertEqual("Missed packets count", 0UL, missed_packets->size(), "Should detect 0 missing packet (already concerted to a pending ack packet)");
277
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!missed_packets->empty()) {
278 runner.assertEqual("Missing packet seqid", 2U, (*missed_packets)[0], "Should detect packet 2 as missing");
279 }
280
281 // Check that receiver generated ACK packets for missing packet
282
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> ack_packets = receiver.fetchPacketsToSend();
283
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertTrue("ACK packets generated", !ack_packets.empty(), "Should generate ACK packets for missing packet");
284
285
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!ack_packets.empty()) {
286 // Find ACK packet for seqid=2
287 1 bool found_ack_for_2 = false;
288
1/2
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 for (const auto& ack_packet : ack_packets) {
289
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (ack_packet->header.ack == 2) {
290 1 found_ack_for_2 = true;
291
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
4 runner.assertEqual("ACK packet type", (uint8_t)0, ack_packet->header.type, "ACK packet should have type 0");
292
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
4 runner.assertEqual("ACK packet seqid", 0U, ack_packet->header.seqid, "ACK packet should have seqid 0");
293
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
4 runner.assertEqual("ACK packet data_size", 0U, ack_packet->header.data_size, "ACK packet should have no data");
294
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertTrue("ACK packet data is null", ack_packet->data == nullptr, "ACK packet should have null data");
295 1 break;
296 }
297 }
298
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
4 runner.assertTrue("ACK for missing packet 2", found_ack_for_2, "Should generate ACK packet with ack=2");
299 }
300
301 // Test received packets - should only have packet 1 and 3
302
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> received_packets = receiver.fetchReceivedPackets();
303
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertEqual("Received packets count", 2UL, received_packets.size(), "Should receive 2 packets (1 and 3)");
304
305
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (received_packets.size() >= 2) {
306 // Packets should be sorted by seqid
307
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
4 runner.assertEqual("First received packet seqid", 1U, received_packets[0]->header.seqid, "First packet should be seqid=1");
308
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
3 runner.assertEqual("Second received packet seqid", 3U, received_packets[1]->header.seqid, "Second packet should be seqid=3");
309
310 // Check data content
311 1 super_packet_t* data1_received = (super_packet_t*)received_packets[0]->data;
312 1 super_packet_t* data3_received = (super_packet_t*)received_packets[1]->data;
313
314
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
4 runner.assertStringEqual("Packet 1 data", "Packet 1", data1_received->my_name, "Packet 1 should contain 'Packet 1'");
315
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
4 runner.assertStringEqual("Packet 3 data", "Packet 3", data3_received->my_name, "Packet 3 should contain 'Packet 3'");
316 }
317
318 // Cleanup
319 1 free(data1);
320 1 free(data2);
321 1 free(data3);
322 1 }
323
324 1 void testAckPacketRetransmission(TestRunner& runner) {
325
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 PacketManager sender, receiver;
326
327 // Create a test packet
328 1 super_packet_t testPacket = PacketTestHelper::createTestPacket(42, true, "Retrans Test");
329 1 void* data = PacketTestHelper::createPacketData(testPacket);
330 1 void* data2 = PacketTestHelper::createPacketData(testPacket);
331 1 size_t data_size = sizeof(super_packet_t);
332 1 size_t data_size2 = sizeof(super_packet_t);
333 size_t output_size, output_size2;
334
335 // Send first packet using the safer method
336
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto packet_data = sender.sendPacketBytesSafe(data, data_size, 1, &output_size, true);
337
338 // Get the packet to send
339
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> packets_to_send = sender.fetchPacketsToSend();
340
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertEqual("Sender has packet to send", 1UL, packets_to_send.size(), "Should have 1 packet to send");
341
342 // Simulate packet loss - don't deliver packet 1
343 // Send packet 2 to trigger missing packet detection
344
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto packet_data2 = sender.sendPacketBytesSafe(data2, data_size2, 2, &output_size2, true);
345
346
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> second_batch = sender.fetchPacketsToSend();
347
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (second_batch.size() > 0) {
348 // Send packet 2, skip packet 1
349
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 std::vector<uint8_t> raw_packet2 = PacketManager::serializePacket(*second_batch[0]);
350
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 receiver.handlePacketBytes(raw_packet2.data(), raw_packet2.size());
351 1 }
352
353 // Get ACK packets from receiver
354
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> ack_packets = receiver.fetchPacketsToSend();
355
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertTrue("Receiver generated ACK packets", !ack_packets.empty(), "Should generate ACK for missing packet 1");
356
357 // Send ACK back to sender to test retransmission logic
358
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!ack_packets.empty()) {
359
1/2
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 for (const auto& ack_packet : ack_packets) {
360
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (ack_packet->header.ack == 1) { // ACK for missing packet 1
361
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 std::vector<uint8_t> ack_raw = PacketManager::serializePacket(*ack_packet);
362
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 sender.handlePacketBytes(ack_raw.data(), ack_raw.size());
363
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
3 runner.assertTrue("ACK processed by sender", true, "Sender should process ACK packet");
364 1 break;
365 1 }
366 }
367 }
368
369 // Check that sender queues packet for retransmission
370
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> retrans_packets = sender.fetchPacketsToSend();
371
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertTrue("Retransmission packets queued", !retrans_packets.empty(), "Sender should queue packets for retransmission after ACK");
372
373 // Cleanup
374 1 free(data);
375 1 free(data2);
376 1 }
377
378 1 void corruptedPacketHeaderIsRejected(TestRunner& runner) {
379
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 PacketManager receiver;
380
381 1 uint8_t corrupted_data[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
382
383
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
3 runner.runTest("Corrupted packet header rejection", [&]() {
384 1 receiver.handlePacketBytes(corrupted_data, sizeof(corrupted_data));
385 1 });
386
387
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
4 runner.assertEqual("No packets received from corrupted header", 0UL, receiver._get_buffer_received()->size(), "Corrupted packets should be rejected");
388
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertEqual("Receiver seqid unchanged after corruption", 0U, receiver._get_recv_seqid(), "Seqid should remain 0");
389 1 }
390
391 1 void packetWithInvalidSizeIsRejected(TestRunner& runner) {
392
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 PacketManager sender, receiver;
393 1 super_packet_t testPacket = PacketTestHelper::createTestPacket();
394 1 void* data = PacketTestHelper::createPacketData(testPacket);
395 1 size_t data_size = sizeof(super_packet_t);
396 size_t output_size;
397
398 // Use safer method to send the packet
399
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto packet_data = sender.sendPacketBytesSafe(data, data_size, 1, &output_size, true);
400
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> packets_to_send = sender.fetchPacketsToSend();
401
402
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!packets_to_send.empty()) {
403
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 std::vector<uint8_t> raw_packet = PacketManager::serializePacket(*packets_to_send[0]);
404
405
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
3 runner.runTest("Invalid packet size rejection", [&]() {
406 1 receiver.handlePacketBytes(raw_packet.data(), raw_packet.size() - 5);
407 1 });
408 1 }
409
410
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
3 runner.assertEqual("No packets received with invalid size", 0UL, receiver._get_buffer_received()->size(), "Invalid size packets should be rejected");
411 1 free(data);
412 1 }
413
414 1 void emptyPacketDataIsHandledCorrectly(TestRunner& runner) {
415
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 PacketManager manager;
416 size_t output_size;
417
418 // Use safer method to send empty packet
419
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto packet_data = manager.sendPacketBytesSafe(nullptr, 0, 1, &output_size, true);
420
421
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
3 runner.assertEqual("Empty packet queued", 1UL, manager._get_buffer_send()->size(), "Empty packets should be allowed");
422
423
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> packets = manager.fetchPacketsToSend();
424
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!packets.empty()) {
425
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
4 runner.assertEqual("Empty packet data size", 0U, packets[0]->header.data_size, "Empty packet should have data_size=0");
426
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
4 runner.assertTrue("Empty packet data is null", packets[0]->data == nullptr, "Empty packet data should be null");
427 }
428 1 }
429
430 1 void veryLargePacketIsHandled(TestRunner& runner) {
431
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 PacketManager manager;
432 1 const size_t large_size = 65536;
433 1 void* large_data = malloc(large_size);
434 1 memset(large_data, 0xAB, large_size);
435 1 size_t data_size = large_size;
436 size_t output_size;
437
438 // Use safer method to send large packet
439
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
3 runner.runTest("Large packet handling", [&]() {
440
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto packet_data = manager.sendPacketBytesSafe(large_data, data_size, 1, &output_size, true);
441 1 });
442
443
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
3 runner.assertEqual("Large packet queued", 1UL, manager._get_buffer_send()->size(), "Large packets should be handled");
444
445
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> packets = manager.fetchPacketsToSend();
446
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!packets.empty()) {
447
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
4 runner.assertEqual("Large packet data size", (uint32_t)large_size, packets[0]->header.data_size, "Large packet size should be preserved");
448 }
449
450 1 free(large_data);
451 1 }
452
453 1 void sequenceIdOverflowIsHandled(TestRunner& runner) {
454
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 PacketManager manager;
455
456
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 for (uint32_t i = 0; i < UINT32_MAX; i += 1000000000) {
457 5 super_packet_t testPacket = PacketTestHelper::createTestPacket();
458 5 void* data = PacketTestHelper::createPacketData(testPacket);
459 5 size_t data_size = sizeof(super_packet_t);
460 size_t output_size;
461
462 // Use safer method to send packets
463
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 auto packet_data = manager.sendPacketBytesSafe(data, data_size, 1, &output_size, true);
464
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 manager.fetchPacketsToSend();
465 5 free(data);
466
467
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (i > UINT32_MAX - 1000000000) break;
468
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
5 }
469
470
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertTrue("Sequence ID near overflow handled", manager._get_send_seqid() > 0, "Sequence ID should handle large values");
471 1 }
472
473 1 void multipleConsecutiveMissingPacketsAreDetected(TestRunner& runner) {
474
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 PacketManager sender, receiver;
475
476
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 for (int i = 1; i <= 5; i++) {
477
1/2
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 super_packet_t packet = PacketTestHelper::createTestPacket(20 + i, true, ("Packet " + std::to_string(i)).c_str());
478 5 void* data = PacketTestHelper::createPacketData(packet);
479 5 size_t data_size = sizeof(super_packet_t);
480 size_t output_size;
481
482 // Use safer method to send packets
483
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 auto packet_data = sender.sendPacketBytesSafe(data, data_size, 1, &output_size, true);
484 5 free(data);
485 5 }
486
487
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> packets_to_send = sender.fetchPacketsToSend();
488
489
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (packets_to_send.size() >= 5) {
490
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 std::vector<uint8_t> packet1 = PacketManager::serializePacket(*packets_to_send[0]);
491
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 receiver.handlePacketBytes(packet1.data(), packet1.size());
492
493
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 std::vector<uint8_t> packet5 = PacketManager::serializePacket(*packets_to_send[4]);
494
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 receiver.handlePacketBytes(packet5.data(), packet5.size());
495 1 }
496
497 1 const std::vector<uint32_t>* missed_packets = receiver._get_missed_packets();
498
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertEqual("Multiple consecutive missing packets detected", 0UL, missed_packets->size(), "Missing packets should be converted to ACKs");
499
500
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> ack_packets = receiver.fetchPacketsToSend();
501
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertTrue("Multiple ACKs generated", ack_packets.size() >= 3, "Should generate ACKs for packets 2, 3, 4");
502 1 }
503
504 1 void duplicatePacketsAreHandledCorrectly(TestRunner& runner) {
505
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 PacketManager sender, receiver;
506 1 super_packet_t testPacket = PacketTestHelper::createTestPacket();
507 1 void* data = PacketTestHelper::createPacketData(testPacket);
508 1 size_t data_size = sizeof(super_packet_t);
509 size_t output_size;
510
511 // Use safer method to send the packet
512
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto packet_data = sender.sendPacketBytesSafe(data, data_size, 1, &output_size, true);
513
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> packets_to_send = sender.fetchPacketsToSend();
514
515
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!packets_to_send.empty()) {
516
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 std::vector<uint8_t> raw_packet = PacketManager::serializePacket(*packets_to_send[0]);
517
518
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 receiver.handlePacketBytes(raw_packet.data(), raw_packet.size());
519
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 receiver.handlePacketBytes(raw_packet.data(), raw_packet.size());
520 1 }
521
522
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> received_packets = receiver.fetchReceivedPackets();
523
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertEqual("Duplicate packet handling", 2UL, received_packets.size(), "Duplicate packets should be processed");
524
525 1 free(data);
526 1 }
527
528 1 void outOfOrderPacketDeliveryWorks(TestRunner& runner) {
529
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 PacketManager sender, receiver;
530
531
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for (int i = 1; i <= 4; i++) {
532
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 super_packet_t packet = PacketTestHelper::createTestPacket(i, true, ("Packet " + std::to_string(i)).c_str());
533 4 void* data = PacketTestHelper::createPacketData(packet);
534 4 size_t data_size = sizeof(super_packet_t);
535 size_t output_size;
536
537 // Use safer method to send packets
538
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 auto packet_data = sender.sendPacketBytesSafe(data, data_size, 1, &output_size, true);
539 4 free(data);
540 4 }
541
542
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> packets_to_send = sender.fetchPacketsToSend();
543
544
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (packets_to_send.size() >= 4) {
545
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 std::vector<uint8_t> packet4 = PacketManager::serializePacket(*packets_to_send[3]);
546
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 std::vector<uint8_t> packet2 = PacketManager::serializePacket(*packets_to_send[1]);
547
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 std::vector<uint8_t> packet1 = PacketManager::serializePacket(*packets_to_send[0]);
548
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 std::vector<uint8_t> packet3 = PacketManager::serializePacket(*packets_to_send[2]);
549
550
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 receiver.handlePacketBytes(packet4.data(), packet4.size());
551
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 receiver.handlePacketBytes(packet2.data(), packet2.size());
552
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 receiver.handlePacketBytes(packet1.data(), packet1.size());
553
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 receiver.handlePacketBytes(packet3.data(), packet3.size());
554 1 }
555
556
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> received_packets = receiver.fetchReceivedPackets();
557
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertEqual("Out of order packets received", 4UL, received_packets.size(), "All packets should be received");
558
559
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (received_packets.size() >= 4) {
560
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
4 runner.assertEqual("Packets sorted by seqid", 1U, received_packets[0]->header.seqid, "First packet should have seqid=1");
561
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
4 runner.assertEqual("Packets sorted by seqid", 2U, received_packets[1]->header.seqid, "Second packet should have seqid=2");
562
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
4 runner.assertEqual("Packets sorted by seqid", 3U, received_packets[2]->header.seqid, "Third packet should have seqid=3");
563
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
4 runner.assertEqual("Packets sorted by seqid", 4U, received_packets[3]->header.seqid, "Fourth packet should have seqid=4");
564 }
565 1 }
566
567 1 void corruptedDataFieldIsDetected(TestRunner& runner) {
568
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 PacketManager sender, receiver;
569 1 super_packet_t testPacket = PacketTestHelper::createTestPacket(25, true, "Original Data");
570 1 void* data = PacketTestHelper::createPacketData(testPacket);
571 1 size_t data_size = sizeof(super_packet_t);
572 size_t output_size;
573
574 // Use safer method to send the packet
575
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto packet_data = sender.sendPacketBytesSafe(data, data_size, 1, &output_size, true);
576
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> packets_to_send = sender.fetchPacketsToSend();
577
578
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!packets_to_send.empty()) {
579
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 std::vector<uint8_t> raw_packet = PacketManager::serializePacket(*packets_to_send[0]);
580
581
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (raw_packet.size() > sizeof(packet_header_t) + 10) {
582 1 raw_packet[sizeof(packet_header_t) + 5] = 0xFF;
583 1 raw_packet[sizeof(packet_header_t) + 6] = 0xFF;
584 }
585
586
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 receiver.handlePacketBytes(raw_packet.data(), raw_packet.size());
587 1 }
588
589
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::vector<std::unique_ptr<packet_t>> received_packets = receiver.fetchReceivedPackets();
590
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!received_packets.empty()) {
591 1 super_packet_t* received_data = (super_packet_t*)received_packets[0]->data;
592
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
4 runner.assertTrue("Corrupted data field detected",
593 1 strcmp(received_data->my_name, "Original Data") != 0,
594 "Corrupted data should be different from original");
595 }
596
597 1 free(data);
598 1 }
599
600 1 void packetManagerCleanupWorksCorrectly(TestRunner& runner) {
601
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 PacketManager manager;
602
603
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
11 for (int i = 0; i < 10; i++) {
604
1/2
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 super_packet_t packet = PacketTestHelper::createTestPacket(i, true, ("Test " + std::to_string(i)).c_str());
605 10 void* data = PacketTestHelper::createPacketData(packet);
606 10 size_t data_size = sizeof(super_packet_t);
607 size_t output_size;
608
609 // Use safer method to send packets
610
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 auto packet_data = manager.sendPacketBytesSafe(data, data_size, 1, &output_size, true);
611 10 free(data);
612 10 }
613
614
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 manager.fetchPacketsToSend();
615
616
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
4 runner.assertTrue("Buffers not empty before cleanup",
617
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
1 manager._get_history_sent()->size() > 0 || manager._get_send_seqid() > 0,
618 "Manager should have some state before cleanup");
619
620
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 manager.clean();
621
622
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
4 runner.assertEqual("Send buffer cleared", 0UL, manager._get_buffer_send()->size(), "Send buffer should be empty after cleanup");
623
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
4 runner.assertEqual("Received buffer cleared", 0UL, manager._get_buffer_received()->size(), "Received buffer should be empty after cleanup");
624
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
4 runner.assertEqual("History cleared", 0UL, manager._get_history_sent()->size(), "History should be empty after cleanup");
625
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
4 runner.assertEqual("Send seqid reset", 0U, manager._get_send_seqid(), "Send seqid should be reset to 0");
626
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 runner.assertEqual("Recv seqid reset", 0U, manager._get_recv_seqid(), "Recv seqid should be reset to 0");
627 1 }
628
629 1 void extremelySmallPacketIsHandled(TestRunner& runner) {
630
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 PacketManager receiver;
631 1 uint8_t tiny_packet[1] = {0x42};
632
633
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
3 runner.runTest("Extremely small packet handling", [&]() {
634 1 receiver.handlePacketBytes(tiny_packet, sizeof(tiny_packet));
635 1 });
636
637
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
3 runner.assertEqual("No packets received from tiny packet", 0UL, receiver._get_buffer_received()->size(), "Tiny packets should be rejected");
638 1 }
639
640 1 int main() {
641 1 TestRunner runner;
642
643
4/8
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
1 std::cout << COLOR_BLUE << "=== Starting PacketManager Tests ===" << COLOR_RESET << std::endl;
644
645 // Run all tests
646
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 testPacketSending(runner);
647
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 testPacketTransfer(runner);
648
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 testPacketReception(runner);
649
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 testPacketData(runner);
650
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 testMissingPacketsAndAck(runner);
651
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 testAckPacketRetransmission(runner);
652
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 corruptedPacketHeaderIsRejected(runner);
653
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 packetWithInvalidSizeIsRejected(runner);
654
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 emptyPacketDataIsHandledCorrectly(runner);
655
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 veryLargePacketIsHandled(runner);
656
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 sequenceIdOverflowIsHandled(runner);
657
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 multipleConsecutiveMissingPacketsAreDetected(runner);
658
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 duplicatePacketsAreHandledCorrectly(runner);
659
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 outOfOrderPacketDeliveryWorks(runner);
660
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 corruptedDataFieldIsDetected(runner);
661
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 packetManagerCleanupWorksCorrectly(runner);
662
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 extremelySmallPacketIsHandled(runner);
663
664 // Print results
665 1 TestResult result = runner.getResult();
666
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result.printSummary();
667
668
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 return result.hasFailures() ? 1 : 0;
669 }
670