DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
dunedaq::datahandlinglibs::test Namespace Reference

Classes

class  TestDefaultRequestHandlerModel
 

Functions

template<template< class > class BufferType, class TypeAdapter >
void fill_buffer (std::shared_ptr< BufferType< TypeAdapter > > &buffer, uint64_t const init_timestamp=0, size_t const n_obj=10, std::set< size_t > const obj_to_skip={})
 
template<template< class > class BufferType, class TypeAdapter >
void print_buffer (std::shared_ptr< BufferType< TypeAdapter > > &buffer, std::string desc="")
 
template<template< class > class BufferType, class TypeAdapter >
void test_queue_model ()
 
template<template< class > class BufferType, class TypeAdapter >
void test_request_model ()
 

Function Documentation

◆ fill_buffer()

template<template< class > class BufferType, class TypeAdapter >
void dunedaq::datahandlinglibs::test::fill_buffer ( std::shared_ptr< BufferType< TypeAdapter > > & buffer,
uint64_t const init_timestamp = 0,
size_t const n_obj = 10,
std::set< size_t > const obj_to_skip = {} )

Definition at line 27 of file TestUtilities.hpp.

30 {}){
31
32 //allocate mem in buffer
33 buffer->allocate_memory(n_obj);
34
35 //some accounting
36 size_t i=0,i_obj=0;
37 uint64_t next_timestamp=init_timestamp;
38
39 //while we want to add to the buffer
40 while(i_obj<n_obj){
41
42 //create a frame with appropriate timestamp
43 TypeAdapter frame;
44 frame.fake_timestamps(next_timestamp);
45
46 //increment to the next timestamp
47 next_timestamp += uint64_t(frame.get_num_frames()*TypeAdapter::expected_tick_difference);
48
49 //only write in buffer if not in the skip list
50 if(obj_to_skip.count(i)==0) {
51 buffer->write(std::move(frame));
52 ++i_obj;
53 }
54 ++i;
55 } // end while(obj_in_buffer<n_obj)
56}//end fill_buffer

◆ print_buffer()

template<template< class > class BufferType, class TypeAdapter >
void dunedaq::datahandlinglibs::test::print_buffer ( std::shared_ptr< BufferType< TypeAdapter > > & buffer,
std::string desc = "" )

Definition at line 59 of file TestUtilities.hpp.

59 {
60 std::stringstream ss;
61 ss << "Buffer (" << desc << "): ";
62 typename BufferType<TypeAdapter>::Iterator iter=buffer->begin();
63 while(iter!=buffer->end()){
64 ss << iter->get_timestamp() << " ";
65 ++iter;
66 }
67 BOOST_TEST_MESSAGE(ss.str());
68}//end print_buffer

◆ test_queue_model()

template<template< class > class BufferType, class TypeAdapter >
void dunedaq::datahandlinglibs::test::test_queue_model ( )

Definition at line 71 of file TestUtilities.hpp.

