mirror of
https://github.com/XRPLF/clio.git
synced 2025-12-06 17:27:58 +00:00
refactor: Clio Config (#1544)
Implementation of new config definition + methods + UT Steps that still need to be implemented: - Make ClioConfigDefinition and it's method to be as constexpr as possible - Getting User Config file and populating the values in ConfigDefinition while checking for constraints on user values - Replacing all the places where we fetch config values (by using config.valueOr/MaybeValue) to instead get it from Config Definition - Generate markdown file using Clio Config Description
This commit is contained in:
@@ -131,6 +131,13 @@ target_sources(
|
||||
web/ServerTests.cpp
|
||||
web/SweepHandlerTests.cpp
|
||||
web/WhitelistHandlerTests.cpp
|
||||
# New Config
|
||||
util/newconfig/ArrayViewTests.cpp
|
||||
util/newconfig/ObjectViewTests.cpp
|
||||
util/newconfig/ValueViewTests.cpp
|
||||
util/newconfig/ArrayTests.cpp
|
||||
util/newconfig/ConfigValueTests.cpp
|
||||
util/newconfig/ClioConfigDefinitionTests.cpp
|
||||
)
|
||||
|
||||
configure_file(test_data/cert.pem ${CMAKE_BINARY_DIR}/tests/unit/test_data/cert.pem COPYONLY)
|
||||
|
||||
50
tests/unit/util/newconfig/ArrayTests.cpp
Normal file
50
tests/unit/util/newconfig/ArrayTests.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2024, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "util/newconfig/Array.hpp"
|
||||
#include "util/newconfig/ConfigValue.hpp"
|
||||
#include "util/newconfig/ValueView.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace util::config;
|
||||
|
||||
TEST(ArrayTest, testConfigArray)
|
||||
{
|
||||
auto arr = Array{
|
||||
ConfigValue{ConfigType::Boolean}.defaultValue(false),
|
||||
ConfigValue{ConfigType::Integer}.defaultValue(1234),
|
||||
ConfigValue{ConfigType::Double}.defaultValue(22.22),
|
||||
};
|
||||
auto cv = arr.at(0);
|
||||
ValueView vv{cv};
|
||||
EXPECT_EQ(vv.asBool(), false);
|
||||
|
||||
auto cv2 = arr.at(1);
|
||||
ValueView vv2{cv2};
|
||||
EXPECT_EQ(vv2.asIntType<int>(), 1234);
|
||||
|
||||
EXPECT_EQ(arr.size(), 3);
|
||||
arr.emplaceBack(ConfigValue{ConfigType::String}.defaultValue("false"));
|
||||
|
||||
EXPECT_EQ(arr.size(), 4);
|
||||
auto cv4 = arr.at(3);
|
||||
ValueView vv4{cv4};
|
||||
EXPECT_EQ(vv4.asString(), "false");
|
||||
}
|
||||
139
tests/unit/util/newconfig/ArrayViewTests.cpp
Normal file
139
tests/unit/util/newconfig/ArrayViewTests.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2024, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "util/newconfig/ArrayView.hpp"
|
||||
#include "util/newconfig/ConfigDefinition.hpp"
|
||||
#include "util/newconfig/ConfigValue.hpp"
|
||||
#include "util/newconfig/FakeConfigData.hpp"
|
||||
#include "util/newconfig/ObjectView.hpp"
|
||||
#include "util/newconfig/ValueView.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
using namespace util::config;
|
||||
|
||||
struct ArrayViewTest : testing::Test {
|
||||
ClioConfigDefinition const configData = generateConfig();
|
||||
};
|
||||
|
||||
TEST_F(ArrayViewTest, ArrayValueTest)
|
||||
{
|
||||
ArrayView const arrVals = configData.getArray("array.[].sub");
|
||||
auto valIt = arrVals.begin<ValueView>();
|
||||
auto const precision = 1e-9;
|
||||
EXPECT_NEAR((*valIt++).asDouble(), 111.11, precision);
|
||||
EXPECT_NEAR((*valIt++).asDouble(), 4321.55, precision);
|
||||
EXPECT_EQ(valIt, arrVals.end<ValueView>());
|
||||
|
||||
EXPECT_NEAR(111.11, arrVals.valueAt(0).asDouble(), precision);
|
||||
EXPECT_NEAR(4321.55, arrVals.valueAt(1).asDouble(), precision);
|
||||
|
||||
ArrayView const arrVals2 = configData.getArray("array.[].sub2");
|
||||
auto val2It = arrVals2.begin<ValueView>();
|
||||
EXPECT_EQ((*val2It++).asString(), "subCategory");
|
||||
EXPECT_EQ((*val2It++).asString(), "temporary");
|
||||
EXPECT_EQ(val2It, arrVals2.end<ValueView>());
|
||||
|
||||
ValueView const tempVal = arrVals2.valueAt(0);
|
||||
EXPECT_EQ(tempVal.type(), ConfigType::String);
|
||||
EXPECT_EQ("subCategory", tempVal.asString());
|
||||
}
|
||||
|
||||
TEST_F(ArrayViewTest, ArrayWithObjTest)
|
||||
{
|
||||
ArrayView const arrVals = configData.getArray("array.[]");
|
||||
ArrayView const arrValAlt = configData.getArray("array");
|
||||
auto const precision = 1e-9;
|
||||
|
||||
auto const obj1 = arrVals.objectAt(0);
|
||||
auto const obj2 = arrValAlt.objectAt(0);
|
||||
EXPECT_NEAR(obj1.getValue("sub").asDouble(), obj2.getValue("sub").asDouble(), precision);
|
||||
EXPECT_NEAR(obj1.getValue("sub").asDouble(), 111.11, precision);
|
||||
}
|
||||
|
||||
TEST_F(ArrayViewTest, IterateArray)
|
||||
{
|
||||
auto arr = configData.getArray("dosguard.whitelist");
|
||||
EXPECT_EQ(2, arr.size());
|
||||
EXPECT_EQ(arr.valueAt(0).asString(), "125.5.5.2");
|
||||
EXPECT_EQ(arr.valueAt(1).asString(), "204.2.2.2");
|
||||
|
||||
auto it = arr.begin<ValueView>();
|
||||
EXPECT_EQ((*it++).asString(), "125.5.5.2");
|
||||
EXPECT_EQ((*it++).asString(), "204.2.2.2");
|
||||
EXPECT_EQ((it), arr.end<ValueView>());
|
||||
}
|
||||
|
||||
TEST_F(ArrayViewTest, DifferentArrayIterators)
|
||||
{
|
||||
auto const subArray = configData.getArray("array.[].sub");
|
||||
auto const dosguardArray = configData.getArray("dosguard.whitelist.[]");
|
||||
ASSERT_EQ(subArray.size(), dosguardArray.size());
|
||||
|
||||
auto itArray = subArray.begin<ValueView>();
|
||||
auto itDosguard = dosguardArray.begin<ValueView>();
|
||||
|
||||
for (std::size_t i = 0; i < subArray.size(); i++)
|
||||
EXPECT_NE(itArray++, itDosguard++);
|
||||
}
|
||||
|
||||
TEST_F(ArrayViewTest, IterateObject)
|
||||
{
|
||||
auto arr = configData.getArray("array");
|
||||
EXPECT_EQ(2, arr.size());
|
||||
|
||||
auto it = arr.begin<ObjectView>();
|
||||
EXPECT_EQ(111.11, (*it).getValue("sub").asDouble());
|
||||
EXPECT_EQ("subCategory", (*it++).getValue("sub2").asString());
|
||||
|
||||
EXPECT_EQ(4321.55, (*it).getValue("sub").asDouble());
|
||||
EXPECT_EQ("temporary", (*it++).getValue("sub2").asString());
|
||||
|
||||
EXPECT_EQ(it, arr.end<ObjectView>());
|
||||
}
|
||||
|
||||
struct ArrayViewDeathTest : ArrayViewTest {};
|
||||
|
||||
TEST_F(ArrayViewDeathTest, IncorrectAccess)
|
||||
{
|
||||
ArrayView const arr = configData.getArray("higher");
|
||||
|
||||
// dies because higher only has 1 object
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto _ = arr.objectAt(1); }, ".*");
|
||||
|
||||
ArrayView const arrVals2 = configData.getArray("array.[].sub2");
|
||||
ValueView const tempVal = arrVals2.valueAt(0);
|
||||
|
||||
// dies because array.[].sub2 only has 2 config values
|
||||
EXPECT_DEATH([[maybe_unused]] auto _ = arrVals2.valueAt(2), ".*");
|
||||
|
||||
// dies as value is not of type int
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto _ = tempVal.asIntType<int>(); }, ".*");
|
||||
}
|
||||
|
||||
TEST_F(ArrayViewDeathTest, IncorrectIterateAccess)
|
||||
{
|
||||
ArrayView const arr = configData.getArray("higher");
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto _ = arr.begin<ValueView>(); }, ".*");
|
||||
|
||||
ArrayView const dosguardWhitelist = configData.getArray("dosguard.whitelist");
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto _ = dosguardWhitelist.begin<ObjectView>(); }, ".*");
|
||||
}
|
||||
167
tests/unit/util/newconfig/ClioConfigDefinitionTests.cpp
Normal file
167
tests/unit/util/newconfig/ClioConfigDefinitionTests.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2024, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "util/newconfig/ArrayView.hpp"
|
||||
#include "util/newconfig/ConfigDefinition.hpp"
|
||||
#include "util/newconfig/ConfigDescription.hpp"
|
||||
#include "util/newconfig/ConfigValue.hpp"
|
||||
#include "util/newconfig/FakeConfigData.hpp"
|
||||
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/parse.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/value_to.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <string_view>
|
||||
#include <unordered_set>
|
||||
|
||||
using namespace util::config;
|
||||
|
||||
// TODO: parsing config file and populating into config will be here once implemented
|
||||
struct NewConfigTest : testing::Test {
|
||||
ClioConfigDefinition const configData = generateConfig();
|
||||
};
|
||||
|
||||
TEST_F(NewConfigTest, fetchValues)
|
||||
{
|
||||
auto const v = configData.getValue("header.port");
|
||||
EXPECT_EQ(v.type(), ConfigType::Integer);
|
||||
|
||||
EXPECT_EQ("value", configData.getValue("header.text1").asString());
|
||||
EXPECT_EQ(123, configData.getValue("header.port").asIntType<int>());
|
||||
EXPECT_EQ(true, configData.getValue("header.admin").asBool());
|
||||
EXPECT_EQ("TSM", configData.getValue("header.sub.sub2Value").asString());
|
||||
EXPECT_EQ(444.22, configData.getValue("ip").asDouble());
|
||||
|
||||
auto const v2 = configData.getValueInArray("dosguard.whitelist", 0);
|
||||
EXPECT_EQ(v2.asString(), "125.5.5.2");
|
||||
}
|
||||
|
||||
TEST_F(NewConfigTest, fetchObject)
|
||||
{
|
||||
auto const obj = configData.getObject("header");
|
||||
EXPECT_TRUE(obj.containsKey("sub.sub2Value"));
|
||||
|
||||
auto const obj2 = obj.getObject("sub");
|
||||
EXPECT_TRUE(obj2.containsKey("sub2Value"));
|
||||
EXPECT_EQ(obj2.getValue("sub2Value").asString(), "TSM");
|
||||
|
||||
auto const objInArr = configData.getObject("array", 0);
|
||||
auto const obj2InArr = configData.getObject("array", 1);
|
||||
EXPECT_EQ(objInArr.getValue("sub").asDouble(), 111.11);
|
||||
EXPECT_EQ(objInArr.getValue("sub2").asString(), "subCategory");
|
||||
EXPECT_EQ(obj2InArr.getValue("sub").asDouble(), 4321.55);
|
||||
EXPECT_EQ(obj2InArr.getValue("sub2").asString(), "temporary");
|
||||
}
|
||||
|
||||
TEST_F(NewConfigTest, fetchArray)
|
||||
{
|
||||
auto const obj = configData.getObject("dosguard");
|
||||
EXPECT_TRUE(obj.containsKey("whitelist.[]"));
|
||||
|
||||
auto const arr = obj.getArray("whitelist");
|
||||
EXPECT_EQ(2, arr.size());
|
||||
|
||||
auto const sameArr = configData.getArray("dosguard.whitelist");
|
||||
EXPECT_EQ(2, sameArr.size());
|
||||
EXPECT_EQ(sameArr.valueAt(0).asString(), arr.valueAt(0).asString());
|
||||
EXPECT_EQ(sameArr.valueAt(1).asString(), arr.valueAt(1).asString());
|
||||
}
|
||||
|
||||
TEST_F(NewConfigTest, CheckKeys)
|
||||
{
|
||||
EXPECT_TRUE(configData.contains("header.port"));
|
||||
EXPECT_TRUE(configData.contains("array.[].sub"));
|
||||
EXPECT_TRUE(configData.contains("dosguard.whitelist.[]"));
|
||||
EXPECT_FALSE(configData.contains("dosguard.whitelist"));
|
||||
|
||||
EXPECT_TRUE(configData.hasItemsWithPrefix("dosguard"));
|
||||
EXPECT_TRUE(configData.hasItemsWithPrefix("ip"));
|
||||
|
||||
EXPECT_EQ(configData.arraySize("array"), 2);
|
||||
EXPECT_EQ(configData.arraySize("higher"), 1);
|
||||
EXPECT_EQ(configData.arraySize("dosguard.whitelist"), 2);
|
||||
}
|
||||
|
||||
TEST_F(NewConfigTest, CheckAllKeys)
|
||||
{
|
||||
auto expected = std::unordered_set<std::string_view>{};
|
||||
auto const actual = std::unordered_set<std::string_view>{
|
||||
"header.text1",
|
||||
"header.port",
|
||||
"header.admin",
|
||||
"header.sub.sub2Value",
|
||||
"ip",
|
||||
"array.[].sub",
|
||||
"array.[].sub2",
|
||||
"higher.[].low.section",
|
||||
"higher.[].low.admin",
|
||||
"dosguard.whitelist.[]",
|
||||
"dosguard.port"
|
||||
};
|
||||
|
||||
for (auto i = configData.begin(); i != configData.end(); ++i) {
|
||||
expected.emplace((i->first));
|
||||
}
|
||||
EXPECT_EQ(expected, actual);
|
||||
}
|
||||
|
||||
struct NewConfigDeathTest : NewConfigTest {};
|
||||
|
||||
TEST_F(NewConfigDeathTest, IncorrectGetValues)
|
||||
{
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a_ = configData.getValue("head"); }, ".*");
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a_ = configData.getValue("head."); }, ".*");
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a_ = configData.getValue("asdf"); }, ".*");
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a_ = configData.getValue("dosguard.whitelist"); }, ".*");
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a_ = configData.getValue("dosguard.whitelist.[]"); }, ".*");
|
||||
}
|
||||
|
||||
TEST_F(NewConfigDeathTest, IncorrectGetObject)
|
||||
{
|
||||
ASSERT_FALSE(configData.contains("head"));
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a_ = configData.getObject("head"); }, ".*");
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a_ = configData.getObject("array"); }, ".*");
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a_ = configData.getObject("array", 2); }, ".*");
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a_ = configData.getObject("doesNotExist"); }, ".*");
|
||||
}
|
||||
|
||||
TEST_F(NewConfigDeathTest, IncorrectGetArray)
|
||||
{
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a_ = configData.getArray("header.text1"); }, ".*");
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a_ = configData.getArray("asdf"); }, ".*");
|
||||
}
|
||||
|
||||
TEST(ConfigDescription, getValues)
|
||||
{
|
||||
ClioConfigDescription definition{};
|
||||
|
||||
EXPECT_EQ(definition.get("database.type"), "Type of database to use.");
|
||||
EXPECT_EQ(definition.get("etl_source.[].ip"), "IP address of the ETL source.");
|
||||
EXPECT_EQ(definition.get("prometheus.enabled"), "Enable or disable Prometheus metrics.");
|
||||
}
|
||||
|
||||
TEST(ConfigDescriptionAssertDeathTest, nonExistingKeyTest)
|
||||
{
|
||||
ClioConfigDescription definition{};
|
||||
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a = definition.get("data"); }, ".*");
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a = definition.get("etl_source.[]"); }, ".*");
|
||||
}
|
||||
40
tests/unit/util/newconfig/ConfigValueTests.cpp
Normal file
40
tests/unit/util/newconfig/ConfigValueTests.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2024, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "util/newconfig/ConfigValue.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace util::config;
|
||||
|
||||
TEST(ConfigValue, testConfigValue)
|
||||
{
|
||||
auto cvStr = ConfigValue{ConfigType::String}.defaultValue("12345");
|
||||
EXPECT_EQ(cvStr.type(), ConfigType::String);
|
||||
EXPECT_TRUE(cvStr.hasValue());
|
||||
EXPECT_FALSE(cvStr.isOptional());
|
||||
|
||||
auto cvInt = ConfigValue{ConfigType::Integer}.defaultValue(543);
|
||||
EXPECT_EQ(cvInt.type(), ConfigType::Integer);
|
||||
EXPECT_TRUE(cvStr.hasValue());
|
||||
EXPECT_FALSE(cvStr.isOptional());
|
||||
|
||||
auto cvOpt = ConfigValue{ConfigType::Integer}.optional();
|
||||
EXPECT_TRUE(cvOpt.isOptional());
|
||||
}
|
||||
107
tests/unit/util/newconfig/ObjectViewTests.cpp
Normal file
107
tests/unit/util/newconfig/ObjectViewTests.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2024, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "util/newconfig/ArrayView.hpp"
|
||||
#include "util/newconfig/ConfigDefinition.hpp"
|
||||
#include "util/newconfig/FakeConfigData.hpp"
|
||||
#include "util/newconfig/ObjectView.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace util::config;
|
||||
|
||||
struct ObjectViewTest : testing::Test {
|
||||
ClioConfigDefinition const configData = generateConfig();
|
||||
};
|
||||
|
||||
TEST_F(ObjectViewTest, ObjectValueTest)
|
||||
{
|
||||
auto const headerObj = configData.getObject("header");
|
||||
EXPECT_FALSE(headerObj.containsKey("header"));
|
||||
EXPECT_TRUE(headerObj.containsKey("text1"));
|
||||
EXPECT_TRUE(headerObj.containsKey("port"));
|
||||
EXPECT_TRUE(headerObj.containsKey("admin"));
|
||||
|
||||
EXPECT_EQ("value", headerObj.getValue("text1").asString());
|
||||
EXPECT_EQ(123, headerObj.getValue("port").asIntType<int>());
|
||||
EXPECT_EQ(true, headerObj.getValue("admin").asBool());
|
||||
}
|
||||
|
||||
TEST_F(ObjectViewTest, ObjectInArray)
|
||||
{
|
||||
ArrayView const arr = configData.getArray("array");
|
||||
EXPECT_EQ(arr.size(), 2);
|
||||
ObjectView const firstObj = arr.objectAt(0);
|
||||
ObjectView const secondObj = arr.objectAt(1);
|
||||
EXPECT_TRUE(firstObj.containsKey("sub"));
|
||||
EXPECT_TRUE(firstObj.containsKey("sub2"));
|
||||
|
||||
// object's key is only "sub" and "sub2"
|
||||
EXPECT_FALSE(firstObj.containsKey("array.[].sub"));
|
||||
|
||||
EXPECT_EQ(firstObj.getValue("sub").asDouble(), 111.11);
|
||||
EXPECT_EQ(firstObj.getValue("sub2").asString(), "subCategory");
|
||||
|
||||
EXPECT_EQ(secondObj.getValue("sub").asDouble(), 4321.55);
|
||||
EXPECT_EQ(secondObj.getValue("sub2").asString(), "temporary");
|
||||
}
|
||||
|
||||
TEST_F(ObjectViewTest, ObjectInArrayMoreComplex)
|
||||
{
|
||||
ArrayView const arr = configData.getArray("higher");
|
||||
ASSERT_EQ(1, arr.size());
|
||||
|
||||
ObjectView const firstObj = arr.objectAt(0);
|
||||
|
||||
// this returns the 1st object inside "low"
|
||||
ObjectView const sameObjFromConfigData = configData.getObject("higher.[].low", 0);
|
||||
EXPECT_EQ(sameObjFromConfigData.getValue("admin").asBool(), firstObj.getValue("low.admin").asBool());
|
||||
EXPECT_FALSE(firstObj.containsKey("low"));
|
||||
EXPECT_TRUE(firstObj.containsKey("low.admin"));
|
||||
|
||||
ObjectView const objLow = firstObj.getObject("low");
|
||||
EXPECT_TRUE(objLow.containsKey("section"));
|
||||
EXPECT_TRUE(objLow.containsKey("admin"));
|
||||
EXPECT_EQ(objLow.getValue("section").asString(), "true");
|
||||
EXPECT_EQ(objLow.getValue("admin").asBool(), false);
|
||||
}
|
||||
|
||||
TEST_F(ObjectViewTest, getArrayInObject)
|
||||
{
|
||||
auto const obj = configData.getObject("dosguard");
|
||||
EXPECT_TRUE(obj.containsKey("whitelist.[]"));
|
||||
|
||||
auto const arr = obj.getArray("whitelist");
|
||||
EXPECT_EQ(2, arr.size());
|
||||
|
||||
EXPECT_EQ("125.5.5.2", arr.valueAt(0).asString());
|
||||
EXPECT_EQ("204.2.2.2", arr.valueAt(1).asString());
|
||||
}
|
||||
|
||||
struct ObjectViewDeathTest : ObjectViewTest {};
|
||||
|
||||
TEST_F(ObjectViewDeathTest, incorrectKeys)
|
||||
{
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto _ = configData.getObject("header.text1"); }, ".*");
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto _ = configData.getObject("head"); }, ".*");
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto _ = configData.getArray("header"); }, ".*");
|
||||
|
||||
// dies because only 1 object in higher.[].low
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto _ = configData.getObject("higher.[].low", 1); }, ".*");
|
||||
}
|
||||
90
tests/unit/util/newconfig/ValueViewTests.cpp
Normal file
90
tests/unit/util/newconfig/ValueViewTests.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2024, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "util/newconfig/ConfigDefinition.hpp"
|
||||
#include "util/newconfig/ConfigValue.hpp"
|
||||
#include "util/newconfig/FakeConfigData.hpp"
|
||||
#include "util/newconfig/ValueView.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
using namespace util::config;
|
||||
|
||||
struct ValueViewTest : testing::Test {
|
||||
ClioConfigDefinition const configData = generateConfig();
|
||||
};
|
||||
|
||||
TEST_F(ValueViewTest, ValueView)
|
||||
{
|
||||
ConfigValue const cv = ConfigValue{ConfigType::String}.defaultValue("value");
|
||||
ValueView const vv = ValueView(cv);
|
||||
EXPECT_EQ("value", vv.asString());
|
||||
EXPECT_EQ(ConfigType::String, vv.type());
|
||||
EXPECT_EQ(true, vv.hasValue());
|
||||
EXPECT_EQ(false, vv.isOptional());
|
||||
}
|
||||
|
||||
TEST_F(ValueViewTest, DifferentIntegerTest)
|
||||
{
|
||||
auto const vv = configData.getValue("header.port");
|
||||
auto const uint32 = vv.asIntType<uint32_t>();
|
||||
auto const uint64 = vv.asIntType<uint64_t>();
|
||||
auto const int32 = vv.asIntType<int32_t>();
|
||||
auto const int64 = vv.asIntType<int64_t>();
|
||||
|
||||
EXPECT_EQ(vv.asIntType<int>(), uint32);
|
||||
EXPECT_EQ(vv.asIntType<int>(), uint64);
|
||||
EXPECT_EQ(vv.asIntType<int>(), int32);
|
||||
EXPECT_EQ(vv.asIntType<int>(), int64);
|
||||
|
||||
auto const doubleVal = vv.asIntType<double>();
|
||||
auto const floatVal = vv.asIntType<float>();
|
||||
auto const sameDouble = vv.asDouble();
|
||||
auto const sameFloat = vv.asFloat();
|
||||
auto const precision = 1e-9;
|
||||
|
||||
EXPECT_NEAR(doubleVal, sameDouble, precision);
|
||||
EXPECT_NEAR(floatVal, sameFloat, precision);
|
||||
|
||||
auto const ipVal = configData.getValue("ip");
|
||||
auto const ipDouble = ipVal.asDouble();
|
||||
auto const ipFloat = ipVal.asFloat();
|
||||
EXPECT_NEAR(ipDouble, 444.22, precision);
|
||||
EXPECT_NEAR(ipFloat, 444.22f, precision);
|
||||
}
|
||||
|
||||
struct ValueDeathTest : ValueViewTest {};
|
||||
|
||||
TEST_F(ValueDeathTest, WrongTypes)
|
||||
{
|
||||
auto const vv = configData.getValue("header.port");
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a_ = vv.asBool(); }, ".*");
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a_ = vv.asString(); }, ".*");
|
||||
|
||||
auto const cv = ConfigValue{ConfigType::Integer}.defaultValue(-5);
|
||||
auto const vv2 = ValueView(cv);
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a_ = vv2.asIntType<uint32_t>(); }, ".*");
|
||||
|
||||
auto const cv2 = ConfigValue{ConfigType::String}.defaultValue("asdf");
|
||||
auto const vv3 = ValueView(cv2);
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a_ = vv3.asDouble(); }, ".*");
|
||||
EXPECT_DEATH({ [[maybe_unused]] auto a_ = vv3.asFloat(); }, ".*");
|
||||
}
|
||||
Reference in New Issue
Block a user