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
44 StoreArray<ProfileInfo> profileData;
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 obivously 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 //seperate 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 obivously 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: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
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:545
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.
Defines interface for accessing relations of objects in StoreArray.
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.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
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