72{
73 //some testing vars
74 TypeAdapter test_element;
75 uint64_t ticks_between = TypeAdapter::expected_tick_difference*test_element.get_num_frames();
76
77 auto test_lower_bound = [&]( std::shared_ptr<BufferType<TypeAdapter>> buffer,
78 uint64_t test_ts,
79 uint32_t expected_idx,
80 bool with_errors=false){
81
82 BOOST_TEST_MESSAGE("\ttesting ts=" << test_ts);
83
84 TypeAdapter test_element; test_element.set_timestamp(test_ts);
85 typename BufferType<TypeAdapter>::Iterator expected_el = buffer->begin();
86 for(size_t i=0; i<expected_idx; ++i){
87 ++expected_el;
88 }
89
90 //get our lower_bound call
91 auto return_el = buffer->lower_bound(test_element,with_errors);
92
93 //loop through to get the previous element to return_el
94 typename BufferType<TypeAdapter>::Iterator scan_el = buffer->begin();
95 typename BufferType<TypeAdapter>::Iterator prev_el = buffer->begin();
96 while(scan_el!=return_el){
97 ++scan_el;
98 if(scan_el==return_el) break;
99 ++prev_el;
100 }
101
102 //check that expected and return timestamps agree
103 BOOST_CHECK_MESSAGE(expected_el->get_timestamp()==return_el->get_timestamp(),
104 "Expected ts{" << expected_el->get_timestamp() << "} == return ts{" << return_el->get_timestamp() << "} for test_ts=" << test_ts);
105
106 //check that we satisfy the lower bound condition
107 BOOST_CHECK_MESSAGE(return_el->get_timestamp()>=test_ts,
108 "Returned ts{" << return_el->get_timestamp() << "} is >= test_ts{" << test_ts << "}");
109 BOOST_CHECK_MESSAGE((prev_el->get_timestamp()<test_ts || return_el==buffer->begin()),
110 "Prev ts{" << prev_el->get_timestamp() << "} is < test_ts{" << test_ts << "} (or lower bound is begin of buffer)");
111 }; //end test_lower_bounds
112
113
114
115 /*
116 * Unskipped buffer should have elements with index [0, 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
117 * and timestamps [0,1*T,2*T,3*T,4*T,5*T,6*T,7*T,8*T,9*T]
118 * where T = DTS ticks between successive elements (tick_diff_per_frame * n_frames_per_obj_in_buffer)
119 */
120 BOOST_TEST_MESSAGE("Testing buffer without skips...");
121 auto buffer_noskip = std::make_shared< BufferType<TypeAdapter> >();
122 fill_buffer<BufferType,TypeAdapter>(buffer_noskip,0,10);
123 print_buffer<BufferType,TypeAdapter>(buffer_noskip,"noskip");
124
125 // get lower bound on aligned element
126 // should return the exact value
127 test_lower_bound(buffer_noskip,ticks_between*2,2);
128
129 if(ticks_between>1) //unaligned tests don't make sense if ticks_between < 1
130 {
131 // get lower bound when maximally unaligned
132 // should get the next element up
133 test_lower_bound(buffer_noskip, ticks_between * 5 / 2, 3);
134
135 // get lower bound when minimally unaligned, next instance
136 test_lower_bound(buffer_noskip, ticks_between + 1, 2);
137 }
138
139 /*
140 * Skipped buffer should have elements with index [0, 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
141 * and timestamps [0,1*T,4*T,5*T,6*T,7*T,8*T,9*T,10*T,11*T]
142 * where T = DTS ticks between successive elements (tick_diff_per_frame * n_frames_per_obj_in_buffer)
143 */
144 BOOST_TEST_MESSAGE("Testing buffer with skips...");
145 std::set<size_t> obj_to_skip = {2,3};
146 auto buffer_skip = std::make_shared< BufferType<TypeAdapter> >();
147 fill_buffer<BufferType,TypeAdapter>(buffer_skip,0,10,obj_to_skip);
148 print_buffer<BufferType,TypeAdapter>(buffer_skip,"skip");
149
150 // get lower bound on aligned but skipped element
151 // should return next available
152 test_lower_bound(buffer_skip,ticks_between*2,2,true);
153 test_lower_bound(buffer_skip,ticks_between*3,2,true);
154 // should be unaffected
155 test_lower_bound(buffer_skip,ticks_between,1,true);
156 test_lower_bound(buffer_skip,ticks_between*4,2,true);
157
158 if(ticks_between>1) //unaligned tests don't make sense if ticks_between < 1
159 {
160 // get lower bound when maximally unaligned
161 test_lower_bound(buffer_skip, ticks_between * 3 / 2, 2, true);
162 test_lower_bound(buffer_skip, ticks_between * 5 / 2, 2, true);
163 test_lower_bound(buffer_skip, ticks_between * 7 / 2, 2, true);
164 // should be unaffected
165 test_lower_bound(buffer_skip, ticks_between * 1 / 2, 1, true);
166 test_lower_bound(buffer_skip, ticks_between * 9 / 2, 3, true);
167 test_lower_bound(buffer_skip, ticks_between * 11 / 2, 4, true);
168
169 // get lower bound when minimally unaligned, next instance
170 test_lower_bound(buffer_skip, ticks_between + 1, 2, true);
171 test_lower_bound(buffer_skip, ticks_between * 2 + 1, 2, true);
172 // should be unaffected
173 test_lower_bound(buffer_skip, 1, 1, true);
174 }
175
176}//end test_queue_model

