JayBeams  0.1
Another project to have fun coding.
ut_config_object_vector.cpp
Go to the documentation of this file.
2 #include <jb/config_object.hpp>
3 
4 #include <boost/test/unit_test.hpp>
5 #include <cstdlib>
6 #include <fstream>
7 #include <string>
8 #include <vector>
9 
10 /**
11  * Helper classes to test jb::config_object and jb::config_attribute
12  */
13 namespace {
14 class simple : public jb::config_object {
15 public:
16  simple()
17  : foo(desc("foo"), this)
18  , bar(desc("bar"), this) {
19  }
21 
24 };
25 
26 class config : public jb::config_object {
27 public:
28  config()
29  : input(desc("input"), this)
30  , outputs(desc("outputs"), this) {
31  }
33 
36 };
37 
38 class nested : public jb::config_object {
39 public:
40  nested()
41  : baz(desc("baz", "config"), this) {
42  }
45 };
46 
47 class verynested : public jb::config_object {
48 public:
49  verynested()
50  : qux(desc("qux", "nested"), this)
51  , quz(desc("quz", "nested"), this) {
52  }
53  config_object_constructors(verynested);
56 };
57 
58 // Convenience functions for the unit tests.
59 std::ostream& operator<<(std::ostream& os, simple const& x) {
60  return os << "{foo=" << x.foo() << ", bar=" << x.bar() << "}";
61 }
62 
63 bool operator==(simple const& lhs, simple const& rhs) {
64  return lhs.foo() == rhs.foo() and lhs.bar() == rhs.bar();
65 }
66 
67 bool operator!=(simple const& lhs, simple const& rhs) {
68  return not(lhs == rhs);
69 }
70 } // anonymous namespace
71 
72 /**
73  * @test Verify we can merge configurations with vectors.
74  */
75 BOOST_AUTO_TEST_CASE(config_object_vector) {
76  char const contents[] = R"""(
77 # YAML overrides
78 input: bar
79 outputs: [ {bar: 6} ]
80 )""";
81 
82  BOOST_TEST_MESSAGE("Applying overrides from\n" << contents << "\n");
83  config tested;
84  tested.input("foo").outputs(std::vector<simple>(
85  {simple().foo("1").bar("2"), simple().foo("3").bar("4")}));
86  BOOST_TEST_MESSAGE("Initial Configuration\n" << tested << "\n");
87  std::istringstream is(contents);
88  int argc = 0;
89  tested.load_overrides(argc, nullptr, is);
90 
91  BOOST_TEST_MESSAGE("Post-Override Configuration\n" << tested << "\n");
92 
93  BOOST_CHECK_EQUAL(tested.input(), "bar");
94  std::vector<simple> expected(
95  {simple().foo("1").bar("6"), simple().foo("3").bar("4")});
96  BOOST_CHECK_EQUAL_COLLECTIONS(
97  tested.outputs().begin(), tested.outputs().end(), expected.begin(),
98  expected.end());
99 }
100 
101 /**
102  * @test Verify we can merge configurations with larger sequences.
103  */
104 BOOST_AUTO_TEST_CASE(config_object_vector_longer) {
105  char const contents[] = R"""(
106 # YAML overrides
107 input: bar
108 outputs: [ {bar: 6}, {}, {foo: 7, bar: 8} ]
109 )""";
110 
111  BOOST_TEST_MESSAGE("Applying overrides from\n" << contents << "\n");
112  config tested;
113  tested.input("foo").outputs(std::vector<simple>(
114  {simple().foo("1").bar("2"), simple().foo("3").bar("4")}));
115  BOOST_TEST_MESSAGE("Initial Configuration\n" << tested << "\n");
116  std::istringstream is(contents);
117  int argc = 0;
118  tested.load_overrides(argc, nullptr, is);
119 
120  BOOST_TEST_MESSAGE("Post-Override Configuration\n" << tested << "\n");
121 
122  BOOST_CHECK_EQUAL(tested.input(), "bar");
123  std::vector<simple> expected({simple().foo("1").bar("6"),
124  simple().foo("3").bar("4"),
125  simple().foo("7").bar("8")});
126  BOOST_CHECK_EQUAL_COLLECTIONS(
127  tested.outputs().begin(), tested.outputs().end(), expected.begin(),
128  expected.end());
129 }
130 
131 /**
132  * @test Verify we can merge configurations with vectors by class.
133  */
134 BOOST_AUTO_TEST_CASE(config_object_vector_by_class) {
135  char const contents[] = R"""(
136 # YAML overrides
137 # This applies to all objects of type 'config'
138 :config:
139  input: bar
140  outputs: [ {bar: 22} ]
141 qux:
142  baz:
143  input: qux.baz
144  outputs: [ {foo: 1, bar: 2}, {foo: 3} ]
145 quz:
146  :config:
147  input: quz.baz
148  outputs: [ {foo: 11}, {foo: 33, bar:44} ]
149  baz:
150  outputs: [ {}, {bar: 4}, {foo: 5, bar: 6} ]
151 )""";
152 
153  verynested tested;
154  std::istringstream is(contents);
155  int argc = 0;
156  tested.load_overrides(argc, nullptr, is);
157 
158  BOOST_CHECK_EQUAL(tested.qux().baz().input(), "qux.baz");
159  std::vector<simple> expected(
160  {simple().foo("1").bar("2"), simple().foo("3").bar("")});
161  BOOST_CHECK_EQUAL_COLLECTIONS(
162  tested.qux().baz().outputs().begin(), tested.qux().baz().outputs().end(),
163  expected.begin(), expected.end());
164 
165  BOOST_CHECK_EQUAL(tested.quz().baz().input(), "quz.baz");
166  expected.assign({simple().foo("11").bar("22"), simple().foo("33").bar("4"),
167  simple().foo("5").bar("6")});
168  BOOST_CHECK_EQUAL_COLLECTIONS(
169  tested.quz().baz().outputs().begin(), tested.quz().baz().outputs().end(),
170  expected.begin(), expected.end());
171 }
bool operator!=(book_update const &a, book_update const &b)
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.
Definition: as_hhmmss.cpp:8
BOOST_AUTO_TEST_CASE(config_object_vector)
#define config_object_constructors(NAME)
Helper class to easily define configuration attributes.