1 #include "artdaq/DAQrate/RequestSender.hh"
3 #define BOOST_TEST_MODULE RequestSender_t
4 #include "cetlib/quiet_unit_test.hpp"
5 #include "cetlib_except/exception.h"
7 #include "artdaq/DAQrate/detail/RoutingPacket.hh"
12 BOOST_AUTO_TEST_SUITE(RequestSender_test)
14 #define TRACE_REQUIRE_EQUAL(l,r) do { \
16 TLOG_DEBUG("RequestSender_t") << __LINE__ << ": Checking if " << #l << " (" << std::to_string(l) << ") equals " << #r << " (" << std::to_string(r) << ")...YES!" << TLOG_ENDL; \
20 TLOG_ERROR("RequestSender_t") << __LINE__ << ": Checking if " << #l << " (" << std::to_string(l) << ") equals " << #r << " (" << std::to_string(r) << ")...NO!" << TLOG_ENDL; \
22 BOOST_REQUIRE_EQUAL(l, r); \
25 BOOST_AUTO_TEST_CASE(Construct)
27 artdaq::configureMessageFacility(
"RequestSender_t",
true,
true);
28 TLOG_INFO(
"RequestSender_t") <<
"Construct Test Case BEGIN" << TLOG_ENDL;
29 fhicl::ParameterSet pset;
34 BOOST_AUTO_TEST_CASE(Tokens)
36 artdaq::configureMessageFacility(
"RequestSender_t",
true,
true);
37 TLOG_INFO(
"RequestSender_t") <<
"Tokens Test Case BEGIN" << TLOG_ENDL;
38 const int TOKEN_PORT = (seedAndRandom() % (32768 - 1024)) + 1024;
39 TLOG_DEBUG(
"RequestSender_t") <<
"Opening token listener socket" << TLOG_ENDL;
42 fhicl::ParameterSet token_pset;
43 token_pset.put(
"routing_token_port", TOKEN_PORT);
44 token_pset.put(
"use_routing_master",
true);
45 fhicl::ParameterSet pset;
46 pset.put(
"routing_token_config", token_pset);
52 BOOST_REQUIRE(token_socket != -1);
53 if (token_socket == -1)
55 TLOG_ERROR(
"RequestSender_t") <<
"Token listener socket was not opened successfully." << TLOG_ENDL;
56 BOOST_REQUIRE_EQUAL(
false,
true);
60 TLOG_DEBUG(
"RequestSender_t") <<
"Accepting new connection on token_socket" << TLOG_ENDL;
62 socklen_t arglen =
sizeof(addr);
63 auto conn_sock = accept(token_socket, (
struct sockaddr*)&addr, &arglen);
65 t.SendRoutingToken(120);
71 TRACE_REQUIRE_EQUAL(buff.
header, TOKEN_MAGIC);
73 TRACE_REQUIRE_EQUAL(buff.
rank, 0);
76 t.SendRoutingToken(335);
81 TRACE_REQUIRE_EQUAL(buff.
header, TOKEN_MAGIC);
83 TRACE_REQUIRE_EQUAL(buff.
rank, 13);
89 BOOST_AUTO_TEST_CASE(Requests)
91 artdaq::configureMessageFacility(
"RequestSender_t",
true,
true);
92 TLOG_INFO(
"RequestSender_t") <<
"Requests Test Case BEGIN" << TLOG_ENDL;
93 const int REQUEST_PORT = (seedAndRandom() % (32768 - 1024)) + 1024;
94 const int DELAY_TIME = 100;
96 const std::string MULTICAST_IP =
"227.28.12.28";
98 const std::string MULTICAST_IP =
"localhost";
100 fhicl::ParameterSet pset;
101 pset.put(
"request_port", REQUEST_PORT);
102 pset.put(
"request_delay_ms", DELAY_TIME);
103 pset.put(
"send_requests",
true);
104 pset.put(
"request_address", MULTICAST_IP);
108 TLOG_DEBUG(
"RequestSender_t") <<
"Opening request listener socket" << TLOG_ENDL;
109 auto request_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
111 struct sockaddr_in si_me_request;
114 if (setsockopt(request_socket, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(yes)) < 0)
116 TLOG_ERROR(
"RequestSender_t") <<
"Unable to set reuse on request socket" << TLOG_ENDL;
117 BOOST_REQUIRE_EQUAL(
true,
false);
120 memset(&si_me_request, 0,
sizeof(si_me_request));
121 si_me_request.sin_family = AF_INET;
122 si_me_request.sin_port = htons(REQUEST_PORT);
123 si_me_request.sin_addr.s_addr = htonl(INADDR_ANY);
124 if (bind(request_socket, (
struct sockaddr *)&si_me_request,
sizeof(si_me_request)) == -1)
126 TLOG_ERROR(
"RequestSender_t") <<
"Cannot bind request socket to port " << std::to_string(REQUEST_PORT) << TLOG_ENDL;
127 BOOST_REQUIRE_EQUAL(
true,
false);
131 if (MULTICAST_IP !=
"localhost")
134 int sts =
ResolveHost(MULTICAST_IP.c_str(), mreq.imr_multiaddr);
137 TLOG_ERROR(
"RequestSender_t") <<
"Unable to resolve multicast request address" << TLOG_ENDL;
138 BOOST_REQUIRE_EQUAL(
true,
false);
141 mreq.imr_interface.s_addr = htonl(INADDR_ANY);
142 if (setsockopt(request_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
sizeof(mreq)) < 0)
144 TLOG_ERROR(
"RequestSender_t") <<
"Unable to join multicast group" << TLOG_ENDL;
145 BOOST_REQUIRE_EQUAL(
true,
false);
150 TLOG_DEBUG(
"RequestSender_t") <<
"Sending request" << TLOG_ENDL;
151 auto start_time = std::chrono::steady_clock::now();
152 t.AddRequest(0, 0x10);
153 struct pollfd ufds[1];
155 TLOG_DEBUG(
"RequestSender_t") <<
"Receiving Request" << TLOG_ENDL;
156 ufds[0].fd = request_socket;
157 ufds[0].events = POLLIN | POLLPRI;
158 int rv = poll(ufds, 1, 10000);
161 if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
163 auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
164 BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
165 TRACE(4,
"CFG: Recieved packet on Request channel");
167 recv(request_socket, &hdr_buffer,
sizeof(hdr_buffer), 0);
168 TRACE_REQUIRE_EQUAL(hdr_buffer.
isValid(),
true);
169 TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.
mode),
175 std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.
packet_count);
178 for (
auto& buffer : pkt_buffer)
180 TRACE_REQUIRE_EQUAL(buffer.isValid(),
true);
181 TRACE_REQUIRE_EQUAL(buffer.sequence_id, 0);
182 TRACE_REQUIRE_EQUAL(buffer.timestamp, 0x10);
187 TLOG_ERROR(
"RequestSender_t") <<
"Invalid header received" << TLOG_ENDL;
188 BOOST_REQUIRE_EQUAL(
false,
true);
194 TLOG_ERROR(
"RequestSender_t") <<
"Wrong event type from poll" << TLOG_ENDL;
195 BOOST_REQUIRE_EQUAL(
false,
true);
201 TLOG_ERROR(
"RequestSender_t") <<
"Timeout occured waiting for request" << TLOG_ENDL;
202 BOOST_REQUIRE_EQUAL(
false,
true);
208 t.AddRequest(2, 0x20);
209 start_time = std::chrono::steady_clock::now();
210 rv = poll(ufds, 1, 1000);
213 if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
215 auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
216 BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
217 TRACE(4,
"CFG: Recieved packet on Request channel");
219 auto sts = recv(request_socket, &hdr_buffer,
sizeof(hdr_buffer), 0);
220 TRACE_REQUIRE_EQUAL(sts,
sizeof(hdr_buffer));
221 TRACE_REQUIRE_EQUAL(hdr_buffer.
isValid(),
true);
222 TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.
mode),
228 std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.
packet_count);
232 TRACE_REQUIRE_EQUAL(pkt_buffer[0].isValid(),
true);
233 TRACE_REQUIRE_EQUAL(pkt_buffer[0].sequence_id, 0);
234 TRACE_REQUIRE_EQUAL(pkt_buffer[0].timestamp, 0x10);
235 TRACE_REQUIRE_EQUAL(pkt_buffer[1].isValid(),
true);
236 TRACE_REQUIRE_EQUAL(pkt_buffer[1].sequence_id, 2);
237 TRACE_REQUIRE_EQUAL(pkt_buffer[1].timestamp, 0x20);
242 TLOG_ERROR(
"RequestSender_t") <<
"Invalid header received" << TLOG_ENDL;
243 BOOST_REQUIRE_EQUAL(
false,
true);
249 TLOG_ERROR(
"RequestSender_t") <<
"Wrong event type from poll" << TLOG_ENDL;
250 BOOST_REQUIRE_EQUAL(
false,
true);
256 TLOG_ERROR(
"RequestSender_t") <<
"Timeout occured waiting for request" << TLOG_ENDL;
257 BOOST_REQUIRE_EQUAL(
false,
true);
260 rv = poll(ufds, 1, 1000);
263 if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
265 auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
266 BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
267 TRACE(4,
"CFG: Recieved packet on Request channel");
269 recv(request_socket, &hdr_buffer,
sizeof(hdr_buffer), 0);
270 TRACE_REQUIRE_EQUAL(hdr_buffer.
isValid(),
true);
271 TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.
mode),
277 std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.
packet_count);
280 TRACE_REQUIRE_EQUAL(pkt_buffer[0].isValid(),
true);
281 TRACE_REQUIRE_EQUAL(pkt_buffer[0].sequence_id, 0);
282 TRACE_REQUIRE_EQUAL(pkt_buffer[0].timestamp, 0x10);
283 TRACE_REQUIRE_EQUAL(pkt_buffer[1].isValid(),
true);
284 TRACE_REQUIRE_EQUAL(pkt_buffer[1].sequence_id, 2);
285 TRACE_REQUIRE_EQUAL(pkt_buffer[1].timestamp, 0x20);
290 TLOG_ERROR(
"RequestSender_t") <<
"Invalid header received" << TLOG_ENDL;
291 BOOST_REQUIRE_EQUAL(
false,
true);
297 TLOG_ERROR(
"RequestSender_t") <<
"Wrong event type from poll" << TLOG_ENDL;
298 BOOST_REQUIRE_EQUAL(
false,
true);
304 TLOG_ERROR(
"RequestSender_t") <<
"Timeout occured waiting for request" << TLOG_ENDL;
305 BOOST_REQUIRE_EQUAL(
false,
true);
311 t.AddRequest(3, 0x30);
312 start_time = std::chrono::steady_clock::now();
313 rv = poll(ufds, 1, 1000);
316 if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
318 auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
319 BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
320 TRACE(4,
"CFG: Recieved packet on Request channel");
322 recv(request_socket, &hdr_buffer,
sizeof(hdr_buffer), 0);
323 TRACE_REQUIRE_EQUAL(hdr_buffer.
isValid(),
true);
324 TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.
mode),
330 std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.
packet_count);
333 TRACE_REQUIRE_EQUAL(pkt_buffer[0].isValid(),
true);
334 TRACE_REQUIRE_EQUAL(pkt_buffer[0].sequence_id, 3);
335 TRACE_REQUIRE_EQUAL(pkt_buffer[0].timestamp, 0x30);
340 TLOG_ERROR(
"RequestSender_t") <<
"Invalid header received" << TLOG_ENDL;
341 BOOST_REQUIRE_EQUAL(
false,
true);
347 TLOG_ERROR(
"RequestSender_t") <<
"Wrong event type from poll" << TLOG_ENDL;
348 BOOST_REQUIRE_EQUAL(
false,
true);
354 TLOG_ERROR(
"RequestSender_t") <<
"Timeout occured waiting for request" << TLOG_ENDL;
355 BOOST_REQUIRE_EQUAL(
false,
true);
359 close(request_socket);
362 BOOST_AUTO_TEST_SUITE_END()
int ResolveHost(char const *host_in, in_addr &addr)
Convert a string hostname to a in_addr suitable for socket communication.
End of Run mode (Used to end request processing on receiver)
The RequestSender contains methods used to send data requests and Routing tokens. ...
unsigned new_slots_free
The number of slots free in the token sender (usually 1)
The RoutingToken contains the magic bytes, the rank of the token sender, and the number of slots free...
int TCP_listen_fd(int port, int rcvbuf)
Create a TCP listening socket on the given port and INADDR_ANY, with the given receive buffer...
The RequestPacket contains information about a single data request.
int rank
The rank from which the RoutingToken came.
uint32_t header
The magic bytes that help validate the RoutingToken.