diff --git a/Tests/BaseLib/TestConfigTree.cpp b/Tests/BaseLib/TestConfigTree.cpp index 7b5bb62362e05c8be7ce8cea9c27468ce2b5a2d9..b6ae5ca45123ab5b5fcf8244b7f170d9aeaf2f19 100644 --- a/Tests/BaseLib/TestConfigTree.cpp +++ b/Tests/BaseLib/TestConfigTree.cpp @@ -15,7 +15,7 @@ #include "BaseLib/ConfigTreeNew.h" -#define DO_EXPECT(cbs, error, warning) do { \ +#define EXPECT_ERR_WARN(cbs, error, warning) do { \ if (error) EXPECT_TRUE((cbs).get_error()); else EXPECT_FALSE((cbs).get_error()); \ if (warning) EXPECT_TRUE((cbs).get_warning()); else EXPECT_FALSE((cbs).get_warning()); \ (cbs).reset(); \ @@ -33,7 +33,8 @@ class Callbacks { public: BaseLib::ConfigTreeNew::Callback - get_error_cb() { + get_error_cb() + { return [this](std::string const& path, std::string const& message) { (void) path; (void) message; @@ -44,7 +45,8 @@ public: } BaseLib::ConfigTreeNew::Callback - get_warning_cb() { + get_warning_cb() + { return [this](std::string const& path, std::string const& message) { (void) path; (void) message; @@ -73,7 +75,7 @@ TEST(BaseLibConfigTree, ConfigTreeEmpty) (void) conf; } // ConfigTree destroyed here - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); } @@ -86,89 +88,163 @@ TEST(BaseLibConfigTree, ConfigTreeGet) "<sub>" " <float>6.1</float>" " <float2>0.1</float2>" + " <bool1>false</bool1>" + " <bool2>false</bool2>" + " <bool3/>" " <ignored/>" " <ignored2/>" " <ignored2/>" "</sub>" - "<x>Y</x>"; + "<x>Y</x>" + "<z attr=\"0.5\">32.0</z>"; boost::property_tree::ptree ptree; std::istringstream xml_str(xml); - read_xml(xml_str, ptree); + read_xml(xml_str, ptree, + boost::property_tree::xml_parser::no_comments | + boost::property_tree::xml_parser::trim_whitespace); Callbacks cbs; { BaseLib::ConfigTreeNew conf(ptree, cbs.get_error_cb(), cbs.get_warning_cb()); EXPECT_EQ(5.6e-4, conf.getConfParam<double>("double")); // read certain types - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); EXPECT_TRUE(conf.getConfParam<bool>("bool")); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); EXPECT_EQ(5, conf.getConfParam<int>("int")); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); EXPECT_EQ(8, conf.getConfParam<int>("intx", 8)); // reading with default value - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); + + // Testing subtree { auto sub = conf.getConfSubtree("sub"); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); EXPECT_EQ(6.1f, sub.getConfParam<float>("float")); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); if (auto f2 = sub.getConfParamOptional<float>("float2")) { // read optional value EXPECT_EQ(0.1f, *f2); - DO_EXPECT(cbs, false, false); } + EXPECT_ERR_WARN(cbs, false, false); auto f3 = sub.getConfParamOptional<float>("float3"); // optional value not existent ASSERT_FALSE(f3); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); + + + // Testing the getConfParam...() (non-template) / getValue() combination + + auto bool1 = sub.getConfParam("bool1"); + EXPECT_ERR_WARN(cbs, false, false); + EXPECT_FALSE(bool1.getValue<bool>()); + EXPECT_ERR_WARN(cbs, false, false); + RUN_SAFE(bool1.getValue<bool>()); // getting data twice + EXPECT_ERR_WARN(cbs, true, false); + + if (auto bool2 = sub.getConfParamOptional("bool2")) { + EXPECT_ERR_WARN(cbs, false, false); + EXPECT_FALSE(bool2->getValue<bool>()); + } + EXPECT_ERR_WARN(cbs, false, false); + + if (auto bool3 = sub.getConfParamOptional("bool3")) { + EXPECT_ERR_WARN(cbs, false, false); + RUN_SAFE(bool3->getValue<bool>()); + EXPECT_ERR_WARN(cbs, true, false); // error because of no data + } + EXPECT_ERR_WARN(cbs, false, false); + + EXPECT_FALSE(sub.getConfParamOptional("bool4")); // optional value not existent + EXPECT_ERR_WARN(cbs, false, false); + + + // Testing ignore sub.ignoreConfParam("ignored"); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); sub.ignoreConfParamAll("ignored2"); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); sub.ignoreConfParamAll("ignored4"); // I can ignore nonexistent stuff - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); // I can not ignore stuff that I already read // this also makes sure that the subtree inherits the callbacks properly RUN_SAFE(sub.ignoreConfParam("float")); - DO_EXPECT(cbs, true, false); + EXPECT_ERR_WARN(cbs, true, false); } for (int i : {0, 1, 2}) { (void) i; EXPECT_EQ("Y", conf.peekConfParam<std::string>("x")); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); } conf.checkConfParam<std::string>("x", "Y"); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); + + + // Testing attributes + { + auto z = conf.getConfParam("z"); + EXPECT_ERR_WARN(cbs, false, false); + EXPECT_EQ(0.5, z.getConfAttribute<double>("attr")); + EXPECT_ERR_WARN(cbs, false, false); + RUN_SAFE(z.getConfAttribute<double>("attr")); // getting attr twice + EXPECT_ERR_WARN(cbs, true, false); + RUN_SAFE(z.getConfAttribute<double>("not_an_attr")); // nonexistent attribute + EXPECT_ERR_WARN(cbs, true, false); + EXPECT_EQ(32.0, z.getValue<double>()); + EXPECT_ERR_WARN(cbs, false, false); + } + EXPECT_ERR_WARN(cbs, false, false); } // ConfigTree destroyed here - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); } -TEST(BaseLibConfigTree, ConfigTreeIncompleteParse) +TEST(BaseLibConfigTree, IncompleteParse) { const char xml[] = "<double>5.6</double>" - "<bool>true</bool>" + "<not_read>true</not_read>" + "<tag>this data won't be read</tag>" + "<pt x=\"0.5\">1</pt>" + "<pt2 x=\"0.5\" y=\"1.0\" z=\"2.0\" />" ; boost::property_tree::ptree ptree; std::istringstream xml_str(xml); - read_xml(xml_str, ptree); + read_xml(xml_str, ptree, + boost::property_tree::xml_parser::no_comments | + boost::property_tree::xml_parser::trim_whitespace); Callbacks cbs; { BaseLib::ConfigTreeNew conf(ptree, cbs.get_error_cb(), cbs.get_warning_cb()); - EXPECT_EQ(5.6, conf.getConfParam<double>("double")); // read certain types - DO_EXPECT(cbs, false, false); + EXPECT_EQ(5.6, conf.getConfParam<double>("double")); + EXPECT_ERR_WARN(cbs, false, false); + + conf.getConfSubtree("tag"); + EXPECT_ERR_WARN(cbs, false, true); // data of <tag> has not been read + + EXPECT_EQ(1, conf.getConfParam<int>("pt")); + EXPECT_ERR_WARN(cbs, false, true); // attribute "x" has not been read + + { + auto pt2 = conf.getConfParam("pt2"); + EXPECT_EQ(0.5, pt2.getConfAttribute<double>("x")); + EXPECT_ERR_WARN(cbs, false, false); + EXPECT_EQ(1.0, pt2.getConfAttribute<double>("y")); + EXPECT_ERR_WARN(cbs, false, false); + } + EXPECT_ERR_WARN(cbs, false, true); // attribute "z" not read + } // ConfigTree destroyed here - DO_EXPECT(cbs, false, true); // expect warning because I didn't read everything + EXPECT_ERR_WARN(cbs, false, true); // expect warning because I didn't read everything } @@ -184,34 +260,38 @@ TEST(BaseLibConfigTree, ConfigTreeCheckRange) boost::property_tree::ptree ptree; std::istringstream xml_str(xml); - read_xml(xml_str, ptree); + read_xml(xml_str, ptree, + boost::property_tree::xml_parser::no_comments | + boost::property_tree::xml_parser::trim_whitespace); Callbacks cbs; { BaseLib::ConfigTreeNew conf(ptree, cbs.get_error_cb(), cbs.get_warning_cb()); { + // check that std::distance can be computed twice in a row auto list = conf.getConfSubtreeList("val"); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); EXPECT_EQ(3, std::distance(list.begin(), list.end())); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); EXPECT_EQ(3, std::distance(list.begin(), list.end())); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); } { + // check that std::distance can be computed twice in a row auto list = conf.getConfParamList<int>("int"); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); EXPECT_EQ(3, std::distance(list.begin(), list.end())); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); EXPECT_EQ(3, std::distance(list.begin(), list.end())); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); } } // ConfigTree destroyed here // there will be warnings because I don't process the list entries - DO_EXPECT(cbs, false, true); + EXPECT_ERR_WARN(cbs, false, true); } @@ -224,7 +304,9 @@ TEST(BaseLibConfigTree, ConfigTreeGetSubtreeList) boost::property_tree::ptree ptree; std::istringstream xml_str(xml); - read_xml(xml_str, ptree); + read_xml(xml_str, ptree, + boost::property_tree::xml_parser::no_comments | + boost::property_tree::xml_parser::trim_whitespace); Callbacks cbs; { @@ -234,11 +316,11 @@ TEST(BaseLibConfigTree, ConfigTreeGetSubtreeList) for (auto ct : conf.getConfSubtreeList("val")) { EXPECT_EQ(i, ct.getConfParam<int>("int")); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); ++i; } } // ConfigTree destroyed here - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); } @@ -261,11 +343,11 @@ TEST(BaseLibConfigTree, ConfigTreeGetValueList) for (auto i : conf.getConfParamList<int>("int")) { EXPECT_EQ(n, i); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); ++n; } } // ConfigTree destroyed here - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); } @@ -282,52 +364,54 @@ TEST(BaseLibConfigTree, ConfigTreeNoConversion) boost::property_tree::ptree ptree; std::istringstream xml_str(xml); - read_xml(xml_str, ptree); + read_xml(xml_str, ptree, + boost::property_tree::xml_parser::no_comments | + boost::property_tree::xml_parser::trim_whitespace); Callbacks cbs; { BaseLib::ConfigTreeNew conf(ptree, cbs.get_error_cb(), cbs.get_warning_cb()); RUN_SAFE(conf.getConfParam<int>("int")); - DO_EXPECT(cbs, true, false); + EXPECT_ERR_WARN(cbs, true, false); RUN_SAFE(conf.ignoreConfParam("int")); // after failure I also cannot ignore something - DO_EXPECT(cbs, true, false); + EXPECT_ERR_WARN(cbs, true, false); RUN_SAFE(conf.getConfParam<double>("double")); - DO_EXPECT(cbs, true, false); + EXPECT_ERR_WARN(cbs, true, false); // peek value existent but not convertible RUN_SAFE(conf.peekConfParam<double>("non_double")); - DO_EXPECT(cbs, true, false); + EXPECT_ERR_WARN(cbs, true, false); // optional value existent but not convertible RUN_SAFE( auto d = conf.getConfParamOptional<double>("non_double"); ASSERT_FALSE(d); ); - DO_EXPECT(cbs, true, false); + EXPECT_ERR_WARN(cbs, true, false); // assert that I can only ignore something once RUN_SAFE(conf.ignoreConfParam("ign")); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); RUN_SAFE(conf.ignoreConfParam("ign")); - DO_EXPECT(cbs, true, false); + EXPECT_ERR_WARN(cbs, true, false); RUN_SAFE(conf.ignoreConfParamAll("ign2")); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); RUN_SAFE(conf.ignoreConfParamAll("ign2")); - DO_EXPECT(cbs, true, false); + EXPECT_ERR_WARN(cbs, true, false); // assert that I cannot read a parameter twice RUN_SAFE(conf.getConfParam<bool>("bool")); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); RUN_SAFE(conf.getConfParam<bool>("bool")); - DO_EXPECT(cbs, true, false); + EXPECT_ERR_WARN(cbs, true, false); } // ConfigTree destroyed here // There will bewarnings because I don't succeed in reading every setting, // and furthermore I read some setting too often. - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); } @@ -337,39 +421,49 @@ TEST(BaseLibConfigTree, BadKeynames) boost::property_tree::ptree ptree; std::istringstream xml_str(xml); - read_xml(xml_str, ptree); + read_xml(xml_str, ptree, + boost::property_tree::xml_parser::no_comments | + boost::property_tree::xml_parser::trim_whitespace); Callbacks cbs; { BaseLib::ConfigTreeNew conf(ptree, cbs.get_error_cb(), cbs.get_warning_cb()); - for (std::string tag : { "<", "Z", ".", "$", "0", "", "/" }) + for (auto tag : { "<", "Z", ".", "$", "0", "", "/", "_", "a__" }) { RUN_SAFE(conf.getConfParam<int>(tag)); - DO_EXPECT(cbs, true, false); + EXPECT_ERR_WARN(cbs, true, false); RUN_SAFE(conf.getConfParam<int>(tag, 500)); - DO_EXPECT(cbs, true, false); + EXPECT_ERR_WARN(cbs, true, false); RUN_SAFE(conf.getConfParamOptional<int>(tag)); - DO_EXPECT(cbs, true, false); + EXPECT_ERR_WARN(cbs, true, false); RUN_SAFE(conf.getConfParamList<int>(tag)); + EXPECT_ERR_WARN(cbs, true, false); + + RUN_SAFE(conf.getConfParam(tag)); + EXPECT_ERR_WARN(cbs, true, false); + RUN_SAFE(conf.getConfParamOptional(tag)); + EXPECT_ERR_WARN(cbs, true, false); - DO_EXPECT(cbs, true, false); RUN_SAFE(conf.peekConfParam<int>(tag)); - DO_EXPECT(cbs, true, false); + EXPECT_ERR_WARN(cbs, true, false); RUN_SAFE(conf.checkConfParam<int>(tag, 500)); + EXPECT_ERR_WARN(cbs, true, false); - DO_EXPECT(cbs, true, false); RUN_SAFE(conf.getConfSubtree(tag)); - DO_EXPECT(cbs, true, false); + EXPECT_ERR_WARN(cbs, true, false); RUN_SAFE(conf.getConfSubtreeOptional(tag)); - DO_EXPECT(cbs, true, false); + EXPECT_ERR_WARN(cbs, true, false); RUN_SAFE(conf.getConfSubtreeList(tag)); - DO_EXPECT(cbs, true, false); + EXPECT_ERR_WARN(cbs, true, false); + + RUN_SAFE(conf.getConfAttribute<int>(tag)); + EXPECT_ERR_WARN(cbs, true, false); } } // ConfigTree destroyed here - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); } // String literals are somewhat special for template classes @@ -381,22 +475,25 @@ TEST(BaseLibConfigTree, ConfigTreeStringLiterals) boost::property_tree::ptree ptree; std::istringstream xml_str(xml); - read_xml(xml_str, ptree); + read_xml(xml_str, ptree, + boost::property_tree::xml_parser::no_comments | + boost::property_tree::xml_parser::trim_whitespace); Callbacks cbs; { BaseLib::ConfigTreeNew conf(ptree, cbs.get_error_cb(), cbs.get_warning_cb()); EXPECT_EQ("test", conf.getConfParam<std::string>("s", "XX")); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); + // <n> not present in the XML, so return the default value EXPECT_EQ("XX", conf.getConfParam<std::string>("n", "XX")); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); conf.checkConfParam("t", "Test"); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); } // ConfigTree destroyed here - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); } // String literals are somewhat special for template classes @@ -408,24 +505,26 @@ TEST(BaseLibConfigTree, ConfigTreeMoveConstruct) boost::property_tree::ptree ptree; std::istringstream xml_str(xml); - read_xml(xml_str, ptree); + read_xml(xml_str, ptree, + boost::property_tree::xml_parser::no_comments | + boost::property_tree::xml_parser::trim_whitespace); Callbacks cbs; { BaseLib::ConfigTreeNew conf(ptree, cbs.get_error_cb(), cbs.get_warning_cb()); EXPECT_EQ("test", conf.getConfParam<std::string>("s", "XX")); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); BaseLib::ConfigTreeNew conf2(std::move(conf)); EXPECT_EQ("XX", conf2.getConfParam<std::string>("n", "XX")); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); conf2.checkConfParam("t", "Test"); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); } // ConfigTree destroyed here - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); } // String literals are somewhat special for template classes @@ -437,27 +536,53 @@ TEST(BaseLibConfigTree, ConfigTreeMoveAssign) boost::property_tree::ptree ptree; std::istringstream xml_str(xml); - read_xml(xml_str, ptree); + read_xml(xml_str, ptree, + boost::property_tree::xml_parser::no_comments | + boost::property_tree::xml_parser::trim_whitespace); Callbacks cbs; { BaseLib::ConfigTreeNew conf(ptree, cbs.get_error_cb(), cbs.get_warning_cb()); EXPECT_EQ("test", conf.getConfParam<std::string>("s", "XX")); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); BaseLib::ConfigTreeNew conf2(ptree, cbs.get_error_cb(), cbs.get_warning_cb()); conf2 = std::move(conf); // Expect warning because config tree has not been traversed // entirely before. - DO_EXPECT(cbs, false, true); + EXPECT_ERR_WARN(cbs, false, true); EXPECT_EQ("XX", conf2.getConfParam<std::string>("n", "XX")); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); conf2.checkConfParam("t", "Test"); - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); } // ConfigTree destroyed here - DO_EXPECT(cbs, false, false); + EXPECT_ERR_WARN(cbs, false, false); +} + + +TEST(BLT, TEST) +{ + const char xml[] = + "<s>test</s>" + "<t>Test</t>" + "<z/>"; + + // boost::property_tree::basic_ptree<std::string, char*, std::less<std::string>> ptree; + // boost::property_tree::basic_ptree<std::string, boost::optional<std::string>, std::less<std::string>> ptree; + boost::property_tree::ptree ptree; + std::istringstream xml_str(xml); + read_xml(xml_str, ptree, + boost::property_tree::xml_parser::no_comments | + boost::property_tree::xml_parser::trim_whitespace); + WARN("value: <%s>", ptree.get_child("z").get_value<std::string>().c_str()); + + auto opt = ptree.get_child("z").get_value_optional<std::string>(); + WARN("has value? -> %s", opt ? "true" : "false"); + + auto dat = ptree.get_child("z").data(); + WARN("value: <%s>", dat.c_str()); }