ATLAS Offline Software
Loading...
Searching...
No Matches
ColumnarMemoryTest.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7
8//
9// includes
10//
11
13
18
19//
20// method implementations
21//
22
23namespace columnar
24{
25 ColumnarMemoryTest ::
26 ColumnarMemoryTest ()
27 {
28 }
29
30
31
32 std::string ColumnarMemoryTest ::
33 makeUniqueName ()
34 {
35 static std::atomic<unsigned> index = 0;
36 return "UniqueMemoryTestTool" + std::to_string(++index);
37 }
38
39
40
41 namespace TestUtils
42 {
43 ColumnarTestToolHandle ::
44 ColumnarTestToolHandle (asg::AsgTool& val_tool)
45 {
46 m_tool = dynamic_cast<IColumnarTool*> (&val_tool);
47 if (m_tool == nullptr)
48 throw std::runtime_error ("tool does not implement IColumnarTool");
49 m_systTool = dynamic_cast<CP::ISystematicsTool*> (m_tool);
50 }
51
52
53
54 void ColumnarTestToolHandle ::
55 renameContainers (const std::vector<std::pair<std::string,std::string>>& renames)
56 {
58 if (m_toolWrapper)
59 {
60 m_columnHeader = std::make_shared<ColumnVectorHeader> ();
61 m_toolWrapper = std::make_shared<ToolColumnVectorMap> (*m_columnHeader, *m_tool);
62 }
63 }
64
65
66
67 void ColumnarTestToolHandle ::
68 initialize ()
69 {
70 m_columnHeader = std::make_shared<ColumnVectorHeader> ();
71 m_toolWrapper = std::make_shared<ToolColumnVectorMap> (*m_columnHeader, *m_tool);
72 }
73
74
75
76 void ColumnarTestToolHandle ::
77 applySystematicVariation (const std::string& sysName)
78 {
79 // by convention setting a systematic on a non-systematics tool
80 // will do nothing
81 if (m_systTool == nullptr)
82 return;
83 if (!m_systTool->applySystematicVariation (CP::SystematicSet (sysName)).isSuccess())
84 throw std::runtime_error ("failed to apply systematic variation");
85 }
86
87
88
89 [[nodiscard]] std::vector<ColumnInfo> ColumnarTestToolHandle ::
90 getColumnInfo () const
91 {
92 if (!m_toolWrapper)
93 throw std::runtime_error ("tool not initialized");
94 return m_tool->getColumnInfo ();
95 }
96
97
98
99 std::vector<std::string> ColumnarTestToolHandle ::
100 getColumnNames () const
101 {
102 if (!m_toolWrapper)
103 throw std::runtime_error ("tool not initialized");
104 return m_toolWrapper->getColumnNames ();
105 }
106
107
108
109 std::vector<std::string> ColumnarTestToolHandle ::
110 getRecommendedSystematics () const
111 {
112 if (!m_systTool)
113 return {""};
114 std::vector<std::string> result;
115 for (auto& sys : CP::make_systematics_vector (m_systTool->recommendedSystematics()))
116 result.push_back (sys.name());
117 return result;
118 }
119
120
121
122 [[nodiscard]] ToolColumnVectorMap& ColumnarTestToolHandle ::
123 getToolWrapper ()
124 {
125 if (!m_toolWrapper)
126 throw std::runtime_error ("tool not initialized");
127 return *m_toolWrapper;
128 }
129
130
131
132 [[nodiscard]] const ToolColumnVectorMap& ColumnarTestToolHandle ::
133 getToolWrapper () const
134 {
135 if (!m_toolWrapper)
136 throw std::runtime_error ("tool not initialized");
137 return *m_toolWrapper;
138 }
139
140
141
142 [[nodiscard]] IColumnarTool* ColumnarTestToolHandle ::
143 getTool ()
144 {
145 return m_tool;
146 }
147
148
149
150 ColumnMapType ::
151 ColumnMapType (ColumnarTestToolHandle& val_toolHandle)
152 : m_toolHandle (&val_toolHandle), m_columnData (std::make_unique<ColumnVectorData> (&val_toolHandle.getColumnHeader()))
153 {
154 for (auto& column : m_toolHandle->getColumnInfo())
155 {
156 auto& userColumn = m_userColumns[column.name];
157 if (userColumn.info.has_value())
158 throw std::runtime_error ("column already exists: " + column.name);
159 userColumn.info = column;
160 }
161 }
162
163
164
165 void ColumnMapType ::
166 addColumn (const std::string& name, std::vector<std::any> data)
167 {
168 auto& userColumn = m_userColumns[name];
169 if (userColumn.input.has_value())
170 throw std::runtime_error ("column added twice: " + name);
171 ManualColumnData manualData {std::move (data)};
172 userColumn.input = std::move (manualData);
173 }
174
175
176
177 void ColumnMapType ::
178 setExpectation (const std::string& name, std::vector<std::any> values)
179 {
180 auto& userColumn = m_userColumns[name];
181 if (userColumn.expectation.has_value())
182 throw std::runtime_error ("column added twice: " + name);
183 ManualColumnData manualData {std::move (values)};
184 userColumn.expectation = std::move (manualData);
185 }
186
187
188
189 std::size_t ColumnMapType ::
190 columnSize (const std::string& name)
191 {
192 auto iter = m_userColumns.find (name);
193 if (iter == m_userColumns.end() || !iter->second.input.has_value())
194 throw std::runtime_error ("column not found: " + name);
195 return iter->second.input.value().columnSize ();
196 }
197
198
199
200 void ColumnMapType ::
201 connectColumnsToTool ()
202 {
203 std::vector<std::string> missingColumns;
204 for (auto& [name, userColumn] : m_userColumns)
205 {
206 if (!userColumn.info.has_value())
207 {
208 // report missing column to gtest, but continue
209 ADD_FAILURE() << "provided a column not requested by tool: " << name;
210 continue;
211 }
212 auto& columnInfo = userColumn.info.value();
213 if (!userColumn.input.has_value())
214 {
215 if (!columnInfo.isOptional)
216 {
217 // for missing non-optional inputs we need to throw, because
218 // the tool will fail otherwise. potentially we could try to
219 // fill dummy input values, but that is more complicated.
220 missingColumns.push_back (name);
221 }
222 continue;
223 }
224 auto& input = userColumn.input.value();
225 switch (columnInfo.accessMode)
226 {
230 {
231 const bool isConst = columnInfo.accessMode == ColumnAccessMode::input;
232 input.configureType (name, *columnInfo.type);
233 m_toolHandle->getToolWrapper().setColumnVoid (*m_columnData, name, input.columnSize(), input.columnVoidData(), *columnInfo.type, isConst);
234 }
235 break;
236 default:
237 throw std::runtime_error ("column mode unknown: " + columnInfo.name);
238 }
239 }
240 if (!missingColumns.empty())
241 {
242 std::string message = "missing input columns:";
243 for (auto& column : missingColumns)
244 message += " " + column;
245 throw std::runtime_error (message);
246 }
247 }
248
249
250
251 void ColumnMapType ::
252 call ()
253 {
254 m_columnData->checkData ();
255 m_columnData->callNoCheck (*m_toolHandle->getTool());
256 }
257
258
259
260 void ColumnMapType ::
261 checkExpectations ()
262 {
263 for (auto& [columnName, userColumn] : m_userColumns)
264 {
265 if (!userColumn.info.has_value())
266 continue;
267 auto& info = userColumn.info.value();
268 if (info.accessMode == ColumnAccessMode::input)
269 {
270 if (userColumn.expectation.has_value())
271 ADD_FAILURE() << "expectation provided for input-only column: " << columnName;
272 continue;
273 }
274 if (!userColumn.input.has_value())
275 {
276 if (info.isOptional)
277 {
278 if (userColumn.expectation.has_value())
279 ADD_FAILURE() << "expectation provided for omitted column: " << columnName;
280 continue;
281 }
282 throw std::logic_error ("output column does not exist: " + columnName);
283 }
284 auto& output = userColumn.input.value();
285
286 if (!userColumn.expectation.has_value())
287 {
288 ADD_FAILURE() << "no expectation provided for output column: " << columnName;
289 } else
290 {
291 auto& expectation = userColumn.expectation.value();
292 expectation.configureType (columnName, *info.type);
293 TestUtils::checkExpectation (columnName, *output.type(), output.columnSize(), output.columnVoidData(), *expectation.type(), expectation.columnSize(), expectation.columnVoidData());
294 }
295 TestUtils::printExpectedOutput (columnName, *output.type(), output.columnSize(), output.columnVoidData());
296 }
297 }
298 }
299}
Interface for all CP tools supporting systematic variations.
Class to wrap a set of SystematicVariations.
Base class for the dual-use tool implementation classes.
Definition AsgTool.h:47
a class that holds the columnar data for a single call
an interface for tools that operate on columnar data
a handle to a columnar tool for running tests
std::shared_ptr< ColumnVectorHeader > m_columnHeader
std::shared_ptr< ToolColumnVectorMap > m_toolWrapper
a class that holds manually specified column data
a class that interfaces an IColumnarTool to a ColumnVectorHeader
std::vector< CP::SystematicSet > make_systematics_vector(const SystematicSet &systematics)
utility functions for working with systematics
void checkExpectation(const std::string &columnName, const std::type_info &outputType, std::size_t outputSize, const void *outputData, const std::type_info &expectationType, std::size_t expectationSize, const void *expectationData)
void printExpectedOutput(const std::string &columnName, const std::type_info &outputType, std::size_t outputSize, const void *outputData)
@ update
an updateable column
Definition ColumnInfo.h:28
@ output
an output column
Definition ColumnInfo.h:25
@ input
an input column
Definition ColumnInfo.h:22
void renameContainers(IColumnarTool &tool, const std::vector< std::pair< std::string, std::string > > &renames)
rename containers in the columnar tool
Definition index.py:1
STL namespace.
ColumnarTestToolHandle * m_toolHandle
std::unique_ptr< ColumnVectorData > m_columnData
std::unordered_map< std::string, MyColumnData > m_userColumns