mavtables  0.2.1
MAVLink router and firewall.
test_UDPInterface.cpp
Go to the documentation of this file.
1 // MAVLink router and firewall.
2 // Copyright (C) 2018 Michael R. Shannon <mrshannon.aerospace@gmail.com>
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 
18 #include <algorithm>
19 #include <chrono>
20 #include <cstdint>
21 #include <memory>
22 #include <set>
23 #include <stdexcept>
24 #include <utility>
25 #include <vector>
26 
27 #include <catch.hpp>
28 #include <fakeit.hpp>
29 
30 #include "ConnectionFactory.hpp"
31 #include "ConnectionPool.hpp"
32 #include "Filter.hpp"
33 #include "IPAddress.hpp"
34 #include "Packet.hpp"
35 #include "PacketVersion2.hpp"
36 #include "UDPInterface.hpp"
37 #include "UDPSocket.hpp"
38 #include "utility.hpp"
39 
40 #include "common.hpp"
41 #include "common_Packet.hpp"
42 
43 
44 using namespace std::chrono_literals;
45 
46 
47 TEST_CASE("UDPInterface's can be constructed.", "[UPDInterface]")
48 {
49  fakeit::Mock<UDPSocket> mock_socket;
50  fakeit::Mock<ConnectionPool> mock_pool;
51  fakeit::Mock<ConnectionFactory<>> mock_factory;
52  auto socket = mock_unique(mock_socket);
53  auto pool = mock_shared(mock_pool);
54  auto factory = mock_unique(mock_factory);
55  SECTION("When all inputs are valid.")
56  {
57  REQUIRE_NOTHROW(
58  UDPInterface(std::move(socket), pool, std::move(factory)));
59  }
60  SECTION("Ensures the socket pointer is not null.")
61  {
62  REQUIRE_THROWS_AS(
63  UDPInterface(nullptr, pool, std::move(factory)),
64  std::invalid_argument);
65  factory = mock_unique(mock_factory);
66  REQUIRE_THROWS_WITH(
67  UDPInterface(nullptr, pool, std::move(factory)),
68  "Given socket pointer is null.");
69  }
70  SECTION("Ensures the connection pool pointer is not null.")
71  {
72  REQUIRE_THROWS_AS(
73  UDPInterface(std::move(socket), nullptr, std::move(factory)),
74  std::invalid_argument);
75  socket = mock_unique(mock_socket);
76  factory = mock_unique(mock_factory);
77  REQUIRE_THROWS_WITH(
78  UDPInterface(std::move(socket), nullptr, std::move(factory)),
79  "Given connection pool pointer is null.");
80  }
81  SECTION("Ensures the connection factory pointer is not null.")
82  {
83  REQUIRE_THROWS_AS(
84  UDPInterface(std::move(socket), pool, nullptr),
85  std::invalid_argument);
86  socket = mock_unique(mock_socket);
87  REQUIRE_THROWS_WITH(
88  UDPInterface(std::move(socket), pool, nullptr),
89  "Given connection factory pointer is null.");
90  }
91 }
92 
93 
94 TEST_CASE("UDPInterace's 'receive_packet' method.", "[UPDInterface]")
95 {
96  // MAVLink packets.
97  auto heartbeat =
98  std::make_shared<packet_v2::Packet>(to_vector(HeartbeatV2()));
99  auto mission_set_current =
100  std::make_shared<packet_v2::Packet>(to_vector(MissionSetCurrentV2()));
101  auto encapsulated_data =
102  std::make_shared<packet_v2::Packet>(to_vector(EncapsulatedDataV2()));
103  // Connection pool
104  ConnectionPool pool_obj;
105  fakeit::Mock<ConnectionPool> spy_pool(pool_obj);
106  fakeit::Spy(Method(spy_pool, add));
107  auto pool = mock_shared(spy_pool);
108  // Filter
109  fakeit::Mock<Filter> mock_filter;
110  std::multiset<packet_v2::Packet,
111  bool(*)(const packet_v2::Packet &, const packet_v2::Packet &)>
112  will_accept_packets([](const auto & a, const auto & b)
113  {
114  return a.data() < b.data();
115  });
116  std::multiset<MAVAddress> will_accept_addresses;
117  fakeit::When(Method(mock_filter, will_accept)).AlwaysDo(
118  [&](auto & a, auto & b)
119  {
120  will_accept_packets.insert(
121  dynamic_cast<const packet_v2::Packet &>(a));
122  will_accept_addresses.insert(b);
123  return std::pair<bool, int>(true, 0);
124  });
125  auto filter = mock_shared(mock_filter);
126  // Socket
127  using receive_type =
128  IPAddress(std::back_insert_iterator<std::vector<uint8_t>>,
129  const std::chrono::nanoseconds &);
130  UDPSocket udp_socket;
131  fakeit::Mock<UDPSocket> mock_socket(udp_socket);
132  auto socket = mock_unique(mock_socket);
133  // Interface
134  UDPInterface udp(
135  std::move(socket), pool,
136  std::make_unique<ConnectionFactory<>>(filter));
137  std::chrono::nanoseconds timeout = 250ms;
138  SECTION("No packet received.")
139  {
140  // Mocks
141  fakeit::When(
142  OverloadedMethod(
143  mock_socket, receive, receive_type)).AlwaysReturn(IPAddress(0));
144  // Test
145  udp.receive_packet(timeout);
146  // Verification
147  fakeit::Verify(
148  OverloadedMethod(mock_socket, receive, receive_type).Matching(
149  [&](auto a, auto b)
150  {
151  (void)a;
152  return b == 250ms;
153  })).Once();
154  fakeit::Verify(Method(mock_filter, will_accept)).Exactly(0);
155  fakeit::Verify(Method(spy_pool, add)).Exactly(0);
156  }
157  SECTION("Partial packet received.")
158  {
159  // Mocks
160  fakeit::When(OverloadedMethod(mock_socket, receive, receive_type)
161  ).Do([](auto a, auto b)
162  {
163  // Load 127.1 mavlink address into connection.
164  (void)b;
165  auto vec = to_vector(HeartbeatV2());
166  std::copy(vec.begin(), vec.end(), a);
167  return IPAddress("127.0.0.1:4000");
168  }).Do([](auto a, auto b)
169  {
170  (void)b;
171  auto vec = to_vector(EncapsulatedDataV2());
172  std::copy(vec.begin(), vec.end() - 1, a);
173  return IPAddress("127.0.0.1:4000");
174  });
175  // Test
176  udp.receive_packet(timeout);
177  udp.receive_packet(timeout);
178  // Verification
179  fakeit::Verify(
180  OverloadedMethod(mock_socket, receive, receive_type).Matching(
181  [&](auto a, auto b)
182  {
183  (void)a;
184  return b == 250ms;
185  })).Exactly(2);
186  fakeit::Verify(Method(mock_filter, will_accept)).Exactly(0);
187  fakeit::Verify(Method(spy_pool, add)).Exactly(1);
188  }
189  SECTION("Full packet received.")
190  {
191  // Mocks
192  fakeit::When(OverloadedMethod(mock_socket, receive, receive_type)
193  ).Do([](auto a, auto b)
194  {
195  // Load 127.1 mavlink address into connection.
196  (void)b;
197  auto vec = to_vector(HeartbeatV2());
198  std::copy(vec.begin(), vec.end(), a);
199  return IPAddress("127.0.0.1:4000");
200  }).Do([](auto a, auto b)
201  {
202  (void)b;
203  auto vec = to_vector(EncapsulatedDataV2());
204  std::copy(vec.begin(), vec.end(), a);
205  return IPAddress("127.0.0.1:4001");
206  });
207  // Test
208  udp.receive_packet(timeout);
209  udp.receive_packet(timeout);
210  // Verification
211  fakeit::Verify(
212  OverloadedMethod(mock_socket, receive, receive_type).Matching(
213  [&](auto a, auto b)
214  {
215  (void)a;
216  return b == 250ms;
217  })).Exactly(2);
218  fakeit::Verify(Method(mock_filter, will_accept)).Once();
219  REQUIRE(will_accept_packets.count(*encapsulated_data) == 1);
220  REQUIRE(will_accept_addresses.count(MAVAddress("127.1")) == 1);
221  fakeit::Verify(Method(spy_pool, add)).Exactly(2);
222  auto it = will_accept_packets.find(*encapsulated_data);
223  REQUIRE(it != will_accept_packets.end());
224  REQUIRE(it->connection() != nullptr);
225  }
226  SECTION("Multiple packets received (same IP and MAVLink addresses).")
227  {
228  // Mocks
229  fakeit::When(OverloadedMethod(mock_socket, receive, receive_type)
230  ).Do([](auto a, auto b)
231  {
232  // Load 127.1 mavlink address into connection.
233  (void)b;
234  auto vec = to_vector(HeartbeatV2());
235  std::copy(vec.begin(), vec.end(), a);
236  return IPAddress("127.0.0.1:4000");
237  }).AlwaysDo([](auto a, auto b)
238  {
239  (void)b;
240  auto vec = to_vector(EncapsulatedDataV2());
241  std::copy(vec.begin(), vec.end(), a);
242  return IPAddress("127.0.0.1:4001");
243  });
244  // Test
245  udp.receive_packet(timeout);
246  udp.receive_packet(timeout);
247  udp.receive_packet(timeout);
248  // Verification
249  fakeit::Verify(
250  OverloadedMethod(mock_socket, receive, receive_type).Matching(
251  [&](auto a, auto b)
252  {
253  (void)a;
254  return b == 250ms;
255  })).Exactly(3);
256  fakeit::Verify(Method(mock_filter, will_accept)).Exactly(2);
257  REQUIRE(will_accept_packets.count(*encapsulated_data) == 2);
258  REQUIRE(will_accept_addresses.count(MAVAddress("127.1")) == 2);
259  fakeit::Verify(Method(spy_pool, add)).Exactly(2);
260  auto it = will_accept_packets.find(*encapsulated_data);
261  REQUIRE(it != will_accept_packets.end());
262  REQUIRE(it->connection() != nullptr);
263  it++;
264  REQUIRE(it != will_accept_packets.end());
265  REQUIRE(it->connection() != nullptr);
266  }
267  SECTION("Multiple packets received (same IP, different MAVLink addresses).")
268  {
269  // Mocks
270  fakeit::When(OverloadedMethod(mock_socket, receive, receive_type)
271  ).Do([](auto a, auto b)
272  {
273  // Load 127.1 mavlink address into connection.
274  (void)b;
275  auto vec = to_vector(HeartbeatV2());
276  std::copy(vec.begin(), vec.end(), a);
277  return IPAddress("127.0.0.1:4000");
278  }).Do([](auto a, auto b)
279  {
280  (void)b;
281  auto vec = to_vector(EncapsulatedDataV2());
282  std::copy(vec.begin(), vec.end(), a);
283  return IPAddress("127.0.0.1:4001");
284  }).Do([](auto a, auto b)
285  {
286  (void)b;
287  auto vec = to_vector(MissionSetCurrentV2());
288  std::copy(vec.begin(), vec.end(), a);
289  return IPAddress("127.0.0.1:4001");
290  });
291  // Test
292  udp.receive_packet(timeout);
293  udp.receive_packet(timeout);
294  udp.receive_packet(timeout);
295  // Verification
296  fakeit::Verify(
297  OverloadedMethod(mock_socket, receive, receive_type).Matching(
298  [&](auto a, auto b)
299  {
300  (void)a;
301  return b == 250ms;
302  })).Exactly(3);
303  fakeit::Verify(Method(mock_filter, will_accept)).Exactly(2);
304  REQUIRE(will_accept_packets.count(*encapsulated_data) == 1);
305  REQUIRE(will_accept_packets.count(*mission_set_current) == 1);
306  REQUIRE(will_accept_addresses.count(MAVAddress("127.1")) == 2);
307  fakeit::Verify(Method(spy_pool, add)).Exactly(2);
308  auto it = will_accept_packets.find(*encapsulated_data);
309  REQUIRE(it != will_accept_packets.end());
310  REQUIRE(it->connection() != nullptr);
311  it = will_accept_packets.find(*mission_set_current);
312  REQUIRE(it != will_accept_packets.end());
313  REQUIRE(it->connection() != nullptr);
314  }
315  SECTION("Multiple packets received (different IP and MAVLink addresses).")
316  {
317  // Mocks
318  fakeit::When(OverloadedMethod(mock_socket, receive, receive_type)
319  ).Do([](auto a, auto b)
320  {
321  // Load 127.1 mavlink address into connection.
322  (void)b;
323  auto vec = to_vector(HeartbeatV2());
324  std::copy(vec.begin(), vec.end(), a);
325  return IPAddress("127.0.0.1:4000");
326  }).Do([](auto a, auto b)
327  {
328  (void)b;
329  auto vec = to_vector(EncapsulatedDataV2());
330  std::copy(vec.begin(), vec.end(), a);
331  return IPAddress("127.0.0.1:4001");
332  }).Do([](auto a, auto b)
333  {
334  (void)b;
335  auto vec = to_vector(MissionSetCurrentV2());
336  std::copy(vec.begin(), vec.end(), a);
337  return IPAddress("127.0.0.1:4002");
338  });
339  // Test
340  udp.receive_packet(timeout);
341  udp.receive_packet(timeout);
342  udp.receive_packet(timeout);
343  // Verification
344  fakeit::Verify(
345  OverloadedMethod(mock_socket, receive, receive_type).Matching(
346  [&](auto a, auto b)
347  {
348  (void)a;
349  return b == 250ms;
350  })).Exactly(3);
351  fakeit::Verify(Method(mock_filter, will_accept)).Exactly(3);
352  REQUIRE(will_accept_packets.count(*encapsulated_data) == 1);
353  REQUIRE(will_accept_packets.count(*mission_set_current) == 2);
354  REQUIRE(will_accept_addresses.count(MAVAddress("127.1")) == 2);
355  REQUIRE(will_accept_addresses.count(MAVAddress("224.255")) == 1);
356  fakeit::Verify(Method(spy_pool, add)).Exactly(3);
357  auto it = will_accept_packets.find(*encapsulated_data);
358  REQUIRE(it != will_accept_packets.end());
359  REQUIRE(it->connection() != nullptr);
360  it = will_accept_packets.find(*mission_set_current);
361  REQUIRE(it != will_accept_packets.end());
362  REQUIRE(it->connection() != nullptr);
363  it++;
364  REQUIRE(it != will_accept_packets.end());
365  REQUIRE(it->connection() != nullptr);
366  }
367  SECTION("Partial packets with same IP address should be combined and "
368  "parsed.")
369  {
370  // Mocks
371  fakeit::When(OverloadedMethod(mock_socket, receive, receive_type)
372  ).Do([](auto a, auto b)
373  {
374  // Load 127.1 mavlink address into connection.
375  (void)b;
376  auto vec = to_vector(HeartbeatV2());
377  std::copy(vec.begin(), vec.end(), a);
378  return IPAddress("127.0.0.1:4000");
379  }).Do([](auto a, auto b)
380  {
381  (void)b;
382  auto vec = to_vector(EncapsulatedDataV2());
383  std::copy(vec.begin(), vec.end() - 10, a);
384  return IPAddress("127.0.0.1:4001");
385  }).Do([](auto a, auto b)
386  {
387  (void)b;
388  auto vec = to_vector(EncapsulatedDataV2());
389  std::copy(vec.end() - 10, vec.end(), a);
390  return IPAddress("127.0.0.1:4001");
391  });
392  // Test
393  udp.receive_packet(timeout);
394  udp.receive_packet(timeout);
395  udp.receive_packet(timeout);
396  // Verification
397  fakeit::Verify(
398  OverloadedMethod(mock_socket, receive, receive_type).Matching(
399  [&](auto a, auto b)
400  {
401  (void)a;
402  return b == 250ms;
403  })).Exactly(3);
404  fakeit::Verify(Method(mock_filter, will_accept)).Once();
405  REQUIRE(will_accept_packets.count(*encapsulated_data) == 1);
406  REQUIRE(will_accept_addresses.count(MAVAddress("127.1")) == 1);
407  fakeit::Verify(Method(spy_pool, add)).Exactly(2);
408  auto it = will_accept_packets.find(*encapsulated_data);
409  REQUIRE(it != will_accept_packets.end());
410  REQUIRE(it->connection() != nullptr);
411  }
412  SECTION("Partial packets with different IP addresses should be dropped.")
413  {
414  // Mocks
415  fakeit::When(OverloadedMethod(mock_socket, receive, receive_type)
416  ).Do([](auto a, auto b)
417  {
418  // Load 127.1 mavlink address into connection.
419  (void)b;
420  auto vec = to_vector(HeartbeatV2());
421  std::copy(vec.begin(), vec.end(), a);
422  return IPAddress("127.0.0.1:4000");
423  }).Do([](auto a, auto b)
424  {
425  (void)b;
426  auto vec = to_vector(EncapsulatedDataV2());
427  std::copy(vec.begin(), vec.end() - 10, a);
428  return IPAddress("127.0.0.1:4001");
429  }).Do([](auto a, auto b)
430  {
431  (void)b;
432  auto vec = to_vector(EncapsulatedDataV2());
433  std::copy(vec.end() - 10, vec.end(), a);
434  return IPAddress("127.0.0.1:4002");
435  });
436  // Test
437  udp.receive_packet(timeout);
438  udp.receive_packet(timeout);
439  udp.receive_packet(timeout);
440  // Verification
441  fakeit::Verify(
442  OverloadedMethod(mock_socket, receive, receive_type).Matching(
443  [&](auto a, auto b)
444  {
445  (void)a;
446  return b == 250ms;
447  })).Exactly(3);
448  fakeit::Verify(Method(mock_filter, will_accept)).Exactly(0);
449  fakeit::Verify(Method(spy_pool, add)).Once();
450  }
451 }
452 
453 
454 TEST_CASE("UDPInterace's 'send_packet' method.", "[UPDInterface]")
455 {
456  // MAVLink packets.
457  auto ping = std::make_shared<packet_v2::Packet>(to_vector(PingV2()));
458  auto heartbeat =
459  std::make_shared<packet_v2::Packet>(to_vector(HeartbeatV2()));
460  auto encapsulated_data =
461  std::make_shared<packet_v2::Packet>(to_vector(EncapsulatedDataV2()));
462  // Filter
463  fakeit::Mock<Filter> mock_filter;
464  fakeit::When(Method(mock_filter, will_accept)).AlwaysDo(
465  [&](auto & a, auto & b)
466  {
467  (void)a;
468  (void)b;
469  return std::pair<bool, int>(true, 0);
470  });
471  auto filter = mock_shared(mock_filter);
472  // Socket
473  std::multiset<std::vector<uint8_t>> send_bytes;
474  std::multiset<IPAddress> send_addresses;
475  using receive_type =
476  IPAddress(std::back_insert_iterator<std::vector<uint8_t>>,
477  const std::chrono::nanoseconds &);
478  using send_type =
479  void(std::vector<uint8_t>::const_iterator,
480  std::vector<uint8_t>::const_iterator,
481  const IPAddress &);
482  UDPSocket udp_socket;
483  fakeit::Mock<UDPSocket> mock_socket(udp_socket);
484  fakeit::When(OverloadedMethod(mock_socket, send, send_type)
485  ).AlwaysDo([&](auto a, auto b, auto c)
486  {
487  std::vector<uint8_t> vec;
488  std::copy(a, b, std::back_inserter(vec));
489  send_bytes.insert(vec);
490  send_addresses.insert(c);
491  });
492  auto socket = mock_unique(mock_socket);
493  // Connection Factory
494  ConnectionFactory<> factory_obj(filter);
495  fakeit::Mock<ConnectionFactory<>> spy_factory(factory_obj);
496  fakeit::Spy(Method(spy_factory, wait_for_packet));
497  // Interface
498  UDPInterface udp(
499  std::move(socket),
500  std::make_shared<ConnectionPool>(),
501  mock_unique(spy_factory));
502  std::chrono::nanoseconds timeout = 1ms;
503  SECTION("No packets, timeout.")
504  {
505  // Test
506  udp.send_packet(timeout);
507  // Verification
508  fakeit::Verify(Method(spy_factory, wait_for_packet).Using(1ms)).Once();
509  fakeit::Verify(
510  OverloadedMethod(mock_socket, send, send_type)).Exactly(0);
511  }
512  SECTION("Single connection, single packet.")
513  {
514  // Mocks
515  fakeit::When(OverloadedMethod(mock_socket, receive, receive_type)
516  ).Do([](auto a, auto b)
517  {
518  // Load 127.1 mavlink address into connection.
519  (void)b;
520  auto vec = to_vector(HeartbeatV2());
521  std::copy(vec.begin(), vec.end(), a);
522  return IPAddress("127.0.0.1:4000");
523  }).Do([](auto a, auto b)
524  {
525  (void)b;
526  auto vec = to_vector(EncapsulatedDataV2());
527  std::copy(vec.begin(), vec.end(), a);
528  return IPAddress("127.0.0.1:4001");
529  });
530  // Test
531  udp.receive_packet(timeout);
532  udp.receive_packet(timeout);
533  udp.send_packet(timeout);
534  // Verification
535  fakeit::Verify(Method(spy_factory, wait_for_packet).Using(1ms)).Once();
536  fakeit::Verify(OverloadedMethod(mock_socket, send, send_type)).Once();
537  REQUIRE(send_bytes.size() == 1);
538  REQUIRE(send_bytes.count(to_vector(EncapsulatedDataV2())) == 1);
539  REQUIRE(send_addresses.count(IPAddress("127.0.0.1:4000")) == 1);
540  }
541  SECTION("Single connection, multiple packets.")
542  {
543  // Mocks
544  fakeit::When(OverloadedMethod(mock_socket, receive, receive_type)
545  ).Do([](auto a, auto b)
546  {
547  // Load 127.1 mavlink address into connection.
548  (void)b;
549  auto vec = to_vector(HeartbeatV2());
550  std::copy(vec.begin(), vec.end(), a);
551  return IPAddress("127.0.0.1:4000");
552  }).Do([](auto a, auto b)
553  {
554  (void)b;
555  auto vec = to_vector(EncapsulatedDataV2());
556  std::copy(vec.begin(), vec.end(), a);
557  return IPAddress("127.0.0.1:4001");
558  }).Do([](auto a, auto b)
559  {
560  (void)b;
561  auto vec = to_vector(MissionSetCurrentV2());
562  std::copy(vec.begin(), vec.end(), a);
563  return IPAddress("127.0.0.1:4001");
564  });
565  // Test
566  udp.receive_packet(timeout);
567  udp.receive_packet(timeout);
568  udp.receive_packet(timeout);
569  udp.send_packet(timeout);
570  // Verification
571  fakeit::Verify(Method(spy_factory, wait_for_packet).Using(1ms)).Once();
572  fakeit::Verify(OverloadedMethod(mock_socket, send, send_type)).Once();
573  REQUIRE(send_bytes.size() == 1);
574  REQUIRE(send_bytes.count(to_vector(EncapsulatedDataV2())) == 1);
575  REQUIRE(send_addresses.count(IPAddress("127.0.0.1:4000")) == 1);
576  // Test
577  udp.send_packet(timeout);
578  // Verification
579  fakeit::Verify(
580  Method(spy_factory, wait_for_packet).Using(1ms)).Exactly(2);
581  fakeit::Verify(
582  OverloadedMethod(mock_socket, send, send_type)).Exactly(2);
583  REQUIRE(send_bytes.size() == 2);
584  REQUIRE(send_bytes.count(to_vector(EncapsulatedDataV2())) == 1);
585  REQUIRE(send_bytes.count(to_vector(MissionSetCurrentV2())) == 1);
586  REQUIRE(send_addresses.count(IPAddress("127.0.0.1:4000")) == 2);
587  }
588  SECTION("Multiple connections, multiple packets.")
589  {
590  // Mocks
591  fakeit::When(OverloadedMethod(mock_socket, receive, receive_type)
592  ).Do([](auto a, auto b)
593  {
594  // Load 127.1 mavlink address into connection.
595  (void)b;
596  auto vec = to_vector(HeartbeatV2());
597  std::copy(vec.begin(), vec.end(), a);
598  return IPAddress("127.0.0.1:4000");
599  }).Do([](auto a, auto b)
600  {
601  (void)b;
602  auto vec = to_vector(EncapsulatedDataV2());
603  std::copy(vec.begin(), vec.end(), a);
604  return IPAddress("127.0.0.1:4001");
605  }).Do([](auto a, auto b)
606  {
607  (void)b;
608  auto vec = to_vector(MissionSetCurrentV2());
609  std::copy(vec.begin(), vec.end(), a);
610  return IPAddress("127.0.0.1:4002");
611  });
612  // Test
613  udp.receive_packet(timeout);
614  udp.receive_packet(timeout);
615  udp.receive_packet(timeout);
616  udp.send_packet(timeout);
617  // Verification
618  fakeit::Verify(Method(spy_factory, wait_for_packet).Using(1ms)).Once();
619  fakeit::Verify(Method(spy_factory, wait_for_packet)).Exactly(2);
620  fakeit::Verify(
621  OverloadedMethod(mock_socket, send, send_type)).Exactly(2);
622  REQUIRE(send_bytes.size() == 2);
623  REQUIRE(send_bytes.count(to_vector(EncapsulatedDataV2())) == 1);
624  REQUIRE(send_bytes.count(to_vector(MissionSetCurrentV2())) == 1);
625  REQUIRE(send_addresses.count(IPAddress("127.0.0.1:4000")) == 1);
626  REQUIRE(send_addresses.count(IPAddress("127.0.0.1:4001")) == 1);
627  // Test
628  udp.send_packet(timeout);
629  // Verification
630  fakeit::Verify(
631  Method(spy_factory, wait_for_packet).Using(1ms)).Exactly(2);
632  fakeit::Verify(Method(spy_factory, wait_for_packet)).Exactly(3);
633  fakeit::Verify(
634  OverloadedMethod(mock_socket, send, send_type)).Exactly(3);
635  REQUIRE(send_bytes.size() == 3);
636  REQUIRE(send_bytes.count(to_vector(EncapsulatedDataV2())) == 1);
637  REQUIRE(send_bytes.count(to_vector(MissionSetCurrentV2())) == 2);
638  REQUIRE(send_addresses.count(IPAddress("127.0.0.1:4000")) == 2);
639  REQUIRE(send_addresses.count(IPAddress("127.0.0.1:4001")) == 1);
640  }
641  SECTION("Multiple connections with broadcast packet.")
642  {
643  // Mocks
644  fakeit::When(Method(mock_filter, will_accept)).AlwaysDo(
645  [&](auto & a, auto & b)
646  {
647  (void)b;
648 
649  if (a.name() == "MISSION_SET_CURRENT")
650  {
651  return std::pair<bool, int>(true, 0);
652  }
653 
654  return std::pair<bool, int>(false, 0);
655  });
656  fakeit::When(OverloadedMethod(mock_socket, receive, receive_type)
657  ).Do([](auto a, auto b)
658  {
659  // Load 127.1 mavlink address into first connection.
660  (void)b;
661  auto vec = to_vector(HeartbeatV2());
662  std::copy(vec.begin(), vec.end(), a);
663  return IPAddress("127.0.0.1:4000");
664  }).Do([](auto a, auto b)
665  {
666  // Load 224.255 mavlink address into second connection.
667  (void)b;
668  auto vec = to_vector(EncapsulatedDataV2());
669  std::copy(vec.begin(), vec.end(), a);
670  return IPAddress("127.0.0.1:4001");
671  }).Do([](auto a, auto b)
672  {
673  (void)b;
674  auto vec = to_vector(MissionSetCurrentV2());
675  std::copy(vec.begin(), vec.end(), a);
676  return IPAddress("127.0.0.1:4002");
677  });
678  // Test
679  udp.receive_packet(timeout);
680  udp.receive_packet(timeout);
681  udp.receive_packet(timeout);
682  udp.send_packet(timeout);
683  // Verification
684  fakeit::Verify(Method(spy_factory, wait_for_packet).Using(1ms)).Once();
685  fakeit::Verify(Method(spy_factory, wait_for_packet)).Exactly(2);
686  fakeit::Verify(
687  OverloadedMethod(mock_socket, send, send_type)).Exactly(2);
688  REQUIRE(send_bytes.size() == 2);
689  REQUIRE(send_bytes.count(to_vector(MissionSetCurrentV2())) == 2);
690  REQUIRE(send_addresses.count(IPAddress("127.0.0.1:4000")) == 1);
691  REQUIRE(send_addresses.count(IPAddress("127.0.0.1:4001")) == 1);
692  // Test
693  udp.send_packet(timeout);
694  // Verification (no futher operations)
695  fakeit::Verify(
696  Method(spy_factory, wait_for_packet).Using(1ms)).Exactly(2);
697  fakeit::Verify(Method(spy_factory, wait_for_packet)).Exactly(3);
698  fakeit::Verify(
699  OverloadedMethod(mock_socket, send, send_type)).Exactly(2);
700  }
701  SECTION("Multiple connections with targeted packet.")
702  {
703  // Mocks
704  fakeit::When(Method(mock_filter, will_accept)).AlwaysDo(
705  [&](auto & a, auto & b)
706  {
707  (void)b;
708 
709  if (a.name() == "PING")
710  {
711  return std::pair<bool, int>(true, 0);
712  }
713 
714  return std::pair<bool, int>(false, 0);
715  });
716  fakeit::When(OverloadedMethod(mock_socket, receive, receive_type)
717  ).Do([](auto a, auto b)
718  {
719  // Load 127.1 mavlink address into first connection.
720  (void)b;
721  auto vec = to_vector(HeartbeatV2());
722  std::copy(vec.begin(), vec.end(), a);
723  return IPAddress("127.0.0.1:4000");
724  }).Do([](auto a, auto b)
725  {
726  // Load 224.255 mavlink address into second connection.
727  (void)b;
728  auto vec = to_vector(EncapsulatedDataV2());
729  std::copy(vec.begin(), vec.end(), a);
730  return IPAddress("127.0.0.1:4001");
731  }).Do([](auto a, auto b)
732  {
733  (void)b;
734  auto vec = to_vector(PingV2());
735  std::copy(vec.begin(), vec.end(), a);
736  return IPAddress("127.0.0.1:4002");
737  });
738  // Test
739  udp.receive_packet(timeout);
740  udp.receive_packet(timeout);
741  udp.receive_packet(timeout);
742  udp.send_packet(timeout);
743  // Verification
744  fakeit::Verify(Method(spy_factory, wait_for_packet).Using(1ms)).Once();
745  fakeit::Verify(Method(spy_factory, wait_for_packet)).Once();
746  fakeit::Verify(
747  OverloadedMethod(mock_socket, send, send_type)).Once();
748  REQUIRE(send_bytes.size() == 1);
749  REQUIRE(send_bytes.count(to_vector(PingV2())) == 1);
750  REQUIRE(send_addresses.count(IPAddress("127.0.0.1:4000")) == 1);
751  // Test
752  udp.send_packet(timeout);
753  // Verification (no futher operations)
754  fakeit::Verify(
755  Method(spy_factory, wait_for_packet).Using(1ms)).Exactly(2);
756  fakeit::Verify(Method(spy_factory, wait_for_packet)).Exactly(2);
757  fakeit::Verify(
758  OverloadedMethod(mock_socket, send, send_type)).Once();
759  }
760 }
761 
762 
763 TEST_CASE("UDPInterface's are printable.", "[UDPInterface]")
764 {
765  fakeit::Mock<ConnectionPool> mock_pool;
766  fakeit::Mock<ConnectionFactory<>> mock_factory;
767  auto pool = mock_shared(mock_pool);
768  auto factory = mock_unique(mock_factory);
769  auto socket = std::make_unique<UDPSocket>();
770  UDPInterface udp(std::move(socket), pool, std::move(factory));
771  REQUIRE(str(udp) == "unknown UDP socket");
772 }
773 
774 
775 // The tests below are from attempts to test the UDPInterface class in different
776 // ways, all failing to provide a method to test the entire class. They have
777 // been kept because they could theoretically find problems not covered by the
778 // tests above and do not cause much overhead.
779 ////////////////////////////////////////////////////////////////////////////////
780 
781 TEST_CASE("OLD TEST: UDPInterface's tests.", "[UPDInterface]")
782 {
783  using receive_type = IPAddress(
784  std::back_insert_iterator<std::vector<uint8_t>>,
785  const std::chrono::nanoseconds &);
786  auto heartbeat =
787  std::make_shared<packet_v2::Packet>(to_vector(HeartbeatV2()));
788  fakeit::Mock<Filter> mock_filter;
789  UDPSocket udp_socket;
790  fakeit::Mock<UDPSocket> mock_socket(udp_socket);
791  auto filter = mock_shared(mock_filter);
792  auto socket = mock_unique(mock_socket);
793  auto pool = std::make_shared<ConnectionPool>();
794  SECTION("Timeout")
795  {
796  fakeit::When(OverloadedMethod(
797  mock_socket, receive, receive_type)).AlwaysReturn(
798  IPAddress(0));
799  UDPInterface udp(
800  std::move(socket), pool,
801  std::make_unique<ConnectionFactory<>>(filter));
802  std::chrono::nanoseconds timeout = 250ms;
803  udp.receive_packet(timeout);
804  fakeit::Verify(
805  OverloadedMethod(mock_socket, receive, receive_type).Matching(
806  [&](auto a, auto b)
807  {
808  (void)a;
809  return b == 250ms;
810  })).Once();
811  }
812 }
813 
814 
815 TEST_CASE("OLD TEST: UDPInterface's 'receive_packet' method receives one or "
816  "more MAVLink packets.", "[UPDInterface]")
817 {
818  using receive_type = IPAddress(
819  std::back_insert_iterator<std::vector<uint8_t>>,
820  const std::chrono::nanoseconds &);
821  auto heartbeat =
822  std::make_shared<packet_v2::Packet>(to_vector(HeartbeatV2()));
823  fakeit::Mock<Filter> mock_filter;
824  UDPSocket udp_socket;
825  fakeit::Mock<UDPSocket> mock_socket(udp_socket);
826  fakeit::Mock<ConnectionPool> mock_pool;
827  fakeit::Mock<ConnectionFactory<>> mock_factory;
828  auto filter = mock_shared(mock_filter);
829  auto socket = mock_unique(mock_socket);
830  auto pool = mock_shared(mock_pool);
831  auto factory = mock_unique(mock_factory);
832  SECTION("When no packets available for sending.")
833  {
834  fakeit::When(OverloadedMethod(mock_socket, receive, receive_type)
835  ).AlwaysDo([](auto a, auto b)
836  {
837  (void)b;
838  auto vec = to_vector(HeartbeatV2());
839  std::copy(vec.begin(), vec.end(), a);
840  return IPAddress("192.168.0.0");
841  });
842  fakeit::Fake(Method(mock_pool, send));
843  fakeit::Fake(Method(mock_pool, add));
844  fakeit::When(Method(mock_factory, get)).AlwaysDo([&](auto a)
845  {
846  return std::make_unique<Connection>(a, filter);
847  });
848  UDPInterface udp(std::move(socket), pool, std::move(factory));
849  std::chrono::nanoseconds timeout = 250ms;
850  udp.receive_packet(timeout);
851  fakeit::Verify(
852  OverloadedMethod(mock_socket, receive, receive_type).Matching(
853  [](auto a, auto c)
854  {
855  (void)a;
856  return c == 250ms;
857  })).Once();
858  fakeit::Verify(Method(mock_pool, send).Matching(
859  [&](auto & a)
860  {
861  return a != nullptr && *a == *heartbeat;
862  })).Once();
863  }
864 }
865 
866 
867 TEST_CASE("OLD TEST: UDPInterface's 'send_packet' method sends one or more "
868  " MAVLink packets.", "[UPDInterface]")
869 {
870  UDPSocket udp_socket;
871  fakeit::Mock<UDPSocket> mock_socket(udp_socket);
872  fakeit::Mock<ConnectionPool> mock_pool;
873  fakeit::Mock<ConnectionFactory<>> mock_factory;
874  auto socket = mock_unique(mock_socket);
875  auto pool = mock_shared(mock_pool);
876  auto factory = mock_unique(mock_factory);
877  SECTION("When no packets available for sending.")
878  {
879  fakeit::When(Method(mock_factory, wait_for_packet)).AlwaysReturn(false);
880  UDPInterface udp(std::move(socket), pool, std::move(factory));
881  std::chrono::nanoseconds timeout = 250ms;
882  udp.send_packet(timeout);
883  fakeit::Verify(
884  Method(mock_factory, wait_for_packet).Using(250ms)).Once();
885  }
886 }
std::string str(const T &object)
Definition: utility.hpp:128
void receive_packet(const std::chrono::nanoseconds &timeout) final
void send_packet(const std::chrono::nanoseconds &timeout) final
TEST_CASE("UDPInterface's can be constructed.", "[UPDInterface]")
def heartbeat(mav)
Definition: logger.py:42
std::shared_ptr< T > mock_shared(fakeit::Mock< T > &mock)
Definition: common.hpp:33
auto ping
Definition: test_Call.cpp:229
std::unique_ptr< T > mock_unique(fakeit::Mock< T > &mock)
Definition: common.hpp:46