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 : bool found_new_request = false;
168 4 : while (!found_new_request)
169 : {
170 3 : rv = poll(ufds, 1, 1000);
171 3 : if (rv > 0)
172 : {
173 3 : if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
174 : {
175 6 : TLOG(TLVL_TRACE) << "Recieved packet on Request channel";
176 3 : std::vector<uint8_t> buffer(MAX_REQUEST_MESSAGE_SIZE);
177 3 : artdaq::detail::RequestHeader hdr_buffer;
178 3 : recv(request_socket, &buffer[0], buffer.size(), 0);
179 3 : memcpy(&hdr_buffer, &buffer[0], sizeof(artdaq::detail::RequestHeader));
180 12 : TRACE_REQUIRE_EQUAL(hdr_buffer.isValid(), true);
181 :
182 3 : if (hdr_buffer.packet_count == 1)
183 : {
184 2 : continue;
185 : }
186 1 : found_new_request = true;
187 1 : auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
188 1 : BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
189 4 : TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.mode),
190 : static_cast<uint8_t>(artdaq::detail::RequestMessageMode::EndOfRun));
191 4 : TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 2);
192 1 : if (hdr_buffer.isValid())
193 : {
194 1 : std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
195 1 : memcpy(&pkt_buffer[0], &buffer[sizeof(artdaq::detail::RequestHeader)], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count);
196 :
197 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[0].isValid(), true);
198 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[0].sequence_id, 0);
199 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[0].timestamp, 0x10);
200 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[1].isValid(), true);
201 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[1].sequence_id, 2);
202 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[1].timestamp, 0x20);
203 1 : }
204 : else
205 : {
206 0 : TLOG(TLVL_ERROR) << "Invalid header received";
207 0 : BOOST_REQUIRE_EQUAL(false, true);
208 0 : return;
209 : }
210 4 : }
211 : else
212 : {
213 0 : TLOG(TLVL_ERROR) << "Wrong event type from poll";
214 0 : BOOST_REQUIRE_EQUAL(false, true);
215 0 : return;
216 : }
217 : }
218 : else
219 : {
220 0 : TLOG(TLVL_ERROR) << "Timeout occured waiting for request";
221 0 : BOOST_REQUIRE_EQUAL(false, true);
222 0 : return;
223 : }
224 : }
225 :
226 1 : t.RemoveRequest(0);
227 1 : t.RemoveRequest(2);
228 1 : t.AddRequest(3, 0x30);
229 1 : start_time = std::chrono::steady_clock::now();
230 1 : rv = poll(ufds, 1, 1000);
231 1 : if (rv > 0)
232 : {
233 1 : if (ufds[0].revents == POLLIN || ufds[0].revents == POLLPRI)
234 : {
235 1 : auto delay_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
236 1 : BOOST_REQUIRE_GE(delay_time, DELAY_TIME);
237 2 : TLOG(TLVL_TRACE) << "Recieved packet on Request channel";
238 1 : std::vector<uint8_t> buffer(MAX_REQUEST_MESSAGE_SIZE);
239 1 : artdaq::detail::RequestHeader hdr_buffer;
240 1 : recv(request_socket, &buffer[0], buffer.size(), 0);
241 1 : memcpy(&hdr_buffer, &buffer[0], sizeof(artdaq::detail::RequestHeader));
242 4 : TRACE_REQUIRE_EQUAL(hdr_buffer.isValid(), true);
243 4 : TRACE_REQUIRE_EQUAL(static_cast<uint8_t>(hdr_buffer.mode),
244 : static_cast<uint8_t>(artdaq::detail::RequestMessageMode::EndOfRun));
245 4 : TRACE_REQUIRE_EQUAL(hdr_buffer.packet_count, 1);
246 1 : if (hdr_buffer.isValid())
247 : {
248 1 : std::vector<artdaq::detail::RequestPacket> pkt_buffer(hdr_buffer.packet_count);
249 1 : memcpy(&pkt_buffer[0], &buffer[sizeof(artdaq::detail::RequestHeader)], sizeof(artdaq::detail::RequestPacket) * hdr_buffer.packet_count);
250 :
251 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[0].isValid(), true);
252 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[0].sequence_id, 3);
253 4 : TRACE_REQUIRE_EQUAL(pkt_buffer[0].timestamp, 0x30);
254 1 : }
255 : else
256 : {
257 0 : TLOG(TLVL_ERROR) << "Invalid header received";
258 0 : BOOST_REQUIRE_EQUAL(false, true);
259 0 : return;
260 : }
261 2 : }
262 : else
263 : {
264 0 : TLOG(TLVL_ERROR) << "Wrong event type from poll";
265 0 : BOOST_REQUIRE_EQUAL(false, true);
266 0 : return;
267 : }
268 : }
269 : else
270 : {
271 0 : TLOG(TLVL_ERROR) << "Timeout occured waiting for request";
272 0 : BOOST_REQUIRE_EQUAL(false, true);
273 0 : return;
274 : }
275 :
276 1 : close(request_socket);
277 3 : TLOG(TLVL_INFO) << "Requests Test Case END";
278 1 : artdaq::Globals::CleanUpGlobals();
279 1 : }
280 :
281 : BOOST_AUTO_TEST_SUITE_END()
|