Belle II Software development
relationsobject.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/datastore/StoreArray.h>
9#include <framework/dataobjects/EventMetaData.h>
10#include <framework/dataobjects/ProfileInfo.h>
11#include <framework/datastore/RelationsObject.h>
12#include <framework/utilities/TestHelpers.h>
13
14#include <gtest/gtest.h>
15
16using namespace std;
17using namespace Belle2;
18
19namespace {
21 class RelationsObjectTest : public ::testing::Test {
22 protected:
24 void SetUp() override
25 {
26 evtData.registerInDataStore();
27 profileData.registerInDataStore();
28 relObjData.registerInDataStore();
29
30 for (int i = 0; i < 10; ++i) {
31 evtData.appendNew();
32 profileData.appendNew();
33 relObjData.appendNew();
34 }
35 }
36
38 void TearDown() override
39 {
41 }
42
43 StoreArray<EventMetaData> evtData;
44 StoreArray<ProfileInfo> profileData;
45 StoreArray<RelationsObject> relObjData;
46 };
47
49 TEST_F(RelationsObjectTest, RelationsObject)
50 {
51 relObjData.registerRelationTo(profileData);
53
54 (relObjData)[0]->addRelationTo((profileData)[0], -42.0);
55
56 //getRelations
57 RelationVector<ProfileInfo> rels = (relObjData)[0]->getRelationsTo<ProfileInfo>();
58 EXPECT_TRUE(rels.size() == 1);
59 EXPECT_TRUE(rels.object(0) == (profileData)[0]);
60 EXPECT_DOUBLE_EQ(rels.weight(0), -42.0);
61 EXPECT_EQ(0u, relObjData[1]->getRelationsTo<ProfileInfo>().size());
62 EXPECT_EQ(0u, relObjData[0]->getRelationsFrom<ProfileInfo>().size());
63 EXPECT_EQ(1u, relObjData[0]->getRelationsWith<ProfileInfo>().size());
64
65 //getRelated
66 EXPECT_TRUE(profileData[0] == relObjData[0]->getRelatedTo<ProfileInfo>());
67 EXPECT_TRUE(nullptr == relObjData[1]->getRelatedTo<ProfileInfo>());
68 EXPECT_TRUE(nullptr == relObjData[0]->getRelatedFrom<ProfileInfo>());
69 EXPECT_TRUE(profileData[0] == relObjData[0]->getRelated<ProfileInfo>());
70
71 //getRelatedWithWeight
72 EXPECT_TRUE(std::make_pair(profileData[0], -42.0f) == relObjData[0]->getRelatedToWithWeight<ProfileInfo>());
73 ProfileInfo* profileNullPtr = nullptr;
74 EXPECT_TRUE(std::make_pair(profileNullPtr, 1.0f) == relObjData[1]->getRelatedToWithWeight<ProfileInfo>());
75 EXPECT_TRUE(std::make_pair(profileNullPtr, 1.0f) == relObjData[0]->getRelatedFromWithWeight<ProfileInfo>());
76 EXPECT_TRUE(std::make_pair(profileData[0], -42.0f) == relObjData[0]->getRelatedWithWeight<ProfileInfo>());
77
78
79 //adding relations to NULL is safe and doesn't do anything
80 (relObjData)[0]->addRelationTo(static_cast<TObject*>(nullptr));
81 (relObjData)[0]->addRelationTo(static_cast<ProfileInfo*>(nullptr));
82
83 //if we cannot create a relation to an actual object given, this is obviously wrong
84 ProfileInfo notInArray;
85 EXPECT_B2FATAL((relObjData)[0]->addRelationTo(&notInArray));
86 }
87
89 TEST_F(RelationsObjectTest, IndexUpdating)
90 {
91 relObjData.registerRelationTo(profileData);
93
94 //not yet set
95 EXPECT_FALSE((relObjData)[0]->getRelated<ProfileInfo>() != nullptr);
96
97 (relObjData)[0]->addRelationTo((profileData)[0], -42.0);
98
99 //now it should be found (index updated because RelationContainer was just created)
100 EXPECT_TRUE((relObjData)[0]->getRelated<ProfileInfo>() != nullptr);
101
102 //test again with different object
103 EXPECT_FALSE((relObjData)[1]->getRelated<ProfileInfo>() != nullptr);
104
105 (relObjData)[1]->addRelationTo((profileData)[0], -42.0);
106
107 //now it should be found (index updated because addRelation marks RelationContainer as modified)
108 EXPECT_TRUE((relObjData)[1]->getRelated<ProfileInfo>() != nullptr);
109 }
110
112 TEST_F(RelationsObjectTest, RelationsObjectArrayIndex)
113 {
114 for (int i = 0; i < relObjData.getEntries(); i++) {
115 EXPECT_TRUE((relObjData)[i]->getArrayName() == relObjData.getName());
116 EXPECT_TRUE((relObjData)[i]->getArrayIndex() == i);
117 }
118
119 RelationsObject bla;
120 EXPECT_TRUE(bla.getArrayName() == "");
121 EXPECT_TRUE(bla.getArrayIndex() == -1);
122 }
123
125 TEST_F(RelationsObjectTest, DuplicateRelations)
126 {
127 evtData.registerRelationTo(relObjData);
128 relObjData.registerRelationTo(evtData);
130
131 //more than a single relation in one direction
132 DataStore::Instance().addRelationFromTo((evtData)[0], (relObjData)[1], 1.0);
133 DataStore::Instance().addRelationFromTo((evtData)[0], (relObjData)[1], 2.0);
134
135 //since the relation wasn't consolidated, these should still show up as
136 //separate things
137 RelationVector<EventMetaData> rels1 = (relObjData)[1]->getRelationsFrom<EventMetaData>();
138 EXPECT_EQ(2u, rels1.size());
139
140
141 //preserve order
142 EXPECT_FLOAT_EQ(1.0, rels1.weight(0));
143 EXPECT_FLOAT_EQ(2.0, rels1.weight(1));
144 EXPECT_FLOAT_EQ(1.0, relObjData[1]->getRelatedFromWithWeight<EventMetaData>().second);
145
146
147 //add another one in opposite direction
148 DataStore::Instance().addRelationFromTo((relObjData)[1], (evtData)[0], 1.0);
149 RelationVector<EventMetaData> rels2 = (relObjData)[1]->getRelationsFrom<EventMetaData>();
150 //wasn't _from_ eventmetadata, so no change
151 EXPECT_EQ(2u, rels2.size());
152
153 RelationVector<EventMetaData> rels3 = (relObjData)[1]->getRelationsWith<EventMetaData>();
154 EXPECT_EQ(3u, rels3.size());
155 double sum = 0.0;
156 for (int i = 0; i < (int)rels3.size(); i++) {
157 sum += rels3.weight(i);
158 }
159 EXPECT_DOUBLE_EQ(sum, 1.0 + 1.0 + 2.0);
160 }
161
162 TEST_F(RelationsObjectTest, RelationsToSameArray)
163 {
164 relObjData.registerRelationTo(relObjData);
166
167 relObjData[0]->addRelationTo(relObjData[1]);
168 EXPECT_TRUE(relObjData[0] == relObjData[1]->getRelated<RelationsObject>());
169 EXPECT_TRUE(relObjData[0] == relObjData[1]->getRelatedFrom<RelationsObject>());
170 EXPECT_TRUE(relObjData[1] == relObjData[0]->getRelated<RelationsObject>());
171 EXPECT_TRUE(relObjData[1] == relObjData[0]->getRelatedTo<RelationsObject>());
172 EXPECT_TRUE(nullptr == relObjData[2]->getRelated<RelationsObject>());
173 EXPECT_TRUE(nullptr == relObjData[2]->getRelatedFrom<RelationsObject>());
174 EXPECT_TRUE(nullptr == relObjData[2]->getRelatedTo<RelationsObject>());
175 //still in one direction
176 EXPECT_TRUE(nullptr == relObjData[1]->getRelatedTo<RelationsObject>());
177 EXPECT_TRUE(nullptr == relObjData[0]->getRelatedFrom<RelationsObject>());
178
179 //to same object
180 relObjData[3]->addRelationTo(relObjData[3]);
181 EXPECT_TRUE(relObjData[3] == relObjData[3]->getRelated<RelationsObject>());
182 EXPECT_TRUE(relObjData[3] == relObjData[3]->getRelatedFrom<RelationsObject>());
183 EXPECT_TRUE(relObjData[3] == relObjData[3]->getRelatedTo<RelationsObject>());
184 }
185
186 TEST_F(RelationsObjectTest, ModifyRelations)
187 {
188 relObjData.registerRelationTo(profileData);
190
191 (relObjData)[0]->addRelationTo((profileData)[0], -42.0);
192
193 //weights
194 RelationVector<ProfileInfo> rels = (relObjData)[0]->getRelationsTo<ProfileInfo>();
195 EXPECT_DOUBLE_EQ(rels.weight(0), -42.0);
196 rels.setWeight(0, -3.0);
197 EXPECT_DOUBLE_EQ(rels.weight(0), -3.0); //updated immediately
198 RelationVector<ProfileInfo> rels2 = (relObjData)[0]->getRelationsTo<ProfileInfo>();
199 EXPECT_DOUBLE_EQ(rels2.weight(0), -3.0); //and in DataStore
200
201 //removal
202 EXPECT_EQ(1u, relObjData[0]->getRelationsTo<ProfileInfo>().size());
203 EXPECT_EQ(1u, relObjData[0]->getRelationsWith<ProfileInfo>().size());
204 rels2.remove(0);
205 EXPECT_EQ(0u, rels2.size());
206 EXPECT_EQ(0u, relObjData[0]->getRelationsTo<ProfileInfo>().size());
207 EXPECT_EQ(0u, relObjData[0]->getRelationsWith<ProfileInfo>().size());
208 }
209
211 TEST_F(RelationsObjectTest, NamedRelationsWithInvalidName)
212 {
213 const std::string relationName = "ExtraRelation WithSpaceInName";
214 EXPECT_B2FATAL(relObjData.registerRelationTo(profileData, DataStore::c_Event, DataStore::c_WriteOut, relationName));
215 }
216
218 TEST_F(RelationsObjectTest, NamedRelations)
219 {
220 const std::string relationName = "ExtraRelation";
221 relObjData.registerRelationTo(profileData, DataStore::c_Event, DataStore::c_WriteOut, relationName);
223
224 //check the hasRelation finder works with and without names
225 EXPECT_TRUE(relObjData.hasRelationTo(profileData, DataStore::c_Event, relationName));
226 EXPECT_FALSE(profileData.hasRelationTo(relObjData, DataStore::c_Event, relationName));
227 EXPECT_FALSE(profileData.hasRelationTo(evtData, DataStore::c_Event, relationName));
228 EXPECT_FALSE(relObjData.hasRelationTo(profileData));
229 EXPECT_FALSE(profileData.hasRelationTo(relObjData));
230
231 (relObjData)[0]->addRelationTo((profileData)[0], -42.0, relationName);
232
233 //getRelations
234 RelationVector<ProfileInfo> rels = (relObjData)[0]->getRelationsTo<ProfileInfo>("", relationName);
235 EXPECT_TRUE(rels.size() == 1);
236 EXPECT_TRUE(rels.object(0) == (profileData)[0]);
237 EXPECT_DOUBLE_EQ(rels.weight(0), -42.0);
238 EXPECT_EQ(0u, relObjData[1]->getRelationsTo<ProfileInfo>("", relationName).size());
239 EXPECT_EQ(0u, relObjData[0]->getRelationsFrom<ProfileInfo>("", relationName).size());
240 EXPECT_EQ(1u, relObjData[0]->getRelationsWith<ProfileInfo>("", relationName).size());
241
242 //getRelated
243 EXPECT_TRUE(profileData[0] == relObjData[0]->getRelatedTo<ProfileInfo>("", relationName));
244 EXPECT_TRUE(nullptr == relObjData[1]->getRelatedTo<ProfileInfo>("", relationName));
245 EXPECT_TRUE(nullptr == relObjData[0]->getRelatedFrom<ProfileInfo>("", relationName));
246 EXPECT_TRUE(profileData[0] == relObjData[0]->getRelated<ProfileInfo>("", relationName));
247
248 //getRelatedWithWeight
249 EXPECT_TRUE(std::make_pair(profileData[0], -42.0f) == relObjData[0]->getRelatedToWithWeight<ProfileInfo>("", relationName));
250 ProfileInfo* profileNullPtr = nullptr;
251 EXPECT_TRUE(std::make_pair(profileNullPtr, 1.0f) == relObjData[1]->getRelatedToWithWeight<ProfileInfo>("", relationName));
252 EXPECT_TRUE(std::make_pair(profileNullPtr, 1.0f) == relObjData[0]->getRelatedFromWithWeight<ProfileInfo>("", relationName));
253 EXPECT_TRUE(std::make_pair(profileData[0], -42.0f) == relObjData[0]->getRelatedWithWeight<ProfileInfo>("", relationName));
254
255 // Check if the "ALL" parameter also works
256 StoreEntry* storeEntry = nullptr;
257 int index = -1;
258 DataStore::Instance().getRelationsWith(DataStore::c_FromSide, (relObjData)[0], storeEntry, index,
259 TObject::Class(), "ALL", "");
260
261 //adding relations to NULL is safe and doesn't do anything
262 (relObjData)[0]->addRelationTo(static_cast<TObject*>(nullptr), 1.0, relationName);
263 (relObjData)[0]->addRelationTo(static_cast<ProfileInfo*>(nullptr), 1.0, relationName);
264
265 //if we cannot create a relation to an actual object given, this is obviously wrong
266 ProfileInfo notInArray;
267 EXPECT_B2FATAL((relObjData)[0]->addRelationTo(&notInArray, 1.0, relationName));
268 }
269
270} // namespace
static void addRelationFromTo(const TObject *fromObject, const TObject *toObject, float weight=1.0, const std::string &namedRelation="")
Add a relation from an object in a store array to another object in a store array.
Definition DataStore.h:387
@ c_WriteOut
Object/array should be saved by output modules.
Definition DataStore.h:70
@ c_FromSide
Return relations/objects pointed from (to a given object).
Definition DataStore.h:77
@ c_Event
Different object in each event, all objects/arrays are invalidated after event() function has been ca...
Definition DataStore.h:59
static DataStore & Instance()
Instance of singleton Store.
Definition DataStore.cc:53
void setInitializeActive(bool active)
Setter for m_initializeActive.
Definition DataStore.cc:93
void reset(EDurability durability)
Frees memory occupied by data store items and removes all objects from the map.
Definition DataStore.cc:85
RelationVectorBase getRelationsWith(ESearchSide searchSide, const TObject *object, StoreEntry *&entry, int &index, const TClass *withClass, const std::string &withName, const std::string &namedRelation)
Get the relations between an object and other objects in a store array.
Definition DataStore.cc:544
Store execution time and memory usage.
Definition ProfileInfo.h:22
Class for type safe access to objects that are referred to in relations.
void setWeight(int index, float weight)
Set a new weight for the given relation.
T * object(int index) const
Get object with index.
size_t size() const
Get number of relations.
void remove(int index)
Remove relation at given index.
float weight(int index) const
Get weight with index.
std::string getArrayName() const
Get name of array this object is stored in, or "" if not found.
int getArrayIndex() const
Returns this object's array index (in StoreArray), or -1 if not found.
RelationsInterface< TObject > RelationsObject
Provides interface for getting/adding relations to objects in StoreArrays.
Abstract base class for different kinds of events.
STL namespace.
Wraps a stored array/object, stored under unique (name, durability) key.
Definition StoreEntry.h:22