artdaq  v3_03_00
RequestSender_t.cc
1 #define TRACE_NAME "RequestSender_t"
2 
3 #include "artdaq/DAQrate/RequestSender.hh"
4 
5 #define BOOST_TEST_MODULE RequestSender_t
6 #include "cetlib/quiet_unit_test.hpp"
7 #include "cetlib_except/exception.h"
9 #include "artdaq/DAQrate/detail/RoutingPacket.hh"
11 #include <sys/poll.h>
12 
13 
14 BOOST_AUTO_TEST_SUITE(RequestSender_test)
15 
16 #define TRACE_REQUIRE_EQUAL(l,r) do { \
17 if(l == r) { \
18 TLOG(TLVL_DEBUG) << __LINE__ << ": Checking if " << #l << " (" << l << ") equals " << #r << " (" << r << ")...YES!" ; \
19 } \
20 else \
21 { \
22  TLOG(TLVL_ERROR) << __LINE__ << ": Checking if " << #l << " (" << l << ") equals " << #r << " (" << r << ")...NO!" ; \
23 } \
24  BOOST_REQUIRE_EQUAL(l, r); \
25 } while(0)
26 
27 BOOST_AUTO_TEST_CASE(Construct)
28 {
29  artdaq::configureMessageFacility("RequestSender_t", true, true);
30  metricMan->initialize(fhicl::ParameterSet());
31  metricMan->do_start();
32  TLOG(TLVL_INFO) << "Construct Test Case BEGIN" ;
33  fhicl::ParameterSet pset;
34  artdaq::RequestSender t(pset);
35  BOOST_REQUIRE_EQUAL(t.GetRequestMode(), artdaq::detail::RequestMessageMode::Normal);
36  TLOG(TLVL_INFO) << "Construct Test Case END";
37 }
38 
39 BOOST_AUTO_TEST_CASE(Tokens)
40 {
41  artdaq::configureMessageFacility("RequestSender_t", true, true);
42  metricMan->initialize(fhicl::ParameterSet());
43  metricMan->do_start();
44  TLOG(TLVL_INFO) << "Tokens Test Case BEGIN" ;
45  const int TOKEN_PORT = (seedAndRandom() % (32768 - 1024)) + 1024;
46  TLOG(TLVL_DEBUG) << "Opening token listener socket" ;
47  auto token_socket = TCP_listen_fd(TOKEN_PORT, 3 * sizeof(artdaq::detail::RoutingToken));
48 
49  fhicl::ParameterSet token_pset;
50  token_pset.put("routing_token_port", TOKEN_PORT);
51  token_pset.put("use_routing_master", true);
52  fhicl::ParameterSet pset;
53  pset.put("routing_token_config", token_pset);
54  artdaq::RequestSender t(pset);
55 
56  my_rank = 0;
57 
58 
59  BOOST_REQUIRE(token_socket != -1);
60  if (token_socket == -1)
61  {
62  TLOG(TLVL_ERROR) << "Token listener socket was not opened successfully." ;
63  BOOST_REQUIRE_EQUAL(false, true);
64  return;
65  }
66 
67  TLOG(TLVL_DEBUG) << "Accepting new connection on token_socket" ;
68  sockaddr_in addr;
69  socklen_t arglen = sizeof(addr);
70  auto conn_sock = accept(token_socket, (struct sockaddr*)&addr, &arglen);
71 
72  t.SendRoutingToken(120);
73 
75  auto sts = read(conn_sock, &buff, sizeof(artdaq::detail::RoutingToken));
76 
77  TRACE_REQUIRE_EQUAL(sts, sizeof(artdaq::detail::RoutingToken));
78  TRACE_REQUIRE_EQUAL(buff.header, TOKEN_MAGIC);
79  TRACE_REQUIRE_EQUAL(buff.new_slots_free, 120);
80  TRACE_REQUIRE_EQUAL(buff.rank, 0);
81 
82  my_rank = 13;
83  t.SendRoutingToken(335);
84 
85  sts = read(conn_sock, &buff, sizeof(artdaq::detail::RoutingToken));
86 
87  TRACE_REQUIRE_EQUAL(sts, sizeof(artdaq::detail::RoutingToken));
88  TRACE_REQUIRE_EQUAL(buff.header, TOKEN_MAGIC);
89  TRACE_REQUIRE_EQUAL(buff.new_slots_free, 335);
90  TRACE_REQUIRE_EQUAL(buff.rank, 13);
91 
92  close(conn_sock);
93  close(token_socket);
94  TLOG(TLVL_INFO) << "Tokens Test Case END";
95 }
96 
97 BOOST_AUTO_TEST_CASE(Requests)
98 {
99  artdaq::configureMessageFacility("RequestSender_t", true, true);
100  metricMan->initialize(fhicl::ParameterSet());
101  metricMan->do_start();
102  TLOG(TLVL_INFO) << "Requests Test Case BEGIN" ;
103  const int REQUEST_PORT = (seedAndRandom() % (32768 - 1024)) + 1024;
104  const int DELAY_TIME = 100;
105 #if 0
106  const std::string MULTICAST_IP = "227.28.12.28";
107 #else
108  const std::string MULTICAST_IP = "localhost";
109 #endif
110  fhicl::ParameterSet pset;
111  pset.put("request_port", REQUEST_PORT);
112  pset.put("request_delay_ms", DELAY_TIME);
113  pset.put("send_requests", true);
114  pset.put("request_address", MULTICAST_IP);
115  artdaq::RequestSender t(pset);
116 
117 
118  TLOG(TLVL_DEBUG) << "Opening request listener socket" ;
119  auto request_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
120 
121  struct sockaddr_in si_me_request;
122 
123  int yes = 1;
124  if (setsockopt(request_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0)
125  {
126  TLOG(TLVL_ERROR) << "Unable to set reuse on request socket" ;
127  BOOST_REQUIRE_EQUAL(true, false);
128  return;
129  }
130  memset(&si_me_request, 0, sizeof(si_me_request));
131  si_me_request.sin_family = AF_INET;
132  si_me_request.sin_port = htons(REQUEST_PORT);
133  si_me_request.sin_addr.s_addr = htonl(INADDR_ANY);
134  if (bind(request_socket, (struct sockaddr *)&si_me_request, sizeof(si_me_request)) == -1)
135  {
136  TLOG(TLVL_ERROR) << "Cannot bind request socket to port " << REQUEST_PORT ;
137  BOOST_REQUIRE_EQUAL(true, false);
138  return;
139  }
140 
141  if (MULTICAST_IP != "localhost")
142  {
143  struct ip_mreq mreq;
144  int sts = ResolveHost(MULTICAST_IP.c_str(), mreq.imr_multiaddr);
145  if (sts == -1)
146  {
147  TLOG(TLVL_ERROR) << "Unable to resolve multicast request address" ;
148  BOOST_REQUIRE_EQUAL(true, false);
149  return;
150  }
151  mreq.imr_interface.s_addr = htonl(INADDR_ANY);
152  if (setsockopt(request_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
153  {
154  TLOG(TLVL_ERROR) << "Unable to join multicast group" ;
155  BOOST_REQUIRE_EQUAL(true, false);
156  return;
157  }
158  }
159 
160  TLOG(TLVL_DEBUG) << "Sending request" ;
161  auto start_time = std::chrono::steady_clock::now();
162  t.AddRequest(0, 0x10);
163  struct pollfd ufds[1];
164 
165  TLOG(TLVL_DEBUG) << "Receiving Request" ;
166  ufds[0].fd = request_socket;
167  ufds[0].events = POLLIN | POLLPRI;
168  int rv = poll(ufds, 1, 10000);
169  if (rv > 0)
170  {
171  if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
172  {
173  auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
174  BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
175  TLOG(TLVL_TRACE) << "Recieved packet on Request channel";
176  std::vector<uint8_t> buffer(MAX_REQUEST_MESSAGE_SIZE);
178  recv(request_socket, &buffer[0], buffer.size(), 0);
179  memcpy(&hdr_buffer, &buffer[0], sizeof(artdaq::detail::RequestHeader));
180  TRACE_REQUIRE_EQUAL(hdr_buffer.isValid(), true);
181  TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.mode),
182  static_cast<uint8_t>(artdaq::detail::RequestMessageMode::Normal));
183  TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 1);
184  if (hdr_buffer.isValid())
185  {
186 
187  std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
188  memcpy(&pkt_buffer[0], &buffer[sizeof(artdaq::detail::RequestHeader)], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count);
189 
190  for (auto& buffer : pkt_buffer)
191  {
192  TRACE_REQUIRE_EQUAL(buffer.isValid(), true);
193  TRACE_REQUIRE_EQUAL(buffer.sequence_id, 0);
194  TRACE_REQUIRE_EQUAL(buffer.timestamp, 0x10);
195  }
196  }
197  else
198  {
199  TLOG(TLVL_ERROR) << "Invalid header received" ;
200  BOOST_REQUIRE_EQUAL(false, true);
201  return;
202  }
203  }
204  else
205  {
206  TLOG(TLVL_ERROR) << "Wrong event type from poll" ;
207  BOOST_REQUIRE_EQUAL(false, true);
208  return;
209  }
210  }
211  else
212  {
213  TLOG(TLVL_ERROR) << "Timeout occured waiting for request" ;
214  BOOST_REQUIRE_EQUAL(false, true);
215  return;
216  }
217 
218  // SetRequestMode and AddRequest BOTH send requests...
219  start_time = std::chrono::steady_clock::now();
221  t.AddRequest(2, 0x20);
222  rv = poll(ufds, 1, 1000);
223  if (rv > 0)
224  {
225  if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
226  {
227  auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
228  BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
229  TLOG(TLVL_TRACE) << "Recieved packet on Request channel";
230  std::vector<uint8_t> buffer(MAX_REQUEST_MESSAGE_SIZE);
232  recv(request_socket, &buffer[0], buffer.size(), 0);
233  memcpy(&hdr_buffer, &buffer[0], sizeof(artdaq::detail::RequestHeader));
234  TRACE_REQUIRE_EQUAL(hdr_buffer.isValid(), true);
235  TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.mode),
236  static_cast<uint8_t>(artdaq::detail::RequestMessageMode::EndOfRun));
237  TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 2);
238  if (hdr_buffer.isValid())
239  {
240 
241  std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
242  memcpy(&pkt_buffer[0], &buffer[sizeof(artdaq::detail::RequestHeader)], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count);
243 
244  TRACE_REQUIRE_EQUAL(pkt_buffer[0].isValid(), true);
245  TRACE_REQUIRE_EQUAL(pkt_buffer[0].sequence_id, 0);
246  TRACE_REQUIRE_EQUAL(pkt_buffer[0].timestamp, 0x10);
247  TRACE_REQUIRE_EQUAL(pkt_buffer[1].isValid(), true);
248  TRACE_REQUIRE_EQUAL(pkt_buffer[1].sequence_id, 2);
249  TRACE_REQUIRE_EQUAL(pkt_buffer[1].timestamp, 0x20);
250 
251  }
252  else
253  {
254  TLOG(TLVL_ERROR) << "Invalid header received" ;
255  BOOST_REQUIRE_EQUAL(false, true);
256  return;
257  }
258  }
259  else
260  {
261  TLOG(TLVL_ERROR) << "Wrong event type from poll" ;
262  BOOST_REQUIRE_EQUAL(false, true);
263  return;
264  }
265  }
266  else
267  {
268  TLOG(TLVL_ERROR) << "Timeout occured waiting for request" ;
269  BOOST_REQUIRE_EQUAL(false, true);
270  return;
271  }
272  rv = poll(ufds, 1, 1000);
273  if (rv > 0)
274  {
275  if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
276  {
277  auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
278  BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
279  TLOG(TLVL_TRACE) << "Recieved packet on Request channel";
280  std::vector<uint8_t> buffer(MAX_REQUEST_MESSAGE_SIZE);
282  recv(request_socket, &buffer[0], buffer.size(), 0);
283  memcpy(&hdr_buffer, &buffer[0], sizeof(artdaq::detail::RequestHeader));
284  TRACE_REQUIRE_EQUAL(hdr_buffer.isValid(), true);
285  TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.mode),
286  static_cast<uint8_t>(artdaq::detail::RequestMessageMode::EndOfRun));
287  TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 2);
288  if (hdr_buffer.isValid())
289  {
290 
291  std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
292  memcpy(&pkt_buffer[0], &buffer[sizeof(artdaq::detail::RequestHeader)], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count);
293 
294  TRACE_REQUIRE_EQUAL(pkt_buffer[0].isValid(), true);
295  TRACE_REQUIRE_EQUAL(pkt_buffer[0].sequence_id, 0);
296  TRACE_REQUIRE_EQUAL(pkt_buffer[0].timestamp, 0x10);
297  TRACE_REQUIRE_EQUAL(pkt_buffer[1].isValid(), true);
298  TRACE_REQUIRE_EQUAL(pkt_buffer[1].sequence_id, 2);
299  TRACE_REQUIRE_EQUAL(pkt_buffer[1].timestamp, 0x20);
300 
301  }
302  else
303  {
304  TLOG(TLVL_ERROR) << "Invalid header received" ;
305  BOOST_REQUIRE_EQUAL(false, true);
306  return;
307  }
308  }
309  else
310  {
311  TLOG(TLVL_ERROR) << "Wrong event type from poll" ;
312  BOOST_REQUIRE_EQUAL(false, true);
313  return;
314  }
315  }
316  else
317  {
318  TLOG(TLVL_ERROR) << "Timeout occured waiting for request" ;
319  BOOST_REQUIRE_EQUAL(false, true);
320  return;
321  }
322 
323  t.RemoveRequest(0);
324  t.RemoveRequest(2);
325  t.AddRequest(3, 0x30);
326  start_time = std::chrono::steady_clock::now();
327  rv = poll(ufds, 1, 1000);
328  if (rv > 0)
329  {
330  if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
331  {
332  auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
333  BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
334  TLOG(TLVL_TRACE) << "Recieved packet on Request channel";
335  std::vector<uint8_t> buffer(MAX_REQUEST_MESSAGE_SIZE);
337  recv(request_socket, &buffer[0], buffer.size(), 0);
338  memcpy(&hdr_buffer, &buffer[0], sizeof(artdaq::detail::RequestHeader));
339  TRACE_REQUIRE_EQUAL(hdr_buffer.isValid(), true);
340  TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.mode),
341  static_cast<uint8_t>(artdaq::detail::RequestMessageMode::EndOfRun));
342  TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 1);
343  if (hdr_buffer.isValid())
344  {
345 
346  std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
347  memcpy(&pkt_buffer[0], &buffer[sizeof(artdaq::detail::RequestHeader)], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count);
348 
349  TRACE_REQUIRE_EQUAL(pkt_buffer[0].isValid(), true);
350  TRACE_REQUIRE_EQUAL(pkt_buffer[0].sequence_id, 3);
351  TRACE_REQUIRE_EQUAL(pkt_buffer[0].timestamp, 0x30);
352 
353  }
354  else
355  {
356  TLOG(TLVL_ERROR) << "Invalid header received" ;
357  BOOST_REQUIRE_EQUAL(false, true);
358  return;
359  }
360  }
361  else
362  {
363  TLOG(TLVL_ERROR) << "Wrong event type from poll" ;
364  BOOST_REQUIRE_EQUAL(false, true);
365  return;
366  }
367  }
368  else
369  {
370  TLOG(TLVL_ERROR) << "Timeout occured waiting for request" ;
371  BOOST_REQUIRE_EQUAL(false, true);
372  return;
373  }
374 
375  close(request_socket);
376  TLOG(TLVL_INFO) << "Requests Test Case END";
377  artdaq::Globals::CleanUpGlobals();
378 }
379 
380 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)
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.
unsigned new_slots_free
The number of slots free in the token sender (usually 1)
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 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.