Belle II Software  release-08-01-10
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 
32 using namespace std;
33 using namespace Belle2;
34 
35 namespace {
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 
47  TestHelpers::TempDirCreator m_tempDir;
50  void SetUp() override
51  {
53  DataStore::Instance().setInitializeActive(true);
54  evtPtr.registerInDataStore();
55  DataStore::Instance().setInitializeActive(false);
56  evtPtr.construct(0, 0, 1);
57 
58  auto& c = Conditions::Configuration::getInstance();
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) {
102  Database::Instance().storeData(query);
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");
119  Database::reset();
120  DataStore::Instance().reset();
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);
234  DBStore::Instance().update();
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);
239  DBStore::Instance().update();
240  EXPECT_TRUE(strcmp(named->GetName(), "Experiment 4") == 0);
241  evtPtr->setExperiment(7);
242  DBStore::Instance().update();
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);
264  DBStore::Instance().update();
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);
271  DBStore::Instance().update();
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);
292  DBStore::Instance().update();
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);
311  DBStore::Instance().update();
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);
335  DBStore::Instance().update();
336  DBStore::Instance().updateEvent();
337  EXPECT_TRUE(strcmp(intraRun->GetName(), "A") == 0);
338 
339  evtPtr->setEvent(10);
340  DBStore::Instance().updateEvent();
341  EXPECT_TRUE(strcmp(intraRun->GetName(), "B") == 0);
342 
343  evtPtr->setEvent(49);
344  DBStore::Instance().updateEvent();
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
348  DBStore::Instance().update();
349  EXPECT_TRUE(strcmp(intraRun->GetName(), "B") == 0);
350 
351  evtPtr->setEvent(50);
352  DBStore::Instance().updateEvent();
353  EXPECT_TRUE(strcmp(intraRun->GetName(), "C") == 0);
354 
355  evtPtr->setRun(2);
356  DBStore::Instance().update();
357  EXPECT_TRUE(strcmp(intraRun->GetName(), "X") == 0);
358  }
359 
361  TEST_F(DataBaseTest, HasChanged)
362  {
364  evtPtr->setExperiment(0);
365  DBStore::Instance().update();
366 
367  DBObjPtr<TNamed> named;
368  EXPECT_FALSE(named.hasChanged());
369 
370  evtPtr->setExperiment(1);
371  EXPECT_FALSE(named.hasChanged());
372 
373  DBStore::Instance().update();
374  EXPECT_TRUE(named.hasChanged());
375 
376  evtPtr->setRun(8);
377  DBStore::Instance().update();
378  EXPECT_FALSE(named.hasChanged());
379 
380  evtPtr->setExperiment(5);
381  DBStore::Instance().update();
382  EXPECT_TRUE(named.hasChanged());
383 
384  evtPtr->setExperiment(7);
385  DBStore::Instance().update();
386  EXPECT_TRUE(named.hasChanged());
387 
388  evtPtr->setExperiment(1);
389  evtPtr->setRun(1);
390  evtPtr->setEvent(1);
391  DBObjPtr<TNamed> intraRun("IntraRun");
392  DBStore::Instance().update();
393  DBStore::Instance().updateEvent();
394  EXPECT_TRUE(intraRun.hasChanged());
395 
396  evtPtr->setEvent(2);
397  DBStore::Instance().updateEvent();
398  EXPECT_FALSE(intraRun.hasChanged());
399 
400  evtPtr->setEvent(10);
401  DBStore::Instance().updateEvent();
402  EXPECT_TRUE(intraRun.hasChanged());
403 
404  evtPtr->setEvent(1000);
405  DBStore::Instance().updateEvent();
406  EXPECT_TRUE(intraRun.hasChanged());
407 
408  evtPtr->setRun(4);
409  DBStore::Instance().update();
410  DBStore::Instance().updateEvent();
411  EXPECT_TRUE(intraRun.hasChanged());
412  }
413 
415  TEST_F(DataBaseTest, PayloadFile)
416  {
418  DBObjPtr<PayloadFile> payload("file.xml");
419 
420  evtPtr->setExperiment(1);
421  DBStore::Instance().update();
422  EXPECT_EQ(payload->getContent(), "Experiment 1\n") << payload->getFileName();
423  evtPtr->setExperiment(4);
424  DBStore::Instance().update();
425  EXPECT_EQ(payload->getContent(), "Experiment 4\n") << payload->getFileName();
426  evtPtr->setExperiment(7);
427  DBStore::Instance().update();
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);
460  DBStore::Instance().update();
461  EXPECT_EQ(callbackCounter, 1);
462 
463  evtPtr->setExperiment(4);
464  DBStore::Instance().update();
465  EXPECT_EQ(callbackCounter, 2);
466  DBStore::Instance().update();
467  EXPECT_EQ(callbackCounter, 2);
468 
469  evtPtr->setExperiment(6);
470  DBStore::Instance().update();
471  EXPECT_EQ(callbackCounter, 3);
472 
473  evtPtr->setExperiment(7);
474  DBStore::Instance().update();
475  EXPECT_EQ(callbackCounter, 3);
476 
477  DBArray<TObject> objects;
478  objects.addCallback(&callback);
479 
480  evtPtr->setExperiment(1);
481  DBStore::Instance().update();
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);
490  DBStore::Instance().updateEvent();
491  EXPECT_EQ(callbackCounter, 5);
492 
493  evtPtr->setEvent(2);
494  DBStore::Instance().updateEvent();
495  EXPECT_EQ(callbackCounter, 5);
496 
497  evtPtr->setEvent(10);
498  DBStore::Instance().updateEvent();
499  EXPECT_EQ(callbackCounter, 6);
500 
501  evtPtr->setEvent(1);
502  DBStore::Instance().updateEvent();
503  EXPECT_EQ(callbackCounter, 7);
504  }
505 
507  TEST_F(DataBaseTest, KeyAccess)
508  {
510  evtPtr->setExperiment(1);
511  DBStore::Instance().update();
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);
520  DBStore::Instance().update();
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);
531  DBStore::Instance().update();
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);
547  DBStore::Instance().update();
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);
553  DBStore::Instance().reset();
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 
579  TestHelpers::TempDirCreator m_tempDir;
581  EventMetaData m_event;
582 
583  DataBaseNoDataStoreTest() : m_event(0, 0, 1) {};
584 
586  void SetUp() override
587  {
588  auto& c = Conditions::Configuration::getInstance();
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) {
632  Database::Instance().storeData(query);
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");
649  Database::reset();
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);
760  DBStore::Instance().updateEvent(m_event.getEvent());
761  EXPECT_TRUE(strcmp(intraRun->GetName(), "A") == 0);
762 
763  m_event.setEvent(10);
764  DBStore::Instance().updateEvent(m_event.getEvent());
765  EXPECT_TRUE(strcmp(intraRun->GetName(), "B") == 0);
766 
767  m_event.setEvent(49);
768  DBStore::Instance().updateEvent(m_event.getEvent());
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);
776  DBStore::Instance().updateEvent(m_event.getEvent());
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);
816  DBStore::Instance().updateEvent(m_event.getEvent());
817  EXPECT_TRUE(intraRun.hasChanged());
818 
819  m_event.setEvent(2);
820  DBStore::Instance().updateEvent(m_event.getEvent());
821  EXPECT_FALSE(intraRun.hasChanged());
822 
823  m_event.setEvent(10);
824  DBStore::Instance().updateEvent(m_event.getEvent());
825  EXPECT_TRUE(intraRun.hasChanged());
826 
827  m_event.setEvent(1000);
828  DBStore::Instance().updateEvent(m_event.getEvent());
829  EXPECT_TRUE(intraRun.hasChanged());
830 
831  m_event.setRun(4);
832  DBStore::Instance().update(m_event);
833  DBStore::Instance().updateEvent(m_event.getEvent());
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);
896  DBStore::Instance().updateEvent(m_event.getEvent());
897  EXPECT_EQ(callbackCounter, 5);
898 
899  m_event.setEvent(2);
900  DBStore::Instance().updateEvent(m_event.getEvent());
901  EXPECT_EQ(callbackCounter, 5);
902 
903  m_event.setEvent(10);
904  DBStore::Instance().updateEvent(m_event.getEvent());
905  EXPECT_EQ(callbackCounter, 6);
906 
907  m_event.setEvent(1);
908  DBStore::Instance().updateEvent(m_event.getEvent());
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
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
Specialization of DBObjPtr in case of PayloadFiles.
Definition: PayloadFile.h:54
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
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
TEST_F(GlobalLabelTest, LargeNumberOfTimeDependentParameters)
Test large number of time-dep params for registration and retrieval.
Definition: globalLabel.cc:72
static DBStore & Instance()
Instance of a singleton DBStore.
Definition: DBStore.cc:28
void addConstantOverride(const std::string &name, TObject *obj, bool oneRun=false)
Add constant override payload.
Definition: DBStore.cc:204
Abstract base class for different kinds of events.
Struct for bulk write queries.
Definition: Database.h:77