artdaq_core  v3_06_11
ContainerFragment_t.cc
1 #include "artdaq-core/Data/ContainerFragmentLoader.hh"
2 
3 #define BOOST_TEST_MODULE(ContainerFragment_t)
4 #include "cetlib/quiet_unit_test.hpp"
5 
6 BOOST_AUTO_TEST_SUITE(ContainerFragment_test)
7 
8 BOOST_AUTO_TEST_CASE(Construct)
9 {
10  artdaq::Fragment f(0);
12  auto cf = reinterpret_cast<artdaq::ContainerFragment*>(&cfl); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
13 
14  BOOST_REQUIRE_EQUAL(f.dataSize(), 1);
15  BOOST_REQUIRE_EQUAL(cf->block_count(), 0);
17  BOOST_REQUIRE_EQUAL(cf->fragment_type(), type);
18  BOOST_REQUIRE_EQUAL(*reinterpret_cast<const size_t*>(cf->dataBegin()), artdaq::ContainerFragment::CONTAINER_MAGIC); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
19 }
20 
21 BOOST_AUTO_TEST_CASE(AddEmptyFragment)
22 {
23  auto frag = new artdaq::Fragment();
24  frag->setSequenceID(0);
25  frag->setSystemType(artdaq::Fragment::EmptyFragmentType);
26 
27  artdaq::Fragment f(0);
29  auto cf = reinterpret_cast<artdaq::ContainerFragment*>(&cfl); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
30  cfl.set_fragment_type(artdaq::Fragment::EmptyFragmentType);
31  cfl.addFragment(*frag);
32 
33  BOOST_REQUIRE_EQUAL(f.dataSizeBytes(), sizeof(artdaq::detail::RawFragmentHeader) + (2 * sizeof(size_t)));
34  BOOST_REQUIRE_EQUAL(cf->block_count(), 1);
36  BOOST_REQUIRE_EQUAL(cf->fragment_type(), type);
37 
38  delete frag;
39 }
40 
41 BOOST_AUTO_TEST_CASE(AddFragment_Ptr)
42 {
43  std::vector<artdaq::Fragment::value_type> fakeData{1, 2, 3, 4};
46  0,
47  fakeData.begin(),
48  fakeData.end()));
49  tmpFrag->setUserType(artdaq::Fragment::FirstUserFragmentType);
50 
51  artdaq::Fragment f(0);
52  f.setSequenceID(1);
54  auto cf = reinterpret_cast<artdaq::ContainerFragment*>(&cfl); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
55  cfl.addFragment(tmpFrag);
56 
57  BOOST_REQUIRE_EQUAL(f.dataSizeBytes(), sizeof(artdaq::detail::RawFragmentHeader) + 4 * sizeof(artdaq::Fragment::value_type) + (2 * sizeof(size_t)));
58  BOOST_REQUIRE_EQUAL(f.sizeBytes(), 2 * sizeof(artdaq::detail::RawFragmentHeader) + 4 * sizeof(artdaq::Fragment::value_type) + (2 * sizeof(size_t)) + sizeof(artdaq::ContainerFragment::Metadata));
59  BOOST_REQUIRE_EQUAL(cf->block_count(), 1);
61  BOOST_REQUIRE_EQUAL(cf->fragment_type(), type);
62  BOOST_REQUIRE_EQUAL(cf->fragSize(0), tmpFrag->sizeBytes());
63 
64  auto outfrag = cf->at(0);
65  BOOST_REQUIRE_EQUAL(outfrag->sequenceID(), 1);
66  BOOST_REQUIRE_EQUAL(outfrag->fragmentID(), 0);
67  BOOST_REQUIRE_EQUAL(outfrag->dataSize(), 4);
68  BOOST_REQUIRE_EQUAL(*outfrag->dataBegin(), 1);
69  BOOST_REQUIRE_EQUAL(*(outfrag->dataBegin() + 1), 2);
70 }
71 
72 BOOST_AUTO_TEST_CASE(AddFragment_Ref)
73 {
74  std::vector<artdaq::Fragment::value_type> fakeData{1, 2, 3, 4};
77  0,
78  fakeData.begin(),
79  fakeData.end()));
80  tmpFrag->setUserType(artdaq::Fragment::FirstUserFragmentType);
81  auto frag = *tmpFrag.get();
82 
83  artdaq::Fragment f(0);
84  f.setSequenceID(1);
86  auto cf = reinterpret_cast<artdaq::ContainerFragment*>(&cfl); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
87  cfl.addFragment(frag);
88 
89  BOOST_REQUIRE_EQUAL(f.dataSizeBytes(), sizeof(artdaq::detail::RawFragmentHeader) + 4 * sizeof(artdaq::Fragment::value_type) + (2 * sizeof(size_t)));
90  BOOST_REQUIRE_EQUAL(f.sizeBytes(), 2 * sizeof(artdaq::detail::RawFragmentHeader) + 4 * sizeof(artdaq::Fragment::value_type) + (2 * sizeof(size_t)) + sizeof(artdaq::ContainerFragment::Metadata));
91  BOOST_REQUIRE_EQUAL(cf->block_count(), 1);
93  BOOST_REQUIRE_EQUAL(cf->fragment_type(), type);
94  BOOST_REQUIRE_EQUAL(cf->fragSize(0), tmpFrag->sizeBytes());
95 
96  auto outfrag = cf->at(0);
97  BOOST_REQUIRE_EQUAL(outfrag->sequenceID(), 1);
98  BOOST_REQUIRE_EQUAL(outfrag->fragmentID(), 0);
99  BOOST_REQUIRE_EQUAL(outfrag->dataSize(), 4);
100  BOOST_REQUIRE_EQUAL(*outfrag->dataBegin(), 1);
101  BOOST_REQUIRE_EQUAL(*(outfrag->dataBegin() + 1), 2);
102 }
103 
104 BOOST_AUTO_TEST_CASE(AddFragments)
105 {
106  std::vector<artdaq::Fragment::value_type> fakeData1{1, 2, 3, 4};
107  std::vector<artdaq::Fragment::value_type> fakeData2{5, 6, 7, 8};
109  tmpFrag1(artdaq::Fragment::dataFrag(1,
110  0,
111  fakeData1.begin(),
112  fakeData1.end()));
113  tmpFrag1->setUserType(artdaq::Fragment::FirstUserFragmentType);
115  tmpFrag2(artdaq::Fragment::dataFrag(1,
116  1,
117  fakeData2.begin(),
118  fakeData2.end()));
119  tmpFrag2->setUserType(artdaq::Fragment::FirstUserFragmentType);
120  artdaq::FragmentPtrs frags;
121  frags.push_back(std::move(tmpFrag1));
122  frags.push_back(std::move(tmpFrag2));
123 
124  artdaq::Fragment f(0);
125  f.setSequenceID(1);
127  auto cf = reinterpret_cast<artdaq::ContainerFragment*>(&cfl); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
128  cfl.addFragments(frags);
129 
130  BOOST_REQUIRE_EQUAL(f.dataSizeBytes(), 2 * (sizeof(artdaq::detail::RawFragmentHeader) + 4 * sizeof(artdaq::Fragment::value_type) + sizeof(size_t)) + sizeof(size_t));
131  BOOST_REQUIRE_EQUAL(f.sizeBytes(), 2 * (sizeof(artdaq::detail::RawFragmentHeader) + 4 * sizeof(artdaq::Fragment::value_type) + sizeof(size_t)) + sizeof(size_t) + sizeof(artdaq::detail::RawFragmentHeader) + sizeof(artdaq::ContainerFragment::Metadata));
132  BOOST_REQUIRE_EQUAL(cf->block_count(), 2);
134  BOOST_REQUIRE_EQUAL(cf->fragment_type(), type);
135 
136  auto outfrag = cf->at(0);
137  BOOST_REQUIRE_EQUAL(outfrag->sequenceID(), 1);
138  BOOST_REQUIRE_EQUAL(outfrag->fragmentID(), 0);
139  BOOST_REQUIRE_EQUAL(outfrag->dataSize(), 4);
140  BOOST_REQUIRE_EQUAL(*outfrag->dataBegin(), 1);
141  BOOST_REQUIRE_EQUAL(*(outfrag->dataBegin() + 1), 2);
142  outfrag = (*cf)[1]; // Alternate access operator
143  BOOST_REQUIRE_EQUAL(outfrag->sequenceID(), 1);
144  BOOST_REQUIRE_EQUAL(outfrag->fragmentID(), 1);
145  BOOST_REQUIRE_EQUAL(outfrag->dataSize(), 4);
146  BOOST_REQUIRE_EQUAL(*outfrag->dataBegin(), 5);
147  BOOST_REQUIRE_EQUAL(*(outfrag->dataBegin() + 1), 6);
148 }
149 
150 #define PERF_TEST_FRAGMENT_COUNT 1000
151 BOOST_AUTO_TEST_CASE(Performance)
152 {
153  artdaq::FragmentPtrs frags;
154  std::vector<artdaq::Fragment::value_type> fakeData1{1, 2, 3, 4};
155  for (int ii = 0; ii < PERF_TEST_FRAGMENT_COUNT; ++ii)
156  {
158  tmpFrag1(artdaq::Fragment::dataFrag(1,
159  ii,
160  fakeData1.begin(),
161  fakeData1.end()));
162  tmpFrag1->setUserType(artdaq::Fragment::FirstUserFragmentType);
163  frags.push_back(std::move(tmpFrag1));
164  }
165 
166  // Test individual adds
167  artdaq::Fragment f(0);
168  f.setSequenceID(1);
170  auto cf = reinterpret_cast<artdaq::ContainerFragment*>(&cfl); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
171  auto start_time = std::chrono::steady_clock::now();
172  for (auto& it : frags)
173  {
174  cfl.addFragment(it);
175  }
176  auto end_time = std::chrono::steady_clock::now();
177 
178  BOOST_REQUIRE_EQUAL(cf->block_count(), PERF_TEST_FRAGMENT_COUNT);
180  BOOST_REQUIRE_EQUAL(cf->fragment_type(), type);
181  TLOG(TLVL_INFO, "ContainerFragment_t") << "Adding " << PERF_TEST_FRAGMENT_COUNT << " Fragments individually took " << artdaq::TimeUtils::GetElapsedTimeMicroseconds(start_time, end_time) << " us";
182 
183  // Test group add
184  artdaq::Fragment f2(0);
185  f2.setSequenceID(1);
187  cf = reinterpret_cast<artdaq::ContainerFragment*>(&cfl2); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
188 
189  start_time = std::chrono::steady_clock::now();
190  cfl2.addFragments(frags);
191  end_time = std::chrono::steady_clock::now();
192 
193  BOOST_REQUIRE_EQUAL(cf->block_count(), PERF_TEST_FRAGMENT_COUNT);
194  BOOST_REQUIRE_EQUAL(cf->fragment_type(), type);
195  TLOG(TLVL_INFO, "ContainerFragment_t") << "Adding " << PERF_TEST_FRAGMENT_COUNT << " Fragments in a group took " << artdaq::TimeUtils::GetElapsedTimeMicroseconds(start_time, end_time) << " us";
196 }
197 
198 BOOST_AUTO_TEST_CASE(Exceptions)
199 {
200  artdaq::Fragment f(0);
201  f.setSequenceID(1);
203  auto cf = reinterpret_cast<artdaq::ContainerFragment*>(&cfl); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
204 
205  // Attempting to access a fragment which is not in the container is an exception
206  BOOST_REQUIRE_EXCEPTION(cf->at(0), cet::exception, [&](cet::exception e) { return e.category() == "ArgumentOutOfRange"; });
207  BOOST_REQUIRE_EXCEPTION(cf->fragSize(0), cet::exception, [&](cet::exception e) { return e.category() == "ArgumentOutOfRange"; });
208  BOOST_REQUIRE_EXCEPTION(cf->fragmentIndex(1), cet::exception, [&](cet::exception e) { return e.category() == "ArgumentOutOfRange"; });
209 
210  // Using an already-initialized Fragment to init a Container Fragment is an exception
211  artdaq::Fragment f2(2);
212  f2.setSequenceID(2);
213  f2.setFragmentID(0);
215  BOOST_REQUIRE_EXCEPTION(artdaq::ContainerFragmentLoader cfl2(f2), cet::exception, [&](cet::exception e) { return e.category() == "InvalidFragment"; });
216 
218  //for (int ii = 0; ii < artdaq::CONTAINER_FRAGMENT_COUNT_MAX; ++ii)
219  //{
220  // cfl.addFragment(f2);
221  //}
222  //BOOST_REQUIRE_EXCEPTION(cfl.addFragment(f2), cet::exception, [&](cet::exception e) { return e.category() == "ContainerFull"; });
223 
224  // Adding a Fragment of different type to a Container is an exception
225  artdaq::Fragment f3(0);
226  f3.setSequenceID(1);
228  cfl3.addFragment(f2);
229  f2.setSystemType(artdaq::Fragment::EmptyFragmentType);
230  BOOST_REQUIRE_EXCEPTION(cfl3.addFragment(f2), cet::exception, [&](cet::exception e) { return e.category() == "WrongFragmentType"; });
231 
233  ff1.emplace_back(new artdaq::Fragment(101, 202, artdaq::Fragment::DataFragmentType));
234  ff1.emplace_back(new artdaq::Fragment(102, 203));
235  ff1.back()->setSystemType(artdaq::Fragment::EmptyFragmentType);
236  BOOST_REQUIRE_EXCEPTION(cfl3.addFragments(ff1), cet::exception, [&](cet::exception e) { return e.category() == "WrongFragmentType"; });
237 }
238 
239 BOOST_AUTO_TEST_CASE(Upgrade)
240 {
243 
244  oldMetadata.block_count = 1;
245  oldMetadata.index[0] = f.dataSizeBytes();
246 
247  f.setMetadata(oldMetadata);
248 
249  std::vector<artdaq::Fragment::value_type> fakeData{1, 2, 3, 4};
251  tmpFrag(artdaq::Fragment::dataFrag(1,
252  0,
253  fakeData.begin(),
254  fakeData.end()));
255  tmpFrag->setUserType(artdaq::Fragment::FirstUserFragmentType);
256  memcpy(f.dataBegin(), tmpFrag->headerAddress(), tmpFrag->sizeBytes());
257 
259  auto md = cf.metadata();
260  BOOST_REQUIRE_EQUAL(md->version, 0);
261 
262  auto outfrag = cf.at(0);
263  BOOST_REQUIRE_EQUAL(outfrag->sequenceID(), 1);
264  BOOST_REQUIRE_EQUAL(outfrag->fragmentID(), 0);
265  BOOST_REQUIRE_EQUAL(outfrag->dataSize(), 4);
266  BOOST_REQUIRE_EQUAL(*outfrag->dataBegin(), 1);
267  BOOST_REQUIRE_EQUAL(*(outfrag->dataBegin() + 1), 2);
268 }
269 
270 BOOST_AUTO_TEST_SUITE_END()
std::unique_ptr< Fragment > FragmentPtr
A std::unique_ptr to a Fragment object.
Definition: Fragment.hh:54
The artdaq::ContainerFragment class represents a Fragment which contains other Fragments.
A Read-Write version of the ContainerFragment, used for filling ContainerFragment objects with other ...
static constexpr type_t EmptyFragmentType
Copy EmptyFragmentType from RawFragmentHeader.
Definition: Fragment.hh:155
static constexpr std::size_t num_words()
Returns the number of RawDataType words present in the header.
The RawFragmentHeader class contains the basic fields used by artdaq for routing Fragment objects thr...
static FragmentPtr dataFrag(sequence_id_t sequenceID, fragment_id_t fragID, InputIterator i, InputIterator e)
Creates a Fragment, copying data from given location. 12-Apr-2013, KAB - this method is deprecated...
Definition: Fragment.hh:711
static constexpr type_t DataFragmentType
Copy DataFragmentType from RawFragmentHeader.
Definition: Fragment.hh:149
size_t GetElapsedTimeMicroseconds(std::chrono::steady_clock::time_point then, std::chrono::steady_clock::time_point now=std::chrono::steady_clock::now())
Gets the number of microseconds in the given time interval
Definition: TimeUtils.hh:41
static constexpr size_t CONTAINER_MAGIC
Marker word used in index.
size_t index[CONTAINER_FRAGMENT_COUNT_MAX]
Offset of each Fragment within the ContainerFragment.
QuickVec< RawDataType >::value_type value_type
Alias value_type type from QuickVec&lt;RawDataType&gt;
Definition: Fragment.hh:185
Contains the information necessary for retrieving Fragment objects from the ContainerFragment.
Contains the information necessary for retrieving Fragment objects from the ContainerFragment.
static constexpr type_t FirstUserFragmentType
Copy FIRST_USER_TYPE from RawFragmentHeader.
Definition: Fragment.hh:154
count_t block_count
The number of Fragment objects stored in the ContainerFragment.
std::list< FragmentPtr > FragmentPtrs
A std::list of FragmentPtrs.
Definition: Fragment.hh:59
A Fragment contains the data from one piece of the DAQ system for one event The artdaq::Fragment is t...
Definition: Fragment.hh:85