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