Skip to content

Commit cec632f

Browse files
f3schsawenzel
authored andcommitted
Common: allow literal suffix and add tests for confkey
Signed-off-by: Felix Schlepper <felix.schlepper@cern.ch>
1 parent c864689 commit cec632f

File tree

6 files changed

+297
-4
lines changed

6 files changed

+297
-4
lines changed

Common/Utils/CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ o2_target_root_dictionary(CommonUtils
5151
include/CommonUtils/IRFrameSelector.h
5252
include/CommonUtils/DebugStreamer.h)
5353

54+
# Extra dictionaries only needed if tests are built
55+
if(BUILD_TESTING)
56+
o2_add_library(CommonUtilsTest
57+
SOURCES src/ConfigurableParamTest.cxx
58+
PUBLIC_LINK_LIBRARIES O2::CommonUtils)
59+
o2_target_root_dictionary(CommonUtilsTest
60+
HEADERS include/CommonUtils/ConfigurableParamTest.h)
61+
endif()
62+
5463
o2_add_test(TreeStream
5564
COMPONENT_NAME CommonUtils
5665
LABELS utils
@@ -87,6 +96,12 @@ o2_add_test(EnumFlags
8796
SOURCES test/testEnumFlags.cxx
8897
PUBLIC_LINK_LIBRARIES O2::CommonUtils)
8998

99+
o2_add_test(ConfigurableParam
100+
COMPONENT_NAME CommonUtils
101+
LABELS utils
102+
SOURCES test/testConfigurableParam.cxx
103+
PUBLIC_LINK_LIBRARIES O2::CommonUtilsTest)
104+
90105
o2_add_executable(treemergertool
91106
COMPONENT_NAME CommonUtils
92107
SOURCES src/TreeMergerTool.cxx
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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+
#ifndef COMMON_CONFIGURABLE_PARAM_TEST_H_
13+
#define COMMON_CONFIGURABLE_PARAM_TEST_H_
14+
15+
#include "CommonUtils/ConfigurableParam.h"
16+
#include "CommonUtils/ConfigurableParamHelper.h"
17+
18+
namespace o2::conf::test
19+
{
20+
struct TestParam : public o2::conf::ConfigurableParamHelper<TestParam> {
21+
enum TestEnum : uint8_t {
22+
A,
23+
B,
24+
C
25+
};
26+
27+
int iValue{42};
28+
float fValue{3.14};
29+
double dValue{3.14};
30+
bool bValue{true};
31+
unsigned uValue{1};
32+
long lValue{1};
33+
unsigned long ulValue{1};
34+
long long llValue{1};
35+
unsigned long long ullValue{1};
36+
std::string sValue = "default";
37+
int iValueProvenanceTest{0};
38+
TestEnum eValue = TestEnum::C;
39+
int caValue[3] = {0, 1, 2};
40+
41+
O2ParamDef(TestParam, "TestParam");
42+
};
43+
} // namespace o2::conf::test
44+
45+
#endif
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
#ifdef __CLING__
13+
14+
#pragma link off all globals;
15+
#pragma link off all classes;
16+
#pragma link off all functions;
17+
18+
#pragma link C++ class o2::conf::test::TestParam + ;
19+
#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::conf::test::TestParam> + ;
20+
21+
#endif

Common/Utils/src/ConfigurableParam.cxx

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,30 @@ bool keyInTree(boost::property_tree::ptree* pt, const std::string& key)
7777
return reply;
7878
}
7979

80+
// Convert a type info to the appropiate literal suffix
81+
std::string getLiteralSuffixFromType(const std::type_info& type)
82+
{
83+
if (type == typeid(float)) {
84+
return "f";
85+
}
86+
if (type == typeid(long double)) {
87+
return "l";
88+
}
89+
if (type == typeid(unsigned int)) {
90+
return "u";
91+
}
92+
if (type == typeid(unsigned long)) {
93+
return "ul";
94+
}
95+
if (type == typeid(long long)) {
96+
return "ll";
97+
}
98+
if (type == typeid(unsigned long long)) {
99+
return "ull";
100+
}
101+
return "";
102+
}
103+
80104
// ------------------------------------------------------------------
81105

82106
void EnumRegistry::add(const std::string& key, const TDataMember* dm)
@@ -204,12 +228,42 @@ void ConfigurableParam::setValue(std::string const& key, std::string const& valu
204228
initialize();
205229
}
206230
assert(sPtree);
231+
auto setValueImpl = [&](std::string const& value) {
232+
sPtree->put(key, value);
233+
auto changed = updateThroughStorageMapWithConversion(key, value);
234+
if (changed != EParamUpdateStatus::Failed) {
235+
sValueProvenanceMap->find(key)->second = kRT; // set to runtime
236+
}
237+
};
207238
try {
208239
if (sPtree->get_optional<std::string>(key).is_initialized()) {
209-
sPtree->put(key, valuestring);
210-
auto changed = updateThroughStorageMapWithConversion(key, valuestring);
211-
if (changed != EParamUpdateStatus::Failed) {
212-
sValueProvenanceMap->find(key)->second = kRT; // set to runtime
240+
try {
241+
// try first setting value without stripping a literal suffix
242+
setValueImpl(valuestring);
243+
} catch (...) {
244+
// try second stripping the expected literal suffix value for fundamental types
245+
auto iter = sKeyToStorageMap->find(key);
246+
if (iter == sKeyToStorageMap->end()) {
247+
std::cerr << "Error in setValue (string) key is not known\n";
248+
return;
249+
}
250+
const auto expectedSuffix = getLiteralSuffixFromType(iter->second.first);
251+
if (!expectedSuffix.empty()) {
252+
auto valuestringLower = valuestring;
253+
std::transform(valuestring.cbegin(), valuestring.cend(), valuestringLower.begin(), tolower);
254+
if (valuestringLower.ends_with(expectedSuffix)) {
255+
std::string strippedValue = valuestringLower.substr(0, valuestringLower.length() - expectedSuffix.length());
256+
setValueImpl(strippedValue);
257+
} else {
258+
// check if it has a different suffix and throw
259+
for (const auto& suffix : {"f", "l", "u", "ul", "ll", "ull"}) {
260+
if (valuestringLower.ends_with(suffix) && suffix != expectedSuffix) {
261+
throw std::invalid_argument("Wrong type suffix: expected " + expectedSuffix + " but got " + suffix);
262+
}
263+
}
264+
throw; // just rethrow the original exception
265+
}
266+
}
213267
}
214268
}
215269
} catch (std::exception const& e) {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
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 "CommonUtils/ConfigurableParamTest.h"
13+
O2ParamImpl(o2::conf::test::TestParam);
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
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+
#define BOOST_TEST_MODULE Test ConfigurableParams
13+
#define BOOST_TEST_MAIN
14+
#define BOOST_TEST_DYN_LINK
15+
16+
#include <boost/test/unit_test.hpp>
17+
#include <boost/property_tree/ptree.hpp>
18+
#include <filesystem>
19+
20+
#include "CommonUtils/ConfigurableParamTest.h"
21+
22+
using namespace o2::conf;
23+
using namespace o2::conf::test;
24+
25+
BOOST_AUTO_TEST_CASE(ConfigurableParam_Basic)
26+
{
27+
// Tests the default parameters and also getter helpers.
28+
auto& param = TestParam::Instance();
29+
BOOST_CHECK_EQUAL(param.iValue, 42);
30+
BOOST_CHECK_EQUAL(param.dValue, 3.14);
31+
BOOST_CHECK_EQUAL(param.bValue, true);
32+
BOOST_CHECK_EQUAL(param.sValue, "default");
33+
BOOST_CHECK_EQUAL(static_cast<int>(param.eValue), 2);
34+
35+
BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<int>("TestParam.iValue"), 42);
36+
BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<double>("TestParam.dValue"), 3.14);
37+
BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<bool>("TestParam.bValue"), true);
38+
BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<std::string>("TestParam.sValue"), "default");
39+
}
40+
41+
BOOST_AUTO_TEST_CASE(ConfigurableParam_SG_Fundamental)
42+
{
43+
// tests runtime setting and getting for fundamental types
44+
ConfigurableParam::setValue("TestParam.iValue", "100");
45+
ConfigurableParam::setValue("TestParam.dValue", "2.718");
46+
ConfigurableParam::setValue("TestParam.bValue", "0");
47+
ConfigurableParam::setValue("TestParam.sValue", "modified");
48+
ConfigurableParam::setValue("TestParam.eValue", "0");
49+
50+
auto& param = TestParam::Instance();
51+
param.printKeyValues();
52+
BOOST_CHECK_EQUAL(param.iValue, 100);
53+
BOOST_CHECK_EQUAL(param.dValue, 2.718);
54+
BOOST_CHECK_EQUAL(param.bValue, false);
55+
BOOST_CHECK_EQUAL(param.sValue, "modified");
56+
BOOST_CHECK_EQUAL(static_cast<int>(param.eValue), 0);
57+
}
58+
59+
BOOST_AUTO_TEST_CASE(ConfigurableParam_SG_CArray)
60+
{
61+
// tests setting and getting for a c-style array type
62+
auto& param = TestParam::Instance();
63+
BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<int>("TestParam.caValue[0]"), 0);
64+
BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<int>("TestParam.caValue[1]"), 1);
65+
BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<int>("TestParam.caValue[2]"), 2);
66+
67+
ConfigurableParam::setValue("TestParam.caValue[1]", "99");
68+
BOOST_CHECK_EQUAL(ConfigurableParam::getValueAs<int>("TestParam.caValue[1]"), 99);
69+
}
70+
71+
BOOST_AUTO_TEST_CASE(ConfigurableParam_Provenance)
72+
{
73+
// tests correct setting of provenance
74+
BOOST_CHECK_EQUAL(ConfigurableParam::getProvenance("TestParam.iValueProvenanceTest"), ConfigurableParam::EParamProvenance::kCODE);
75+
ConfigurableParam::setValue("TestParam.iValueProvenanceTest", "123");
76+
BOOST_CHECK_EQUAL(ConfigurableParam::getProvenance("TestParam.iValueProvenanceTest"), ConfigurableParam::EParamProvenance::kRT);
77+
}
78+
79+
BOOST_AUTO_TEST_CASE(ConfigurableParam_FileIO_Ini)
80+
{
81+
// test for ini file serialization
82+
const std::string testFileName = "test_config.ini";
83+
auto iValueBefore = TestParam::Instance().iValue;
84+
auto sValueBefore = TestParam::Instance().sValue;
85+
ConfigurableParam::writeINI(testFileName);
86+
ConfigurableParam::setValue("TestParam.iValue", "999");
87+
ConfigurableParam::setValue("TestParam.sValue", testFileName);
88+
ConfigurableParam::updateFromFile(testFileName);
89+
BOOST_CHECK_EQUAL(TestParam::Instance().iValue, iValueBefore);
90+
BOOST_CHECK_EQUAL(TestParam::Instance().sValue, sValueBefore);
91+
std::remove(testFileName.c_str());
92+
}
93+
94+
BOOST_AUTO_TEST_CASE(ConfigurableParam_FileIO_Json)
95+
{
96+
// test for json file serialization
97+
const std::string testFileName = "test_config.json";
98+
auto iValueBefore = TestParam::Instance().iValue;
99+
auto sValueBefore = TestParam::Instance().sValue;
100+
ConfigurableParam::writeJSON(testFileName);
101+
ConfigurableParam::setValue("TestParam.iValue", "999");
102+
ConfigurableParam::setValue("TestParam.sValue", testFileName);
103+
ConfigurableParam::updateFromFile(testFileName);
104+
BOOST_CHECK_EQUAL(TestParam::Instance().iValue, iValueBefore);
105+
BOOST_CHECK_EQUAL(TestParam::Instance().sValue, sValueBefore);
106+
std::remove(testFileName.c_str());
107+
}
108+
109+
BOOST_AUTO_TEST_CASE(ConfigurableParam_FileIO_ROOT)
110+
{
111+
// test for root file serialization
112+
const std::string testFileName = "test_config.root";
113+
auto iValueBefore = TestParam::Instance().iValue;
114+
auto sValueBefore = TestParam::Instance().sValue;
115+
TFile* testFile = TFile::Open(testFileName.c_str(), "RECREATE");
116+
TestParam::Instance().serializeTo(testFile);
117+
testFile->Close();
118+
ConfigurableParam::setValue("TestParam.iValue", "999");
119+
ConfigurableParam::setValue("TestParam.sValue", testFileName);
120+
ConfigurableParam::fromCCDB(testFileName);
121+
BOOST_CHECK_EQUAL(TestParam::Instance().iValue, iValueBefore);
122+
BOOST_CHECK_EQUAL(TestParam::Instance().sValue, sValueBefore);
123+
std::remove(testFileName.c_str());
124+
}
125+
126+
BOOST_AUTO_TEST_CASE(ConfigurableParam_Cli)
127+
{
128+
// test setting values from as a cli arg string
129+
ConfigurableParam::updateFromString("TestParam.iValue=55;TestParam.sValue=cli");
130+
BOOST_CHECK_EQUAL(TestParam::Instance().iValue, 55);
131+
BOOST_CHECK_EQUAL(TestParam::Instance().sValue, "cli");
132+
}
133+
134+
BOOST_AUTO_TEST_CASE(ConfigurableParam_LiteralSuffix)
135+
{
136+
// test setting values with the correct literal suffix
137+
ConfigurableParam::updateFromString("TestParam.fValue=42.f");
138+
BOOST_CHECK_EQUAL(TestParam::Instance().fValue, 42.f);
139+
140+
ConfigurableParam::setValue("TestParam.ullValue", "999ull");
141+
BOOST_CHECK_EQUAL(TestParam::Instance().ullValue, 999ULL);
142+
// check using wrong literal suffix fails, prints error to std
143+
ConfigurableParam::setValue("TestParam.ullValue", "888u");
144+
BOOST_CHECK_NE(TestParam::Instance().ullValue, 888);
145+
}

0 commit comments

Comments
 (0)