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 bool ColumnarMemoryTest ::
42 checkMode ()
43 {
44 return std::is_same_v<ColumnarModeDefault,ColumnarModeArray>;
45 }
46
47
48
49 namespace TestUtils
50 {
51 ColumnarTestToolHandle ::
52 ColumnarTestToolHandle (asg::AsgTool& val_tool)
53 {
54 m_tool = dynamic_cast<IColumnarTool*> (&val_tool);
55 if (m_tool == nullptr)
56 throw std::runtime_error ("tool does not implement IColumnarTool");
57 m_systTool = dynamic_cast<CP::ISystematicsTool*> (m_tool);
58 }
59
60
61
62 void ColumnarTestToolHandle ::
63 renameContainers (const std::vector<std::pair<std::string,std::string>>& renames)
64 {
66 if (m_toolWrapper)
67 {
68 m_columnHeader = std::make_shared<ColumnVectorHeader> ();
69 m_toolWrapper = std::make_shared<ToolColumnVectorMap> (*m_columnHeader, *m_tool);
70 }
71 }
72
73
74
75 void ColumnarTestToolHandle ::
76 initialize ()
77 {
78 m_columnHeader = std::make_shared<ColumnVectorHeader> ();
79 m_toolWrapper = std::make_shared<ToolColumnVectorMap> (*m_columnHeader, *m_tool);
80 }
81
82
83
84 void ColumnarTestToolHandle ::
85 applySystematicVariation (const std::string& sysName)
86 {
87 // by convention setting a systematic on a non-systematics tool
88 // will do nothing
89 if (m_systTool == nullptr)
90 return;
91 if (!m_systTool->applySystematicVariation (CP::SystematicSet (sysName)).isSuccess())
92 throw std::runtime_error ("failed to apply systematic variation");
93 }
94
95
96
97 [[nodiscard]] std::vector<ColumnInfo> ColumnarTestToolHandle ::
98 getColumnInfo () const
99 {
100 if (!m_toolWrapper)
101 throw std::runtime_error ("tool not initialized");
102 return m_tool->getColumnInfo ();
103 }
104
105
106
107 std::vector<std::string> ColumnarTestToolHandle ::
108 getColumnNames () const
109 {
110 if (!m_toolWrapper)
111 throw std::runtime_error ("tool not initialized");
112 return m_toolWrapper->getColumnNames ();
113 }
114
115
116
117 std::vector<std::string> ColumnarTestToolHandle ::
118 getRecommendedSystematics () const
119 {
120 if (!m_systTool)
121 return {""};
122 std::vector<std::string> result;
123 for (auto& sys : CP::make_systematics_vector (m_systTool->recommendedSystematics()))
124 result.push_back (sys.name());
125 return result;
126 }
127
128
129
130 [[nodiscard]] ToolColumnVectorMap& ColumnarTestToolHandle ::
131 getToolWrapper ()
132 {
133 if (!m_toolWrapper)
134 throw std::runtime_error ("tool not initialized");
135 return *m_toolWrapper;
136 }
137
138
139
140 [[nodiscard]] const ToolColumnVectorMap& ColumnarTestToolHandle ::
141 getToolWrapper () const
142 {
143 if (!m_toolWrapper)
144 throw std::runtime_error ("tool not initialized");
145 return *m_toolWrapper;
146 }
147
148
149
150 [[nodiscard]] IColumnarTool* ColumnarTestToolHandle ::
151 getTool ()
152 {
153 return m_tool;
154 }
155
156
157
158 ColumnMapType ::
159 ColumnMapType (ColumnarTestToolHandle& val_toolHandle)
160 : m_toolHandle (&val_toolHandle), m_columnData (std::make_unique<ColumnVectorData> (&val_toolHandle.getColumnHeader()))
161 {
162 for (auto& column : m_toolHandle->getColumnInfo())
163 {
164 auto& userColumn = m_userColumns[column.name];
165 if (userColumn.info.has_value())
166 throw std::runtime_error ("column already exists: " + column.name);
167 userColumn.info = column;
168 }
169 }
170
171
172
173 void ColumnMapType ::
174 addColumn (const std::string& name, std::vector<std::any> data)
175 {
176 auto& userColumn = m_userColumns[name];
177 if (userColumn.input.has_value())
178 throw std::runtime_error ("column added twice: " + name);
179 ManualColumnData manualData {std::move (data)};
180 userColumn.input = std::move (manualData);
181 }
182
183
184
185 void ColumnMapType ::
186 setExpectation (const std::string& name, std::vector<std::any> values)
187 {
188 auto& userColumn = m_userColumns[name];
189 if (userColumn.expectation.has_value())
190 throw std::runtime_error ("column added twice: " + name);
191 ManualColumnData manualData {std::move (values)};
192 userColumn.expectation = std::move (manualData);
193 }
194
195
196
197 std::size_t ColumnMapType ::
198 columnSize (const std::string& name)
199 {
200 auto iter = m_userColumns.find (name);
201 if (iter == m_userColumns.end() || !iter->second.input.has_value())
202 throw std::runtime_error ("column not found: " + name);
203 return iter->second.input.value().columnSize ();
204 }
205
206
207
208 void ColumnMapType ::
209 connectColumnsToTool ()
210 {
211 std::vector<std::string> missingColumns;
212 for (auto& [name, userColumn] : m_userColumns)
213 {
214 if (!userColumn.info.has_value())
215 {
216 // report missing column to gtest, but continue
217 ADD_FAILURE() << "provided a column not requested by tool: " << name;
218 continue;
219 }
220 auto& columnInfo = userColumn.info.value();
221 if (!userColumn.input.has_value())
222 {
223 if (!columnInfo.isOptional)
224 {
225 // for missing non-optional inputs we need to throw, because
226 // the tool will fail otherwise. potentially we could try to
227 // fill dummy input values, but that is more complicated.
228 missingColumns.push_back (name);
229 }
230 continue;
231 }
232 auto& input = userColumn.input.value();
233 switch (columnInfo.accessMode)
234 {
238 {
239 const bool isConst = columnInfo.accessMode == ColumnAccessMode::input;
240 input.configureType (name, *columnInfo.type);
241 m_toolHandle->getToolWrapper().setColumnVoid (*m_columnData, name, input.columnSize(), input.columnVoidData(), *columnInfo.type, isConst);
242 }
243 break;
244 default:
245 throw std::runtime_error ("column mode unknown: " + columnInfo.name);
246 }
247 }
248 if (!missingColumns.empty())
249 {
250 std::string message = "missing input columns:";
251 for (auto& column : missingColumns)
252 message += " " + column;
253 throw std::runtime_error (message);
254 }
255 }
256
257
258
259 void ColumnMapType ::
260 call ()
261 {
262 m_columnData->checkData ();
263 m_columnData->callNoCheck (*m_toolHandle->getTool());
264 }
265
266
267
268 void ColumnMapType ::
269 checkExpectations ()
270 {
271 for (auto& [columnName, userColumn] : m_userColumns)
272 {
273 if (!userColumn.info.has_value())
274 continue;
275 auto& info = userColumn.info.value();
276 if (info.accessMode == ColumnAccessMode::input)
277 {
278 if (userColumn.expectation.has_value())
279 ADD_FAILURE() << "expectation provided for input-only column: " << columnName;
280 continue;
281 }
282 if (!userColumn.input.has_value())
283 {
284 if (info.isOptional)
285 {
286 if (userColumn.expectation.has_value())
287 ADD_FAILURE() << "expectation provided for omitted column: " << columnName;
288 continue;
289 }
290 throw std::logic_error ("output column does not exist: " + columnName);
291 }
292 auto& output = userColumn.input.value();
293
294 if (!userColumn.expectation.has_value())
295 {
296 ADD_FAILURE() << "no expectation provided for output column: " << columnName;
297 } else
298 {
299 auto& expectation = userColumn.expectation.value();
300 expectation.configureType (columnName, *info.type);
301 TestUtils::checkExpectation (columnName, *output.type(), output.columnSize(), output.columnVoidData(), *expectation.type(), expectation.columnSize(), expectation.columnVoidData());
302 }
303 TestUtils::printExpectedOutput (columnName, *output.type(), output.columnSize(), output.columnVoidData());
304 }
305 }
306 }
307}
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
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:27
@ output
an output column
Definition ColumnInfo.h:24
@ input
an input column
Definition ColumnInfo.h:21
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