/***************************************************************************************** * * * GHOUL * * General Helpful Open Utility Library * * * * Copyright (c) 2012-2018 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * * without restriction, including without limitation the rights to use, copy, modify, * * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * * permit persons to whom the Software is furnished to do so, subject to the following * * conditions: * * * * The above copyright notice and this permission notice shall be included in all copies * * or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ #include #include #include #include #include namespace { // A non-existing configuration file const std::string _configuration0 = "${TEST_DIR}/configurationmanager/test0.cfg"; // The configuration1 test configuration has one key "t" = 1 const std::string _configuration1 = "${TEST_DIR}/configurationmanager/test1.cfg"; // The configuration1 test configuration has two keys "t" and "s" const std::string _configuration2 = "${TEST_DIR}/configurationmanager/test2.cfg"; // More complicated configuration file with nested tables const std::string _configuration3 = "${TEST_DIR}/configurationmanager/test3.cfg"; // Deeply nested configuration file with 12 level const std::string _configuration4 = "${TEST_DIR}/configurationmanager/test4.cfg"; // Testfile with glm::vecX, glm::matX const std::string _configuration5 = "${TEST_DIR}/configurationmanager/test5.cfg"; } /* Test checklist: --- loadConfiguration: existing file --- loadConfiguration: non-existing file --- getValue: key does not exist --- getValue: subtable does not exist --- getValue: overriding previous configuration --- getValue: function does not change passed value on error --- getValue: nested keys --- getValue: deep nesting of keys --- getValue: correct values returned for each type --- getValue: are all basic types implemented --- getValue: glm::vec2, glm::vec3, glm::vec4 implemented --- getValue: glm::matXxY implemented --- getValue: valid conversions --- setValue: all types implemented --- setValue: create subtables on the way --- setValue: value gets set correctly for each type --- setValue: value overwrites setting in configuration file --- setValue: deep nesting of keys --- setValue: nested keys --- setValue: glm::vec2, glm::vec3, glm::vec4, glm::mat3, glm::mat4 implemented --- hasKeys: deep nesting of keys --- hasKeys: subtables on the way do not exist --- hasKeys: correct values for all types --- hasKeys: nestedKeys --- timing */ class ConfigurationManagerTest : public testing::Test { protected: ConfigurationManagerTest() { _m = new ghoul::ConfigurationManager; } ~ConfigurationManagerTest() { if (_m) { delete _m; _m = nullptr; } } void reset() { _m->clear(); } ghoul::ConfigurationManager* _m; }; #ifdef GHL_TIMING_TESTS TEST_F(ConfigurationManagerTest, TimingTest) { std::ofstream logFile("ConfigurationManagerTest.timing"); START_TIMER(loadConfiguration1, logFile, 25); _m->loadConfiguration(_configuration1); FINISH_TIMER(loadConfiguration1, logFile); START_TIMER(loadConfiguration2, logFile, 25); _m->loadConfiguration(_configuration2); FINISH_TIMER(loadConfiguration2, logFile); START_TIMER(loadConfiguration3, logFile, 25); _m->loadConfiguration(_configuration3); FINISH_TIMER(loadConfiguration3, logFile); START_TIMER(loadConfiguration4, logFile, 25); _m->loadConfiguration(_configuration4); FINISH_TIMER(loadConfiguration4, logFile); START_TIMER(loadConfiguration5, logFile, 25); _m->loadConfiguration(_configuration5); FINISH_TIMER(loadConfiguration5, logFile); START_TIMER(loadConfiguration12, logFile, 25); _m->loadConfiguration(_configuration1); _m->loadConfiguration(_configuration2); FINISH_TIMER(loadConfiguration12, logFile); START_TIMER(loadConfiguration123, logFile, 25); _m->loadConfiguration(_configuration1); _m->loadConfiguration(_configuration2); _m->loadConfiguration(_configuration3); FINISH_TIMER(loadConfiguration123, logFile); START_TIMER(loadConfiguration1234, logFile, 25); _m->loadConfiguration(_configuration1); _m->loadConfiguration(_configuration2); _m->loadConfiguration(_configuration3); _m->loadConfiguration(_configuration4); FINISH_TIMER(loadConfiguration1234, logFile); START_TIMER(loadConfiguration12345, logFile, 25); _m->loadConfiguration(_configuration1); _m->loadConfiguration(_configuration2); _m->loadConfiguration(_configuration3); _m->loadConfiguration(_configuration4); _m->loadConfiguration(_configuration5); FINISH_TIMER(loadConfiguration12345, logFile); START_TIMER(setValueLevel0Int, logFile, 25); _m->setValue("t", 1); FINISH_TIMER(setValueLevel0Int, logFile); START_TIMER(setValueLevel1Int, logFile, 25); _m->setValue("t.t", 1); FINISH_TIMER(setValueLevel1Int, logFile); START_TIMER(setValueLevel10Int, logFile, 25); _m->setValue("t.t.t.t.t.t.t.t.t.t", 1); FINISH_TIMER(setValueLevel10Int, logFile); START_TIMER(setValueLevel0dvec4, logFile, 25); _m->setValue("t", glm::dvec4(1.0)); FINISH_TIMER(setValueLevel0dvec4, logFile); START_TIMER(setValueLevel0dmat4, logFile, 25); _m->setValue("t", glm::dmat4(1.0)); FINISH_TIMER(setValueLevel0dmat4, logFile); { int i; START_TIMER_PREPARE(getValueLevel0Int, logFile, 25, {_m->setValue("t", 1);}); _m->getValue("t", i); FINISH_TIMER(getValueLevel0Int, logFile); START_TIMER(getValueLevel0IntEmpty, logFile, 25); _m->getValue("t", i); FINISH_TIMER(getValueLevel0IntEmpty, logFile); START_TIMER_PREPARE(getValueLevel1Int, logFile, 25, {_m->setValue("t.t", 1);}); _m->getValue("t.t", i); FINISH_TIMER(getValueLevel1Int, logFile); START_TIMER_PREPARE(getValueLevel10Int, logFile, 25, {_m->setValue("t.t.t.t.t.t.t.t.t.t", 1);}); _m->getValue("t.t.t.t.t.t.t.t.t.t", i); FINISH_TIMER(getValueLevel10Int, logFile); START_TIMER(getValueLevel10IntEmpty, logFile, 25); _m->getValue("t.t.t.t.t.t.t.t.t.t", i); FINISH_TIMER(getValueLevel10IntEmpty, logFile); } { START_TIMER(setValueLevel1vec2, logFile, 25); _m->setValue("t", glm::vec2(1.0)); FINISH_TIMER(setValueLevel1vec2, logFile); } { START_TIMER(setValueLevel1vec3, logFile, 25); _m->setValue("t", glm::vec3(1.0)); FINISH_TIMER(setValueLevel1vec3, logFile); } { START_TIMER(setValueLevel1vec4, logFile, 25); _m->setValue("t", glm::vec4(1.0)); FINISH_TIMER(setValueLevel1vec4, logFile); } { START_TIMER(setValueLevel1dvec2, logFile, 25); _m->setValue("t", glm::dvec2(1.0)); FINISH_TIMER(setValueLevel1dvec2, logFile); } { START_TIMER(setValueLevel1dvec3, logFile, 25); _m->setValue("t", glm::dvec3(1.0)); FINISH_TIMER(setValueLevel1dvec3, logFile); } { START_TIMER(setValueLevel1dvec4, logFile, 25); _m->setValue("t", glm::dvec4(1.0)); FINISH_TIMER(setValueLevel1dvec4, logFile); } { START_TIMER(setValueLevel1ivec2, logFile, 25); _m->setValue("t", glm::ivec2(1.0)); FINISH_TIMER(setValueLevel1ivec2, logFile); } { START_TIMER(setValueLevel1ivec3, logFile, 25); _m->setValue("t", glm::ivec3(1.0)); FINISH_TIMER(setValueLevel1ivec3, logFile); } { START_TIMER(setValueLevel1ivec4, logFile, 25); _m->setValue("t", glm::ivec4(1.0)); FINISH_TIMER(setValueLevel1ivec4, logFile); } { START_TIMER(setValueLevel1bvec2, logFile, 25); _m->setValue("t", glm::bvec2(true)); FINISH_TIMER(setValueLevel1bvec2, logFile); } { START_TIMER(setValueLevel1bvec3, logFile, 25); _m->setValue("t", glm::bvec3(true)); FINISH_TIMER(setValueLevel1bvec3, logFile); } { START_TIMER(setValueLevel1bvec4, logFile, 25); _m->setValue("t", glm::bvec4(true)); FINISH_TIMER(setValueLevel1bvec4, logFile); } { START_TIMER(setValueLevel1uvec2, logFile, 25); _m->setValue("t", glm::uvec2(1.0)); FINISH_TIMER(setValueLevel1uvec2, logFile); } { START_TIMER(setValueLevel1uvec3, logFile, 25); _m->setValue("t", glm::uvec3(1.0)); FINISH_TIMER(setValueLevel1uvec3, logFile); } { START_TIMER(setValueLevel1uvec4, logFile, 25); _m->setValue("t", glm::uvec4(1.0)); FINISH_TIMER(setValueLevel1uvec4, logFile); } { START_TIMER(setValueLevel1dmat2x4, logFile, 25); _m->setValue("t", glm::dmat2x4(1.0)); FINISH_TIMER(setValueLevel1dmat2x4, logFile); } { START_TIMER(setValueLevel1dmat2x3, logFile, 25); _m->setValue("t", glm::dmat2x3(1.0)); FINISH_TIMER(setValueLevel1dmat2x3, logFile); } { START_TIMER(setValueLevel1dmat2, logFile, 25); _m->setValue("t", glm::dmat2(1.0)); FINISH_TIMER(setValueLevel1dmat2, logFile); } { START_TIMER(setValueLevel1dmat3x2, logFile, 25); _m->setValue("t", glm::dmat3x2(1.0)); FINISH_TIMER(setValueLevel1dmat3x2, logFile); } { START_TIMER(setValueLevel1dmat3x4, logFile, 25); _m->setValue("t", glm::dmat3x4(1.0)); FINISH_TIMER(setValueLevel1dmat3x4, logFile); } { START_TIMER(setValueLevel1dmat3, logFile, 25); _m->setValue("t", glm::dmat3(1.0)); FINISH_TIMER(setValueLevel1dmat3, logFile); } { START_TIMER(setValueLevel1dmat4x2, logFile, 25); _m->setValue("t", glm::dmat4x3(1.0)); FINISH_TIMER(setValueLevel1dmat4x2, logFile); } { START_TIMER(setValueLevel1dmat4x3, logFile, 25); _m->setValue("t", glm::dmat4x3(1.0)); FINISH_TIMER(setValueLevel1dmat4x3, logFile); } { START_TIMER(setValueLevel1dmat4, logFile, 25); _m->setValue("t", glm::dmat4(1.0)); FINISH_TIMER(setValueLevel1dmat4, logFile); } { glm::vec2 i; START_TIMER_PREPARE(getValueLevel1vec2, logFile, 25, {_m->setValue("t", glm::vec2(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1vec2, logFile); } { glm::vec3 i; START_TIMER_PREPARE(getValueLevel1vec3, logFile, 25, {_m->setValue("t", glm::vec3(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1vec3, logFile); } { glm::vec4 i; START_TIMER_PREPARE(getValueLevel1vec4, logFile, 25, {_m->setValue("t", glm::vec4(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1vec4, logFile); } { glm::dvec2 i; START_TIMER_PREPARE(getValueLevel1dvec2, logFile, 25, {_m->setValue("t", glm::dvec2(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1dvec2, logFile); } { glm::dvec3 i; START_TIMER_PREPARE(getValueLevel1dvec3, logFile, 25, {_m->setValue("t", glm::dvec3(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1dvec3, logFile); } { glm::dvec4 i; START_TIMER_PREPARE(getValueLevel1dvec4, logFile, 25, {_m->setValue("t", glm::dvec4(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1dvec4, logFile); } { glm::ivec2 i; START_TIMER_PREPARE(getValueLevel1ivec2, logFile, 25, {_m->setValue("t", glm::ivec2(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1ivec2, logFile); } { glm::ivec3 i; START_TIMER_PREPARE(getValueLevel1ivec3, logFile, 25, {_m->setValue("t", glm::ivec3(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1ivec3, logFile); } { glm::ivec4 i; START_TIMER_PREPARE(getValueLevel1ivec4, logFile, 25, {_m->setValue("t", glm::ivec4(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1ivec4, logFile); } { glm::bvec2 i; START_TIMER_PREPARE(getValueLevel1bvec2, logFile, 25, {_m->setValue("t", glm::bvec2(true));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1bvec2, logFile); } { glm::bvec3 i; START_TIMER_PREPARE(getValueLevel1bvec3, logFile, 25, {_m->setValue("t", glm::bvec3(true));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1bvec3, logFile); } { glm::bvec4 i; START_TIMER_PREPARE(getValueLevel1bvec4, logFile, 25, {_m->setValue("t", glm::bvec4(true));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1bvec4, logFile); } { glm::uvec2 i; START_TIMER_PREPARE(getValueLevel1uvec2, logFile, 25, {_m->setValue("t", glm::uvec2(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1uvec2, logFile); } { glm::uvec3 i; START_TIMER_PREPARE(getValueLevel1uvec3, logFile, 25, {_m->setValue("t", glm::uvec3(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1uvec3, logFile); } { glm::uvec4 i; START_TIMER_PREPARE(getValueLevel1uvec4, logFile, 25, {_m->setValue("t", glm::uvec4(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1uvec4, logFile); } { glm::dmat2x4 i; START_TIMER_PREPARE(getValueLevel1dmat2x4, logFile, 25, {_m->setValue("t", glm::dmat2x4(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1dmat2x4, logFile); } { glm::dmat2x3 i; START_TIMER_PREPARE(getValueLevel1dmat2x3, logFile, 25, {_m->setValue("t", glm::dmat2x3(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1dmat2x3, logFile); } { glm::dmat2 i; START_TIMER_PREPARE(getValueLevel1dmat2, logFile, 25, {_m->setValue("t", glm::dmat2(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1dmat2, logFile); } { glm::dmat3x2 i; START_TIMER_PREPARE(getValueLevel1dmat3x2, logFile, 25, {_m->setValue("t", glm::dmat3x2(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1dmat3x2, logFile); } { glm::dmat3x4 i; START_TIMER_PREPARE(getValueLevel1dmat3x4, logFile, 25, {_m->setValue("t", glm::dmat3x4(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1dmat3x4, logFile); } { glm::dmat3 i; START_TIMER_PREPARE(getValueLevel1dmat3, logFile, 25, {_m->setValue("t", glm::dmat3(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1dmat3, logFile); } { glm::dmat4x2 i; START_TIMER_PREPARE(getValueLevel1dmat4x2, logFile, 25, {_m->setValue("t", glm::dmat4x2(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1dmat4x2, logFile); } { glm::dmat4x3 i; START_TIMER_PREPARE(getValueLevel1dmat4x3, logFile, 25, {_m->setValue("t", glm::dmat4x3(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1dmat4x3, logFile); } { glm::dmat4 i; START_TIMER_PREPARE(getValueLevel1dmat4, logFile, 25, {_m->setValue("t", glm::dmat4(1.0));}); _m->getValue("t", i); FINISH_TIMER(getValueLevel1dmat4, logFile); } START_TIMER(hasKeyLevel0Empty, logFile, 25); _m->hasKey("t"); FINISH_TIMER(hasKeyLevel0Empty, logFile); START_TIMER(hasKeyLevel10Empty, logFile, 25); _m->hasKey("t.t.t.t.t.t.t.t.t.t"); FINISH_TIMER(hasKeyLevel10Empty, logFile); START_TIMER_PREPARE(hasKeyLevel0, logFile, 25, {_m->setValue("t", 1);}); _m->hasKey("t"); FINISH_TIMER(hasKeyLevel0, logFile); START_TIMER_PREPARE(hasKeyLevel10, logFile, 25, {_m->setValue("t.t.t.t.t.t.t.t.t.t", 1);}); _m->hasKey("t.t.t.t.t.t.t.t.t.t"); FINISH_TIMER(hasKeyLevel10, logFile); } #endif // GHL_TIMING_TESTS TEST_F(ConfigurationManagerTest, ReinitTest) { _m->setValue("t", int(2)); _m->clear(); const bool success = _m->hasKey("t"); EXPECT_EQ(false, success); } TEST_F(ConfigurationManagerTest, LoadConfigurationTest) { const bool success0 = _m->loadConfiguration(_configuration0); ASSERT_EQ(false, success0) << "Loading a non-existing file should fail gracefully"; const bool success1 = _m->loadConfiguration(_configuration1); ASSERT_EQ(true, success1) << "Loading of configuration file 'test1.cfg'"; const bool success2 = _m->loadConfiguration(_configuration2); ASSERT_EQ(true, success2) << "Loading of configuration file 'test2.cfg'"; const bool success3 = _m->loadConfiguration(_configuration3); ASSERT_EQ(true, success3) << "Loading of configuration file 'test3.cfg'"; const bool success4 = _m->loadConfiguration(_configuration4); ASSERT_EQ(true, success4) << "Loading of configuration file 'test4.cfg'"; } TEST_F(ConfigurationManagerTest, KeysFunction) { // The empty configuration should not have any keys size_t nKeys = _m->keys().size(); EXPECT_EQ(0, nKeys) << "The empty configuration should not have any keys"; _m->loadConfiguration(_configuration1); nKeys = _m->keys().size(); EXPECT_EQ(1, nKeys) << "test1"; _m->loadConfiguration(_configuration3); nKeys = _m->keys().size(); EXPECT_EQ(3, nKeys) << "base: test1 + test3"; nKeys = _m->keys("s").size(); EXPECT_EQ(3, nKeys) << "s: test1 + test3"; nKeys = _m->keys("s.3").size(); EXPECT_EQ(2, nKeys) << "s.3: test1 + test3"; _m->loadConfiguration(_configuration4); const char* keys[] = { "a", "a.a", "a.a.a", "a.a.a.a", "a.a.a.a.a", "a.a.a.a.a.a", "a.a.a.a.a.a.a", "a.a.a.a.a.a.a.a", "a.a.a.a.a.a.a.a.a", "a.a.a.a.a.a.a.a.a.a", "a.a.a.a.a.a.a.a.a.a.a", "a.a.a.a.a.a.a.a.a.a.a.a" }; for (int i = 0; i < 12; ++i) { nKeys = _m->keys(keys[i]).size(); EXPECT_EQ(2, nKeys) << keys[i] <<": test1 + test3"; } for (int i = 0; i < 12; ++i) { const bool hasKey = _m->hasKey(keys[i]); EXPECT_EQ(true, hasKey) << keys[i] <<": test1 + test3"; } const char* keysB[] = { "b", "b.b", "b.b.b", "b.b.b.b", "b.b.b.b.b", "b.b.b.b.b.b", "b.b.b.b.b.b.b", "b.b.b.b.b.b.b.b", "b.b.b.b.b.b.b.b.b", "b.b.b.b.b.b.b.b.b.b", "b.b.b.b.b.b.b.b.b.b.b", "b.b.b.b.b.b.b.b.b.b.b.b" }; _m->setValue(keysB[11], int(0), true); for (int i = 0; i < 12; ++i) EXPECT_EQ(true, _m->hasKey(keysB[i])) << keysB[i] <<": test1 + test3"; } TEST_F(ConfigurationManagerTest, HasKeySubtable) { _m->loadConfiguration(_configuration1); const bool tSuccess = _m->hasKey("t"); ASSERT_EQ(true, tSuccess) << "t"; const bool tsSuccess = _m->hasKey("t.s"); EXPECT_EQ(false, tsSuccess) << "t.s"; const bool sSuccess = _m->hasKey("s"); EXPECT_EQ(false, sSuccess) << "s"; const bool sxSuccess = _m->hasKey("s.x"); EXPECT_EQ(false, sxSuccess) << "s.x"; } TEST_F(ConfigurationManagerTest, HasKeyTypes) { _m->setValue("t", ghoul::Dictionary()); _m->setValue("t.bool", bool(1)); _m->setValue("t.char", char(1)); _m->setValue("t.unsignedchar", (unsigned char)(1)); _m->setValue("t.signedchar", (signed char)(1)); _m->setValue("t.wchar", wchar_t(1)); _m->setValue("t.short", short(1)); _m->setValue("t.unsignedshort", (unsigned short)(1)); _m->setValue("t.int", int(1)); _m->setValue("t.unsignedint", (unsigned int)(1)); _m->setValue("t.long", long(1)); _m->setValue("t.unsignedlong", (unsigned long)(1)); _m->setValue("t.longlong", (long long)(1)); _m->setValue("t.unsignedlonglong", (unsigned long long)(1)); _m->setValue("t.float", float(1)); _m->setValue("t.double", double(1)); _m->setValue("t.longdouble", (long double)(1)); _m->setValue("t.string", "1"); bool success = _m->hasKey("t.bool"); EXPECT_EQ(true, success) << "t.bool"; success = _m->hasKey("t.char"); EXPECT_EQ(true, success) << "t.char"; success = _m->hasKey("t.unsignedchar"); EXPECT_EQ(true, success) << "t.unsignedchar"; success = _m->hasKey("t.signedchar"); EXPECT_EQ(true, success) << "t.signedchar"; success = _m->hasKey("t.wchar"); EXPECT_EQ(true, success) << "t.wchar"; success = _m->hasKey("t.short"); EXPECT_EQ(true, success) << "t.short"; success = _m->hasKey("t.unsignedshort"); EXPECT_EQ(true, success) << "t.unsignedshort"; success = _m->hasKey("t.int"); EXPECT_EQ(true, success) << "t.int"; success = _m->hasKey("t.unsignedint"); EXPECT_EQ(true, success) << "t.unsignedint"; success = _m->hasKey("t.long"); EXPECT_EQ(true, success) << "t.long"; success = _m->hasKey("t.unsignedlong"); EXPECT_EQ(true, success) << "t.unsignedlong"; success = _m->hasKey("t.longlong"); EXPECT_EQ(true, success) << "t.longlong"; success = _m->hasKey("t.unsignedlonglong"); EXPECT_EQ(true, success) << "t.unsignedlonglong"; success = _m->hasKey("t.float"); EXPECT_EQ(true, success) << "t.float"; success = _m->hasKey("t.double"); EXPECT_EQ(true, success) << "t.double"; success = _m->hasKey("t.longdouble"); EXPECT_EQ(true, success) << "t.longdouble"; success = _m->hasKey("t.string"); EXPECT_EQ(true, success) << "t.string"; } TEST_F(ConfigurationManagerTest, GetValueFunction) { std::string test; bool success = _m->getValue("key", test); EXPECT_EQ(false, success) << "Empty configuration"; success = _m->getValue("key.key", test); EXPECT_EQ(false, success) << "Empty configuration recursive"; _m->loadConfiguration(_configuration1); _m->loadConfiguration(_configuration3); int testInt; success = _m->getValue("t", testInt); EXPECT_EQ(true, success) << "test1+test3 (t)"; EXPECT_EQ(1, testInt) << "test1+test3 (t)"; success = _m->getValue("s.a", test); EXPECT_EQ(false, success) << "test1+test3 (s.a)"; success = _m->getValue("s.1", test); EXPECT_EQ(true, success) << "test1+test3 (s.1)"; success = _m->getValue("s.1.a", test); EXPECT_EQ(false, success) << "test1+test3 (s.1.a)"; success = _m->getValue("s.3.a", test); EXPECT_EQ(true, success) << "test1+test3 (s.3.a)"; std::vector testVec; success = _m->getValue("key", testVec); EXPECT_EQ(false, success) << "test1+test3: Vector access"; } template void correctnessHelperGetValue(ghoul::ConfigurationManager* m, const std::string& key) { T value = T(0); const bool success = m->getValue(key, value); EXPECT_EQ(true, success) << "Type: " << typeid(T).name(); EXPECT_EQ(T(1), value) << "Type: " << typeid(T).name(); } TEST_F(ConfigurationManagerTest, GetValueCorrectness) { _m->loadConfiguration(_configuration1); correctnessHelperGetValue(_m, "t"); correctnessHelperGetValue(_m, "t"); correctnessHelperGetValue(_m, "t"); correctnessHelperGetValue(_m, "t"); correctnessHelperGetValue(_m, "t"); correctnessHelperGetValue(_m, "t"); correctnessHelperGetValue(_m, "t"); correctnessHelperGetValue(_m, "t"); correctnessHelperGetValue(_m, "t"); correctnessHelperGetValue(_m, "t"); correctnessHelperGetValue(_m, "t"); correctnessHelperGetValue(_m, "t"); correctnessHelperGetValue(_m, "t"); correctnessHelperGetValue(_m, "t"); correctnessHelperGetValue(_m, "t"); correctnessHelperGetValue(_m, "t"); std::string value; const bool success = _m->getValue("t", value); EXPECT_EQ(true, success) << "Type: " << typeid(std::string).name(); EXPECT_STREQ("1", value.c_str()) << "Type: " << typeid(std::string).name(); } TEST_F(ConfigurationManagerTest, SetValueRecursive) { _m->setValue("t.a.b.c", 1); EXPECT_EQ(true, _m->hasKey("t")); EXPECT_EQ(true, _m->hasKey("t.a")); EXPECT_EQ(true, _m->hasKey("t.a.b")); EXPECT_EQ(true, _m->hasKey("t.a.b.c")); } TEST_F(ConfigurationManagerTest, SetValueCorrectness) { _m->setValue("t.bool", bool(1)); _m->setValue("t.char", char(1)); _m->setValue("t.unsignedchar", (unsigned char)(1)); _m->setValue("t.signedchar", (signed char)(1)); _m->setValue("t.wchar", wchar_t(1)); _m->setValue("t.short", short(1)); _m->setValue("t.unsignedshort", (unsigned short)(1)); _m->setValue("t.int", int(1)); _m->setValue("t.unsignedint", (unsigned int)(1)); _m->setValue("t.long", long(1)); _m->setValue("t.unsignedlong", (unsigned long)(1)); _m->setValue("t.longlong", (long long)(1)); _m->setValue("t.unsignedlonglong", (unsigned long long)(1)); _m->setValue("t.float", float(1)); _m->setValue("t.double", double(1)); _m->setValue("t.longdouble", (long double)(1)); _m->setValue("t.string", "1"); correctnessHelperGetValue(_m, "t.bool"); correctnessHelperGetValue(_m, "t.char"); correctnessHelperGetValue(_m, "t.unsignedchar"); correctnessHelperGetValue(_m, "t.signedchar"); correctnessHelperGetValue(_m, "t.wchar"); correctnessHelperGetValue(_m, "t.short"); correctnessHelperGetValue(_m, "t.unsignedshort"); correctnessHelperGetValue(_m, "t.int"); correctnessHelperGetValue(_m, "t.unsignedint"); correctnessHelperGetValue(_m, "t.long"); correctnessHelperGetValue(_m, "t.unsignedlong"); correctnessHelperGetValue(_m, "t.longlong"); correctnessHelperGetValue(_m, "t.unsignedlonglong"); correctnessHelperGetValue(_m, "t.float"); correctnessHelperGetValue(_m, "t.double"); correctnessHelperGetValue(_m, "t.longdouble"); std::string value; const bool success = _m->getValue("t.string", value); EXPECT_EQ(true, success) << "Type: " << typeid(std::string).name(); EXPECT_STREQ("1", value.c_str()) << "Type: " << typeid(std::string).name(); } TEST_F(ConfigurationManagerTest, SetValueOverridesConfiguration) { _m->loadConfiguration(_configuration1); int v = 0; bool success = _m->getValue("t", v); ASSERT_EQ(true, success) << "t"; ASSERT_EQ(1, v) << "t"; _m->setValue("t", int(2)); success = _m->getValue("t", v); ASSERT_EQ(true, success) << "t"; ASSERT_EQ(2, v) << "t"; } TEST_F(ConfigurationManagerTest, GetValueConversions) { // converting from 1 -> all types is done in GetValueCorrectness _m->loadConfiguration(_configuration2); correctnessHelperGetValue(_m, "s.a1"); correctnessHelperGetValue(_m, "s.a1"); correctnessHelperGetValue(_m, "s.a1"); correctnessHelperGetValue(_m, "s.a1"); correctnessHelperGetValue(_m, "s.a1"); correctnessHelperGetValue(_m, "s.a1"); correctnessHelperGetValue(_m, "s.a1"); correctnessHelperGetValue(_m, "s.a1"); correctnessHelperGetValue(_m, "s.a1"); correctnessHelperGetValue(_m, "s.a1"); correctnessHelperGetValue(_m, "s.a1"); correctnessHelperGetValue(_m, "s.a1"); correctnessHelperGetValue(_m, "s.a1"); correctnessHelperGetValue(_m, "s.a1"); correctnessHelperGetValue(_m, "s.a1"); correctnessHelperGetValue(_m, "s.a1"); std::string value; const bool success = _m->getValue("s.a1", value); EXPECT_EQ(true, success) << "Type: " << typeid(std::string).name(); EXPECT_STREQ("1", value.c_str()) << "Type: " << typeid(std::string).name(); } TEST_F(ConfigurationManagerTest, StringKeyVsIntKey) { _m->loadConfiguration(_configuration3); int v = 0; bool success = _m->getValue("tt[\"1\"]", v); ASSERT_EQ(true, success) << "tt.1"; EXPECT_EQ(2, v) << "tt.1"; success = _m->getValue("tt[1]", v); ASSERT_EQ(true, success) << "tt[1]"; EXPECT_EQ(1, v) << "tt[1]"; } TEST_F(ConfigurationManagerTest, InvalidKeyAccessInvariant) { // Accessing an invalid key should not change the tested argument std::mt19937 rd; { std::uniform_int_distribution dist; for (int i = 0; i < 10; ++i) { const int testValue = dist(rd); int test = testValue; _m->getValue("key", test); ASSERT_EQ(testValue, test) << "invariant int"; } } { std::uniform_real_distribution dist; for (int i = 0; i < 10; ++i) { const float testValue = dist(rd); float test = testValue; _m->getValue("key", test); ASSERT_EQ(testValue, test) << "invariant float"; } } } TEST_F(ConfigurationManagerTest, HasKeyFunction) { bool success = _m->hasKey("key"); EXPECT_EQ(false, success) << "empty configuration"; _m->loadConfiguration(_configuration1); success = _m->hasKey("t"); EXPECT_EQ(true, success) << "test1 (t)"; success = _m->hasKey("s"); EXPECT_EQ(false, success) << "test1 (s)"; _m->loadConfiguration(_configuration2); success = _m->hasKey("s.a"); EXPECT_EQ(true, success) << "test1+test2 (s.a)"; success = _m->hasKey("s.c"); EXPECT_EQ(false, success) << "test1+test2 (s.c)"; } TEST_F(ConfigurationManagerTest, MultipleKeyLoadOverwrite) { _m->loadConfiguration(_configuration1); int value; _m->getValue("t", value); EXPECT_EQ(1, value); _m->loadConfiguration(_configuration2); // configuration2 should overwrite the value t in configuration1 _m->getValue("t", value); EXPECT_EQ(2, value); } template void vectorClassHelper(ghoul::ConfigurationManager* m, const std::string& key) { T value = T(0); const bool success = m->getValue(key, value); EXPECT_EQ(true, success) << "Type: " << typeid(T).name() << " | Key: " << key; EXPECT_EQ(T(glm::vec4(5, 6, 7, 8)), value) << "Type: " << typeid(T).name() << " | Key: " << key; } template <> void vectorClassHelper(ghoul::ConfigurationManager* m, const std::string& key) { glm::bvec2 value = glm::bvec2(false); const bool success = m->getValue(key, value); EXPECT_EQ(true, success) << "Type: bvec2 | Key: " << key; EXPECT_EQ(true, value.x) << "Type: bvec2 | Key: " << key; EXPECT_EQ(true, value.y) << "Type: bvec2 | Key: " << key; } template <> void vectorClassHelper(ghoul::ConfigurationManager* m, const std::string& key) { glm::bvec3 value = glm::bvec3(false); const bool success = m->getValue(key, value); EXPECT_EQ(true, success) << "Type: bvec3 | Key: " << key; EXPECT_EQ(true, value.x) << "Type: bvec3 | Key: " << key; EXPECT_EQ(true, value.y) << "Type: bvec3 | Key: " << key; EXPECT_EQ(true, value.z) << "Type: bvec3 | Key: " << key; } template <> void vectorClassHelper(ghoul::ConfigurationManager* m, const std::string& key) { glm::bvec4 value = glm::bvec4(false); const bool success = m->getValue(key, value); EXPECT_EQ(true, success) << "Type: bvec4 | Key: " << key; EXPECT_EQ(true, value.x) << "Type: bvec4 | Key: " << key; EXPECT_EQ(true, value.y) << "Type: bvec4 | Key: " << key; EXPECT_EQ(true, value.z) << "Type: bvec4 | Key: " << key; EXPECT_EQ(true, value.w) << "Type: bvec4 | Key: " << key; } TEST_F(ConfigurationManagerTest, VectorClassesGet) { _m->loadConfiguration(_configuration5); vectorClassHelper(_m, "n2"); vectorClassHelper(_m, "num2"); vectorClassHelper(_m, "xy"); vectorClassHelper(_m, "rg"); vectorClassHelper(_m, "st"); vectorClassHelper(_m, "n2"); vectorClassHelper(_m, "num2"); vectorClassHelper(_m, "xy"); vectorClassHelper(_m, "rg"); vectorClassHelper(_m, "st"); vectorClassHelper(_m, "n2"); vectorClassHelper(_m, "num2"); vectorClassHelper(_m, "xy"); vectorClassHelper(_m, "rg"); vectorClassHelper(_m, "st"); vectorClassHelper(_m, "n2"); vectorClassHelper(_m, "num2"); vectorClassHelper(_m, "xy"); vectorClassHelper(_m, "rg"); vectorClassHelper(_m, "st"); vectorClassHelper(_m, "n2"); vectorClassHelper(_m, "num2"); vectorClassHelper(_m, "xy"); vectorClassHelper(_m, "rg"); vectorClassHelper(_m, "st"); vectorClassHelper(_m, "n3"); vectorClassHelper(_m, "num3"); vectorClassHelper(_m, "xyz"); vectorClassHelper(_m, "rgb"); vectorClassHelper(_m, "stp"); vectorClassHelper(_m, "n3"); vectorClassHelper(_m, "num3"); vectorClassHelper(_m, "xyz"); vectorClassHelper(_m, "rgb"); vectorClassHelper(_m, "stp"); vectorClassHelper(_m, "n3"); vectorClassHelper(_m, "num3"); vectorClassHelper(_m, "xyz"); vectorClassHelper(_m, "rgb"); vectorClassHelper(_m, "stp"); vectorClassHelper(_m, "n3"); vectorClassHelper(_m, "num3"); vectorClassHelper(_m, "xyz"); vectorClassHelper(_m, "rgb"); vectorClassHelper(_m, "stp"); vectorClassHelper(_m, "n3"); vectorClassHelper(_m, "num3"); vectorClassHelper(_m, "xyz"); vectorClassHelper(_m, "rgb"); vectorClassHelper(_m, "stp"); vectorClassHelper(_m, "n4"); vectorClassHelper(_m, "num4"); vectorClassHelper(_m, "xyzw"); vectorClassHelper(_m, "rgba"); vectorClassHelper(_m, "stpq"); vectorClassHelper(_m, "n4"); vectorClassHelper(_m, "num4"); vectorClassHelper(_m, "xyzw"); vectorClassHelper(_m, "rgba"); vectorClassHelper(_m, "stpq"); vectorClassHelper(_m, "num4"); vectorClassHelper(_m, "n4"); vectorClassHelper(_m, "xyzw"); vectorClassHelper(_m, "rgba"); vectorClassHelper(_m, "stpq"); vectorClassHelper(_m, "num4"); vectorClassHelper(_m, "n4"); vectorClassHelper(_m, "xyzw"); vectorClassHelper(_m, "rgba"); vectorClassHelper(_m, "stpq"); vectorClassHelper(_m, "num4"); vectorClassHelper(_m, "n4"); vectorClassHelper(_m, "xyzw"); vectorClassHelper(_m, "rgba"); vectorClassHelper(_m, "stpq"); glm::vec3 value = glm::vec3(0.f); const bool success = _m->getValue("mix", value); EXPECT_EQ(false, success) << "Type: mixed"; EXPECT_EQ(glm::vec3(0.f), value) << "Type: mixed"; } TEST_F(ConfigurationManagerTest, VectorClassesSet) { _m->setValue("t.vec2", glm::vec2(5,6)); _m->setValue("t.vec3", glm::vec3(5,6,7)); _m->setValue("t.vec4", glm::vec4(5,6,7,8)); _m->setValue("t.dvec2", glm::dvec2(5,6)); _m->setValue("t.dvec3", glm::dvec3(5,6,7)); _m->setValue("t.dvec4", glm::dvec4(5,6,7,8)); _m->setValue("t.ivec2", glm::ivec2(5,6)); _m->setValue("t.ivec3", glm::ivec3(5,6,7)); _m->setValue("t.ivec4", glm::ivec4(5,6,7,8)); _m->setValue("t.uvec2", glm::uvec2(5,6)); _m->setValue("t.uvec3", glm::uvec3(5,6,7)); _m->setValue("t.uvec4", glm::uvec4(5,6,7,8)); _m->setValue("t.bvec2", glm::bvec2(true)); _m->setValue("t.bvec3", glm::bvec3(true)); _m->setValue("t.bvec4", glm::bvec4(true)); vectorClassHelper(_m, "t.vec2"); vectorClassHelper(_m, "t.vec3"); vectorClassHelper(_m, "t.vec4"); vectorClassHelper(_m, "t.dvec2"); vectorClassHelper(_m, "t.dvec3"); vectorClassHelper(_m, "t.dvec4"); vectorClassHelper(_m, "t.ivec2"); vectorClassHelper(_m, "t.ivec3"); vectorClassHelper(_m, "t.ivec4"); vectorClassHelper(_m, "t.uvec2"); vectorClassHelper(_m, "t.uvec3"); vectorClassHelper(_m, "t.uvec4"); vectorClassHelper(_m, "t.bvec2"); vectorClassHelper(_m, "t.bvec3"); vectorClassHelper(_m, "t.bvec4"); } template void matrixClassHelper(ghoul::ConfigurationManager* m, const std::string& key) { T value = T(0); const bool success = m->getValue(key, value); EXPECT_EQ(success, true) << "Type: " << typeid(T).name(); const glm::detail::tmat4x4 res4 = glm::detail::tmat4x4( 5.0, 6.0, 7.0, 8.0, 9.0, 10.0,11.0,12.0, 13.0,14.0,15.0,16.0, 17.0,18.0,19.0,20.0 ); const T res = T(res4); EXPECT_EQ(res, value) << "Type: " << typeid(T).name(); } TEST_F(ConfigurationManagerTest, MatrixClassesGet) { _m->loadConfiguration(_configuration5); matrixClassHelper(_m, "m2x2"); matrixClassHelper(_m, "m2x3"); matrixClassHelper(_m, "m2x4"); matrixClassHelper(_m, "m3x2"); matrixClassHelper(_m, "m3x3"); matrixClassHelper(_m, "m3x4"); matrixClassHelper(_m, "m4x2"); matrixClassHelper(_m, "m4x3"); matrixClassHelper(_m, "m4x4"); matrixClassHelper(_m, "m2x2"); matrixClassHelper(_m, "m2x3"); matrixClassHelper(_m, "m2x4"); matrixClassHelper(_m, "m3x2"); matrixClassHelper(_m, "m3x3"); matrixClassHelper(_m, "m3x4"); matrixClassHelper(_m, "m4x2"); matrixClassHelper(_m, "m4x3"); matrixClassHelper(_m, "m4x4"); } TEST_F(ConfigurationManagerTest, MatrixClassSet) { _m->setValue("f.m2x2", glm::mat2x2(5, 6, 9, 10)); _m->setValue("f.m2x3", glm::mat2x3(5, 6, 7, 9, 10, 11)); _m->setValue("f.m2x4", glm::mat2x4(5, 6, 7, 8, 9, 10, 11, 12)); _m->setValue("f.m3x2", glm::mat3x2(5, 6, 9, 10, 13, 14)); _m->setValue("f.m3x3", glm::mat3x3(5, 6, 7, 9, 10, 11, 13, 14, 15)); _m->setValue("f.m3x4", glm::mat3x4(5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)); _m->setValue("f.m4x2", glm::mat4x2(5, 6, 9, 10, 13, 14, 17, 18)); _m->setValue("f.m4x3", glm::mat4x3(5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18, 19)); _m->setValue("f.m4x4", glm::mat4x4(5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)); matrixClassHelper(_m, "f.m2x2"); matrixClassHelper(_m, "f.m2x3"); matrixClassHelper(_m, "f.m2x4"); matrixClassHelper(_m, "f.m3x2"); matrixClassHelper(_m, "f.m3x3"); matrixClassHelper(_m, "f.m3x4"); matrixClassHelper(_m, "f.m4x2"); matrixClassHelper(_m, "f.m4x3"); matrixClassHelper(_m, "f.m4x4"); _m->setValue("d.m2x2", glm::dmat2x2(5, 6, 9, 10)); _m->setValue("d.m2x3", glm::dmat2x3(5, 6, 7, 9, 10, 11)); _m->setValue("d.m2x4", glm::dmat2x4(5, 6, 7, 8, 9, 10, 11, 12)); _m->setValue("d.m3x2", glm::dmat3x2(5, 6, 9, 10, 13, 14)); _m->setValue("d.m3x3", glm::dmat3x3(5, 6, 7, 9, 10, 11, 13, 14, 15)); _m->setValue("d.m3x4", glm::dmat3x4(5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)); _m->setValue("d.m4x2", glm::dmat4x2(5, 6, 9, 10, 13, 14, 17, 18)); _m->setValue("d.m4x3", glm::dmat4x3(5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18, 19)); _m->setValue("d.m4x4", glm::dmat4x4( 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)); matrixClassHelper(_m, "d.m2x2"); matrixClassHelper(_m, "d.m2x3"); matrixClassHelper(_m, "d.m2x4"); matrixClassHelper(_m, "d.m3x2"); matrixClassHelper(_m, "d.m3x3"); matrixClassHelper(_m, "d.m3x4"); matrixClassHelper(_m, "d.m4x2"); matrixClassHelper(_m, "d.m4x3"); matrixClassHelper(_m, "d.m4x4"); }