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 |