artdaq  v3_00_03
RequestSender_t.cc
1 #include "artdaq/DAQrate/RequestSender.hh"
2 
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"
9 #include <sys/poll.h>
10 
11 
12 BOOST_AUTO_TEST_SUITE(RequestSender_test)
13 
14 #define TRACE_REQUIRE_EQUAL(l,r) do { \
15 if(l == r) { \
16 TLOG_DEBUG("RequestSender_t") << __LINE__ << ": Checking if " << #l << " (" << std::to_string(l) << ") equals " << #r << " (" << std::to_string(r) << ")...YES!" << TLOG_ENDL; \
17 } \
18 else \
19 { \
20  TLOG_ERROR("RequestSender_t") << __LINE__ << ": Checking if " << #l << " (" << std::to_string(l) << ") equals " << #r << " (" << std::to_string(r) << ")...NO!" << TLOG_ENDL; \
21 } \
22  BOOST_REQUIRE_EQUAL(l, r); \
23 } while(0)
24 
25 BOOST_AUTO_TEST_CASE(Construct)
26 {
27  artdaq::configureMessageFacility("RequestSender_t", true, true);
28  TLOG_INFO("RequestSender_t") << "Construct Test Case BEGIN" << TLOG_ENDL;
29  fhicl::ParameterSet pset;
30  artdaq::RequestSender t(pset);
31  BOOST_REQUIRE_EQUAL(t.GetRequestMode(), artdaq::detail::RequestMessageMode::Normal);
32 }
33 
34 BOOST_AUTO_TEST_CASE(Tokens)
35 {
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;
40  auto token_socket = TCP_listen_fd(TOKEN_PORT, 3 * sizeof(artdaq::detail::RoutingToken));
41 
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);
47  artdaq::RequestSender t(pset);
48 
49  my_rank = 0;
50 
51 
52  BOOST_REQUIRE(token_socket != -1);
53  if (token_socket == -1)
54  {
55  TLOG_ERROR("RequestSender_t") << "Token listener socket was not opened successfully." << TLOG_ENDL;
56  BOOST_REQUIRE_EQUAL(false, true);
57  return;
58  }
59 
60  TLOG_DEBUG("RequestSender_t") << "Accepting new connection on token_socket" << TLOG_ENDL;
61  sockaddr_in addr;
62  socklen_t arglen = sizeof(addr);
63  auto conn_sock = accept(token_socket, (struct sockaddr*)&addr, &arglen);
64 
65  t.SendRoutingToken(120);
66 
68  auto sts = read(conn_sock, &buff, sizeof(artdaq::detail::RoutingToken));
69 
70  TRACE_REQUIRE_EQUAL(sts, sizeof(artdaq::detail::RoutingToken));
71  TRACE_REQUIRE_EQUAL(buff.header, TOKEN_MAGIC);
72  TRACE_REQUIRE_EQUAL(buff.new_slots_free, 120);
73  TRACE_REQUIRE_EQUAL(buff.rank, 0);
74 
75  my_rank = 13;
76  t.SendRoutingToken(335);
77 
78  sts = read(conn_sock, &buff, sizeof(artdaq::detail::RoutingToken));
79 
80  TRACE_REQUIRE_EQUAL(sts, sizeof(artdaq::detail::RoutingToken));
81  TRACE_REQUIRE_EQUAL(buff.header, TOKEN_MAGIC);
82  TRACE_REQUIRE_EQUAL(buff.new_slots_free, 335);
83  TRACE_REQUIRE_EQUAL(buff.rank, 13);
84 
85  close(conn_sock);
86  close(token_socket);
87 }
88 
89 BOOST_AUTO_TEST_CASE(Requests)
90 {
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;
95 #if 0
96  const std::string MULTICAST_IP = "227.28.12.28";
97 #else
98  const std::string MULTICAST_IP = "localhost";
99 #endif
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);
105  artdaq::RequestSender t(pset);
106 
107 
108  TLOG_DEBUG("RequestSender_t") << "Opening request listener socket" << TLOG_ENDL;
109  auto request_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
110 
111  struct sockaddr_in si_me_request;
112 
113  int yes = 1;
114  if (setsockopt(request_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0)
115  {
116  TLOG_ERROR("RequestSender_t") << "Unable to set reuse on request socket" << TLOG_ENDL;
117  BOOST_REQUIRE_EQUAL(true, false);
118  return;
119  }
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)
125  {
126  TLOG_ERROR("RequestSender_t") << "Cannot bind request socket to port " << std::to_string(REQUEST_PORT) << TLOG_ENDL;
127  BOOST_REQUIRE_EQUAL(true, false);
128  return;
129  }
130 
131  if (MULTICAST_IP != "localhost")
132  {
133  struct ip_mreq mreq;
134  int sts = ResolveHost(MULTICAST_IP.c_str(), mreq.imr_multiaddr);
135  if (sts == -1)
136  {
137  TLOG_ERROR("RequestSender_t") << "Unable to resolve multicast request address" << TLOG_ENDL;
138  BOOST_REQUIRE_EQUAL(true, false);
139  return;
140  }
141  mreq.imr_interface.s_addr = htonl(INADDR_ANY);
142  if (setsockopt(request_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
143  {
144  TLOG_ERROR("RequestSender_t") << "Unable to join multicast group" << TLOG_ENDL;
145  BOOST_REQUIRE_EQUAL(true, false);
146  return;
147  }
148  }
149 
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];
154 
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);
159  if (rv > 0)
160  {
161  if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
162  {
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),
170  static_cast<uint8_t>(artdaq::detail::RequestMessageMode::Normal));
171  TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 1);
172  if (hdr_buffer.isValid())
173  {
174 
175  std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
176  recv(request_socket, &pkt_buffer[0], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count, 0);
177 
178  for (auto& buffer : pkt_buffer)
179  {
180  TRACE_REQUIRE_EQUAL(buffer.isValid(), true);
181  TRACE_REQUIRE_EQUAL(buffer.sequence_id, 0);
182  TRACE_REQUIRE_EQUAL(buffer.timestamp, 0x10);
183  }
184  }
185  else
186  {
187  TLOG_ERROR("RequestSender_t") << "Invalid header received" << TLOG_ENDL;
188  BOOST_REQUIRE_EQUAL(false, true);
189  return;
190  }
191  }
192  else
193  {
194  TLOG_ERROR("RequestSender_t") << "Wrong event type from poll" << TLOG_ENDL;
195  BOOST_REQUIRE_EQUAL(false, true);
196  return;
197  }
198  }
199  else
200  {
201  TLOG_ERROR("RequestSender_t") << "Timeout occured waiting for request" << TLOG_ENDL;
202  BOOST_REQUIRE_EQUAL(false, true);
203  return;
204  }
205 
206  // SetRequestMode and AddRequest BOTH send requests...
208  t.AddRequest(2, 0x20);
209  start_time = std::chrono::steady_clock::now();
210  rv = poll(ufds, 1, 1000);
211  if (rv > 0)
212  {
213  if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
214  {
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),
223  static_cast<uint8_t>(artdaq::detail::RequestMessageMode::EndOfRun));
224  TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 2);
225  if (hdr_buffer.isValid())
226  {
227 
228  std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
229  sts = recv(request_socket, &pkt_buffer[0], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count, 0);
230  TRACE_REQUIRE_EQUAL(static_cast<size_t>(sts), static_cast<size_t>(sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count));
231 
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);
238 
239  }
240  else
241  {
242  TLOG_ERROR("RequestSender_t") << "Invalid header received" << TLOG_ENDL;
243  BOOST_REQUIRE_EQUAL(false, true);
244  return;
245  }
246  }
247  else
248  {
249  TLOG_ERROR("RequestSender_t") << "Wrong event type from poll" << TLOG_ENDL;
250  BOOST_REQUIRE_EQUAL(false, true);
251  return;
252  }
253  }
254  else
255  {
256  TLOG_ERROR("RequestSender_t") << "Timeout occured waiting for request" << TLOG_ENDL;
257  BOOST_REQUIRE_EQUAL(false, true);
258  return;
259  }
260  rv = poll(ufds, 1, 1000);
261  if (rv > 0)
262  {
263  if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
264  {
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),
272  static_cast<uint8_t>(artdaq::detail::RequestMessageMode::EndOfRun));
273  TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 2);
274  if (hdr_buffer.isValid())
275  {
276 
277  std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
278  recv(request_socket, &pkt_buffer[0], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count, 0);
279 
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);
286 
287  }
288  else
289  {
290  TLOG_ERROR("RequestSender_t") << "Invalid header received" << TLOG_ENDL;
291  BOOST_REQUIRE_EQUAL(false, true);
292  return;
293  }
294  }
295  else
296  {
297  TLOG_ERROR("RequestSender_t") << "Wrong event type from poll" << TLOG_ENDL;
298  BOOST_REQUIRE_EQUAL(false, true);
299  return;
300  }
301  }
302  else
303  {
304  TLOG_ERROR("RequestSender_t") << "Timeout occured waiting for request" << TLOG_ENDL;
305  BOOST_REQUIRE_EQUAL(false, true);
306  return;
307  }
308 
309  t.RemoveRequest(0);
310  t.RemoveRequest(2);
311  t.AddRequest(3, 0x30);
312  start_time = std::chrono::steady_clock::now();
313  rv = poll(ufds, 1, 1000);
314  if (rv > 0)
315  {
316  if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
317  {
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),
325  static_cast<uint8_t>(artdaq::detail::RequestMessageMode::EndOfRun));
326  TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 1);
327  if (hdr_buffer.isValid())
328  {
329 
330  std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
331  recv(request_socket, &pkt_buffer[0], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count, 0);
332 
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);
336 
337  }
338  else
339  {
340  TLOG_ERROR("RequestSender_t") << "Invalid header received" << TLOG_ENDL;
341  BOOST_REQUIRE_EQUAL(false, true);
342  return;
343  }
344  }
345  else
346  {
347  TLOG_ERROR("RequestSender_t") << "Wrong event type from poll" << TLOG_ENDL;
348  BOOST_REQUIRE_EQUAL(false, true);
349  return;
350  }
351  }
352  else
353  {
354  TLOG_ERROR("RequestSender_t") << "Timeout occured waiting for request" << TLOG_ENDL;
355  BOOST_REQUIRE_EQUAL(false, true);
356  return;
357  }
358 
359  close(request_socket);
360 }
361 
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.
Definition: TCPConnect.cc:27
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.