netxsimdg
Loading...
Searching...
No Matches
Configurator_test.cpp
Go to the documentation of this file.
1
8#include "ArgV.hpp"
9#include "Configurator.hpp"
10#include "Configured.hpp"
11
12#include <iostream>
13#include <memory>
14#include <sstream>
15#include <string>
16
17#include <boost/program_options.hpp>
18
19#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
20#include <doctest/doctest.h>
21
22class Config1 {
23public:
24 Config1()
25 : value(0)
26 {
27 }
28 void configure()
29 {
30 const std::string valueKey = "config.value";
31
32 boost::program_options::options_description opt("Options");
33 opt.add_options()(valueKey.c_str(), boost::program_options::value<int>()->default_value(-1),
34 "Specify a value");
35 boost::program_options::variables_map vm = Nextsim::Configurator::parse(opt);
36
37 value = vm[valueKey].as<int>();
38 }
39
40 bool checkValue(int target) { return value == target; }
41
42private:
43 int value;
44};
45
46class Config2 : public Nextsim::Configured<Config2> {
47public:
48 enum {
49 VALUE_KEY,
50 NAME_KEY,
51 };
52
53 Config2();
54 int getValue() { return value; }
55 std::string getName() { return name; }
56
57 void configure() override;
58
59private:
60 int value;
61 std::string name;
62};
63
64template<>
65const std::map<int, std::string> Nextsim::Configured<Config2>::keyMap = {
66 {Config2::VALUE_KEY, "config.value"},
67 {Config2::NAME_KEY, "config.name"},
68};
69
70Config2::Config2()
71 : value(0)
72{
73addOption<int>(keyMap.at(VALUE_KEY), -1);
74addOption<std::string>(keyMap.at(NAME_KEY), "");
75}
76
78{
79 value = retrieveValue<int>(keyMap.at(VALUE_KEY));
80 name = retrieveValue<std::string>(keyMap.at(NAME_KEY));
81}
82
83
84class Config3 : public Nextsim::Configured<Config3> {
85public:
86 enum {
87 VALUE_KEY,
88 WEIGHT_KEY,
89 };
90 Config3()
91 : value(0)
92 , weight(0.)
93{
94}
95 int getValue() { return value; }
96 double getWeight() { return weight; }
97
98 void configure() override;
99
100private:
101 int value;
102 double weight;
103};
104
105template<>
106const std::map<int, std::string> Nextsim::Configured<Config3>::keyMap = {
107 {Config3::VALUE_KEY, "config.value"},
108 {Config3::WEIGHT_KEY, "data.weight"},
109};
110
112{
113 value = Configured::getConfiguration(keyMap.at(VALUE_KEY), -1);
114 weight = Configured::getConfiguration(keyMap.at(WEIGHT_KEY), 1.);
115}
116
117namespace Nextsim {
118
119TEST_SUITE_BEGIN("Configurator");
120TEST_CASE("Parse one config stream using the raw configurator")
121{
122 // Since tests are not different execution environments, clear the streams from other tests.
124 Config1 config;
125
126 int target = 42;
127 std::stringstream text;
128 text << "[config]" << std::endl << "value = " << target << std::endl;
129
130 // Check for the initialized value
131 REQUIRE(config.checkValue(0));
132
133 config.configure();
134 // Check for the default initialized value
135 REQUIRE(config.checkValue(-1));
136
137 std::unique_ptr<std::istream> pcstream(new std::stringstream(text.str()));
138
139 Configurator::addStream(std::move(pcstream));
140
141 config.configure();
142
143 // Check for the configured value
144 REQUIRE(config.checkValue(target));
145}
146
147TEST_CASE("Parse one config stream using the pointer configuration function")
148{
149 // Since tests are not different execution environments, clear the streams from other tests.
152 Config2 config;
153
154 int target = 69105;
155 std::string targetName = "Zork";
156 std::stringstream text;
157 text << "[config]" << std::endl
158 << "value = " << target << std::endl
159 << "name = " << targetName << std::endl;
160
161 Configurator::addStream(std::unique_ptr<std::istream>(new std::stringstream(text.str())));
162
163 tryConfigure(&config);
164
165 REQUIRE(config.getValue() == target);
166 REQUIRE(config.getName() == targetName);
167}
168
169TEST_CASE("Parse two config streams for one class, reference helper function")
170{
171 // Since tests are not different execution environments, clear the streams from other tests.
174 Config2 config;
175
176 int target = 69105;
177 std::string targetName = "Zork";
178 std::stringstream text1;
179 text1 << "[config]" << std::endl << "value = " << target << std::endl;
180 Configurator::addStream(std::unique_ptr<std::istream>(new std::stringstream(text1.str())));
181
182 std::stringstream text2;
183 text2 << "[config]" << std::endl << "name = " << targetName << std::endl;
184 Configurator::addStream(std::unique_ptr<std::istream>(new std::stringstream(text2.str())));
185
186 Config2& ref = config;
187 tryConfigure(ref);
188
189 REQUIRE(config.getValue() == target);
190 REQUIRE(config.getName() == targetName);
191}
192
193TEST_CASE("Parse config streams for two overlapping class, try")
194{
195 // Since tests are not different execution environments, clear the streams from other tests.
199 Config2 config;
200 Config3 confih;
201
202
203 int target = 69105;
204 std::string targetName = "Zork II";
205 std::stringstream text1;
206 text1 << "[config]" << std::endl
207 << "value = " << target << std::endl
208 << "name = " << targetName << std::endl;
209 Configurator::addStream(std::unique_ptr<std::istream>(new std::stringstream(text1.str())));
210
211 double targetWeight = 0.467836;
212 std::stringstream text2;
213 text2 << "[data]" << std::endl << "weight = " << targetWeight << std::endl;
214 Configurator::addStream(std::unique_ptr<std::istream>(new std::stringstream(text2.str())));
215
216 // Test that the target values are not already present before configuring
217 REQUIRE(config.getValue() != target);
218 REQUIRE(config.getName() != targetName);
219
220 REQUIRE(confih.getValue() != target);
221 REQUIRE(confih.getWeight() != targetWeight);
222
223 tryConfigure(config);
224 tryConfigure(confih);
225
226 REQUIRE(config.getValue() == target);
227 REQUIRE(config.getName() == targetName);
228
229 REQUIRE(confih.getValue() == target);
230 REQUIRE(confih.getWeight() == targetWeight);
231}
232TEST_SUITE_END();
233
234} /* namespace Nextsim */
void tryConfigure(T &t)
Template function for conditionally configuring references.
void configure() override
The configuration function.
void configure() override
The configuration function.
static void addStream(std::unique_ptr< std::istream > pis)
Adds a istream source of configuration data.
static void clearStreams()
static boost::program_options::variables_map parse(const boost::program_options::options_description &opt)
Parses all configuration sources.
static const std::map< int, std::string > keyMap
void addOption(const std::string &name, const T &defaultValue)
T retrieveValue(const std::string &name)