4 #include <boost/filesystem.hpp> 5 #include <boost/test/unit_test.hpp> 19 , bar(this,
"default value")
33 , names(this, {
"one",
"two",
"3"}) {
58 BOOST_CHECK_EQUAL(tested.foo(), std::string(
""));
59 BOOST_CHECK_EQUAL(tested.bar(), std::string(
"default value"));
60 BOOST_CHECK_EQUAL(tested.baz(), 123);
62 tested.foo(
"new value").baz(456);
63 BOOST_CHECK_EQUAL(tested.foo(), std::string(
"new value"));
64 BOOST_CHECK_EQUAL(tested.baz(), 456);
73 BOOST_CHECK_EQUAL(tested.base().foo(), std::string(
""));
74 BOOST_CHECK_EQUAL(tested.base().bar(), std::string(
"default value"));
75 BOOST_CHECK_EQUAL(tested.base().baz(), 123);
76 BOOST_REQUIRE_EQUAL(tested.names().size(), 3);
77 BOOST_CHECK_EQUAL(tested.names()[0],
"one");
78 BOOST_CHECK_EQUAL(tested.names()[1],
"two");
79 BOOST_CHECK_EQUAL(tested.names()[2],
"3");
81 auto tmp = tested.base();
82 tmp.foo(
"new value").baz(456);
83 tested.base(std::move(tmp));
85 complex other(tested);
86 BOOST_CHECK_EQUAL(other.base().foo(), std::string(
"new value"));
87 BOOST_CHECK_EQUAL(other.base().baz(), 456);
96 auto tmp = src.base();
97 tmp.foo(
"new value").baz(456);
98 src.base(std::move(tmp));
99 src.names(std::vector<std::string>({
"1",
"2",
"three"}));
102 tested = std::move(src);
103 BOOST_REQUIRE_EQUAL(tested.names().size(), 3);
104 BOOST_CHECK_EQUAL(tested.names()[0],
"1");
105 BOOST_CHECK_EQUAL(tested.names()[1],
"2");
106 BOOST_CHECK_EQUAL(tested.names()[2],
"three");
107 BOOST_CHECK_EQUAL(src.names().size(), 0);
109 complex other(std::move(tested));
110 BOOST_REQUIRE_EQUAL(other.names().size(), 3);
111 BOOST_CHECK_EQUAL(other.names()[0],
"1");
112 BOOST_CHECK_EQUAL(other.names()[1],
"2");
113 BOOST_CHECK_EQUAL(other.names()[2],
"three");
114 BOOST_CHECK_EQUAL(tested.names().size(), 0);
122 test_variadic tested;
124 BOOST_CHECK_EQUAL(tested.foo().first, 1);
125 BOOST_CHECK_EQUAL(tested.foo().second, 2);
135 , z(desc(
"z"),
this) {
146 std::ostream&
operator<<(std::ostream& os, config0
const& x) {
147 return os <<
"{x=" << x.x() <<
", y=" << x.y() <<
", z=" << x.z() <<
"}";
150 bool operator==(config0
const& lhs, config0
const& rhs) {
151 return lhs.x() == rhs.x() and lhs.y() == rhs.y() and lhs.z() == rhs.z();
154 config0 make_config0(
int x,
int y,
int z) {
155 return std::move(config0().x(x).y(y).z(z));
161 : list(desc(
"list"),
this, {
"ini",
"mini",
"myni",
"mo"})
162 , pos(desc(
"pos",
"config0"),
this) {
178 char const contents[] = R
"""(# YAML overrides 179 # This applies to all objects of type 'config0' 184 list: ['1', '3', '5', '7'] 190 BOOST_TEST_MESSAGE("Applying overrides from\n" << contents <<
"\n");
192 std::vector<std::string> expected({
"ini",
"mini",
"myni",
"mo"});
193 BOOST_CHECK_EQUAL_COLLECTIONS(
194 tested.list().begin(), tested.list().end(), expected.begin(),
196 BOOST_CHECK_EQUAL(tested.pos(), make_config0(0, 0, 0));
198 std::istringstream is(contents);
200 tested.load_overrides(argc,
nullptr, is);
202 expected.assign({
"1",
"3",
"5",
"7"});
203 BOOST_CHECK_EQUAL_COLLECTIONS(
204 tested.list().begin(), tested.list().end(), expected.begin(),
206 BOOST_CHECK_EQUAL(tested.pos(), make_config0(2, 4, -3));
213 : vars(desc(
"vars"),
this) {
226 char const contents[] = R
"""(# YAML overrides 228 - list: ['1', '3', '5', '7'] 232 - list: ['2', '4', '6', '8'] 243 BOOST_TEST_MESSAGE("Applying overrides from\n" << contents <<
"\n");
246 std::istringstream is(contents);
248 tested.load_overrides(argc,
nullptr, is);
250 BOOST_REQUIRE_EQUAL(tested.vars().size(), 3);
252 std::vector<std::string> expected;
254 expected.assign({
"1",
"3",
"5",
"7"});
255 BOOST_CHECK_EQUAL_COLLECTIONS(
256 tested.vars()[0].list().begin(), tested.vars()[0].list().end(),
257 expected.begin(), expected.end());
258 BOOST_CHECK_EQUAL(tested.vars()[0].pos().x(), 2);
259 BOOST_CHECK_EQUAL(tested.vars()[0].pos().y(), 4);
261 expected.assign({
"2",
"4",
"6",
"8"});
262 BOOST_CHECK_EQUAL_COLLECTIONS(
263 tested.vars()[1].list().begin(), tested.vars()[1].list().end(),
264 expected.begin(), expected.end());
265 BOOST_CHECK_EQUAL(tested.vars()[1].pos().y(), 1);
266 BOOST_CHECK_EQUAL(tested.vars()[1].pos().z(), 3);
268 expected.assign({
"11"});
269 BOOST_CHECK_EQUAL_COLLECTIONS(
270 tested.vars()[2].list().begin(), tested.vars()[2].list().end(),
271 expected.begin(), expected.end());
272 BOOST_CHECK_EQUAL(tested.vars()[2].pos(), make_config0(1, 2, 3));
281 std::istringstream is(
"");
282 char argv0[] =
"not_a_path";
283 char argv1[] =
"--vars.0.pos.x=2";
284 char* argv[] = {argv0, argv1,
nullptr};
285 int argc =
sizeof(argv) /
sizeof(argv[0]) - 1;
286 tested.load_overrides(argc, argv, is);
288 BOOST_REQUIRE_EQUAL(tested.vars().size(), 1);
289 BOOST_CHECK_EQUAL(tested.vars()[0].pos().x(), 2);
291 std::ostringstream os;
292 BOOST_CHECK_NO_THROW(os << tested);
294 BOOST_CHECK_NO_THROW(os << empty);
301 : foo(desc(
"foo",
"config0"),
this)
302 , bar(desc(
"bar",
"config0"),
this)
303 , baz(desc(
"baz",
"config0"),
this) {
316 : ini(desc(
"ini"),
this)
317 , mini(desc(
"mini"),
this)
318 , myni(desc(
"myni"),
this) {
334 char const contents[] = R
"""(# YAML overrides 335 # This override applies to all objects of type config0, wherever 342 # While this configuration only applies to the objects in this scope... 356 # Notice that we can override just a few fields too 363 BOOST_TEST_MESSAGE("Applying overrides from doc\n" << contents <<
"\n");
366 std::istringstream is(contents);
368 tested.load_overrides(argc,
nullptr, is);
370 BOOST_CHECK_EQUAL(tested.ini().foo(), make_config0(-2, -2, -2));
371 BOOST_CHECK_EQUAL(tested.ini().bar(), make_config0(1, 2, -2));
372 BOOST_CHECK_EQUAL(tested.ini().baz(), make_config0(-2, -2, -2));
374 BOOST_CHECK_EQUAL(tested.mini().foo(), make_config0(3, -1, -1));
375 BOOST_CHECK_EQUAL(tested.mini().bar(), make_config0(-1, 4, -1));
376 BOOST_CHECK_EQUAL(tested.mini().baz(), make_config0(-1, -1, -1));
378 BOOST_CHECK_EQUAL(tested.myni().foo(), make_config0(-1, -1, -3));
379 BOOST_CHECK_EQUAL(tested.myni().bar(), make_config0(-1, -1, -3));
380 BOOST_CHECK_EQUAL(tested.myni().baz(), make_config0(-1, -1, 5));
382 std::ostringstream os;
390 char const contents[] = R
"""(# YAML overrides 395 list: ['1', '3', '5', '7'] 401 std::istringstream is(contents); 404 char argv0[] =
"not_a_path";
405 char* argv[] = {argv0,
nullptr};
406 int argc =
sizeof(argv) /
sizeof(argv[0]) - 1;
408 tested.load_overrides(argc, argv, is);
410 std::vector<std::string> expected({
"1",
"3",
"5",
"7"});
411 BOOST_CHECK_EQUAL_COLLECTIONS(
412 tested.list().begin(), tested.list().end(), expected.begin(),
414 BOOST_CHECK_EQUAL(tested.pos(), make_config0(2, 4, -3));
421 char const contents[] = R
"""(# YAML overrides 431 std::istringstream is(contents); 434 char argv0[] =
"not_a_path";
435 char argv1[] =
"--pos.x=3";
436 char argv2[] =
"--list=1";
437 char argv3[] =
"--list=3";
438 char argv4[] =
"--list=5";
439 char argv5[] =
"--list=7";
440 char* argv[] = {argv0, argv1, argv2, argv3, argv4, argv5,
nullptr};
441 int argc =
sizeof(argv) /
sizeof(argv[0]) - 1;
443 tested.load_overrides(argc, argv, is);
445 std::vector<std::string> expected({
"1",
"3",
"5",
"7"});
446 BOOST_CHECK_EQUAL_COLLECTIONS(
447 tested.list().begin(), tested.list().end(), expected.begin(),
449 BOOST_CHECK_EQUAL(tested.pos(), make_config0(3, 4, -3));
457 char argv0[] =
"binary";
458 char argv1[] =
"--help";
459 char* argv[] = {argv0, argv1,
nullptr};
460 int argc =
sizeof(argv) /
sizeof(argv[0]) - 1;
461 std::istringstream is(
"");
463 BOOST_CHECK_THROW(tested.load_overrides(argc, argv, is),
jb::usage);
472 char argv0[] =
"binary";
473 char argv1[] =
"--invalid-option";
474 char* argv[] = {argv0, argv1,
nullptr};
475 int argc =
sizeof(argv) /
sizeof(argv[0]) - 1;
476 std::istringstream is(
"");
478 BOOST_CHECK_THROW(tested.load_overrides(argc, argv, is), std::exception);
485 : foo(desc(
"foo"),
this) {
498 char const contents[] = R
"""(# YAML overrides 504 std::istringstream is(contents); 507 tested.load_overrides(argc,
nullptr, is);
509 BOOST_CHECK_EQUAL(tested.foo().first, 2);
510 BOOST_CHECK_EQUAL(tested.foo().second, 7);
517 char const contents[] = R
"""(# YAML overrides 523 std::istringstream is(contents); 525 char argv0[] =
"binary";
526 char argv1[] =
"--foo.first=42";
527 char argv2[] =
"--foo.second=43";
528 char* argv[] = {argv0, argv1, argv2,
nullptr};
529 int argc =
sizeof(argv) /
sizeof(argv[0]) - 1;
530 tested.load_overrides(argc, argv, is);
532 BOOST_CHECK_EQUAL(tested.foo().first, 42);
533 BOOST_CHECK_EQUAL(tested.foo().second, 43);
535 std::ostringstream os;
536 BOOST_CHECK_NO_THROW(os << tested);
543 : foo(desc(
"foo"),
this)
544 , bar(desc(
"bar",
"config0").help(
"not much help"),
this)
545 , baz(desc(
"baz",
"config0").help(
"not much help"),
this) {
561 char const contents[] = R
"""(# YAML overrides 566 foo: this is a long string 571 fs::path tmpdir = fs::temp_directory_path() / fs::unique_path();
572 BOOST_TEST_MESSAGE(
"creating unique tempdir at " << tmpdir);
573 BOOST_REQUIRE(fs::create_directories(tmpdir));
574 std::shared_ptr<int> delete_dir(
new int(5), [tmpdir](
int* x) {
576 fs::remove_all(tmpdir);
578 std::string filename =
"test.yml";
582 BOOST_REQUIRE(fs::create_directories(tmpdir / base));
583 fs::path fullpath = tmpdir / base / filename;
584 BOOST_TEST_MESSAGE(
"writing contents to " << fullpath.string());
585 std::ofstream os(fullpath.string());
590 (void)setenv(
"TEST_ROOT", tmpdir.string().c_str(),
true);
591 char argv0[] =
"binary";
592 char argv1[] =
"--bar.x=42";
593 char argv2[] =
"--baz.y=24";
594 char* argv[] = {argv0, argv1, argv2,
nullptr};
595 int argc =
sizeof(argv) /
sizeof(argv[0]) - 1;
597 tested.load_overrides(argc, argv, filename,
"TEST_ROOT");
598 BOOST_CHECK_EQUAL(tested.foo(),
"this is a long string");
599 BOOST_CHECK_EQUAL(tested.bar(), make_config0(42, -2, -3));
600 BOOST_CHECK_EQUAL(tested.baz(), make_config0(-1, 24, 4));
609 fs::path tmpdir = fs::temp_directory_path() / fs::unique_path();
610 BOOST_TEST_MESSAGE(
"creating unique tempdir at " << tmpdir);
611 BOOST_REQUIRE(fs::create_directories(tmpdir));
612 std::shared_ptr<int> delete_dir(
new int(5), [tmpdir](
int* x) {
614 fs::remove_all(tmpdir);
616 std::string filename =
"test.yml";
619 (void)setenv(
"TEST_ROOT", tmpdir.string().c_str(),
true);
620 char argv0[] =
"binary";
621 char argv1[] =
"--bar.x=42";
622 char argv2[] =
"--baz.y=24";
623 char* argv[] = {argv0, argv1, argv2,
nullptr};
624 int argc =
sizeof(argv) /
sizeof(argv[0]) - 1;
626 tested.load_overrides(argc, argv, filename,
"TEST_ROOT");
627 BOOST_CHECK_EQUAL(tested.foo(),
"");
628 BOOST_CHECK_EQUAL(tested.bar(), make_config0(42, 0, 0));
629 BOOST_CHECK_EQUAL(tested.baz(), make_config0(0, 24, 0));
637 char const contents[] = R
"""(# YAML overrides 642 foo: this is a long string 647 fs::path tmpdir = fs::temp_directory_path() / fs::unique_path();
648 BOOST_TEST_MESSAGE(
"creating unique tempdir at " << tmpdir);
649 BOOST_REQUIRE(fs::create_directories(tmpdir));
650 std::shared_ptr<int> delete_dir(
new int(5), [tmpdir](
int* x) {
652 fs::remove_all(tmpdir);
654 std::string filename =
"test.yml";
658 BOOST_REQUIRE(fs::create_directories(tmpdir / base));
659 fs::path fullpath = tmpdir / base / filename;
660 BOOST_TEST_MESSAGE(
"writing contents to " << fullpath.string());
661 std::ofstream os(fullpath.string());
666 (void)setenv(
"JAYBEAMS_ROOT", tmpdir.string().c_str(),
true);
667 char argv0[] =
"binary";
668 char argv1[] =
"--bar.x=42";
669 char argv2[] =
"--baz.y=24";
670 char* argv[] = {argv0, argv1, argv2,
nullptr};
671 int argc =
sizeof(argv) /
sizeof(argv[0]) - 1;
673 tested.load_overrides(argc, argv, filename);
674 BOOST_CHECK_EQUAL(tested.foo(),
"this is a long string");
675 BOOST_CHECK_EQUAL(tested.bar(), make_config0(42, -2, -3));
676 BOOST_CHECK_EQUAL(tested.baz(), make_config0(-1, 24, 4));
684 std::string filename(
"missing-config-file.bad.bad.bad.yml");
686 char argv0[] =
"binary";
687 char argv1[] =
"--foo=this is a long string";
688 char argv2[] =
"--baz.y=24";
689 char* argv[] = {argv0, argv1, argv2,
nullptr};
690 int argc =
sizeof(argv) /
sizeof(argv[0]) - 1;
692 tested.load_overrides(argc, argv, filename);
693 BOOST_CHECK_EQUAL(tested.foo(),
"this is a long string");
694 BOOST_CHECK_EQUAL(tested.bar(), make_config0(0, 0, 0));
695 BOOST_CHECK_EQUAL(tested.baz(), make_config0(0, 24, 0));
702 : foo(desc(
"foo"),
this)
703 , bar(desc(
"bar").help(
"not much help").positional(),
this)
704 , baz(desc(
"baz").help(
"not much help").positional(),
this) {
720 std::istringstream is(
"");
721 char argv0[] =
"binary";
722 char argv1[] =
"should-be-bar";
723 char argv2[] =
"should-be-baz";
724 char argv3[] =
"--foo=another";
725 char* argv[] = {argv0, argv1, argv2, argv3,
nullptr};
726 int argc =
sizeof(argv) /
sizeof(argv[0]) - 1;
728 tested.load_overrides(argc, argv, is);
729 BOOST_CHECK_EQUAL(tested.foo(),
"another");
730 BOOST_CHECK_EQUAL(tested.bar(),
"should-be-bar");
731 BOOST_CHECK_EQUAL(tested.baz(),
"should-be-baz");
742 BOOST_CHECK_EQUAL(a.what(), b.what());
bool operator==(book_update const &a, book_update const &b)
Base class for all configuration objects.
std::ostream & operator<<(std::ostream &os, as_hhmmssu const &x)
Format as_hhmmssu into an iostream.
BOOST_AUTO_TEST_CASE(config_attribute_simple)
#define config_object_constructors(NAME)
Helper class to easily define configuration attributes.
A simple class to communicate the result of parsing the options.
char const * sysconfdir()
Return the system configuration directory.