Belle II Software  release-06-02-00
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 <boost/filesystem.hpp>
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) boost::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 
431  //disable (wrong) warnings about unused functions
432 #if defined(__INTEL_COMPILER)
433 #pragma warning disable 177
434 #endif
435 
437  int callbackCounter = 0;
438 
439  void callback()
440  {
441  callbackCounter++;
442  }
443 
444  class Callback {
445  public:
446  void callback()
447  {
448  callbackCounter++;
449  }
450  };
451  Callback callbackObject;
452 
453  TEST_F(DataBaseTest, Callbacks)
454  {
456  evtPtr->setRun(1);
457  evtPtr->setEvent(1);
458  callbackCounter = 0;
459 
460  DBObjPtr<TNamed> named;
461  named.addCallback(&callback);
462  EXPECT_EQ(callbackCounter, 0);
463 
464  evtPtr->setExperiment(2);
465  DBStore::Instance().update();
466  EXPECT_EQ(callbackCounter, 1);
467 
468  evtPtr->setExperiment(4);
469  DBStore::Instance().update();
470  EXPECT_EQ(callbackCounter, 2);
471  DBStore::Instance().update();
472  EXPECT_EQ(callbackCounter, 2);
473 
474  evtPtr->setExperiment(6);
475  DBStore::Instance().update();
476  EXPECT_EQ(callbackCounter, 3);
477 
478  evtPtr->setExperiment(7);
479  DBStore::Instance().update();
480  EXPECT_EQ(callbackCounter, 3);
481 
482  DBArray<TObject> objects;
483  objects.addCallback(&callback);
484 
485  evtPtr->setExperiment(1);
486  DBStore::Instance().update();
487  // callbacks will now be called once for each payload so there is an extra call
488  EXPECT_EQ(callbackCounter, 5);
489 
490  DBObjPtr<TNamed> intraRun("IntraRun");
491  intraRun.addCallback(&callbackObject, &Callback::callback);
492 
493  //There won't be any callback here because the correct object is already set on creation
494  evtPtr->setEvent(1);
495  DBStore::Instance().updateEvent();
496  EXPECT_EQ(callbackCounter, 5);
497 
498  evtPtr->setEvent(2);
499  DBStore::Instance().updateEvent();
500  EXPECT_EQ(callbackCounter, 5);
501 
502  evtPtr->setEvent(10);
503  DBStore::Instance().updateEvent();
504  EXPECT_EQ(callbackCounter, 6);
505 
506  evtPtr->setEvent(1);
507  DBStore::Instance().updateEvent();
508  EXPECT_EQ(callbackCounter, 7);
509  }
510 
512  TEST_F(DataBaseTest, KeyAccess)
513  {
515  evtPtr->setExperiment(1);
516  DBStore::Instance().update();
517 
518  DBArray<TObject> objects;
519  EXPECT_EQ(objects.getByKey<unsigned int>(&TObject::GetUniqueID, 1)->GetUniqueID(), 1);
520  EXPECT_EQ(objects.getByKey<unsigned int>(&TObject::GetUniqueID, 2), nullptr);
521  EXPECT_EQ(objects.getByKey(&TObject::IsFolder, false)->GetUniqueID(), 1);
522  EXPECT_EQ(objects.getByKey(&TObject::IsFolder, true), nullptr);
523 
524  evtPtr->setExperiment(2);
525  DBStore::Instance().update();
526 
527  EXPECT_EQ(objects.getByKey<unsigned int>(&TObject::GetUniqueID, 1)->GetUniqueID(), 1);
528  EXPECT_EQ(objects.getByKey<unsigned int>(&TObject::GetUniqueID, 2)->GetUniqueID(), 2);
529  }
530 
532  TEST_F(DataBaseTest, DBPointer)
533  {
535  evtPtr->setExperiment(2);
536  DBStore::Instance().update();
537 
539  EXPECT_EQ(ptr.key(), 1);
540  EXPECT_TRUE(ptr.isValid());
541  EXPECT_EQ(ptr->GetUniqueID(), 1);
542  ptr = 2;
543  EXPECT_EQ(ptr->GetUniqueID(), 2);
544  ptr = 3;
545  EXPECT_FALSE(ptr.isValid());
546  }
547 
548  TEST_F(DataBaseTest, CleanupReattachDeathtest)
549  {
551  evtPtr->setExperiment(2);
552  DBStore::Instance().update();
553 
554  DBObjPtr<TNamed> named;
555  EXPECT_TRUE(named.isValid());
556  double Bz = BFieldManager::getFieldInTesla({0, 0, 0}).Z();
557  EXPECT_EQ(Bz, 1.5);
558  DBStore::Instance().reset();
559  //Ok, on next access the DBObjPtr should try to reconnect
560  EXPECT_TRUE(named.isValid());
561  //Which means the magnetic field should die a horrible death: It's not
562  //found in the database during testing, just a override.
563  EXPECT_B2FATAL(BFieldManager::getFieldInTesla({0, 0, 0}));
564  //Unless we add a new one
565  auto* field = new Belle2::MagneticField();
566  field->addComponent(new Belle2::MagneticFieldComponentConstant({0, 0, 1.5 * Belle2::Unit::T}));
567  Belle2::DBStore::Instance().addConstantOverride("MagneticField", field, false);
568  //So now it should work again
569  Bz = BFieldManager::getFieldInTesla({0, 0, 0}).Z();
570  EXPECT_EQ(Bz, 1.5);
571  }
572 
575  class DataBaseNoDataStoreTest : public ::testing::Test {
576  protected:
577 
579  enum EDatabaseType {c_local, c_central, c_chain, c_default};
580 
582  EDatabaseType m_dbType = c_local;
583 
584  TestHelpers::TempDirCreator m_tempDir;
586  EventMetaData m_event;
587 
588  DataBaseNoDataStoreTest() : m_event(0, 0, 1) {};
589 
591  void SetUp() override
592  {
593  auto& c = Conditions::Configuration::getInstance();
594  switch (m_dbType) {
595  case c_local:
596  c.setGlobalTags({});
597  c.overrideGlobalTags();
598  c.setMetadataProviders({});
599  c.setNewPayloadLocation("testPayloads/TestDatabase.txt");
600  c.appendTestingPayloadLocation("testPayloads/TestDatabase.txt");
601  break;
602  case c_central:
603  c.setGlobalTags({"default"});
604  c.overrideGlobalTags();
605  break;
606  case c_chain:
607  c.setGlobalTags({"default"});
608  c.overrideGlobalTags();
609  c.setMetadataProviders({});
610  c.setNewPayloadLocation("testPayloads/TestDatabase.txt");
611  c.appendTestingPayloadLocation("testPayloads/TestDatabase.txt");
612  break;
613  case c_default:
614  break;
615  }
616 
617  if (m_dbType != c_central) {
618  list<Database::DBImportQuery> query;
619  TClonesArray array("TObject");
620  for (int experiment = 1; experiment <= 5; experiment++) {
621  IntervalOfValidity iov(experiment, -1, experiment, -1);
622 
623  TString name = "Experiment ";
624  name += experiment;
625  query.push_back(Database::DBImportQuery("TNamed", new TNamed(name, name), iov));
626 
627  new(array[experiment - 1]) TObject;
628  array[experiment - 1]->SetUniqueID(experiment);
629  Database::Instance().storeData("TObjects", &array, iov);
630 
631  FILE* f = fopen("file.xml", "w");
632  fprintf(f, "Experiment %d\n", experiment);
633  fclose(f);
634  Database::Instance().addPayload("file.xml", "file.xml", iov);
635  }
636  if (m_dbType != c_chain) {
637  Database::Instance().storeData(query);
638  }
639 
640  EventDependency intraRunDep(new TNamed("A", "A"));
641  intraRunDep.add(10, new TNamed("B", "B"));
642  intraRunDep.add(50, new TNamed("C", "C"));
643  IntervalOfValidity iov1(1, 1, 1, 1);
644  Database::Instance().storeData("IntraRun", &intraRunDep, iov1);
645  IntervalOfValidity iov2(1, 2, 1, -1);
646  Database::Instance().storeData("IntraRun", new TNamed("X", "X"), iov2);
647  }
648  }
649 
651  void TearDown() override
652  {
653  if (m_dbType != c_central) boost::filesystem::remove_all("testPayloads");
654  Database::reset();
655  }
656 
657  };
658 
660  TEST_F(DataBaseNoDataStoreTest, DBObjPtr)
661  {
662  DBStore::Instance().update(m_event); // The DBStore takes a reference to an EventMetaData object
663  DBObjPtr<TNamed> named;
664  m_event.setExperiment(1);
665  DBStore::Instance().update(m_event); // The DBStore takes a reference to an EventMetaData object
666  ASSERT_TRUE(named);
667  EXPECT_TRUE(strcmp(named->GetName(), "Experiment 1") == 0);
668  m_event.setExperiment(4);
669  EXPECT_TRUE(strcmp(named->GetName(), "Experiment 1") == 0);
670  DBStore::Instance().update(m_event);
671  EXPECT_TRUE(strcmp(named->GetName(), "Experiment 4") == 0);
672  m_event.setExperiment(7);
673  DBStore::Instance().update(m_event);
674  EXPECT_FALSE(named);
675  }
676 
678  TEST_F(DataBaseNoDataStoreTest, DBArray)
679  {
680  DBStore::Instance().update(m_event);
681  DBArray<TObject> objects;
682  DBArray<TObject> missing("notexisting");
683  // check iteration on fresh object
684  {
685  int i = 0;
686  for (const auto& o : missing) {
687  (void)o;
688  ++i;
689  }
690  EXPECT_EQ(i, 0);
691  }
692 
693 
694  m_event.setExperiment(1);
695  DBStore::Instance().update(m_event);
696  EXPECT_TRUE(objects);
697  EXPECT_FALSE(missing);
698  EXPECT_EQ(objects.getEntries(), 1);
699  EXPECT_EQ(objects[0]->GetUniqueID(), 1);
700  m_event.setExperiment(4);
701  EXPECT_EQ(objects.getEntries(), 1);
702  DBStore::Instance().update(m_event);
703  EXPECT_EQ(objects.getEntries(), 4);
704  // check iteration on existing
705  {
706  int i = 0;
707  for (const auto& o : objects) {
708  EXPECT_EQ(o.GetUniqueID(), ++i);
709  }
710  EXPECT_EQ(i, 4);
711  }
712 
713  // check iteration on missing object
714  {
715  int i = 0;
716  for (const auto& o : missing) {
717  (void)o;
718  ++i;
719  }
720  EXPECT_EQ(i, 0);
721  }
722  m_event.setExperiment(7);
723  DBStore::Instance().update(m_event);
724  EXPECT_FALSE(objects);
725  // check iteration over missing but previously existing
726  {
727  int i = 0;
728  for (const auto& o : objects) {
729  EXPECT_EQ(o.GetUniqueID(), ++i);
730  }
731  EXPECT_EQ(i, 0);
732  }
733  }
734 
736  TEST_F(DataBaseNoDataStoreTest, DBArrayRange)
737  {
738  DBArray<TObject> objects;
739 
740  m_event.setExperiment(3);
741  DBStore::Instance().update(m_event);
742  EXPECT_THROW(objects[-1], std::out_of_range);
743  EXPECT_THROW(objects[3], std::out_of_range);
744  }
745 
747  TEST_F(DataBaseNoDataStoreTest, TypeCheck)
748  {
749  DBObjPtr<TNamed> named;
750  EXPECT_B2FATAL(DBObjPtr<EventMetaData> wrongType("TNamed"));
751 
752  DBArray<TObject> objects;
753  EXPECT_B2FATAL(DBArray<EventMetaData> wrongType("TObjects"));
754  }
755 
757  TEST_F(DataBaseNoDataStoreTest, IntraRun)
758  {
759  DBObjPtr<TNamed> intraRun("IntraRun");
760 
761  m_event.setExperiment(1);
762  m_event.setRun(1);
763  m_event.setEvent(9);
764  DBStore::Instance().update(m_event);
765  DBStore::Instance().updateEvent(m_event.getEvent());
766  EXPECT_TRUE(strcmp(intraRun->GetName(), "A") == 0);
767 
768  m_event.setEvent(10);
769  DBStore::Instance().updateEvent(m_event.getEvent());
770  EXPECT_TRUE(strcmp(intraRun->GetName(), "B") == 0);
771 
772  m_event.setEvent(49);
773  DBStore::Instance().updateEvent(m_event.getEvent());
774  EXPECT_TRUE(strcmp(intraRun->GetName(), "B") == 0);
775 
776  //let's run an update in between and make sure intra run continues to work
777  DBStore::Instance().update(m_event);
778  EXPECT_TRUE(strcmp(intraRun->GetName(), "B") == 0);
779 
780  m_event.setEvent(50);
781  DBStore::Instance().updateEvent(m_event.getEvent());
782  EXPECT_TRUE(strcmp(intraRun->GetName(), "C") == 0);
783 
784  m_event.setRun(2);
785  DBStore::Instance().update(m_event);
786  EXPECT_TRUE(strcmp(intraRun->GetName(), "X") == 0);
787  }
788 
790  TEST_F(DataBaseNoDataStoreTest, HasChanged)
791  {
792  m_event.setExperiment(0);
793  DBStore::Instance().update(m_event);
794 
795  DBObjPtr<TNamed> named;
796  EXPECT_FALSE(named.hasChanged());
797 
798  m_event.setExperiment(1);
799  EXPECT_FALSE(named.hasChanged());
800 
801  DBStore::Instance().update(m_event);
802  EXPECT_TRUE(named.hasChanged());
803 
804  m_event.setRun(8);
805  DBStore::Instance().update(m_event);
806  EXPECT_FALSE(named.hasChanged());
807 
808  m_event.setExperiment(5);
809  DBStore::Instance().update(m_event);
810  EXPECT_TRUE(named.hasChanged());
811 
812  m_event.setExperiment(7);
813  DBStore::Instance().update(m_event);
814  EXPECT_TRUE(named.hasChanged());
815 
816  m_event.setExperiment(1);
817  m_event.setRun(1);
818  m_event.setEvent(1);
819  DBObjPtr<TNamed> intraRun("IntraRun");
820  DBStore::Instance().update(m_event);
821  DBStore::Instance().updateEvent(m_event.getEvent());
822  EXPECT_TRUE(intraRun.hasChanged());
823 
824  m_event.setEvent(2);
825  DBStore::Instance().updateEvent(m_event.getEvent());
826  EXPECT_FALSE(intraRun.hasChanged());
827 
828  m_event.setEvent(10);
829  DBStore::Instance().updateEvent(m_event.getEvent());
830  EXPECT_TRUE(intraRun.hasChanged());
831 
832  m_event.setEvent(1000);
833  DBStore::Instance().updateEvent(m_event.getEvent());
834  EXPECT_TRUE(intraRun.hasChanged());
835 
836  m_event.setRun(4);
837  DBStore::Instance().update(m_event);
838  DBStore::Instance().updateEvent(m_event.getEvent());
839  EXPECT_TRUE(intraRun.hasChanged());
840  }
841 
843  TEST_F(DataBaseNoDataStoreTest, PayloadFile)
844  {
845  DBStore::Instance().update(m_event);
846  DBObjPtr<PayloadFile> payload("file.xml");
847  m_event.setExperiment(1);
848  DBStore::Instance().update(m_event);
849  EXPECT_EQ(payload->getContent(), "Experiment 1\n") << payload->getFileName();
850  m_event.setExperiment(4);
851  DBStore::Instance().update(m_event);
852  EXPECT_EQ(payload->getContent(), "Experiment 4\n") << payload->getFileName();
853  m_event.setExperiment(7);
854  DBStore::Instance().update(m_event);
855  EXPECT_FALSE(payload);
856  }
857 
860  TEST_F(DataBaseNoDataStoreTest, Callbacks)
861  {
862  m_event.setRun(1);
863  m_event.setEvent(1);
864  callbackCounter = 0;
865 
866  DBObjPtr<TNamed> named;
867  named.addCallback(&callback);
868  EXPECT_EQ(callbackCounter, 0);
869 
870  m_event.setExperiment(2);
871  DBStore::Instance().update(m_event);
872  EXPECT_EQ(callbackCounter, 1);
873 
874  m_event.setExperiment(4);
875  DBStore::Instance().update(m_event);
876  EXPECT_EQ(callbackCounter, 2);
877  DBStore::Instance().update(m_event);
878  EXPECT_EQ(callbackCounter, 2);
879 
880  m_event.setExperiment(6);
881  DBStore::Instance().update(m_event);
882  EXPECT_EQ(callbackCounter, 3);
883 
884  m_event.setExperiment(7);
885  DBStore::Instance().update(m_event);
886  EXPECT_EQ(callbackCounter, 3);
887 
888  DBArray<TObject> objects;
889  objects.addCallback(&callback);
890 
891  m_event.setExperiment(1);
892  DBStore::Instance().update(m_event);
893  // callbacks will now be called once for each payload so there is an extra call
894  EXPECT_EQ(callbackCounter, 5);
895 
896  DBObjPtr<TNamed> intraRun("IntraRun");
897  intraRun.addCallback(&callbackObject, &Callback::callback);
898 
899  //There won't be any callback here because the correct object is already set on creation
900  m_event.setEvent(1);
901  DBStore::Instance().updateEvent(m_event.getEvent());
902  EXPECT_EQ(callbackCounter, 5);
903 
904  m_event.setEvent(2);
905  DBStore::Instance().updateEvent(m_event.getEvent());
906  EXPECT_EQ(callbackCounter, 5);
907 
908  m_event.setEvent(10);
909  DBStore::Instance().updateEvent(m_event.getEvent());
910  EXPECT_EQ(callbackCounter, 6);
911 
912  m_event.setEvent(1);
913  DBStore::Instance().updateEvent(m_event.getEvent());
914  EXPECT_EQ(callbackCounter, 7);
915  }
916 
918  TEST_F(DataBaseNoDataStoreTest, KeyAccess)
919  {
920  m_event.setExperiment(1);
921  DBStore::Instance().update(m_event);
922 
923  DBArray<TObject> objects;
924  EXPECT_EQ(objects.getByKey<unsigned int>(&TObject::GetUniqueID, 1)->GetUniqueID(), 1);
925  EXPECT_EQ(objects.getByKey<unsigned int>(&TObject::GetUniqueID, 2), nullptr);
926  EXPECT_EQ(objects.getByKey(&TObject::IsFolder, false)->GetUniqueID(), 1);
927  EXPECT_EQ(objects.getByKey(&TObject::IsFolder, true), nullptr);
928 
929  m_event.setExperiment(2);
930  DBStore::Instance().update(m_event);
931 
932  EXPECT_EQ(objects.getByKey<unsigned int>(&TObject::GetUniqueID, 1)->GetUniqueID(), 1);
933  EXPECT_EQ(objects.getByKey<unsigned int>(&TObject::GetUniqueID, 2)->GetUniqueID(), 2);
934  }
935 
936  TEST_F(DataBaseNoDataStoreTest, DBPointer)
937  {
938  m_event.setExperiment(2);
939  DBStore::Instance().update(m_event);
940 
942  EXPECT_EQ(ptr.key(), 1);
943  EXPECT_TRUE(ptr.isValid());
944  EXPECT_EQ(ptr->GetUniqueID(), 1);
945  ptr = 2;
946  EXPECT_EQ(ptr->GetUniqueID(), 2);
947  ptr = 3;
948  EXPECT_FALSE(ptr.isValid());
949  }
950 } // 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:33
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:95
bool construct(Args &&... params)
Construct an object of type T in this StoreObjPtr, using the provided constructor arguments.
Definition: StoreObjPtr.h:118
changes working directory into a newly created directory, and removes it (and contents) on destructio...
Definition: TestHelpers.h:64
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:26
void addConstantOverride(const std::string &name, TObject *obj, bool oneRun=false)
Add constant override payload.
Definition: DBStore.cc:194
Abstract base class for different kinds of events.
Struct for bulk write queries.
Definition: Database.h:77