Belle II Software development
database.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8#include <framework/database/IntervalOfValidity.h>
9#include <framework/database/Database.h>
10#include <framework/database/Configuration.h>
11#include <framework/database/DBObjPtr.h>
12#include <framework/database/DBArray.h>
13#include <framework/database/EventDependency.h>
14#include <framework/database/PayloadFile.h>
15#include <framework/database/DBPointer.h>
16#include <framework/datastore/StoreObjPtr.h>
17#include <framework/dataobjects/EventMetaData.h>
18#include <framework/utilities/TestHelpers.h>
19#include <framework/geometry/BFieldManager.h>
20#include <framework/dbobjects/MagneticField.h>
21#include <framework/dbobjects/MagneticFieldComponentConstant.h>
22
23#include <TNamed.h>
24#include <TClonesArray.h>
25
26#include <gtest/gtest.h>
27
28#include <filesystem>
29#include <list>
30#include <cstdio>
31
32using namespace std;
33using namespace Belle2;
34
35namespace {
36
38 class DataBaseTest : public ::testing::Test {
39 protected:
40
42 enum EDatabaseType {c_local, c_central, c_chain, c_default};
43
45 EDatabaseType m_dbType = c_local;
46
50 void SetUp() override
51 {
54 evtPtr.registerInDataStore();
56 evtPtr.construct(0, 0, 1);
57
59 switch (m_dbType) {
60 case c_local:
61 c.setGlobalTags({});
62 c.overrideGlobalTags();
63 c.setMetadataProviders({});
64 c.setNewPayloadLocation("testPayloads/TestDatabase.txt");
65 c.appendTestingPayloadLocation("testPayloads/TestDatabase.txt");
66 break;
67 case c_central:
68 c.setGlobalTags({"default"});
69 c.overrideGlobalTags();
70 break;
71 case c_chain:
72 c.setGlobalTags({"default"});
73 c.overrideGlobalTags();
74 c.setMetadataProviders({});
75 c.setNewPayloadLocation("testPayloads/TestDatabase.txt");
76 c.appendTestingPayloadLocation("testPayloads/TestDatabase.txt");
77 break;
78 case c_default:
79 break;
80 }
81
82 if (m_dbType != c_central) {
83 list<Database::DBImportQuery> query;
84 TClonesArray array("TObject");
85 for (int experiment = 1; experiment <= 5; experiment++) {
86 IntervalOfValidity iov(experiment, -1, experiment, -1);
87
88 TString name = "Experiment ";
89 name += experiment;
90 query.push_back(Database::DBImportQuery("TNamed", new TNamed(name, name), iov));
91
92 new (array[experiment - 1]) TObject;
93 array[experiment - 1]->SetUniqueID(experiment);
94 Database::Instance().storeData("TObjects", &array, iov);
95
96 FILE* f = fopen("file.xml", "w");
97 fprintf(f, "Experiment %d\n", experiment);
98 fclose(f);
99 Database::Instance().addPayload("file.xml", "file.xml", iov);
100 }
101 if (m_dbType != c_chain) {
103 }
104
105 EventDependency intraRunDep(new TNamed("A", "A"));
106 intraRunDep.add(10, new TNamed("B", "B"));
107 intraRunDep.add(50, new TNamed("C", "C"));
108 IntervalOfValidity iov1(1, 1, 1, 1);
109 Database::Instance().storeData("IntraRun", &intraRunDep, iov1);
110 IntervalOfValidity iov2(1, 2, 1, -1);
111 Database::Instance().storeData("IntraRun", new TNamed("X", "X"), iov2);
112 }
113 }
114
116 void TearDown() override
117 {
118 if (m_dbType != c_central) std::filesystem::remove_all("testPayloads");
121 }
122
123 };
124
126 TEST_F(DataBaseTest, IntervalOfValidity)
127 {
128 EXPECT_TRUE(IntervalOfValidity().empty());
129 EXPECT_FALSE(IntervalOfValidity(1, -1, -1, -1).empty());
130 EXPECT_FALSE(IntervalOfValidity(-1, -1, 1, -1).empty());
131 EXPECT_FALSE(IntervalOfValidity(1, 2, 3, 4).empty());
132
133 EventMetaData event(0, 8, 15); // experiment 15, run 8
134 EXPECT_FALSE(IntervalOfValidity().contains(event));
135 EXPECT_FALSE(IntervalOfValidity(16, 1, -1, -1).contains(event));
136 EXPECT_FALSE(IntervalOfValidity(16, -1, -1, -1).contains(event));
137 EXPECT_FALSE(IntervalOfValidity(15, 9, -1, -1).contains(event));
138 EXPECT_TRUE(IntervalOfValidity(15, 8, -1, -1).contains(event));
139 EXPECT_TRUE(IntervalOfValidity(15, 8, 15, -1).contains(event));
140 EXPECT_TRUE(IntervalOfValidity(15, 8, 15, 8).contains(event));
141 EXPECT_TRUE(IntervalOfValidity(15, -1, 15, 8).contains(event));
142 EXPECT_TRUE(IntervalOfValidity(-1, -1, 15, 8).contains(event));
143 EXPECT_FALSE(IntervalOfValidity(-1, -1, 15, 7).contains(event));
144 EXPECT_FALSE(IntervalOfValidity(-1, -1, 14, -1).contains(event));
145 EXPECT_FALSE(IntervalOfValidity(-1, -1, 14, 1).contains(event));
146 }
147
149 TEST_F(DataBaseTest, IntervalOfValidityOperations)
150 {
151 IntervalOfValidity iov(1, 1, 3, 10);
152 EXPECT_TRUE(IntervalOfValidity(1, 1, 3, 10).contains(iov));
153 EXPECT_TRUE(IntervalOfValidity(1, -1, 3, 10).contains(iov));
154 EXPECT_TRUE(IntervalOfValidity(-1, -1, 3, 10).contains(iov));
155 EXPECT_TRUE(IntervalOfValidity(1, 1, 3, -1).contains(iov));
156 EXPECT_TRUE(IntervalOfValidity(1, 1, -1, -1).contains(iov));
157 EXPECT_FALSE(IntervalOfValidity(1, 2, 3, 10).contains(iov));
158 EXPECT_FALSE(IntervalOfValidity(2, -1, 3, 10).contains(iov));
159 EXPECT_FALSE(IntervalOfValidity(1, 1, 3, 9).contains(iov));
160 EXPECT_FALSE(IntervalOfValidity(1, 1, 2, -1).contains(iov));
161 EXPECT_TRUE(iov.contains(IntervalOfValidity(2, -1, 2, -1)));
162 EXPECT_FALSE(iov.contains(IntervalOfValidity(1, -1, 2, 1)));
163 EXPECT_FALSE(iov.contains(IntervalOfValidity(-1, -1, 3, 10)));
164 EXPECT_FALSE(iov.contains(IntervalOfValidity(1, 1, 3, -1)));
165 EXPECT_FALSE(iov.contains(IntervalOfValidity(1, 1, -1, -1)));
166
167 EXPECT_TRUE(IntervalOfValidity(1, 1, 3, 10).overlaps(iov));
168 EXPECT_TRUE(IntervalOfValidity(1, -1, 1, 1).overlaps(iov));
169 EXPECT_TRUE(IntervalOfValidity(-1, -1, 1, 1).overlaps(iov));
170 EXPECT_TRUE(IntervalOfValidity(-1, -1, 1, -1).overlaps(iov));
171 EXPECT_TRUE(IntervalOfValidity(3, -1, -1, -1).overlaps(iov));
172 EXPECT_TRUE(IntervalOfValidity(3, 10, -1, -1).overlaps(iov));
173 EXPECT_FALSE(IntervalOfValidity(-1, -1, -1, -1).overlaps(iov));
174 EXPECT_FALSE(IntervalOfValidity(-1, -1, 0, -1).overlaps(iov));
175 EXPECT_FALSE(IntervalOfValidity(-1, -1, 1, 0).overlaps(iov));
176 EXPECT_FALSE(IntervalOfValidity(3, 11, 3, -1).overlaps(iov));
177 EXPECT_FALSE(IntervalOfValidity(4, -1, 4, -1).overlaps(iov));
178
179 IntervalOfValidity iov1, iov2;
180 iov1 = IntervalOfValidity(1, 1, 3, 10);
181 iov2 = IntervalOfValidity(1, 1, 3, 10);
182 EXPECT_TRUE(iov1.trimOverlap(iov2, true));
183 EXPECT_TRUE(iov1.empty());
184 EXPECT_TRUE(iov2 == IntervalOfValidity(1, 1, 3, 10));
185
186 iov1 = IntervalOfValidity(1, 1, 3, 10);
187 iov2 = IntervalOfValidity(2, -1, 4, -1);
188 EXPECT_TRUE(iov1.trimOverlap(iov2, true));
189 EXPECT_TRUE(iov1 == IntervalOfValidity(1, 1, 1, -1));
190 EXPECT_TRUE(iov2 == IntervalOfValidity(2, -1, 4, -1));
191
192 iov1 = IntervalOfValidity(1, 1, 3, 11);
193 iov2 = IntervalOfValidity(1, 1, 3, 10);
194 EXPECT_FALSE(iov1.trimOverlap(iov2, true));
195 EXPECT_TRUE(iov1 == IntervalOfValidity(1, 1, 3, 11));
196 EXPECT_TRUE(iov2 == IntervalOfValidity(1, 1, 3, 10));
197
198 iov1 = IntervalOfValidity(1, 1, 3, 10);
199 iov2 = IntervalOfValidity(1, 1, 3, 10);
200 EXPECT_TRUE(iov1.trimOverlap(iov2, false));
201 EXPECT_TRUE(iov1 == IntervalOfValidity(1, 1, 3, 10));
202 EXPECT_TRUE(iov2.empty());
203
204 iov1 = IntervalOfValidity(1, 1, 3, 10);
205 iov2 = IntervalOfValidity(2, -1, 4, -1);
206 EXPECT_TRUE(iov1.trimOverlap(iov2, false));
207 EXPECT_TRUE(iov1 == IntervalOfValidity(1, 1, 3, 10));
208 EXPECT_TRUE(iov2 == IntervalOfValidity(3, 11, 4, -1));
209
210 // Validity is larger than we want on the lower edge
211 iov1 = IntervalOfValidity(11, 0, 12, 86);
212 // Want to trim off everything below exp=12
213 iov2 = IntervalOfValidity(0, 0, 11, -1);
214 EXPECT_TRUE(iov1.trimOverlap(iov2, false));
215 EXPECT_EQ(iov1, IntervalOfValidity(12, 0, 12, 86));
216 EXPECT_EQ(iov2, IntervalOfValidity(0, 0, 11, -1));
217 }
218
220 TEST_F(DataBaseTest, getData)
221 {
222 EXPECT_TRUE(strcmp(Database::Instance().getData("TNamed", 1, 1)->GetName(), "Experiment 1") == 0);
223 EXPECT_TRUE(strcmp(Database::Instance().getData("TNamed", 4, 1)->GetName(), "Experiment 4") == 0);
224 EXPECT_TRUE(Database::Instance().getData("TNamed", 6, 1) == 0);
225 }
226
228 TEST_F(DataBaseTest, DBObjPtr)
229 {
231 DBObjPtr<TNamed> named;
232
233 evtPtr->setExperiment(1);
235 ASSERT_TRUE(named);
236 EXPECT_TRUE(strcmp(named->GetName(), "Experiment 1") == 0);
237 evtPtr->setExperiment(4);
238 EXPECT_TRUE(strcmp(named->GetName(), "Experiment 1") == 0);
240 EXPECT_TRUE(strcmp(named->GetName(), "Experiment 4") == 0);
241 evtPtr->setExperiment(7);
243 EXPECT_FALSE(named);
244 }
245
247 TEST_F(DataBaseTest, DBArray)
248 {
250 DBArray<TObject> objects;
251 DBArray<TObject> missing("notexisting");
252 // check iteration on fresh object
253 {
254 int i = 0;
255 for (const auto& o : missing) {
256 (void)o;
257 ++i;
258 }
259 EXPECT_EQ(i, 0);
260 }
261
262
263 evtPtr->setExperiment(1);
265 EXPECT_TRUE(objects);
266 EXPECT_FALSE(missing);
267 EXPECT_EQ(objects.getEntries(), 1);
268 EXPECT_EQ(objects[0]->GetUniqueID(), 1);
269 evtPtr->setExperiment(4);
270 EXPECT_EQ(objects.getEntries(), 1);
272 EXPECT_EQ(objects.getEntries(), 4);
273 // check iteration on existing
274 {
275 int i = 0;
276 for (const auto& o : objects) {
277 EXPECT_EQ(o.GetUniqueID(), ++i);
278 }
279 EXPECT_EQ(i, 4);
280 }
281
282 // check iteration on missing object
283 {
284 int i = 0;
285 for (const auto& o : missing) {
286 (void)o;
287 ++i;
288 }
289 EXPECT_EQ(i, 0);
290 }
291 evtPtr->setExperiment(7);
293 EXPECT_FALSE(objects);
294 // check iteration over missing but previously existing
295 {
296 int i = 0;
297 for (const auto& o : objects) {
298 EXPECT_EQ(o.GetUniqueID(), ++i);
299 }
300 EXPECT_EQ(i, 0);
301 }
302 }
303
305 TEST_F(DataBaseTest, DBArrayRange)
306 {
308 DBArray<TObject> objects;
309
310 evtPtr->setExperiment(3);
312 EXPECT_THROW(objects[-1], std::out_of_range);
313 EXPECT_THROW(objects[3], std::out_of_range);
314 }
315
317 TEST_F(DataBaseTest, TypeCheck)
318 {
319 DBObjPtr<TNamed> named;
320 EXPECT_B2FATAL(DBObjPtr<EventMetaData> wrongType("TNamed"));
321
322 DBArray<TObject> objects;
323 EXPECT_B2FATAL(DBArray<EventMetaData> wrongType("TObjects"));
324 }
325
327 TEST_F(DataBaseTest, IntraRun)
328 {
330 DBObjPtr<TNamed> intraRun("IntraRun");
331
332 evtPtr->setExperiment(1);
333 evtPtr->setRun(1);
334 evtPtr->setEvent(9);
337 EXPECT_TRUE(strcmp(intraRun->GetName(), "A") == 0);
338
339 evtPtr->setEvent(10);
341 EXPECT_TRUE(strcmp(intraRun->GetName(), "B") == 0);
342
343 evtPtr->setEvent(49);
345 EXPECT_TRUE(strcmp(intraRun->GetName(), "B") == 0);
346
347 //let's run an update in between and make sure intra run continues to work
349 EXPECT_TRUE(strcmp(intraRun->GetName(), "B") == 0);
350
351 evtPtr->setEvent(50);
353 EXPECT_TRUE(strcmp(intraRun->GetName(), "C") == 0);
354
355 evtPtr->setRun(2);
357 EXPECT_TRUE(strcmp(intraRun->GetName(), "X") == 0);
358 }
359
361 TEST_F(DataBaseTest, HasChanged)
362 {
364 evtPtr->setExperiment(0);
366
367 DBObjPtr<TNamed> named;
368 EXPECT_FALSE(named.hasChanged());
369
370 evtPtr->setExperiment(1);
371 EXPECT_FALSE(named.hasChanged());
372
374 EXPECT_TRUE(named.hasChanged());
375
376 evtPtr->setRun(8);
378 EXPECT_FALSE(named.hasChanged());
379
380 evtPtr->setExperiment(5);
382 EXPECT_TRUE(named.hasChanged());
383
384 evtPtr->setExperiment(7);
386 EXPECT_TRUE(named.hasChanged());
387
388 evtPtr->setExperiment(1);
389 evtPtr->setRun(1);
390 evtPtr->setEvent(1);
391 DBObjPtr<TNamed> intraRun("IntraRun");
394 EXPECT_TRUE(intraRun.hasChanged());
395
396 evtPtr->setEvent(2);
398 EXPECT_FALSE(intraRun.hasChanged());
399
400 evtPtr->setEvent(10);
402 EXPECT_TRUE(intraRun.hasChanged());
403
404 evtPtr->setEvent(1000);
406 EXPECT_TRUE(intraRun.hasChanged());
407
408 evtPtr->setRun(4);
411 EXPECT_TRUE(intraRun.hasChanged());
412 }
413
415 TEST_F(DataBaseTest, PayloadFile)
416 {
418 DBObjPtr<PayloadFile> payload("file.xml");
419
420 evtPtr->setExperiment(1);
422 EXPECT_EQ(payload->getContent(), "Experiment 1\n") << payload->getFileName();
423 evtPtr->setExperiment(4);
425 EXPECT_EQ(payload->getContent(), "Experiment 4\n") << payload->getFileName();
426 evtPtr->setExperiment(7);
428 EXPECT_FALSE(payload);
429 }
430
432 int callbackCounter = 0;
433
434 void callback()
435 {
436 callbackCounter++;
437 }
438
439 class Callback {
440 public:
441 void callback()
442 {
443 callbackCounter++;
444 }
445 };
446 Callback callbackObject;
447
448 TEST_F(DataBaseTest, Callbacks)
449 {
451 evtPtr->setRun(1);
452 evtPtr->setEvent(1);
453 callbackCounter = 0;
454
455 DBObjPtr<TNamed> named;
456 named.addCallback(&callback);
457 EXPECT_EQ(callbackCounter, 0);
458
459 evtPtr->setExperiment(2);
461 EXPECT_EQ(callbackCounter, 1);
462
463 evtPtr->setExperiment(4);
465 EXPECT_EQ(callbackCounter, 2);
467 EXPECT_EQ(callbackCounter, 2);
468
469 evtPtr->setExperiment(6);
471 EXPECT_EQ(callbackCounter, 3);
472
473 evtPtr->setExperiment(7);
475 EXPECT_EQ(callbackCounter, 3);
476
477 DBArray<TObject> objects;
478 objects.addCallback(&callback);
479
480 evtPtr->setExperiment(1);
482 // callbacks will now be called once for each payload so there is an extra call
483 EXPECT_EQ(callbackCounter, 5);
484
485 DBObjPtr<TNamed> intraRun("IntraRun");
486 intraRun.addCallback(&callbackObject, &Callback::callback);
487
488 //There won't be any callback here because the correct object is already set on creation
489 evtPtr->setEvent(1);
491 EXPECT_EQ(callbackCounter, 5);
492
493 evtPtr->setEvent(2);
495 EXPECT_EQ(callbackCounter, 5);
496
497 evtPtr->setEvent(10);
499 EXPECT_EQ(callbackCounter, 6);
500
501 evtPtr->setEvent(1);
503 EXPECT_EQ(callbackCounter, 7);
504 }
505
507 TEST_F(DataBaseTest, KeyAccess)
508 {
510 evtPtr->setExperiment(1);
512
513 DBArray<TObject> objects;
514 EXPECT_EQ(objects.getByKey<unsigned int>(&TObject::GetUniqueID, 1)->GetUniqueID(), 1);
515 EXPECT_EQ(objects.getByKey<unsigned int>(&TObject::GetUniqueID, 2), nullptr);
516 EXPECT_EQ(objects.getByKey(&TObject::IsFolder, false)->GetUniqueID(), 1);
517 EXPECT_EQ(objects.getByKey(&TObject::IsFolder, true), nullptr);
518
519 evtPtr->setExperiment(2);
521
522 EXPECT_EQ(objects.getByKey<unsigned int>(&TObject::GetUniqueID, 1)->GetUniqueID(), 1);
523 EXPECT_EQ(objects.getByKey<unsigned int>(&TObject::GetUniqueID, 2)->GetUniqueID(), 2);
524 }
525
527 TEST_F(DataBaseTest, DBPointer)
528 {
530 evtPtr->setExperiment(2);
532
534 EXPECT_EQ(ptr.key(), 1);
535 EXPECT_TRUE(ptr.isValid());
536 EXPECT_EQ(ptr->GetUniqueID(), 1);
537 ptr = 2;
538 EXPECT_EQ(ptr->GetUniqueID(), 2);
539 ptr = 3;
540 EXPECT_FALSE(ptr.isValid());
541 }
542
543 TEST_F(DataBaseTest, CleanupReattachDeathtest)
544 {
546 evtPtr->setExperiment(2);
548
549 DBObjPtr<TNamed> named;
550 EXPECT_TRUE(named.isValid());
551 double Bz = BFieldManager::getField(0, 0, 0).Z() / Unit::T;
552 EXPECT_EQ(Bz, 1.5);
554 //Ok, on next access the DBObjPtr should try to reconnect
555 EXPECT_TRUE(named.isValid());
556 //Which means the magnetic field should die a horrible death: It's not
557 //found in the database during testing, just a override.
558 EXPECT_B2FATAL(BFieldManager::getFieldInTesla({0, 0, 0}));
559 //Unless we add a new one
560 auto* field = new Belle2::MagneticField();
561 field->addComponent(new Belle2::MagneticFieldComponentConstant({0, 0, 1.5 * Belle2::Unit::T}));
562 Belle2::DBStore::Instance().addConstantOverride("MagneticField", field, false);
563 //So now it should work again
564 Bz = BFieldManager::getField(0, 0, 0).Z() / Unit::T;
565 EXPECT_EQ(Bz, 1.5);
566 }
567
570 class DataBaseNoDataStoreTest : public ::testing::Test {
571 protected:
572
574 enum EDatabaseType {c_local, c_central, c_chain, c_default};
575
577 EDatabaseType m_dbType = c_local;
578
581 EventMetaData m_event;
582
583 DataBaseNoDataStoreTest() : m_event(0, 0, 1) {};
584
586 void SetUp() override
587 {
589 switch (m_dbType) {
590 case c_local:
591 c.setGlobalTags({});
592 c.overrideGlobalTags();
593 c.setMetadataProviders({});
594 c.setNewPayloadLocation("testPayloads/TestDatabase.txt");
595 c.appendTestingPayloadLocation("testPayloads/TestDatabase.txt");
596 break;
597 case c_central:
598 c.setGlobalTags({"default"});
599 c.overrideGlobalTags();
600 break;
601 case c_chain:
602 c.setGlobalTags({"default"});
603 c.overrideGlobalTags();
604 c.setMetadataProviders({});
605 c.setNewPayloadLocation("testPayloads/TestDatabase.txt");
606 c.appendTestingPayloadLocation("testPayloads/TestDatabase.txt");
607 break;
608 case c_default:
609 break;
610 }
611
612 if (m_dbType != c_central) {
613 list<Database::DBImportQuery> query;
614 TClonesArray array("TObject");
615 for (int experiment = 1; experiment <= 5; experiment++) {
616 IntervalOfValidity iov(experiment, -1, experiment, -1);
617
618 TString name = "Experiment ";
619 name += experiment;
620 query.push_back(Database::DBImportQuery("TNamed", new TNamed(name, name), iov));
621
622 new (array[experiment - 1]) TObject;
623 array[experiment - 1]->SetUniqueID(experiment);
624 Database::Instance().storeData("TObjects", &array, iov);
625
626 FILE* f = fopen("file.xml", "w");
627 fprintf(f, "Experiment %d\n", experiment);
628 fclose(f);
629 Database::Instance().addPayload("file.xml", "file.xml", iov);
630 }
631 if (m_dbType != c_chain) {
633 }
634
635 EventDependency intraRunDep(new TNamed("A", "A"));
636 intraRunDep.add(10, new TNamed("B", "B"));
637 intraRunDep.add(50, new TNamed("C", "C"));
638 IntervalOfValidity iov1(1, 1, 1, 1);
639 Database::Instance().storeData("IntraRun", &intraRunDep, iov1);
640 IntervalOfValidity iov2(1, 2, 1, -1);
641 Database::Instance().storeData("IntraRun", new TNamed("X", "X"), iov2);
642 }
643 }
644
646 void TearDown() override
647 {
648 if (m_dbType != c_central) std::filesystem::remove_all("testPayloads");
650 }
651
652 };
653
655 TEST_F(DataBaseNoDataStoreTest, DBObjPtr)
656 {
657 DBStore::Instance().update(m_event); // The DBStore takes a reference to an EventMetaData object
658 DBObjPtr<TNamed> named;
659 m_event.setExperiment(1);
660 DBStore::Instance().update(m_event); // The DBStore takes a reference to an EventMetaData object
661 ASSERT_TRUE(named);
662 EXPECT_TRUE(strcmp(named->GetName(), "Experiment 1") == 0);
663 m_event.setExperiment(4);
664 EXPECT_TRUE(strcmp(named->GetName(), "Experiment 1") == 0);
665 DBStore::Instance().update(m_event);
666 EXPECT_TRUE(strcmp(named->GetName(), "Experiment 4") == 0);
667 m_event.setExperiment(7);
668 DBStore::Instance().update(m_event);
669 EXPECT_FALSE(named);
670 }
671
673 TEST_F(DataBaseNoDataStoreTest, DBArray)
674 {
675 DBStore::Instance().update(m_event);
676 DBArray<TObject> objects;
677 DBArray<TObject> missing("notexisting");
678 // check iteration on fresh object
679 {
680 int i = 0;
681 for (const auto& o : missing) {
682 (void)o;
683 ++i;
684 }
685 EXPECT_EQ(i, 0);
686 }
687
688
689 m_event.setExperiment(1);
690 DBStore::Instance().update(m_event);
691 EXPECT_TRUE(objects);
692 EXPECT_FALSE(missing);
693 EXPECT_EQ(objects.getEntries(), 1);
694 EXPECT_EQ(objects[0]->GetUniqueID(), 1);
695 m_event.setExperiment(4);
696 EXPECT_EQ(objects.getEntries(), 1);
697 DBStore::Instance().update(m_event);
698 EXPECT_EQ(objects.getEntries(), 4);
699 // check iteration on existing
700 {
701 int i = 0;
702 for (const auto& o : objects) {
703 EXPECT_EQ(o.GetUniqueID(), ++i);
704 }
705 EXPECT_EQ(i, 4);
706 }
707
708 // check iteration on missing object
709 {
710 int i = 0;
711 for (const auto& o : missing) {
712 (void)o;
713 ++i;
714 }
715 EXPECT_EQ(i, 0);
716 }
717 m_event.setExperiment(7);
718 DBStore::Instance().update(m_event);
719 EXPECT_FALSE(objects);
720 // check iteration over missing but previously existing
721 {
722 int i = 0;
723 for (const auto& o : objects) {
724 EXPECT_EQ(o.GetUniqueID(), ++i);
725 }
726 EXPECT_EQ(i, 0);
727 }
728 }
729
731 TEST_F(DataBaseNoDataStoreTest, DBArrayRange)
732 {
733 DBArray<TObject> objects;
734
735 m_event.setExperiment(3);
736 DBStore::Instance().update(m_event);
737 EXPECT_THROW(objects[-1], std::out_of_range);
738 EXPECT_THROW(objects[3], std::out_of_range);
739 }
740
742 TEST_F(DataBaseNoDataStoreTest, TypeCheck)
743 {
744 DBObjPtr<TNamed> named;
745 EXPECT_B2FATAL(DBObjPtr<EventMetaData> wrongType("TNamed"));
746
747 DBArray<TObject> objects;
748 EXPECT_B2FATAL(DBArray<EventMetaData> wrongType("TObjects"));
749 }
750
752 TEST_F(DataBaseNoDataStoreTest, IntraRun)
753 {
754 DBObjPtr<TNamed> intraRun("IntraRun");
755
756 m_event.setExperiment(1);
757 m_event.setRun(1);
758 m_event.setEvent(9);
759 DBStore::Instance().update(m_event);
761 EXPECT_TRUE(strcmp(intraRun->GetName(), "A") == 0);
762
763 m_event.setEvent(10);
765 EXPECT_TRUE(strcmp(intraRun->GetName(), "B") == 0);
766
767 m_event.setEvent(49);
769 EXPECT_TRUE(strcmp(intraRun->GetName(), "B") == 0);
770
771 //let's run an update in between and make sure intra run continues to work
772 DBStore::Instance().update(m_event);
773 EXPECT_TRUE(strcmp(intraRun->GetName(), "B") == 0);
774
775 m_event.setEvent(50);
777 EXPECT_TRUE(strcmp(intraRun->GetName(), "C") == 0);
778
779 m_event.setRun(2);
780 DBStore::Instance().update(m_event);
781 EXPECT_TRUE(strcmp(intraRun->GetName(), "X") == 0);
782 }
783
785 TEST_F(DataBaseNoDataStoreTest, HasChanged)
786 {
787 m_event.setExperiment(0);
788 DBStore::Instance().update(m_event);
789
790 DBObjPtr<TNamed> named;
791 EXPECT_FALSE(named.hasChanged());
792
793 m_event.setExperiment(1);
794 EXPECT_FALSE(named.hasChanged());
795
796 DBStore::Instance().update(m_event);
797 EXPECT_TRUE(named.hasChanged());
798
799 m_event.setRun(8);
800 DBStore::Instance().update(m_event);
801 EXPECT_FALSE(named.hasChanged());
802
803 m_event.setExperiment(5);
804 DBStore::Instance().update(m_event);
805 EXPECT_TRUE(named.hasChanged());
806
807 m_event.setExperiment(7);
808 DBStore::Instance().update(m_event);
809 EXPECT_TRUE(named.hasChanged());
810
811 m_event.setExperiment(1);
812 m_event.setRun(1);
813 m_event.setEvent(1);
814 DBObjPtr<TNamed> intraRun("IntraRun");
815 DBStore::Instance().update(m_event);
817 EXPECT_TRUE(intraRun.hasChanged());
818
819 m_event.setEvent(2);
821 EXPECT_FALSE(intraRun.hasChanged());
822
823 m_event.setEvent(10);
825 EXPECT_TRUE(intraRun.hasChanged());
826
827 m_event.setEvent(1000);
829 EXPECT_TRUE(intraRun.hasChanged());
830
831 m_event.setRun(4);
832 DBStore::Instance().update(m_event);
834 EXPECT_TRUE(intraRun.hasChanged());
835 }
836
838 TEST_F(DataBaseNoDataStoreTest, PayloadFile)
839 {
840 DBStore::Instance().update(m_event);
841 DBObjPtr<PayloadFile> payload("file.xml");
842 m_event.setExperiment(1);
843 DBStore::Instance().update(m_event);
844 EXPECT_EQ(payload->getContent(), "Experiment 1\n") << payload->getFileName();
845 m_event.setExperiment(4);
846 DBStore::Instance().update(m_event);
847 EXPECT_EQ(payload->getContent(), "Experiment 4\n") << payload->getFileName();
848 m_event.setExperiment(7);
849 DBStore::Instance().update(m_event);
850 EXPECT_FALSE(payload);
851 }
852
855 TEST_F(DataBaseNoDataStoreTest, Callbacks)
856 {
857 m_event.setRun(1);
858 m_event.setEvent(1);
859 callbackCounter = 0;
860
861 DBObjPtr<TNamed> named;
862 named.addCallback(&callback);
863 EXPECT_EQ(callbackCounter, 0);
864
865 m_event.setExperiment(2);
866 DBStore::Instance().update(m_event);
867 EXPECT_EQ(callbackCounter, 1);
868
869 m_event.setExperiment(4);
870 DBStore::Instance().update(m_event);
871 EXPECT_EQ(callbackCounter, 2);
872 DBStore::Instance().update(m_event);
873 EXPECT_EQ(callbackCounter, 2);
874
875 m_event.setExperiment(6);
876 DBStore::Instance().update(m_event);
877 EXPECT_EQ(callbackCounter, 3);
878
879 m_event.setExperiment(7);
880 DBStore::Instance().update(m_event);
881 EXPECT_EQ(callbackCounter, 3);
882
883 DBArray<TObject> objects;
884 objects.addCallback(&callback);
885
886 m_event.setExperiment(1);
887 DBStore::Instance().update(m_event);
888 // callbacks will now be called once for each payload so there is an extra call
889 EXPECT_EQ(callbackCounter, 5);
890
891 DBObjPtr<TNamed> intraRun("IntraRun");
892 intraRun.addCallback(&callbackObject, &Callback::callback);
893
894 //There won't be any callback here because the correct object is already set on creation
895 m_event.setEvent(1);
897 EXPECT_EQ(callbackCounter, 5);
898
899 m_event.setEvent(2);
901 EXPECT_EQ(callbackCounter, 5);
902
903 m_event.setEvent(10);
905 EXPECT_EQ(callbackCounter, 6);
906
907 m_event.setEvent(1);
909 EXPECT_EQ(callbackCounter, 7);
910 }
911
913 TEST_F(DataBaseNoDataStoreTest, KeyAccess)
914 {
915 m_event.setExperiment(1);
916 DBStore::Instance().update(m_event);
917
918 DBArray<TObject> objects;
919 EXPECT_EQ(objects.getByKey<unsigned int>(&TObject::GetUniqueID, 1)->GetUniqueID(), 1);
920 EXPECT_EQ(objects.getByKey<unsigned int>(&TObject::GetUniqueID, 2), nullptr);
921 EXPECT_EQ(objects.getByKey(&TObject::IsFolder, false)->GetUniqueID(), 1);
922 EXPECT_EQ(objects.getByKey(&TObject::IsFolder, true), nullptr);
923
924 m_event.setExperiment(2);
925 DBStore::Instance().update(m_event);
926
927 EXPECT_EQ(objects.getByKey<unsigned int>(&TObject::GetUniqueID, 1)->GetUniqueID(), 1);
928 EXPECT_EQ(objects.getByKey<unsigned int>(&TObject::GetUniqueID, 2)->GetUniqueID(), 2);
929 }
930
931 TEST_F(DataBaseNoDataStoreTest, DBPointer)
932 {
933 m_event.setExperiment(2);
934 DBStore::Instance().update(m_event);
935
937 EXPECT_EQ(ptr.key(), 1);
938 EXPECT_TRUE(ptr.isValid());
939 EXPECT_EQ(ptr->GetUniqueID(), 1);
940 ptr = 2;
941 EXPECT_EQ(ptr->GetUniqueID(), 2);
942 ptr = 3;
943 EXPECT_FALSE(ptr.isValid());
944 }
945} // namespace
static ROOT::Math::XYZVector getFieldInTesla(const ROOT::Math::XYZVector &pos)
return the magnetic field at a given position in Tesla.
Definition: BFieldManager.h:61
static Configuration & getInstance()
Get a reference to the instance which will be used when the Database is initialized.
void addCallback(std::function< void(const std::string &)> callback, bool onDestruction=false)
Add a callback method.
bool isValid() const
Check whether a valid object was obtained from the database.
bool hasChanged()
Check whether the object has changed since the last call to hasChanged of the accessor).
Class for accessing arrays of objects in the database.
Definition: DBArray.h:26
Class for accessing objects in the database.
Definition: DBObjPtr.h:21
Class for pointing to an element in an array stored in the database.
Definition: DBPointer.h:24
static DataStore & Instance()
Instance of singleton Store.
Definition: DataStore.cc:54
void setInitializeActive(bool active)
Setter for m_initializeActive.
Definition: DataStore.cc:94
void reset(EDurability durability)
Frees memory occupied by data store items and removes all objects from the map.
Definition: DataStore.cc:86
bool addPayload(const std::string &name, const std::string &fileName, const IntervalOfValidity &iov)
Add a payload file to the database.
Definition: Database.h:192
Class for handling changing conditions as a function of event number.
Store event, run, and experiment numbers.
Definition: EventMetaData.h:33
void setEvent(unsigned int event)
Event Setter.
Definition: EventMetaData.h:55
void setExperiment(int experiment)
Experiment Setter.
Definition: EventMetaData.h:73
unsigned int getEvent() const
Event Getter.
void setRun(int run)
Run Setter.
Definition: EventMetaData.h:61
A class that describes the interval of experiments/runs for which an object in the database is valid.
bool trimOverlap(IntervalOfValidity &iov, bool trimOlder=true)
Remove the overlap between two intervals of validity by shortening one of them.
bool empty() const
Function that checks whether the validity interval is empty.
Describe one component of the Geometry.
Magnetic field map.
Definition: MagneticField.h:32
A wrapper class for payload files used by the Database and DBStore classes.
Definition: PayloadFile.h:23
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
bool construct(Args &&... params)
Construct an object of type T in this StoreObjPtr, using the provided constructor arguments.
Definition: StoreObjPtr.h:119
changes working directory into a newly created directory, and removes it (and contents) on destructio...
Definition: TestHelpers.h:66
static const double T
[tesla]
Definition: Unit.h:120
void reset(bool keepEntries=false)
Invalidate all payloads.
Definition: DBStore.cc:177
static Database & Instance()
Instance of a singleton Database.
Definition: Database.cc:42
static DBStore & Instance()
Instance of a singleton DBStore.
Definition: DBStore.cc:28
bool storeData(const std::string &name, TObject *object, const IntervalOfValidity &iov)
Store an object in the database.
Definition: Database.cc:141
void updateEvent()
Updates all intra-run dependent objects.
Definition: DBStore.cc:142
void update()
Updates all objects that are outside their interval of validity.
Definition: DBStore.cc:79
void addConstantOverride(const std::string &name, TObject *obj, bool oneRun=false)
Add constant override payload.
Definition: DBStore.cc:204
static void getField(const double *pos, double *field)
return the magnetic field at a given position.
Definition: BFieldManager.h:91
static void reset(bool keepConfig=false)
Reset the database instance.
Definition: Database.cc:50
Abstract base class for different kinds of events.
STL namespace.
Struct for bulk write queries.
Definition: Database.h:77