Project
Loading...
Searching...
No Matches
testConfigurableParam.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#include <boost/test/tools/old/interface.hpp>
13#include <stdexcept>
14#define BOOST_TEST_MODULE Test ConfigurableParams
15#define BOOST_TEST_MAIN
16#define BOOST_TEST_DYN_LINK
17
18#include <boost/test/unit_test.hpp>
19#include <boost/property_tree/ptree.hpp>
20#include <cstdlib>
21#include <deque>
22#include <filesystem>
23#include <list>
24#include <set>
25#include <unordered_set>
26#include <vector>
27
29
30using namespace o2::conf;
31using namespace o2::conf::test;
32
33BOOST_AUTO_TEST_CASE(ConfigurableParam_Basic)
34{
35 // Tests the default parameters and also getter helpers.
36 auto& param = TestParam::Instance();
37 BOOST_CHECK_EQUAL(param.iValue, 42);
38 BOOST_CHECK_EQUAL(param.dValue, 3.14);
39 BOOST_CHECK_EQUAL(param.bValue, true);
40 BOOST_CHECK_EQUAL(param.sValue, "default");
41 BOOST_CHECK_EQUAL(static_cast<int>(param.eValue), 2);
42
43 BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<int>("TestParam.iValue"), 42);
44 BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<double>("TestParam.dValue"), 3.14);
45 BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<bool>("TestParam.bValue"), true);
46 BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<std::string>("TestParam.sValue"), "default");
47}
48
49BOOST_AUTO_TEST_CASE(ConfigurableParam_SG_Fundamental)
50{
51 // tests runtime setting and getting for fundamental types
52 ConfigurableParam::setValue("TestParam.iValue", "100");
53 ConfigurableParam::setValue("TestParam.dValue", "2.718");
54 ConfigurableParam::setValue("TestParam.bValue", "0");
55 ConfigurableParam::setValue("TestParam.sValue", "modified");
56 ConfigurableParam::setValue("TestParam.eValue", "0");
57
58 auto& param = TestParam::Instance();
59 BOOST_CHECK_EQUAL(param.iValue, 100);
60 BOOST_CHECK_EQUAL(param.dValue, 2.718);
61 BOOST_CHECK_EQUAL(param.bValue, false);
62 BOOST_CHECK_EQUAL(param.sValue, "modified");
63 BOOST_CHECK_EQUAL(static_cast<int>(param.eValue), 0);
64}
65
66BOOST_AUTO_TEST_CASE(ConfigurableParam_SG_CArray)
67{
68 // tests setting and getting for a c-style array type
69 auto& param = TestParam::Instance();
70 BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<int>("TestParam.caValue[0]"), 0);
71 BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<int>("TestParam.caValue[1]"), 1);
72 BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<int>("TestParam.caValue[2]"), 2);
73
74 ConfigurableParam::setValue("TestParam.caValue[1]", "99");
75 BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<int>("TestParam.caValue[1]"), 99);
76}
77
78BOOST_AUTO_TEST_CASE(ConfigurableParam_SG_STD)
79{
80 // tests setting and getting for a std type
81 ConfigurableParam::setValue("TestParam.vec", "[10,20,30,40]");
82 auto& param = TestParam::Instance();
83 BOOST_CHECK_EQUAL(param.vec.size(), 4);
84 BOOST_CHECK_EQUAL(param.vec[0], 10);
85 BOOST_CHECK_EQUAL(param.vec[1], 20);
86 BOOST_CHECK_EQUAL(param.vec[2], 30);
87 BOOST_CHECK_EQUAL(param.vec[3], 40);
88 BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<std::string>("TestParam.vec"), "[10,20,30,40]");
89
90 ConfigurableParam::setValue("TestParam.u8vec", "[1,2,255]");
91 BOOST_CHECK_EQUAL(param.u8vec.size(), 3);
92 BOOST_CHECK_EQUAL(static_cast<unsigned int>(param.u8vec[0]), 1);
93 BOOST_CHECK_EQUAL(static_cast<unsigned int>(param.u8vec[1]), 2);
94 BOOST_CHECK_EQUAL(static_cast<unsigned int>(param.u8vec[2]), 255);
95 BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<std::string>("TestParam.u8vec"), "[1,2,255]");
96
97 ConfigurableParam::setValues({{"TestParam.map", "{0:1,10:42}"}});
98 BOOST_CHECK_EQUAL(param.map.size(), 2);
99 BOOST_CHECK(param.map.contains(0));
100 BOOST_CHECK_EQUAL(param.map.at(0), 1);
101 BOOST_CHECK(param.map.contains(10));
102 BOOST_CHECK_EQUAL(param.map.at(10), 42);
103 BOOST_CHECK_THROW(param.map.at(33), std::out_of_range);
104}
105
106BOOST_AUTO_TEST_CASE(ConfigurableParam_Provenance)
107{
108 // tests correct setting of provenance
109 BOOST_CHECK_EQUAL(ConfigurableParam::getProvenance("TestParam.iValueProvenanceTest"), ConfigurableParam::EParamProvenance::kCODE);
110 ConfigurableParam::setValue("TestParam.iValueProvenanceTest", "123");
111 BOOST_CHECK_EQUAL(ConfigurableParam::getProvenance("TestParam.iValueProvenanceTest"), ConfigurableParam::EParamProvenance::kRT);
112}
113
114BOOST_AUTO_TEST_CASE(ConfigurableParam_FileIO_Ini)
115{
116 // test for ini file serialization
117 const std::string testFileName = "test_config.ini";
118 auto iValueBefore = TestParam::Instance().iValue;
119 auto sValueBefore = TestParam::Instance().sValue;
120 ConfigurableParam::setValue("TestParam.vec", "[7,8]");
121 const std::vector<int> vecBefore = TestParam::Instance().vec;
122 ConfigurableParam::writeINI(testFileName);
123 ConfigurableParam::setValue("TestParam.iValue", "999");
124 ConfigurableParam::setValue("TestParam.sValue", testFileName);
125 ConfigurableParam::setValue("TestParam.vec", "[1]");
127 BOOST_CHECK_EQUAL(TestParam::Instance().iValue, iValueBefore);
128 BOOST_CHECK_EQUAL(TestParam::Instance().sValue, sValueBefore);
129 BOOST_CHECK_EQUAL_COLLECTIONS(TestParam::Instance().vec.begin(), TestParam::Instance().vec.end(), vecBefore.begin(), vecBefore.end());
130 std::remove(testFileName.c_str());
131}
132
133BOOST_AUTO_TEST_CASE(ConfigurableParam_FileIO_Json)
134{
135 // test for json file serialization
136 const std::string testFileName = "test_config.json";
137 auto iValueBefore = TestParam::Instance().iValue;
138 auto sValueBefore = TestParam::Instance().sValue;
139 ConfigurableParam::setValues({{"TestParam.map", "{3:4,5:6}"}});
140 const std::map<int, unsigned int> mapBefore = TestParam::Instance().map;
141 ConfigurableParam::writeJSON(testFileName);
142 ConfigurableParam::setValue("TestParam.iValue", "999");
143 ConfigurableParam::setValue("TestParam.sValue", testFileName);
144 ConfigurableParam::setValues({{"TestParam.map", "{1:2}"}});
146 BOOST_CHECK_EQUAL(TestParam::Instance().iValue, iValueBefore);
147 BOOST_CHECK_EQUAL(TestParam::Instance().sValue, sValueBefore);
148 BOOST_CHECK_EQUAL(TestParam::Instance().map.size(), mapBefore.size());
149 BOOST_CHECK_EQUAL(TestParam::Instance().map.at(3), mapBefore.at(3));
150 BOOST_CHECK_EQUAL(TestParam::Instance().map.at(5), mapBefore.at(5));
151 std::remove(testFileName.c_str());
152}
153
154BOOST_AUTO_TEST_CASE(ConfigurableParam_FileIO_ROOT)
155{
156 // test for root file serialization
157 const std::string testFileName = "test_config.root";
158 auto iValueBefore = TestParam::Instance().iValue;
159 auto sValueBefore = TestParam::Instance().sValue;
160 TFile* testFile = TFile::Open(testFileName.c_str(), "RECREATE");
161 TestParam::Instance().serializeTo(testFile);
162 testFile->Close();
163 ConfigurableParam::setValue("TestParam.iValue", "999");
164 ConfigurableParam::setValue("TestParam.sValue", testFileName);
165 ConfigurableParam::fromCCDB(testFileName);
166 BOOST_CHECK_EQUAL(TestParam::Instance().iValue, iValueBefore);
167 BOOST_CHECK_EQUAL(TestParam::Instance().sValue, sValueBefore);
168 std::remove(testFileName.c_str());
169}
170
171BOOST_AUTO_TEST_CASE(ConfigurableParam_Cli)
172{
173 // test setting values from as a cli arg string
174 ConfigurableParam::updateFromString("TestParam.iValue=55;TestParam.sValue=cli");
175 BOOST_CHECK_EQUAL(TestParam::Instance().iValue, 55);
176 BOOST_CHECK_EQUAL(TestParam::Instance().sValue, "cli");
177}
178
179BOOST_AUTO_TEST_CASE(ConfigurableParam_LiteralSuffix)
180{
181 // test setting values with the correct literal suffix
182 ConfigurableParam::updateFromString("TestParam.fValue=42.f");
183 BOOST_CHECK_EQUAL(TestParam::Instance().fValue, 42.f);
184
185 ConfigurableParam::setValue("TestParam.ullValue", "999ull");
186 BOOST_CHECK_EQUAL(TestParam::Instance().ullValue, 999ULL);
187 // check using wrong literal suffix fails, prints error to std
188 ConfigurableParam::setValue("TestParam.ullValue", "888u");
189 BOOST_CHECK_NE(TestParam::Instance().ullValue, 888);
190}
191
192BOOST_AUTO_TEST_CASE(ConfigurableParam_ContainerParserVector)
193{
194 auto v = ContainerParser::parse<std::vector<int>>("[1,2,3,4,5]");
195 BOOST_CHECK_EQUAL(v.size(), 5);
196 BOOST_CHECK_EQUAL(v[0], 1);
197 BOOST_CHECK_EQUAL(v[4], 5);
198}
199
200BOOST_AUTO_TEST_CASE(ConfigurableParam_ContainerParserMap)
201{
202 auto m = ContainerParser::parse<std::map<std::string, double>>("{alpha:0.5,beta:0.3,gamma:0.2}");
203 BOOST_CHECK_EQUAL(m.size(), 3);
204 BOOST_CHECK_EQUAL(m["alpha"], 0.5);
205 BOOST_CHECK_EQUAL(m["beta"], 0.3);
206}
207
208BOOST_AUTO_TEST_CASE(ConfigurableParam_ContainerParserSetAndSequenceTypes)
209{
210 // All non-map containers go through the single parseSequence path. Verify the
211 // set containers (which previously took a separate, doubly-parsing parseSet
212 // branch) still parse and de-duplicate correctly.
213 auto se = ContainerParser::parse<std::set<int>>("[2,3,2,3,2,5]");
214 BOOST_CHECK_EQUAL(se.size(), 3);
215 BOOST_CHECK(se == (std::set<int>{2, 3, 5}));
216
217 auto us = ContainerParser::parse<std::unordered_set<int>>("[1,2,3,3]");
218 BOOST_CHECK_EQUAL(us.size(), 3);
219 BOOST_CHECK(us.count(1) && us.count(2) && us.count(3));
220
221 auto li = ContainerParser::parse<std::list<int>>("[7,8]");
222 BOOST_CHECK(li == (std::list<int>{7, 8}));
223
224 auto dq = ContainerParser::parse<std::deque<int>>("[9,10]");
225 BOOST_CHECK(dq == (std::deque<int>{9, 10}));
226}
227
228BOOST_AUTO_TEST_CASE(ConfigurableParam_ContainerParserRejectsEmptyToken)
229{
230 // A stray delimiter must be reported, not silently swallowed: "[1,,3]" used to
231 // parse to a 2-element vector with no error, masking malformed configuration.
232 BOOST_CHECK_THROW(ContainerParser::parse<std::vector<int>>("[1,,3]"), std::exception);
233 BOOST_CHECK_THROW(ContainerParser::parse<std::vector<int>>("[1,2,]"), std::exception);
234 // ... and on the map side, an empty value/entry is rejected too.
235 BOOST_CHECK_THROW((ContainerParser::parse<std::map<int, int>>("{1:2,,3:4}")), std::exception);
236 BOOST_CHECK_THROW((ContainerParser::parse<std::map<int, int>>("{1:}")), std::exception);
237 // Well-formed input is unaffected.
238 auto v = ContainerParser::parse<std::vector<int>>("[1,2,3]");
239 BOOST_CHECK_EQUAL(v.size(), 3);
240}
241
242BOOST_AUTO_TEST_CASE(ConfigurableParam_DamerauLevenshteinDistance)
243{
244 BOOST_CHECK_EQUAL(damerauLevenshteinDistance("TestParam.iValue", "TestParam.iValue"), 0);
245 BOOST_CHECK_EQUAL(damerauLevenshteinDistance("TestParam.iValu", "TestParam.iValue"), 1);
246 BOOST_CHECK_EQUAL(damerauLevenshteinDistance("TestParam.jValue", "TestParam.iValue"), 1);
247 BOOST_CHECK_EQUAL(damerauLevenshteinDistance("TestParam.iVaule", "TestParam.iValue"), 1);
248}
249
250BOOST_AUTO_TEST_CASE(ConfigurableParam_UnknownKeySuggestionsNonFatal)
251{
252 setenv("ALICEO2_CONFIGURABLEPARAM_WRONGKEYISNONFATAL", "1", 1);
253 ConfigurableParam::setValue("TestParam.iValue", "222");
254 ConfigurableParam::setValue("TestParam.caValue[1]", "33");
255 ConfigurableParam::setValues({{"TestParam.iValu", "777"},
256 {"TstParam.iValue", "888"},
257 {"TestParam.caValue[", "999"}});
258 BOOST_CHECK_EQUAL(TestParam::Instance().iValue, 222);
259 BOOST_CHECK_EQUAL(TestParam::Instance().caValue[1], 33);
260 unsetenv("ALICEO2_CONFIGURABLEPARAM_WRONGKEYISNONFATAL");
261}
262
263BOOST_AUTO_TEST_CASE(ConfigurableParam_Container_FileIO_ROOT)
264{
265 // test for root file serialization
266 const std::string testFileName = "test_config.root";
267 TFile* testFile = TFile::Open(testFileName.c_str(), "RECREATE");
268 ConfigurableParam::setValue("TestParam.vec", "[1,2,3]");
269 ConfigurableParam::setValue("TestParam.u8vec", "[4,5,6]");
270 ConfigurableParam::setValue("TestParam.map", "{1:16,2:9,3:23456}");
271 ConfigurableParam::setValue("TestParam.smap", "{a:16,b:9,c:23456}");
272 ConfigurableParam::setValue("TestParam.set", "[2,3,2,3,2,5]");
273 TestParam::Instance().serializeTo(testFile);
274 testFile->Close();
275 ConfigurableParam::setValue("TestParam.vec", "[9]");
276 ConfigurableParam::fromCCDB(testFileName);
277 const auto& tp = TestParam::Instance();
278 const std::vector<int> v = {1, 2, 3};
279 BOOST_CHECK_EQUAL_COLLECTIONS(tp.vec.begin(), tp.vec.end(), v.begin(), v.end());
280 const std::vector<uint8_t> v8 = {4, 5, 6};
281 BOOST_CHECK_EQUAL_COLLECTIONS(tp.u8vec.begin(), tp.u8vec.end(), v8.begin(), v8.end());
282 std::map<int, uint32_t> map{{1, 16}, {2, 9}, {3, 23456}};
283 auto testMapEqual = [](const auto& m1, const auto& m2) {
284 for (const auto& [k, v] : m1) {
285 BOOST_CHECK(m2.find(k) != m2.end());
286 BOOST_CHECK_EQUAL(v, m2.at(k));
287 }
288 };
289 testMapEqual(map, tp.map);
290 std::map<std::string, uint32_t> smap{{"a", 16}, {"b", 9}, {"c", 23456}};
291 testMapEqual(smap, tp.smap);
292 std::set<uint16_t> set{2, 3, 5};
293 BOOST_CHECK_EQUAL(set.size(), tp.set.size());
294 for (const auto& s : set) {
295 BOOST_CHECK(tp.set.contains(s));
296 }
297 std::remove(testFileName.c_str());
298}
static void writeINI(std::string const &filename, std::string const &keyOnly="")
static void setValues(std::vector< std::pair< std::string, std::string > > const &keyValues)
static void updateFromFile(std::string const &, std::string const &paramsList="", bool unchangedOnly=false)
static void setValue(std::string const &mainkey, std::string const &subkey, T x)
static EParamProvenance getProvenance(const std::string &key)
static void writeJSON(std::string const &filename, std::string const &keyOnly="")
static void fromCCDB(std::string filename)
static void updateFromString(std::string const &)
static T parse(const std::string &str)
const GLfloat * m
Definition glcorearb.h:4066
const GLdouble * v
Definition glcorearb.h:832
GLenum GLfloat param
Definition glcorearb.h:271
std::size_t damerauLevenshteinDistance(std::string_view a, std::string_view b)
BOOST_AUTO_TEST_CASE(ConfigurableParam_Basic)
std::vector< o2::ctf::BufferType > vec
BOOST_CHECK(tree)
BOOST_CHECK_EQUAL(triggersD.size(), triggers.size())