Skip to content

Commit 93ba0a8

Browse files
Adding unit test for DeviceSpecHelpers
Testing the forwarding of execution options
1 parent 0df2864 commit 93ba0a8

File tree

2 files changed

+179
-0
lines changed

2 files changed

+179
-0
lines changed

Framework/Core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ set(TEST_SRCS
254254
test/test_TypeTraits.cxx
255255
test/test_Variants.cxx
256256
test/test_WorkflowHelpers.cxx
257+
test/test_DeviceSpecHelpers.cxx
257258
)
258259

259260
set(BENCH_SRCS
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
// Copyright CERN and copyright holders of ALICE O2. This software is
2+
// distributed under the terms of the GNU General Public License v3 (GPL
3+
// Version 3), copied verbatim in the file "COPYING".
4+
//
5+
// See http://alice-o2.web.cern.ch/license for full licensing information.
6+
//
7+
// In applying this license CERN does not waive the privileges and immunities
8+
// granted to it by virtue of its status as an Intergovernmental Organization
9+
// or submit itself to any jurisdiction.
10+
#define BOOST_TEST_MODULE Test Framework DeviceSpecHelpers
11+
#define BOOST_TEST_MAIN
12+
#define BOOST_TEST_DYN_LINK
13+
14+
#include "Framework/WorkflowSpec.h"
15+
#include "Framework/DataProcessorSpec.h"
16+
#include "Framework/DeviceExecution.h"
17+
#include "../src/DeviceSpecHelpers.h"
18+
#include <boost/test/unit_test.hpp>
19+
#include <boost/test/tools/detail/per_element_manip.hpp>
20+
#include <algorithm>
21+
#include <sstream>
22+
#include <cstring>
23+
#include <vector>
24+
#include <map>
25+
#include "../src/SimpleResourceManager.h"
26+
27+
namespace o2
28+
{
29+
namespace framework
30+
{
31+
32+
using CheckMatrix = std::map<std::string, std::vector<std::pair<std::string, std::string>>>;
33+
34+
// search for an option in the device execution
35+
bool search(DeviceExecution const& execution, std::string const& option, std::string const& argument)
36+
{
37+
bool foundOption = false;
38+
for (auto const& execArg : execution.args) {
39+
if (execArg == nullptr) {
40+
break;
41+
}
42+
if (!foundOption) {
43+
foundOption = option == execArg;
44+
} else if (argument == execArg) {
45+
return true;
46+
} else {
47+
// the required argument to the option is not found
48+
foundOption = false;
49+
}
50+
}
51+
return false;
52+
}
53+
54+
// create the device execution from the device specs and process the command line arguments
55+
// the check matrix contains a map of options to be founf per processor
56+
void check(const std::vector<std::string>& arguments,
57+
const std::vector<ConfigParamSpec>& workflowOptions,
58+
const std::vector<DeviceSpec>& deviceSpecs,
59+
CheckMatrix& matrix)
60+
{
61+
std::stringstream output;
62+
std::vector<char*> argv;
63+
argv.push_back(strdup("executable-name"));
64+
for (auto const& arg : arguments) {
65+
output << " " << arg;
66+
argv.push_back(strdup(arg.c_str()));
67+
}
68+
std::cout << "checking for arguments: " << output.str() << std::endl;
69+
70+
std::vector<DeviceExecution> deviceExecutions(deviceSpecs.size());
71+
std::vector<DeviceControl> deviceControls(deviceSpecs.size());
72+
DeviceSpecHelpers::prepareArguments(argv.size(), argv.data(), true, true,
73+
deviceSpecs,
74+
workflowOptions,
75+
deviceExecutions,
76+
deviceControls);
77+
78+
std::cout << "created execution for " << deviceSpecs.size() << " device(s)" << std::endl;
79+
80+
for (size_t index = 0; index < deviceSpecs.size(); index++) {
81+
const auto& deviceSpec = deviceSpecs[index];
82+
const auto& deviceExecution = deviceExecutions[index];
83+
std::cout << deviceSpec.name << std::endl;
84+
std::stringstream execArgs;
85+
for (const auto& arg : deviceExecution.args) {
86+
if (arg == nullptr) {
87+
// the nullptr terminates the argument list
88+
break;
89+
}
90+
execArgs << " " << arg;
91+
}
92+
std::cout << execArgs.str() << std::endl;
93+
for (auto const& testCase : matrix[deviceSpec.name]) {
94+
BOOST_TEST_INFO(std::string("can not find option: ") + testCase.first + " " + testCase.second);
95+
BOOST_CHECK(search(deviceExecution, testCase.first, testCase.second));
96+
}
97+
}
98+
for (auto arg : argv) {
99+
free(arg);
100+
}
101+
}
102+
103+
BOOST_AUTO_TEST_CASE(test_prepareArguments)
104+
{
105+
std::vector<ConfigParamSpec> workflowOptions{
106+
{ "foo", VariantType::String, "bar", { "the famous foo option" } },
107+
{ "depth", VariantType::Int, 1, { "number of processors" } },
108+
};
109+
110+
auto algorithm = [](ProcessingContext& ctx) {};
111+
112+
WorkflowSpec workflow{
113+
{ "processor0",
114+
{},
115+
{ OutputSpec{ { "output" }, "TST", "DUMMYDATA", 0, Lifetime::Timeframe } },
116+
AlgorithmSpec(algorithm),
117+
Options{
118+
{ "mode", VariantType::String, "default", { "The Mode" } },
119+
} },
120+
{ "processor1",
121+
{ InputSpec{ "input", "TST", "DUMMYDATA", 0, Lifetime::Timeframe } },
122+
{},
123+
AlgorithmSpec(algorithm),
124+
Options{
125+
{ "mode", VariantType::String, "default", { "The Mode" } },
126+
} },
127+
};
128+
129+
std::vector<DeviceSpec> deviceSpecs;
130+
131+
auto resourceManager = std::make_unique<SimpleResourceManager>(42000, 100);
132+
auto resources = resourceManager->getAvailableResources();
133+
134+
DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(workflow,
135+
ChannelConfigurationPolicy::createDefaultPolicies(),
136+
CompletionPolicy::createDefaultPolicies(),
137+
deviceSpecs,
138+
resources);
139+
140+
// Now doing the test cases
141+
CheckMatrix matrix;
142+
143+
// checking with empty command line arguments, all processors must have the options with
144+
// default arguments
145+
matrix["processor0"] = { { "--depth", "1" }, { "--foo", "bar" }, { "--mode", "default" } };
146+
matrix["processor1"] = matrix["processor0"];
147+
check({}, workflowOptions, deviceSpecs, matrix);
148+
149+
// checking with unknown arguments, silently ignored, same test matrix
150+
check({ "--unknown", "option" }, workflowOptions, deviceSpecs, matrix);
151+
152+
// configuring mode, both devices must have the option set
153+
matrix["processor0"] = { { "--depth", "1" }, { "--foo", "bar" }, { "--mode", "silly" } };
154+
matrix["processor1"] = matrix["processor0"];
155+
check({ "--mode", "silly" }, workflowOptions, deviceSpecs, matrix);
156+
157+
// configuring option group, only processor0 must have the option set, processor1 default
158+
matrix["processor0"] = { { "--depth", "1" }, { "--foo", "bar" }, { "--mode", "silly" } };
159+
matrix["processor1"] = { { "--depth", "1" }, { "--foo", "bar" }, { "--mode", "default" } };
160+
check({ "--processor0", "--mode silly" }, workflowOptions, deviceSpecs, matrix);
161+
162+
// processor0 must have the mode set to silly via option group, processor1 advanced from the argument
163+
matrix["processor0"] = { { "--depth", "1" }, { "--foo", "bar" }, { "--mode", "silly" } };
164+
matrix["processor1"] = { { "--depth", "1" }, { "--foo", "bar" }, { "--mode", "advanced" } };
165+
check({ "--mode", "advanced", "--processor0", "--mode silly" }, workflowOptions, deviceSpecs, matrix);
166+
167+
// both devices have the workflow option propagated, others defaulted
168+
matrix["processor0"] = { { "--depth", "2" }, { "--foo", "bar" }, { "--mode", "default" } };
169+
matrix["processor1"] = matrix["processor0"];
170+
check({ "--depth", "2" }, workflowOptions, deviceSpecs, matrix);
171+
172+
// both devices have the workflow option propagated, processor0 mode silly via option group
173+
matrix["processor0"] = { { "--depth", "2" }, { "--foo", "bar" }, { "--mode", "silly" } };
174+
matrix["processor1"] = { { "--depth", "2" }, { "--foo", "bar" }, { "--mode", "default" } };
175+
check({ "--depth", "2", "--processor0", "--mode silly" }, workflowOptions, deviceSpecs, matrix);
176+
}
177+
}
178+
}

0 commit comments

Comments
 (0)