22 #include <system_error> 38 TEST_CASE(
"UnixUDPSocket's create and bind a UDP socket on construction and " 39 "closes the socket on destruction.",
"[UnixUDPSocket]")
41 SECTION(
"Without a specific IP address (no errors).")
44 fakeit::Mock<UnixSyscalls> mock_sys;
46 fakeit::When(Method(mock_sys, socket)).Return(3);
48 struct sockaddr_in address;
49 fakeit::When(Method(mock_sys, bind)).Do(
50 [&](
auto fd,
auto addr,
auto addrlen)
53 std::memcpy(&address, addr, addrlen);
57 fakeit::When(Method(mock_sys, close)).Return(0);
61 fakeit::Verify(Method(mock_sys, socket).Matching(
62 [&](
auto family,
auto type,
auto protocol)
64 return family == AF_INET && type == SOCK_DGRAM && protocol == 0;
66 fakeit::Verify(Method(mock_sys, bind).Matching(
67 [&](
auto fd,
auto addr,
auto addrlen)
70 return fd == 3 && addrlen ==
sizeof(address);
72 REQUIRE(address.sin_family == AF_INET);
73 REQUIRE(ntohs(address.sin_port) == 14050);
74 REQUIRE(ntohl(address.sin_addr.s_addr) == INADDR_ANY);
76 for (
size_t i = 0; i <
sizeof(address.sin_zero); ++i)
78 REQUIRE(address.sin_zero[i] ==
'\0');
81 fakeit::Verify(Method(mock_sys, close).Using(3)).Exactly(0);
83 fakeit::Verify(Method(mock_sys, close).Using(3)).Once();
85 SECTION(
"With a specific IP address (no errors).")
87 fakeit::Mock<UnixSyscalls> mock_sys;
88 fakeit::When(Method(mock_sys, socket)).Return(3);
89 struct sockaddr_in address;
90 fakeit::When(Method(mock_sys, bind)).Do(
91 [&](
auto fd,
auto addr,
auto addrlen)
94 std::memcpy(&address, addr, addrlen);
97 fakeit::When(Method(mock_sys, close)).Return(0);
101 fakeit::Verify(Method(mock_sys, socket).Matching(
102 [&](
auto family,
auto type,
auto protocol)
104 return family == AF_INET && type == SOCK_DGRAM && protocol == 0;
106 fakeit::Verify(Method(mock_sys, bind).Matching(
107 [](
auto fd,
auto addr,
auto addrlen)
110 return fd == 3 && addrlen ==
sizeof(address);
112 REQUIRE(address.sin_family == AF_INET);
113 REQUIRE(ntohs(address.sin_port) == 14050);
114 REQUIRE(ntohl(address.sin_addr.s_addr) == 1234567890);
116 for (
size_t i = 0; i <
sizeof(address.sin_zero); ++i)
118 REQUIRE(address.sin_zero[i] ==
'\0');
121 fakeit::Verify(Method(mock_sys, close).Using(3)).Exactly(0);
123 fakeit::Verify(Method(mock_sys, close).Using(3)).Once();
125 SECTION(
"Emmits errors from 'socket' system call.")
127 fakeit::Mock<UnixSyscalls> mock_sys;
128 fakeit::When(Method(mock_sys, socket)).AlwaysReturn(-1);
129 std::array<int, 7> errors{{
139 for (
auto error : errors)
147 SECTION(
"Emmits errors from 'bind' system call.")
149 fakeit::Mock<UnixSyscalls> mock_sys;
150 fakeit::When(Method(mock_sys, socket)).AlwaysReturn(4);
151 fakeit::When(Method(mock_sys, bind)).AlwaysReturn(-1);
152 std::array<int, 13> errors{{
168 for (
auto error : errors)
179 TEST_CASE(
"UnixUDPSocket's 'send' method sends data on the socket.",
183 fakeit::Mock<UnixSyscalls> mock_sys;
185 fakeit::When(Method(mock_sys, socket)).Return(3);
187 fakeit::When(Method(mock_sys, bind)).Return(0);
189 fakeit::When(Method(mock_sys, close)).Return(0);
190 SECTION(
"Without error.")
194 std::vector<uint8_t> sent;
195 struct sockaddr_in address;
196 fakeit::When(Method(mock_sys, sendto)).Do(
197 [&](
auto fd,
auto buf,
auto len,
auto flags,
198 auto addr,
auto addrlen)
203 std::memcpy(sent.data(), buf, len);
204 std::memcpy(&address, addr, addrlen);
208 std::vector<uint8_t> vec = {1, 3, 3, 7};
211 fakeit::Verify(Method(mock_sys, sendto).Matching(
212 [](
auto fd,
auto buf,
auto len,
auto flags,
213 auto addr,
auto addrlen)
217 return fd == 3 && len == 4 && flags == 0 &&
218 addrlen ==
sizeof(address);
220 REQUIRE(sent == vec);
221 REQUIRE(address.sin_family == AF_INET);
222 REQUIRE(ntohs(address.sin_port) == 14050);
223 REQUIRE(ntohl(address.sin_addr.s_addr) == 1234567890);
225 for (
size_t i = 0; i <
sizeof(address.sin_zero); ++i)
227 REQUIRE(address.sin_zero[i] ==
'\0');
230 SECTION(
"Bitrate limit prevents writing packets too fast.")
233 fakeit::Fake(Method(mock_sys, sendto));
234 std::vector<uint8_t> vec = {1, 3, 3, 7};
235 socket.send(vec,
IPAddress(1234567890, 14050));
236 fakeit::Verify(Method(mock_sys, sendto)).Once();
237 auto tic = std::chrono::steady_clock::now();
238 socket.send(vec,
IPAddress(1234567890, 14050));
239 auto toc = std::chrono::steady_clock::now();
241 std::chrono::duration_cast<std::chrono::milliseconds>(
242 toc - tic).count() >= 150);
244 std::chrono::duration_cast<std::chrono::milliseconds>(
245 toc - tic).count() <= 350);
246 fakeit::Verify(Method(mock_sys, sendto)).Exactly(2);
248 SECTION(
"Emmits errors from 'sendto' system call.")
251 fakeit::When(Method(mock_sys, sendto)).AlwaysReturn(-1);
252 std::array<int, 18> errors{{
273 for (
auto error : errors)
277 socket.send({1, 3, 3, 7},
IPAddress(1234567890, 14050)),
284 TEST_CASE(
"UnixUDPSocket's 'receive' method receives data on the socket.",
288 fakeit::Mock<UnixSyscalls> mock_sys;
290 fakeit::When(Method(mock_sys, socket)).AlwaysReturn(3);
292 fakeit::When(Method(mock_sys, bind)).AlwaysReturn(0);
294 fakeit::When(Method(mock_sys, close)).AlwaysReturn(0);
297 SECTION(
"Timeout, no packet (no errors).")
301 fakeit::When(Method(mock_sys, poll)).Do(
302 [&](
auto fds_,
auto nfds,
auto timeout)
305 std::memcpy(&fds, fds_, nfds *
sizeof(fds));
310 socket.receive(250ms) ==
313 fakeit::Verify(Method(mock_sys, poll).Matching(
314 [](
auto fds_,
auto nfds,
auto timeout)
317 return nfds == 1 && timeout == 250;
319 REQUIRE(fds.fd == 3);
320 REQUIRE(fds.events == POLLIN);
321 REQUIRE(fds.revents == 0);
323 SECTION(
"Poll error, close and restart the socket (no other errors).")
326 struct sockaddr_in address;
327 fakeit::When(Method(mock_sys, bind)).Do(
328 [&](
auto fd,
auto addr,
auto addrlen)
331 std::memcpy(&address, addr, addrlen);
336 fakeit::When(Method(mock_sys, poll)).Do(
337 [&](
auto fds_,
auto nfds,
auto timeout)
340 std::memcpy(&fds, fds_, nfds *
sizeof(fds));
341 fds_->revents = POLLERR;
346 socket.receive(250ms) ==
349 fakeit::Verify(Method(mock_sys, poll).Matching(
350 [](
auto fds_,
auto nfds,
auto timeout)
353 return nfds == 1 && timeout == 250;
355 REQUIRE(fds.fd == 3);
356 REQUIRE(fds.events == POLLIN);
357 REQUIRE(fds.revents == 0);
359 fakeit::Verify(Method(mock_sys, socket).Matching(
360 [&](
auto family,
auto type,
auto protocol)
362 return family == AF_INET && type == SOCK_DGRAM && protocol == 0;
365 fakeit::Verify(Method(mock_sys, bind).Matching(
366 [&](
auto fd,
auto addr,
auto addrlen)
369 return fd == 3 && addrlen ==
sizeof(address);
371 REQUIRE(address.sin_family == AF_INET);
372 REQUIRE(ntohs(address.sin_port) == 14050);
373 REQUIRE(ntohl(address.sin_addr.s_addr) == INADDR_ANY);
375 for (
size_t i = 0; i <
sizeof(address.sin_zero); ++i)
377 REQUIRE(address.sin_zero[i] ==
'\0');
381 fakeit::Verify(Method(mock_sys, close).Using(3)).Once();
383 SECTION(
"Packet available (no errors).")
387 fakeit::When(Method(mock_sys, poll)).Do(
388 [&](
auto fds_,
auto nfds,
auto timeout)
391 std::memcpy(&fds, fds_, nfds *
sizeof(fds));
392 fds_->revents = POLLIN;
396 fakeit::When(Method(mock_sys, ioctl)).Do(
397 [](
auto fd,
auto request,
auto size)
401 *
reinterpret_cast<int *
>(size) = 4;
405 socklen_t address_length = 0;
406 fakeit::When(Method(mock_sys, recvfrom)).Do(
407 [&](
auto fd,
auto buf,
auto len,
auto flags,
408 auto addr,
auto addrlen)
413 std::vector<uint8_t> vec = {1, 3, 3, 7};
414 std::memcpy(buf, vec.data(), std::min(vec.size(), len));
416 struct sockaddr_in address;
417 address.sin_family = AF_INET;
418 address.sin_port = htons(static_cast<uint16_t>(5000));
419 address.sin_addr.s_addr = htonl(static_cast<uint32_t>(1234567890));
420 memset(address.sin_zero,
'\0',
sizeof(address.sin_zero));
423 std::min(static_cast<size_t>(*addrlen),
sizeof(address)));
424 address_length = *addrlen;
425 *addrlen =
static_cast<socklen_t
>(
426 std::min(static_cast<size_t>(*addrlen),
429 return std::min(vec.size(), len);
432 auto [data, ip] = socket.receive(250ms);
433 REQUIRE(data == std::vector<uint8_t>({1, 3, 3, 7}));
434 REQUIRE(ip ==
IPAddress(1234567890, 5000));
436 fakeit::Verify(Method(mock_sys, poll).Matching(
437 [](
auto fds_,
auto nfds,
auto timeout)
440 return nfds == 1 && timeout == 250;
442 REQUIRE(fds.fd == 3);
443 REQUIRE(fds.events == POLLIN);
444 REQUIRE(fds.revents == 0);
446 fakeit::Verify(Method(mock_sys, ioctl).Matching(
447 [](
auto fd,
auto request,
auto size)
450 return fd == 3 && request == FIONREAD;
453 fakeit::Verify(Method(mock_sys, recvfrom).Matching(
454 [](
auto fd,
auto buf,
auto len,
auto flags,
455 auto addr,
auto addrlen)
460 return fd == 3 && len >= 4 && flags == 0;
462 REQUIRE(address_length >=
sizeof(sockaddr_in));
464 SECTION(
"Packet available (not IPv4).")
468 fakeit::When(Method(mock_sys, poll)).Do(
469 [&](
auto fds_,
auto nfds,
auto timeout)
472 std::memcpy(&fds, fds_, nfds *
sizeof(fds));
473 fds_->revents = POLLIN;
477 fakeit::When(Method(mock_sys, ioctl)).Do(
478 [](
auto fd,
auto request,
auto size)
482 *
reinterpret_cast<int *
>(size) = 4;
486 socklen_t address_length = 0;
487 fakeit::When(Method(mock_sys, recvfrom)).Do(
488 [&](
auto fd,
auto buf,
auto len,
auto flags,
489 auto addr,
auto addrlen)
494 std::vector<uint8_t> vec = {1, 3, 3, 7};
495 std::memcpy(buf, vec.data(), std::min(vec.size(), len));
497 struct sockaddr_in address;
498 address.sin_family = AF_INET6;
499 address.sin_port = htons(static_cast<uint16_t>(5000));
500 address.sin_addr.s_addr = htonl(static_cast<uint32_t>(1234567890));
501 memset(address.sin_zero,
'\0',
sizeof(address.sin_zero));
504 std::min(static_cast<size_t>(*addrlen),
sizeof(address)));
505 address_length = *addrlen;
506 *addrlen =
static_cast<socklen_t
>(
507 std::min(static_cast<size_t>(*addrlen),
510 return std::min(vec.size(), len);
513 auto [data, ip] = socket.receive(250ms);
514 REQUIRE(data == std::vector<uint8_t>());
517 fakeit::Verify(Method(mock_sys, poll).Matching(
518 [](
auto fds_,
auto nfds,
auto timeout)
521 return nfds == 1 && timeout == 250;
523 REQUIRE(fds.fd == 3);
524 REQUIRE(fds.events == POLLIN);
525 REQUIRE(fds.revents == 0);
527 fakeit::Verify(Method(mock_sys, ioctl).Matching(
528 [](
auto fd,
auto request,
auto size)
531 return fd == 3 && request == FIONREAD;
534 fakeit::Verify(Method(mock_sys, recvfrom).Matching(
535 [](
auto fd,
auto buf,
auto len,
auto flags,
536 auto addr,
auto addrlen)
541 return fd == 3 && len >= 4 && flags == 0;
543 REQUIRE(address_length >=
sizeof(sockaddr_in));
545 SECTION(
"Packet available (IP address truncated).")
549 fakeit::When(Method(mock_sys, poll)).Do(
550 [&](
auto fds_,
auto nfds,
auto timeout)
553 std::memcpy(&fds, fds_, nfds *
sizeof(fds));
554 fds_->revents = POLLIN;
558 fakeit::When(Method(mock_sys, ioctl)).Do(
559 [](
auto fd,
auto request,
auto size)
563 *
reinterpret_cast<int *
>(size) = 4;
567 socklen_t address_length = 0;
568 fakeit::When(Method(mock_sys, recvfrom)).Do(
569 [&](
auto fd,
auto buf,
auto len,
auto flags,
570 auto addr,
auto addrlen)
575 std::vector<uint8_t> vec = {1, 3, 3, 7};
576 std::memcpy(buf, vec.data(), std::min(vec.size(), len));
578 struct sockaddr_in address;
579 address.sin_family = AF_INET;
580 address.sin_port = htons(static_cast<uint16_t>(5000));
581 address.sin_addr.s_addr = htonl(static_cast<uint32_t>(1234567890));
582 memset(address.sin_zero,
'\0',
sizeof(address.sin_zero));
585 std::min(static_cast<size_t>(*addrlen),
sizeof(address)));
586 address_length = *addrlen;
587 *addrlen =
static_cast<socklen_t
>(
588 std::min(static_cast<size_t>(*addrlen),
589 sizeof(address))) + 1;
591 return std::min(vec.size(), len);
594 auto [data, ip] = socket.receive(250ms);
595 REQUIRE(data == std::vector<uint8_t>());
598 fakeit::Verify(Method(mock_sys, poll).Matching(
599 [](
auto fds_,
auto nfds,
auto timeout)
602 return nfds == 1 && timeout == 250;
604 REQUIRE(fds.fd == 3);
605 REQUIRE(fds.events == POLLIN);
606 REQUIRE(fds.revents == 0);
608 fakeit::Verify(Method(mock_sys, ioctl).Matching(
609 [](
auto fd,
auto request,
auto size)
612 return fd == 3 && request == FIONREAD;
615 fakeit::Verify(Method(mock_sys, recvfrom).Matching(
616 [](
auto fd,
auto buf,
auto len,
auto flags,
617 auto addr,
auto addrlen)
622 return fd == 3 && len >= 4 && flags == 0;
624 REQUIRE(address_length >=
sizeof(sockaddr_in));
626 SECTION(
"Emmits errors from 'recvfrom' system call.")
630 fakeit::When(Method(mock_sys, poll)).AlwaysDo(
631 [&](
auto fds_,
auto nfds,
auto timeout)
634 std::memcpy(&fds, fds_, nfds *
sizeof(fds));
635 fds_->revents = POLLIN;
639 fakeit::When(Method(mock_sys, ioctl)).AlwaysDo(
640 [](
auto fd,
auto request,
auto size)
644 *
reinterpret_cast<int *
>(size) = 4;
648 fakeit::When(Method(mock_sys, recvfrom)).AlwaysReturn(-1);
650 std::array<int, 13> errors{{
666 for (
auto error : errors)
669 REQUIRE_THROWS_AS(socket.receive(250ms), std::system_error);
672 SECTION(
"Emmits errors from 'ioctl' system call.")
676 fakeit::When(Method(mock_sys, poll)).AlwaysDo(
677 [&](
auto fds_,
auto nfds,
auto timeout)
680 std::memcpy(&fds, fds_, nfds *
sizeof(fds));
681 fds_->revents = POLLIN;
685 fakeit::When(Method(mock_sys, ioctl)).AlwaysReturn(-1);
687 std::array<int, 4> errors{{
694 for (
auto error : errors)
697 REQUIRE_THROWS_AS(socket.receive(250ms), std::system_error);
700 SECTION(
"Emmits errors from 'poll' system call.")
703 fakeit::When(Method(mock_sys, poll)).AlwaysReturn(-1);
705 std::array<int, 4> errors{{
712 for (
auto error : errors)
715 REQUIRE_THROWS_AS(socket.receive(250ms), std::system_error);
721 TEST_CASE(
"UnixUDPSocket's are printable.",
"[UnixUDPSocket]")
724 fakeit::Mock<UnixSyscalls> mock_sys;
726 fakeit::When(Method(mock_sys, socket)).Return(3);
728 struct sockaddr_in address;
729 fakeit::When(Method(mock_sys, bind)).Do(
730 [&](
auto fd,
auto addr,
auto addrlen)
733 std::memcpy(&address, addr, addrlen);
737 fakeit::When(Method(mock_sys, close)).Return(0);
738 SECTION(
"Without explicit IP address.")
747 SECTION(
"With explicit IP address.")
755 " address 127.0.0.1;\n" 758 SECTION(
"Without explicit IP address (and maximum bitrate).")
765 " max_bitrate 8192;\n" 768 SECTION(
"With explicit IP address (and maximum bitrate).")
776 " address 127.0.0.1;\n" 777 " max_bitrate 8192;\n" TEST_CASE("UnixUDPSocket's create and bind a UDP socket on construction and " "closes the socket on destruction.", "[UnixUDPSocket]")
std::string str(const T &object)
virtual void send(const std::vector< uint8_t > &data, const IPAddress &address) final
std::unique_ptr< T > mock_unique(fakeit::Mock< T > &mock)