1 //
2 // Copyright 2019 Ettus Research, a National Instruments Brand
3 //
4 // SPDX-License-Identifier: GPL-3.0-or-later
5 //
6 
7 #include "common/mock_link.hpp"
8 #include <boost/test/unit_test.hpp>
9 
10 using namespace uhd::transport;
11 
BOOST_AUTO_TEST_CASE(test_send_get_release)12 BOOST_AUTO_TEST_CASE(test_send_get_release)
13 {
14     // Just call get_send_buff, release_send_buff, and pop_send_packet
15     // from a link containing a single frame_buff.
16     const size_t num_frames  = 1;
17     const int32_t timeout_ms = 1;
18 
19     const mock_send_link::link_params params = {1000, num_frames};
20 
21     auto xport = std::make_shared<mock_send_link>(params);
22 
23     // Check sizes
24     BOOST_CHECK_EQUAL(xport->get_num_send_frames(), params.num_frames);
25     BOOST_CHECK_EQUAL(xport->get_send_frame_size(), params.frame_size);
26 
27     // Call get and release a few times and check packet contents
28     for (size_t i = 0; i < 5; i++) {
29         auto buff = xport->get_send_buff(timeout_ms);
30         BOOST_CHECK(buff);
31 
32         auto* ptr = static_cast<uint8_t*>(buff->data());
33         ptr[0]    = i;
34 
35         buff->set_packet_size(sizeof(uint8_t));
36         xport->release_send_buff(std::move(buff));
37         BOOST_CHECK(!buff);
38 
39         auto packet = xport->pop_send_packet();
40         BOOST_CHECK_EQUAL(packet.first[0], i);
41         BOOST_CHECK_EQUAL(packet.second, sizeof(uint8_t));
42     }
43 }
44 
BOOST_AUTO_TEST_CASE(test_send_timeout)45 BOOST_AUTO_TEST_CASE(test_send_timeout)
46 {
47     // Test that the link returns timeouts correctly and continues to
48     // operate properly after a timeout condition.
49     const size_t num_frames  = 10;
50     const int32_t timeout_ms = 1;
51 
52     const mock_send_link::link_params params = {1000, num_frames};
53 
54     auto xport = std::make_shared<mock_send_link>(params);
55 
56     // Repeat the following a few times to check buffers are not lost
57     for (size_t i = 0; i < 3; i++) {
58         // Cause a timeout by simulating an I/O delay in the underlying
59         // link implementation.
60         std::vector<frame_buff::uptr> buffs;
61 
62         for (size_t j = 0; j < num_frames / 2; j++) {
63             buffs.push_back(xport->get_send_buff(timeout_ms));
64             BOOST_CHECK(buffs.back());
65         }
66 
67         // Simulate a timeout
68         xport->set_simulate_io_timeout(true);
69         BOOST_CHECK(!xport->get_send_buff(timeout_ms));
70         xport->set_simulate_io_timeout(false);
71 
72         for (size_t j = 0; j < num_frames / 2; j++) {
73             buffs.push_back(xport->get_send_buff(timeout_ms));
74             BOOST_CHECK(buffs.back());
75         }
76 
77         for (auto& buff : buffs) {
78             buff->set_packet_size(params.frame_size);
79             xport->release_send_buff(std::move(buff));
80             BOOST_CHECK(!buff);
81         }
82     }
83 }
84 
BOOST_AUTO_TEST_CASE(test_recv_get_release)85 BOOST_AUTO_TEST_CASE(test_recv_get_release)
86 {
87     // Just call push_recv_packet, get_recv_buff, and release_recv_buff
88     // from a link containing a single frame_buff.
89     const size_t num_frames  = 1;
90     const int32_t timeout_ms = 1;
91 
92     const mock_recv_link::link_params params = {1000, num_frames};
93 
94     auto xport = std::make_shared<mock_recv_link>(params);
95 
96     // Check sizes
97     BOOST_CHECK_EQUAL(xport->get_num_recv_frames(), params.num_frames);
98     BOOST_CHECK_EQUAL(xport->get_recv_frame_size(), params.frame_size);
99 
100     // Call get and release a few times and check packet contents
101     for (size_t i = 0; i < 5; i++) {
102         size_t packet_size = sizeof(uint8_t);
103         auto packet_data   = boost::shared_array<uint8_t>(new uint8_t[packet_size]);
104         packet_data[0]     = i;
105         xport->push_back_recv_packet(packet_data, packet_size);
106 
107         auto buff = xport->get_recv_buff(timeout_ms);
108         BOOST_CHECK(buff);
109         BOOST_CHECK(buff->data());
110 
111         auto* ptr = static_cast<uint8_t*>(buff->data());
112         ptr[0]    = i;
113 
114         xport->release_recv_buff(std::move(buff));
115         BOOST_CHECK(!buff);
116     }
117 }
118 
BOOST_AUTO_TEST_CASE(test_recv_timeout)119 BOOST_AUTO_TEST_CASE(test_recv_timeout)
120 {
121     // Test that the link returns timeouts correctly and continues to
122     // operate properly after a timeout condition.
123     const size_t num_frames  = 10;
124     const int32_t timeout_ms = 1;
125 
126     const mock_recv_link::link_params params = {1000, num_frames};
127 
128     auto xport = std::make_shared<mock_recv_link>(params);
129 
130     // Repeat the following a few times to check buffers are not lost
131     for (size_t i = 0; i < 3; i++) {
132         // Cause a timeout by simulating an I/O delay in the underlying
133         // link implementation.
134         std::vector<frame_buff::uptr> buffs;
135 
136         for (size_t i = 0; i < num_frames / 2; i++) {
137             size_t packet_size = sizeof(uint8_t);
138             auto packet_data   = boost::shared_array<uint8_t>(new uint8_t[packet_size]);
139             xport->push_back_recv_packet(packet_data, packet_size);
140 
141             buffs.push_back(xport->get_recv_buff(timeout_ms));
142             BOOST_CHECK(buffs.back());
143         }
144 
145         // Simulate a timeout by getting a buffer without queueing a data array
146         BOOST_CHECK(!xport->get_recv_buff(timeout_ms));
147 
148         for (size_t i = 0; i < num_frames / 2; i++) {
149             size_t packet_size = sizeof(uint8_t);
150             auto packet_data   = boost::shared_array<uint8_t>(new uint8_t[packet_size]);
151             xport->push_back_recv_packet(packet_data, packet_size);
152 
153             buffs.push_back(xport->get_recv_buff(timeout_ms));
154             BOOST_CHECK(buffs.back());
155         }
156 
157         for (auto& buff : buffs) {
158             xport->release_recv_buff(std::move(buff));
159             BOOST_CHECK(!buff);
160         }
161     }
162 }
163