◆ test_request_model()

template<template< class > class BufferType, class TypeAdapter >
void dunedaq::datahandlinglibs::test::test_request_model ( )

Definition at line 190 of file TestUtilities.hpp.

190 {
191
193
194 //some testing vars
195 TypeAdapter test_element;
196 uint64_t n_frames = test_element.get_num_frames();
197 uint64_t ticks_per_frame = TypeAdapter::expected_tick_difference;
198 uint64_t ticks_between = ticks_per_frame*n_frames;
199
200
201 // function for testing get_fragment_pieces in cases where there are no skips in the buffer
202 auto test_req_bounds = [&](std::shared_ptr<BufferType<TypeAdapter>> buffer,
203 uint64_t start_win, uint64_t end_win,
204 std::set<size_t> objects_skipped={}){
205
206 BOOST_TEST_MESSAGE("\ttesting [start_win{" << start_win << "}, end_win{" << end_win << "})");
207
208 //make the error registry we need
209 auto errorRegistry = std::make_unique<dunedaq::datahandlinglibs::FrameErrorRegistry>();
210
211 //create the request handler
212 DefaultRequestHandler requestHandler(buffer,errorRegistry);
213
214 //call the get_fragment_pieces
215 auto dfmessage = dunedaq::dfmessages::DataRequest();
216 auto req_res = typename DefaultRequestHandler::RequestResult(DefaultRequestHandler::ResultCode::kUnknown,dfmessage);
217 auto ret = requestHandler.get_fragment_pieces(start_win,end_win,req_res);
218
219 //check that the return code is correct.
220 BOOST_CHECK_EQUAL(req_res.result_code,DefaultRequestHandler::ResultCode::kFound);
221
222
223
224 //check that the first and last returned blocks are not empty
225 BOOST_REQUIRE_GT(ret.front().second,0);
226 BOOST_REQUIRE_GT(ret.back().second,0);
227
228 //grab the (first) timestamps of the first and last frames
229 uint64_t first_ts = reinterpret_cast<const TypeAdapter::FrameType*>(ret.front().first)->get_timestamp();
230
231 // if n_frames is 1, then all payloads are just one frame, and we can grab the timestamp directly
232 // this is particularly useful for not having to deal with wrapper objects, as those complicate things a bunch
233 // if not, then we really hope that sizeof(TypeAdapter::FrameType) is what we want ...
234 uint64_t last_ts=0;
235 if(n_frames==1)
236 last_ts = reinterpret_cast<const TypeAdapter::FrameType*>(ret.back().first)->get_timestamp();
237 else
238 last_ts = reinterpret_cast<const TypeAdapter::FrameType*>((char*)(ret.back().first)+(ret.back().second)-sizeof(typename TypeAdapter::FrameType))->get_timestamp();
239
240 //general check:
241 // first_ts <= start_win < first_ts + ticks_per_frame
242 // last_ts < end_win <= last_ts + ticks_per_frame
243 if(objects_skipped.size()==0)
244 BOOST_CHECK_MESSAGE(first_ts<=start_win,
245 "first_frame_ts{" << first_ts << "} <= start_win{" << start_win << "}");
246 BOOST_CHECK_MESSAGE(start_win<first_ts+ticks_per_frame,
247 "start_win{" << start_win << "} < first_frame_ts+ticks_per_frame{" << first_ts+ticks_per_frame << "}");
248 BOOST_CHECK_MESSAGE(last_ts<end_win,
249 "Check last_frame_ts{" << last_ts << "} < end_win{" << end_win << "}");
250 if(objects_skipped.size()==0)
251 BOOST_CHECK_MESSAGE(end_win<=last_ts+ticks_per_frame,
252 "end_win{" << end_win << "} <= last_frame_ts+ticks_per_frame{" << last_ts+ticks_per_frame << "}");
253
254 //expected timestamps for begin of fragment and 'end' of fragment, assuming no skipping
255 auto expected_start = TypeAdapter::expected_tick_difference *
256 (uint64_t) std::floor((float) (start_win) / (float) (ticks_per_frame));
257 auto expected_end = TypeAdapter::expected_tick_difference *
258 (uint64_t) std::ceil((float) (end_win) / (float) (ticks_per_frame));
259
260 //correct for the cases there that object has been skipped
261 auto expected_start_obj = expected_start - expected_start%ticks_between;
262 while(objects_skipped.count(expected_start_obj/ticks_between)>0 && expected_start<expected_end) {
263 expected_start += ticks_per_frame;
264 expected_start_obj = expected_start - expected_start%ticks_between;
265 }
266
267 auto expected_end_obj = expected_end - ticks_per_frame - (expected_end-ticks_per_frame)%ticks_between;
268 while(objects_skipped.count(expected_end_obj/ticks_between)>0 && expected_end>(expected_start+ticks_per_frame) ) {
269 expected_end -= ticks_per_frame;
270 expected_start_obj = expected_end - ticks_per_frame - (expected_end-ticks_per_frame)%ticks_between;
271 }
272
273 //specfic check: are values for this request what we expect
274 BOOST_CHECK_MESSAGE(first_ts == expected_start,
275 "Fragment start ts {" << first_ts << "} is expected value {" << expected_start << "}");
276 BOOST_CHECK_MESSAGE((last_ts + TypeAdapter::expected_tick_difference) == expected_end,
277 "Fragment 'end' ts {" << last_ts + TypeAdapter::expected_tick_difference
278 << "} is expected value {" << expected_end << "}");
279 };//end test_req_bounds
280
281 /*
282 * Unskipped buffer should have elements with index [0, 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
283 * and timestamps [0,1*T,2*T,3*T,4*T,5*T,6*T,7*T,8*T,9*T]
284 * where T = DTS ticks between successive elements (tick_diff_per_frame * n_frames_per_obj_in_buffer)
285 */
286 BOOST_TEST_MESSAGE("Testing buffer without skips...");
287 auto buffer_noskip = std::make_shared< BufferType<TypeAdapter> >();
288 fill_buffer<BufferType,TypeAdapter>(buffer_noskip,0,10);
289 print_buffer<BufferType,TypeAdapter>(buffer_noskip,"noskip");
290
291 test_req_bounds(buffer_noskip,ticks_between*2,ticks_between*5);
292 test_req_bounds(buffer_noskip,ticks_between*3/2,ticks_between*9/2);
293 test_req_bounds(buffer_noskip,ticks_between*11/5,ticks_between*21/5);
294 test_req_bounds(buffer_noskip,ticks_between*2+1,ticks_between*5+1);
295
296 /*
297 * Skipped buffer should have elements with index [0, 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
298 * and timestamps [0,1*T,4*T,5*T,6*T,7*T,8*T,9*T,10*T,11*T]
299 * where T = DTS ticks between successive elements (tick_diff_per_frame * n_frames_per_obj_in_buffer)
300 */
301 BOOST_TEST_MESSAGE("Testing buffer with skips...");
302 std::set<size_t> obj_to_skip = {2,3};
303 auto buffer_skip = std::make_shared< BufferType<TypeAdapter> >();
304 fill_buffer<BufferType,TypeAdapter>(buffer_skip,0,10,obj_to_skip);
305 print_buffer<BufferType,TypeAdapter>(buffer_skip,"skip");
306
307 test_req_bounds(buffer_skip,ticks_between*2,ticks_between*5,obj_to_skip);
308 test_req_bounds(buffer_skip,ticks_between*3/2,ticks_between*9/2,obj_to_skip);
309 if((ticks_between*21/5)>4*ticks_between) //protect in cases where ticks_between is very small (e.g. 1)
310 test_req_bounds(buffer_skip,ticks_between*11/5,ticks_between*21/5,obj_to_skip);
311 test_req_bounds(buffer_skip,ticks_between*2+1,ticks_between*5+1,obj_to_skip);
312
313}//end test_request_model
This message represents a request for data sent to a single component of the DAQ.