Line data Source code
1 : #define BOOST_TEST_MODULE RequestSender_t
2 : #include "boost/test/unit_test.hpp"
3 :
4 : #include "tracemf.h"
5 : #define TRACE_NAME "RequestSender_t"
6 :
7 : #include "artdaq-core/Utilities/configureMessageFacility.hh"
8 : #include "artdaq/DAQdata/TCPConnect.hh"
9 : #include "artdaq/DAQdata/TCP_listen_fd.hh"
10 : #include "artdaq/DAQrate/detail/RequestSender.hh"
11 : #include "artdaq/DAQrate/detail/RoutingPacket.hh"
12 :
13 : #include <sys/poll.h>
14 :
15 : BOOST_AUTO_TEST_SUITE(RequestSender_test)
16 :
17 : #define TRACE_REQUIRE_EQUAL(l, r) \
18 : do \
19 : { \
20 : if ((l) == (r)) \
21 : { \
22 : TLOG(TLVL_DEBUG) << __LINE__ << ": Checking if " << #l << " (" << (l) << ") equals " << #r << " (" << (r) << ")...YES!"; \
23 : } \
24 : else \
25 : { \
26 : TLOG(TLVL_ERROR) << __LINE__ << ": Checking if " << #l << " (" << (l) << ") equals " << #r << " (" << (r) << ")...NO!"; \
27 : } \
28 : BOOST_REQUIRE_EQUAL((l), (r)); \
29 : } while (0)
30 :
31 2 : BOOST_AUTO_TEST_CASE(Construct)
32 : {
33 1 : artdaq::configureMessageFacility("RequestSender_t", true, true);
34 2 : metricMan->initialize(fhicl::ParameterSet());
35 1 : metricMan->do_start();
36 3 : TLOG(TLVL_INFO) << "Construct Test Case BEGIN";
37 1 : fhicl::ParameterSet pset;
38 1 : artdaq::RequestSender t(pset);
39 1 : BOOST_REQUIRE_EQUAL(t.GetRequestMode(), artdaq::detail::RequestMessageMode::Normal);
40 3 : TLOG(TLVL_INFO) << "Construct Test Case END";
41 1 : }
42 :
43 : // NOLINTNEXTLINE(readability-function-size)
44 2 : BOOST_AUTO_TEST_CASE(Requests)
45 : {
46 1 : artdaq::configureMessageFacility("RequestSender_t", true, true);
47 2 : metricMan->initialize(fhicl::ParameterSet());
48 1 : metricMan->do_start();
49 3 : TLOG(TLVL_INFO) << "Requests Test Case BEGIN";
50 1 : const int REQUEST_PORT = (artdaq::Globals::SeedAndRandom() % (32768 - 1024)) + 1024;
51 1 : const int DELAY_TIME = 100;
52 : #if 0
53 : const std::string MULTICAST_IP = "227.28.12.28";
54 : #else
55 1 : const std::string MULTICAST_IP = "localhost";
56 : #endif
57 1 : fhicl::ParameterSet pset;
58 2 : pset.put("request_port", REQUEST_PORT);
59 1 : pset.put("request_delay_ms", DELAY_TIME);
60 3 : pset.put("send_requests", true);
61 1 : pset.put("request_address", MULTICAST_IP);
62 1 : artdaq::RequestSender t(pset);
63 :
64 3 : TLOG(TLVL_DEBUG) << "Opening request listener socket";
65 1 : auto request_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
66 :
67 : struct sockaddr_in si_me_request;
68 :
69 1 : int yes = 1;
70 1 : if (setsockopt(request_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0)
71 : {
72 0 : TLOG(TLVL_ERROR) << "Unable to set reuse on request socket";
73 0 : BOOST_REQUIRE_EQUAL(true, false);
74 0 : return;
75 : }
76 1 : memset(&si_me_request, 0, sizeof(si_me_request));
77 1 : si_me_request.sin_family = AF_INET;
78 1 : si_me_request.sin_port = htons(REQUEST_PORT);
79 1 : si_me_request.sin_addr.s_addr = htonl(INADDR_ANY);
80 1 : if (bind(request_socket, reinterpret_cast<struct sockaddr*>(&si_me_request), sizeof(si_me_request)) == -1) // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
81 : {
82 0 : TLOG(TLVL_ERROR) << "Cannot bind request socket to port " << REQUEST_PORT;
83 0 : BOOST_REQUIRE_EQUAL(true, false);
84 0 : return;
85 : }
86 :
87 1 : if (MULTICAST_IP != "localhost")
88 : {
89 : struct ip_mreq mreq;
90 0 : int sts = ResolveHost(MULTICAST_IP.c_str(), mreq.imr_multiaddr);
91 0 : if (sts == -1)
92 : {
93 0 : TLOG(TLVL_ERROR) << "Unable to resolve multicast request address";
94 0 : BOOST_REQUIRE_EQUAL(true, false);
95 0 : return;
96 : }
97 0 : mreq.imr_interface.s_addr = htonl(INADDR_ANY);
98 0 : if (setsockopt(request_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
99 : {
100 0 : TLOG(TLVL_ERROR) << "Unable to join multicast group";
101 0 : BOOST_REQUIRE_EQUAL(true, false);
102 0 : return;
103 : }
104 : }
105 :
106 3 : TLOG(TLVL_DEBUG) << "Sending request";
107 1 : auto start_time = std::chrono::steady_clock::now();
108 1 : t.AddRequest(0, 0x10);
109 : struct pollfd ufds[1];
110 :
111 3 : TLOG(TLVL_DEBUG) << "Receiving Request";
112 1 : ufds[0].fd = request_socket;
113 1 : ufds[0].events = POLLIN | POLLPRI;
114 1 : int rv = poll(ufds, 1, 10000);
115 1 : if (rv > 0)
116 : {
117 1 : if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
118 : {
119 1 : auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
120 1 : BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
121 2 : TLOG(TLVL_TRACE) << "Recieved packet on Request channel";
122 1 : std::vector<uint8_t> buffer(MAX_REQUEST_MESSAGE_SIZE);
123 1 : artdaq::detail::RequestHeader hdr_buffer;
124 1 : recv(request_socket, &buffer[0], buffer.size(), 0);
125 1 : memcpy(&hdr_buffer, &buffer[0], sizeof(artdaq::detail::RequestHeader));
126 4 : TRACE_REQUIRE_EQUAL(hdr_buffer.isValid(), true);
127 4 : TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.mode),
128 : static_cast<uint8_t>(artdaq::detail::RequestMessageMode::Normal));
129 4 : TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 1);
130 1 : if (hdr_buffer.isValid())
131 : {
132 1 : std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
133 1 : memcpy(&pkt_buffer[0], &buffer[sizeof(artdaq::detail::RequestHeader)], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count);
134 :
135 2 : for (auto& buffer : pkt_buffer)
136 : {
137 4 : TRACE_REQUIRE_EQUAL(buffer.isValid(), true);
138 4 : TRACE_REQUIRE_EQUAL(buffer.sequence_id, 0);
139 4 : TRACE_REQUIRE_EQUAL(buffer.timestamp, 0x10);
140 : }
141 1 : }
142 : else
143 : {
144 0 : TLOG(TLVL_ERROR) << "Invalid header received";
145 0 : BOOST_REQUIRE_EQUAL(false, true);
146 0 : return;
147 : }
148 2 : }
149 : else
150 : {
151 0 : TLOG(TLVL_ERROR) << "Wrong event type from poll";
152 0 : BOOST_REQUIRE_EQUAL(false, true);
153 0 : return;
154 : }
155 : }
156 : else
157 : {
158 0 : TLOG(TLVL_ERROR) << "Timeout occured waiting for request";
159 0 : BOOST_REQUIRE_EQUAL(false, true);
160 0 : return;
161 : }
162 :
163 : // SetRequestMode and AddRequest BOTH send requests...
164 1 : start_time = std::chrono::steady_clock::now();
165 1 : t.SetRequestMode(artdaq::detail::RequestMessageMode::EndOfRun);
166 1 : t.AddRequest(2, 0x20);
167 1 : rv = poll(ufds, 1, 1000);
168 1 : if (rv > 0)
169 : {
170 1 : if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
171 : {
172 1 : auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
173 1 : BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
174 2 : TLOG(TLVL_TRACE) << "Recieved packet on Request channel";
175 1 : std::vector<uint8_t> buffer(MAX_REQUEST_MESSAGE_SIZE);
176 1 : artdaq::detail::RequestHeader hdr_buffer;
177 1 : recv(request_socket, &buffer[0], buffer.size(), 0);
178 1 : memcpy(&hdr_buffer, &buffer[0], sizeof(artdaq::detail::RequestHeader));
179 4 : TRACE_REQUIRE_EQUAL(hdr_buffer.isValid(), true);
180 4 : TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.mode),
181 : static_cast<uint8_t>(artdaq::detail::RequestMessageMode::EndOfRun));
182 4 : TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 2);
183 1 : if (hdr_buffer.isValid())
184 : {
185 1 : std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
186 1 : memcpy(&pkt_buffer[0], &buffer[sizeof(artdaq::detail::RequestHeader)], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count);
187 :
188 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[0].isValid(), true);
189 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[0].sequence_id, 0);
190 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[0].timestamp, 0x10);
191 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[1].isValid(), true);
192 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[1].sequence_id, 2);
193 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[1].timestamp, 0x20);
194 1 : }
195 : else
196 : {
197 0 : TLOG(TLVL_ERROR) << "Invalid header received";
198 0 : BOOST_REQUIRE_EQUAL(false, true);
199 0 : return;
200 : }
201 2 : }
202 : else
203 : {
204 0 : TLOG(TLVL_ERROR) << "Wrong event type from poll";
205 0 : BOOST_REQUIRE_EQUAL(false, true);
206 0 : return;
207 : }
208 : }
209 : else
210 : {
211 0 : TLOG(TLVL_ERROR) << "Timeout occured waiting for request";
212 0 : BOOST_REQUIRE_EQUAL(false, true);
213 0 : return;
214 : }
215 1 : rv = poll(ufds, 1, 1000);
216 1 : if (rv > 0)
217 : {
218 1 : if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
219 : {
220 1 : auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
221 1 : BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
222 2 : TLOG(TLVL_TRACE) << "Recieved packet on Request channel";
223 1 : std::vector<uint8_t> buffer(MAX_REQUEST_MESSAGE_SIZE);
224 1 : artdaq::detail::RequestHeader hdr_buffer;
225 1 : recv(request_socket, &buffer[0], buffer.size(), 0);
226 1 : memcpy(&hdr_buffer, &buffer[0], sizeof(artdaq::detail::RequestHeader));
227 4 : TRACE_REQUIRE_EQUAL(hdr_buffer.isValid(), true);
228 4 : TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.mode),
229 : static_cast<uint8_t>(artdaq::detail::RequestMessageMode::EndOfRun));
230 4 : TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 2);
231 1 : if (hdr_buffer.isValid())
232 : {
233 1 : std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
234 1 : memcpy(&pkt_buffer[0], &buffer[sizeof(artdaq::detail::RequestHeader)], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count);
235 :
236 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[0].isValid(), true);
237 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[0].sequence_id, 0);
238 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[0].timestamp, 0x10);
239 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[1].isValid(), true);
240 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[1].sequence_id, 2);
241 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[1].timestamp, 0x20);
242 1 : }
243 : else
244 : {
245 0 : TLOG(TLVL_ERROR) << "Invalid header received";
246 0 : BOOST_REQUIRE_EQUAL(false, true);
247 0 : return;
248 : }
249 2 : }
250 : else
251 : {
252 0 : TLOG(TLVL_ERROR) << "Wrong event type from poll";
253 0 : BOOST_REQUIRE_EQUAL(false, true);
254 0 : return;
255 : }
256 : }
257 : else
258 : {
259 0 : TLOG(TLVL_ERROR) << "Timeout occured waiting for request";
260 0 : BOOST_REQUIRE_EQUAL(false, true);
261 0 : return;
262 : }
263 :
264 1 : t.RemoveRequest(0);
265 1 : t.RemoveRequest(2);
266 1 : t.AddRequest(3, 0x30);
267 1 : start_time = std::chrono::steady_clock::now();
268 1 : rv = poll(ufds, 1, 1000);
269 1 : if (rv > 0)
270 : {
271 1 : if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
272 : {
273 1 : auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
274 1 : BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
275 2 : TLOG(TLVL_TRACE) << "Recieved packet on Request channel";
276 1 : std::vector<uint8_t> buffer(MAX_REQUEST_MESSAGE_SIZE);
277 1 : artdaq::detail::RequestHeader hdr_buffer;
278 1 : recv(request_socket, &buffer[0], buffer.size(), 0);
279 1 : memcpy(&hdr_buffer, &buffer[0], sizeof(artdaq::detail::RequestHeader));
280 4 : TRACE_REQUIRE_EQUAL(hdr_buffer.isValid(), true);
281 4 : TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.mode),
282 : static_cast<uint8_t>(artdaq::detail::RequestMessageMode::EndOfRun));
283 4 : TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 1);
284 1 : if (hdr_buffer.isValid())
285 : {
286 1 : std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
287 1 : memcpy(&pkt_buffer[0], &buffer[sizeof(artdaq::detail::RequestHeader)], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count);
288 :
289 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[0].isValid(), true);
290 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[0].sequence_id, 3);
291 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[0].timestamp, 0x30);
292 1 : }
293 : else
294 : {
295 0 : TLOG(TLVL_ERROR) << "Invalid header received";
296 0 : BOOST_REQUIRE_EQUAL(false, true);
297 0 : return;
298 : }
299 2 : }
300 : else
301 : {
302 0 : TLOG(TLVL_ERROR) << "Wrong event type from poll";
303 0 : BOOST_REQUIRE_EQUAL(false, true);
304 0 : return;
305 : }
306 : }
307 : else
308 : {
309 0 : TLOG(TLVL_ERROR) << "Timeout occured waiting for request";
310 0 : BOOST_REQUIRE_EQUAL(false, true);
311 0 : return;
312 : }
313 :
314 1 : close(request_socket);
315 3 : TLOG(TLVL_INFO) << "Requests Test Case END";
316 1 : artdaq::Globals::CleanUpGlobals();
317 1 : }
318 :
319 : BOOST_AUTO_TEST_SUITE_END()
|