mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-16 17:55:50 +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:
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "data/cassandra/impl/ManagedObject.hpp"
|
||||
#include "data/cassandra/impl/Tuple.hpp"
|
||||
#include "util/UnsupportedType.hpp"
|
||||
|
||||
#include <cassandra.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
@@ -41,9 +42,6 @@
|
||||
|
||||
namespace data::cassandra::impl {
|
||||
|
||||
template <typename>
|
||||
static constexpr bool unsupported_v = false;
|
||||
|
||||
template <typename Type>
|
||||
inline Type
|
||||
extractColumn(CassRow const* row, std::size_t idx)
|
||||
@@ -103,7 +101,7 @@ extractColumn(CassRow const* row, std::size_t idx)
|
||||
output = static_cast<DecayedType>(out);
|
||||
} else {
|
||||
// type not supported for extraction
|
||||
static_assert(unsupported_v<DecayedType>);
|
||||
static_assert(util::Unsupported<DecayedType>);
|
||||
}
|
||||
|
||||
return output;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "data/cassandra/impl/Collection.hpp"
|
||||
#include "data/cassandra/impl/ManagedObject.hpp"
|
||||
#include "data/cassandra/impl/Tuple.hpp"
|
||||
#include "util/UnsupportedType.hpp"
|
||||
|
||||
#include <cassandra.h>
|
||||
#include <fmt/core.h>
|
||||
@@ -44,9 +45,6 @@ namespace data::cassandra::impl {
|
||||
class Statement : public ManagedObject<CassStatement> {
|
||||
static constexpr auto deleter = [](CassStatement* ptr) { cass_statement_free(ptr); };
|
||||
|
||||
template <typename>
|
||||
static constexpr bool unsupported_v = false;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new statement with optionally provided arguments.
|
||||
@@ -141,7 +139,7 @@ public:
|
||||
throwErrorIfNeeded(rc, "Bind int64");
|
||||
} else {
|
||||
// type not supported for binding
|
||||
static_assert(unsupported_v<DecayedType>);
|
||||
static_assert(util::Unsupported<DecayedType>);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "data/cassandra/impl/ManagedObject.hpp"
|
||||
#include "util/UnsupportedType.hpp"
|
||||
|
||||
#include <cassandra.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
@@ -38,9 +39,6 @@ namespace data::cassandra::impl {
|
||||
class Tuple : public ManagedObject<CassTuple> {
|
||||
static constexpr auto deleter = [](CassTuple* ptr) { cass_tuple_free(ptr); };
|
||||
|
||||
template <typename>
|
||||
static constexpr bool unsupported_v = false;
|
||||
|
||||
public:
|
||||
/* implicit */ Tuple(CassTuple* ptr);
|
||||
|
||||
@@ -91,15 +89,12 @@ public:
|
||||
throwErrorIfNeeded(rc, "Bind ripple::uint256");
|
||||
} else {
|
||||
// type not supported for binding
|
||||
static_assert(unsupported_v<DecayedType>);
|
||||
static_assert(util::Unsupported<DecayedType>);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class TupleIterator : public ManagedObject<CassIterator> {
|
||||
template <typename>
|
||||
static constexpr bool unsupported_v = false;
|
||||
|
||||
public:
|
||||
/* implicit */ TupleIterator(CassIterator* ptr);
|
||||
|
||||
@@ -141,7 +136,7 @@ private:
|
||||
output = static_cast<DecayedType>(out);
|
||||
} else {
|
||||
// type not supported for extraction
|
||||
static_assert(unsupported_v<DecayedType>);
|
||||
static_assert(util::Unsupported<DecayedType>);
|
||||
}
|
||||
|
||||
return output;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "rpc/common/Checkers.hpp"
|
||||
#include "rpc/common/Concepts.hpp"
|
||||
#include "rpc/common/Types.hpp"
|
||||
#include "util/UnsupportedType.hpp"
|
||||
|
||||
#include <boost/json/array.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
@@ -36,9 +37,6 @@
|
||||
|
||||
namespace rpc::impl {
|
||||
|
||||
template <typename>
|
||||
static constexpr bool unsupported_v = false;
|
||||
|
||||
using FieldSpecProcessor = std::function<MaybeError(boost::json::value&)>;
|
||||
|
||||
static FieldSpecProcessor const EMPTY_FIELD_PROCESSOR = [](boost::json::value&) -> MaybeError { return {}; };
|
||||
@@ -64,7 +62,7 @@ makeFieldProcessor(std::string const& key, Processors&&... procs)
|
||||
if (auto const res = req->modify(j, key); not res)
|
||||
firstFailure = res.error();
|
||||
} else {
|
||||
static_assert(unsupported_v<decltype(*req)>);
|
||||
static_assert(util::Unsupported<decltype(*req)>);
|
||||
}
|
||||
}(),
|
||||
...
|
||||
|
||||
@@ -24,6 +24,10 @@ target_sources(
|
||||
TimeUtils.cpp
|
||||
TxUtils.cpp
|
||||
LedgerUtils.cpp
|
||||
newconfig/ConfigDefinition.cpp
|
||||
newconfig/ObjectView.cpp
|
||||
newconfig/ArrayView.cpp
|
||||
newconfig/ValueView.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
|
||||
28
src/util/UnsupportedType.hpp
Normal file
28
src/util/UnsupportedType.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace util {
|
||||
|
||||
/** @brief used for compile time checking of unsupported types */
|
||||
template <typename>
|
||||
static constexpr bool Unsupported = false;
|
||||
|
||||
} // namespace util
|
||||
92
src/util/newconfig/Array.hpp
Normal file
92
src/util/newconfig/Array.hpp
Normal file
@@ -0,0 +1,92 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/Assert.hpp"
|
||||
#include "util/newconfig/ConfigValue.hpp"
|
||||
#include "util/newconfig/ObjectView.hpp"
|
||||
#include "util/newconfig/ValueView.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace util::config {
|
||||
|
||||
/**
|
||||
* @brief Array definition for Json/Yaml config
|
||||
*
|
||||
* Used in ClioConfigDefinition to represent multiple potential values (like whitelist)
|
||||
*/
|
||||
class Array {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs an Array with the provided arguments
|
||||
*
|
||||
* @tparam Args Types of the arguments
|
||||
* @param args Arguments to initialize the elements of the Array
|
||||
*/
|
||||
template <typename... Args>
|
||||
constexpr Array(Args&&... args) : elements_{std::forward<Args>(args)...}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add ConfigValues to Array class
|
||||
*
|
||||
* @param value The ConfigValue to add
|
||||
*/
|
||||
void
|
||||
emplaceBack(ConfigValue value)
|
||||
{
|
||||
elements_.push_back(std::move(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the number of values stored in the Array
|
||||
*
|
||||
* @return Number of values stored in the Array
|
||||
*/
|
||||
[[nodiscard]] size_t
|
||||
size() const
|
||||
{
|
||||
return elements_.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the ConfigValue at the specified index
|
||||
*
|
||||
* @param idx Index of the ConfigValue to retrieve
|
||||
* @return ConfigValue at the specified index
|
||||
*/
|
||||
[[nodiscard]] ConfigValue const&
|
||||
at(std::size_t idx) const
|
||||
{
|
||||
ASSERT(idx < elements_.size(), "index is out of scope");
|
||||
return elements_[idx];
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<ConfigValue> elements_;
|
||||
};
|
||||
|
||||
} // namespace util::config
|
||||
60
src/util/newconfig/ArrayView.cpp
Normal file
60
src/util/newconfig/ArrayView.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/Assert.hpp"
|
||||
#include "util/newconfig/Array.hpp"
|
||||
#include "util/newconfig/ConfigDefinition.hpp"
|
||||
#include "util/newconfig/ConfigValue.hpp"
|
||||
#include "util/newconfig/ObjectView.hpp"
|
||||
#include "util/newconfig/ValueView.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <string_view>
|
||||
|
||||
namespace util::config {
|
||||
|
||||
ArrayView::ArrayView(std::string_view prefix, ClioConfigDefinition const& configDef)
|
||||
: prefix_{prefix}, clioConfig_{configDef}
|
||||
{
|
||||
}
|
||||
|
||||
ValueView
|
||||
ArrayView::valueAt(std::size_t idx) const
|
||||
{
|
||||
ASSERT(clioConfig_.get().contains(prefix_), "Current string {} is a prefix, not a key of config", prefix_);
|
||||
ConfigValue const& val = clioConfig_.get().asArray(prefix_).at(idx);
|
||||
return ValueView{val};
|
||||
}
|
||||
|
||||
size_t
|
||||
ArrayView::size() const
|
||||
{
|
||||
return clioConfig_.get().arraySize(prefix_);
|
||||
}
|
||||
|
||||
ObjectView
|
||||
ArrayView::objectAt(std::size_t idx) const
|
||||
{
|
||||
ASSERT(idx < this->size(), "Object index is out of scope");
|
||||
return ObjectView{prefix_, idx, clioConfig_};
|
||||
}
|
||||
|
||||
} // namespace util::config
|
||||
203
src/util/newconfig/ArrayView.hpp
Normal file
203
src/util/newconfig/ArrayView.hpp
Normal file
@@ -0,0 +1,203 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/Assert.hpp"
|
||||
#include "util/newconfig/ConfigDefinition.hpp"
|
||||
#include "util/newconfig/ObjectView.hpp"
|
||||
#include "util/newconfig/ValueView.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace util::config {
|
||||
|
||||
/**
|
||||
* @brief View for array structure for config.
|
||||
*
|
||||
* This class provides a view into an array structure within ClioConfigDefinition.
|
||||
* It allows accessing individual elements of the array as either values or objects, and
|
||||
* is used within the ClioConfigDefinition to represent multiple potential values.
|
||||
*/
|
||||
class ArrayView {
|
||||
public:
|
||||
/**
|
||||
* @brief Custom iterator class which contains config object or value underneath ArrayView
|
||||
*/
|
||||
template <typename T>
|
||||
struct ArrayIterator {
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using pointer = T const*;
|
||||
using reference = T const&;
|
||||
using value_type = T;
|
||||
|
||||
/**
|
||||
* @brief Constructs an ArrayIterator with underlying ArrayView and index value
|
||||
*
|
||||
* @param arr ArrayView to iterate
|
||||
* @param index Current index of the ArrayView
|
||||
*/
|
||||
ArrayIterator(ArrayView const& arr, std::size_t index) : arr_{arr}, index_{index}
|
||||
{
|
||||
if (arr_.clioConfig_.get().contains(arr_.prefix_)) {
|
||||
ASSERT((std::is_same_v<T, ValueView>), "Array iterator must be ValueView");
|
||||
} else {
|
||||
ASSERT((std::is_same_v<T, ObjectView>), "Array iterator must be ObjectView");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prefix increment operator
|
||||
*
|
||||
* @return Reference to the incremented ArrayIterator
|
||||
*/
|
||||
ArrayIterator&
|
||||
operator++()
|
||||
{
|
||||
if (index_ < arr_.size())
|
||||
++index_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Postfix increment operator
|
||||
*
|
||||
* @return Copy of the ArrayIterator before increment
|
||||
*/
|
||||
ArrayIterator
|
||||
operator++(int)
|
||||
{
|
||||
ArrayIterator temp = *this;
|
||||
if (index_ < arr_.size())
|
||||
++index_;
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Dereference operator to get a ValueView or ObjectView
|
||||
*
|
||||
* @return ValueView of the ConfigValue
|
||||
*/
|
||||
T
|
||||
operator*()
|
||||
{
|
||||
if constexpr (std::is_same_v<T, ObjectView>) {
|
||||
return ObjectView{arr_.prefix_, index_, arr_.clioConfig_.get()};
|
||||
} else {
|
||||
return arr_.clioConfig_.get().getValueInArray(arr_.prefix_, index_);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Equality operator
|
||||
*
|
||||
* @param other Another ArrayIterator to compare
|
||||
* @return true if iterators are pointing to the same element in the same ArrayView object, otherwise false
|
||||
*/
|
||||
bool
|
||||
operator==(ArrayIterator const& other) const
|
||||
{
|
||||
return &arr_ == &(other.arr_) && index_ == other.index_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inequality operator
|
||||
*
|
||||
* @param other Another ArrayIterator to compare
|
||||
* @return true if iterators are not equal, otherwise false
|
||||
*/
|
||||
bool
|
||||
operator!=(ArrayIterator const& other) const
|
||||
{
|
||||
return &arr_ != &(other.arr_) || index_ != other.index_;
|
||||
}
|
||||
|
||||
private:
|
||||
ArrayView const& arr_;
|
||||
std::size_t index_ = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator to the beginning of the Array
|
||||
*
|
||||
* @return Iterator to the beginning of the Array
|
||||
*/
|
||||
template <typename T>
|
||||
[[nodiscard]] auto
|
||||
begin() const
|
||||
{
|
||||
return ArrayIterator<T>(*this, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator to the end of the Array
|
||||
*
|
||||
* @return Iterator to the end of the Array
|
||||
*/
|
||||
template <typename T>
|
||||
[[nodiscard]] auto
|
||||
end() const
|
||||
{
|
||||
return ArrayIterator<T>(*this, this->size());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructs an ArrayView with the given prefix and config definition.
|
||||
*
|
||||
* @param prefix The prefix for the array view.
|
||||
* @param configDef The ClioConfigDefinition instance.
|
||||
*/
|
||||
ArrayView(std::string_view prefix, ClioConfigDefinition const& configDef);
|
||||
|
||||
/**
|
||||
* @brief Returns an ObjectView at the specified index.
|
||||
*
|
||||
* @param idx Index of the object to retrieve.
|
||||
* @return ObjectView at the specified index.
|
||||
*/
|
||||
[[nodiscard]] ObjectView
|
||||
objectAt(std::size_t idx) const;
|
||||
|
||||
/**
|
||||
* @brief Returns a ValueView at the specified index.
|
||||
*
|
||||
* @param idx Index of the value to retrieve.
|
||||
* @return ValueView at the specified index.
|
||||
*/
|
||||
[[nodiscard]] ValueView
|
||||
valueAt(std::size_t idx) const;
|
||||
|
||||
/**
|
||||
* @brief Returns the number of elements in the array.
|
||||
*
|
||||
* @return Number of elements in the array.
|
||||
*/
|
||||
[[nodiscard]] size_t
|
||||
size() const;
|
||||
|
||||
private:
|
||||
std::string prefix_;
|
||||
std::reference_wrapper<ClioConfigDefinition const> clioConfig_;
|
||||
};
|
||||
|
||||
} // namespace util::config
|
||||
209
src/util/newconfig/ConfigDefinition.cpp
Normal file
209
src/util/newconfig/ConfigDefinition.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/Assert.hpp"
|
||||
#include "util/newconfig/Array.hpp"
|
||||
#include "util/newconfig/ArrayView.hpp"
|
||||
#include "util/newconfig/ConfigValue.hpp"
|
||||
#include "util/newconfig/ObjectView.hpp"
|
||||
#include "util/newconfig/ValueView.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <initializer_list>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
|
||||
namespace util::config {
|
||||
/**
|
||||
* @brief Full Clio Configuration definition.
|
||||
*
|
||||
* Specifies which keys are valid in Clio Config and provides default values if user's do not specify one. Those
|
||||
* without default values must be present in the user's config file.
|
||||
*/
|
||||
static ClioConfigDefinition ClioConfig = ClioConfigDefinition{
|
||||
{{"database.type", ConfigValue{ConfigType::String}.defaultValue("cassandra")},
|
||||
{"database.cassandra.contact_points", ConfigValue{ConfigType::String}.defaultValue("localhost")},
|
||||
{"database.cassandra.port", ConfigValue{ConfigType::Integer}},
|
||||
{"database.cassandra.keyspace", ConfigValue{ConfigType::String}.defaultValue("clio")},
|
||||
{"database.cassandra.replication_factor", ConfigValue{ConfigType::Integer}.defaultValue(3u)},
|
||||
{"database.cassandra.table_prefix", ConfigValue{ConfigType::String}.defaultValue("table_prefix")},
|
||||
{"database.cassandra.max_write_requests_outstanding", ConfigValue{ConfigType::Integer}.defaultValue(10'000)},
|
||||
{"database.cassandra.max_read_requests_outstanding", ConfigValue{ConfigType::Integer}.defaultValue(100'000)},
|
||||
{"database.cassandra.threads",
|
||||
ConfigValue{ConfigType::Integer}.defaultValue(static_cast<uint32_t>(std::thread::hardware_concurrency()))},
|
||||
{"database.cassandra.core_connections_per_host", ConfigValue{ConfigType::Integer}.defaultValue(1)},
|
||||
{"database.cassandra.queue_size_io", ConfigValue{ConfigType::Integer}.optional()},
|
||||
{"database.cassandra.write_batch_size", ConfigValue{ConfigType::Integer}.defaultValue(20)},
|
||||
{"etl_source.[].ip", Array{ConfigValue{ConfigType::String}.optional()}},
|
||||
{"etl_source.[].ws_port", Array{ConfigValue{ConfigType::String}.optional().min(1).max(65535)}},
|
||||
{"etl_source.[].grpc_port", Array{ConfigValue{ConfigType::String}.optional().min(1).max(65535)}},
|
||||
{"forwarding.cache_timeout", ConfigValue{ConfigType::Double}.defaultValue(0.0)},
|
||||
{"forwarding.request_timeout", ConfigValue{ConfigType::Double}.defaultValue(10.0)},
|
||||
{"dos_guard.whitelist.[]", Array{ConfigValue{ConfigType::String}}},
|
||||
{"dos_guard.max_fetches", ConfigValue{ConfigType::Integer}.defaultValue(1000'000)},
|
||||
{"dos_guard.max_connections", ConfigValue{ConfigType::Integer}.defaultValue(20)},
|
||||
{"dos_guard.max_requests", ConfigValue{ConfigType::Integer}.defaultValue(20)},
|
||||
{"dos_guard.sweep_interval", ConfigValue{ConfigType::Double}.defaultValue(1.0)},
|
||||
{"cache.peers.[].ip", Array{ConfigValue{ConfigType::String}}},
|
||||
{"cache.peers.[].port", Array{ConfigValue{ConfigType::String}}},
|
||||
{"server.ip", ConfigValue{ConfigType::String}},
|
||||
{"server.port", ConfigValue{ConfigType::Integer}},
|
||||
{"server.max_queue_size", ConfigValue{ConfigType::Integer}.defaultValue(0)},
|
||||
{"server.local_admin", ConfigValue{ConfigType::Boolean}.optional()},
|
||||
{"prometheus.enabled", ConfigValue{ConfigType::Boolean}.defaultValue(true)},
|
||||
{"prometheus.compress_reply", ConfigValue{ConfigType::Boolean}.defaultValue(true)},
|
||||
{"io_threads", ConfigValue{ConfigType::Integer}.defaultValue(2)},
|
||||
{"cache.num_diffs", ConfigValue{ConfigType::Integer}.defaultValue(32)},
|
||||
{"cache.num_markers", ConfigValue{ConfigType::Integer}.defaultValue(48)},
|
||||
{"cache.num_cursors_from_diff", ConfigValue{ConfigType::Integer}.defaultValue(0)},
|
||||
{"cache.num_cursors_from_account", ConfigValue{ConfigType::Integer}.defaultValue(0)},
|
||||
{"cache.page_fetch_size", ConfigValue{ConfigType::Integer}.defaultValue(512)},
|
||||
{"cache.load", ConfigValue{ConfigType::String}.defaultValue("async")},
|
||||
{"log_channels.[].channel", Array{ConfigValue{ConfigType::String}.optional()}},
|
||||
{"log_channels.[].log_level", Array{ConfigValue{ConfigType::String}.optional()}},
|
||||
{"log_level", ConfigValue{ConfigType::String}.defaultValue("info")},
|
||||
{"log_format",
|
||||
ConfigValue{ConfigType::String}.defaultValue(
|
||||
R"(%TimeStamp% (%SourceLocation%) [%ThreadID%] %Channel%:%Severity% %Message%)"
|
||||
)},
|
||||
{"log_to_console", ConfigValue{ConfigType::Boolean}.defaultValue(false)},
|
||||
{"log_directory", ConfigValue{ConfigType::String}.optional()},
|
||||
{"log_rotation_size", ConfigValue{ConfigType::Integer}.defaultValue(2048)},
|
||||
{"log_directory_max_size", ConfigValue{ConfigType::Integer}.defaultValue(50 * 1024)},
|
||||
{"log_rotation_hour_interval", ConfigValue{ConfigType::Integer}.defaultValue(12)},
|
||||
{"log_tag_style", ConfigValue{ConfigType::String}.defaultValue("uint")},
|
||||
{"extractor_threads", ConfigValue{ConfigType::Integer}.defaultValue(2u)},
|
||||
{"read_only", ConfigValue{ConfigType::Boolean}.defaultValue(false)},
|
||||
{"txn_threshold", ConfigValue{ConfigType::Integer}.defaultValue(0)},
|
||||
{"start_sequence", ConfigValue{ConfigType::String}.optional()},
|
||||
{"finish_sequence", ConfigValue{ConfigType::String}.optional()},
|
||||
{"ssl_cert_file", ConfigValue{ConfigType::String}.optional()},
|
||||
{"ssl_key_file", ConfigValue{ConfigType::String}.optional()},
|
||||
{"api_version.min", ConfigValue{ConfigType::Integer}},
|
||||
{"api_version.max", ConfigValue{ConfigType::Integer}}}
|
||||
};
|
||||
|
||||
ClioConfigDefinition::ClioConfigDefinition(std::initializer_list<KeyValuePair> pair)
|
||||
{
|
||||
for (auto const& [key, value] : pair) {
|
||||
if (key.contains("[]"))
|
||||
ASSERT(std::holds_alternative<Array>(value), "Value must be array if key has \"[]\"");
|
||||
map_.insert({key, value});
|
||||
}
|
||||
}
|
||||
|
||||
ObjectView
|
||||
ClioConfigDefinition::getObject(std::string_view prefix, std::optional<std::size_t> idx) const
|
||||
{
|
||||
auto const prefixWithDot = std::string(prefix) + ".";
|
||||
for (auto const& [mapKey, mapVal] : map_) {
|
||||
auto const hasPrefix = mapKey.starts_with(prefixWithDot);
|
||||
if (idx.has_value() && hasPrefix && std::holds_alternative<Array>(mapVal)) {
|
||||
ASSERT(std::get<Array>(mapVal).size() > idx.value(), "Index provided is out of scope");
|
||||
// we want to support getObject("array") and getObject("array.[]"), so we check if "[]" exists
|
||||
if (!prefix.contains("[]"))
|
||||
return ObjectView{prefixWithDot + "[]", idx.value(), *this};
|
||||
return ObjectView{prefix, idx.value(), *this};
|
||||
}
|
||||
if (hasPrefix && !idx.has_value() && !mapKey.contains(prefixWithDot + "[]"))
|
||||
return ObjectView{prefix, *this};
|
||||
}
|
||||
ASSERT(false, "Key {} is not found in config", prefixWithDot);
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
ArrayView
|
||||
ClioConfigDefinition::getArray(std::string_view prefix) const
|
||||
{
|
||||
auto const key = addBracketsForArrayKey(prefix);
|
||||
|
||||
for (auto const& [mapKey, mapVal] : map_) {
|
||||
if (mapKey.starts_with(key)) {
|
||||
ASSERT(
|
||||
std::holds_alternative<Array>(mapVal), "Trying to retrieve Object or ConfigValue, instead of an Array "
|
||||
);
|
||||
return ArrayView{key, *this};
|
||||
}
|
||||
}
|
||||
ASSERT(false, "Key {} is not found in config", key);
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
bool
|
||||
ClioConfigDefinition::contains(std::string_view key) const
|
||||
{
|
||||
return map_.contains(key);
|
||||
}
|
||||
|
||||
bool
|
||||
ClioConfigDefinition::hasItemsWithPrefix(std::string_view key) const
|
||||
{
|
||||
return std::ranges::any_of(map_, [&key](auto const& pair) { return pair.first.starts_with(key); });
|
||||
}
|
||||
|
||||
ValueView
|
||||
ClioConfigDefinition::getValue(std::string_view fullKey) const
|
||||
{
|
||||
ASSERT(map_.contains(fullKey), "key {} does not exist in config", fullKey);
|
||||
if (std::holds_alternative<ConfigValue>(map_.at(fullKey))) {
|
||||
return ValueView{std::get<ConfigValue>(map_.at(fullKey))};
|
||||
}
|
||||
ASSERT(false, "Value of key {} is an Array, not an object", fullKey);
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
ValueView
|
||||
ClioConfigDefinition::getValueInArray(std::string_view fullKey, std::size_t index) const
|
||||
{
|
||||
auto const it = getArrayIterator(fullKey);
|
||||
return ValueView{std::get<Array>(it->second).at(index)};
|
||||
}
|
||||
|
||||
Array const&
|
||||
ClioConfigDefinition::asArray(std::string_view fullKey) const
|
||||
{
|
||||
auto const it = getArrayIterator(fullKey);
|
||||
return std::get<Array>(it->second);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
ClioConfigDefinition::arraySize(std::string_view prefix) const
|
||||
{
|
||||
auto const key = addBracketsForArrayKey(prefix);
|
||||
|
||||
for (auto const& pair : map_) {
|
||||
if (pair.first.starts_with(key)) {
|
||||
return std::get<Array>(pair.second).size();
|
||||
}
|
||||
}
|
||||
ASSERT(false, "Prefix {} not found in any of the config keys", key);
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
} // namespace util::config
|
||||
230
src/util/newconfig/ConfigDefinition.hpp
Normal file
230
src/util/newconfig/ConfigDefinition.hpp
Normal file
@@ -0,0 +1,230 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/Assert.hpp"
|
||||
#include "util/newconfig/Array.hpp"
|
||||
#include "util/newconfig/ConfigDescription.hpp"
|
||||
#include "util/newconfig/ConfigFileInterface.hpp"
|
||||
#include "util/newconfig/ConfigValue.hpp"
|
||||
#include "util/newconfig/Errors.hpp"
|
||||
#include "util/newconfig/ObjectView.hpp"
|
||||
#include "util/newconfig/ValueView.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <expected>
|
||||
#include <initializer_list>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
|
||||
namespace util::config {
|
||||
|
||||
/**
|
||||
* @brief All the config data will be stored and extracted from this class
|
||||
*
|
||||
* Represents all the possible config data
|
||||
*/
|
||||
class ClioConfigDefinition {
|
||||
public:
|
||||
using KeyValuePair = std::pair<std::string_view, std::variant<ConfigValue, Array>>;
|
||||
|
||||
/**
|
||||
* @brief Constructs a new ClioConfigDefinition
|
||||
*
|
||||
* Initializes the configuration with a predefined set of key-value pairs
|
||||
* If a key contains "[]", the corresponding value must be an Array
|
||||
*
|
||||
* @param pair A list of key-value pairs for the predefined set of clio configurations
|
||||
*/
|
||||
ClioConfigDefinition(std::initializer_list<KeyValuePair> pair);
|
||||
|
||||
/**
|
||||
* @brief Parses the configuration file
|
||||
*
|
||||
* Should also check that no extra configuration key/value pairs are present
|
||||
*
|
||||
* @param config The configuration file interface
|
||||
* @return An optional Error object if parsing fails
|
||||
*/
|
||||
[[nodiscard]] std::optional<Error>
|
||||
parse(ConfigFileInterface const& config);
|
||||
|
||||
/**
|
||||
* @brief Validates the configuration file
|
||||
*
|
||||
* Should only check for valid values, without populating
|
||||
*
|
||||
* @param config The configuration file interface
|
||||
* @return An optional Error object if validation fails
|
||||
*/
|
||||
[[nodiscard]] std::optional<Error>
|
||||
validate(ConfigFileInterface const& config) const;
|
||||
|
||||
/**
|
||||
* @brief Generate markdown file of all the clio config descriptions
|
||||
*
|
||||
* @param configDescription The configuration description object
|
||||
* @return An optional Error if generating markdown fails
|
||||
*/
|
||||
[[nodiscard]] std::expected<std::string, Error>
|
||||
getMarkdown(ClioConfigDescription const& configDescription) const;
|
||||
|
||||
/**
|
||||
* @brief Returns the ObjectView specified with the prefix
|
||||
*
|
||||
* @param prefix The key prefix for the ObjectView
|
||||
* @param idx Used if getting Object in an Array
|
||||
* @return ObjectView with the given prefix
|
||||
*/
|
||||
[[nodiscard]] ObjectView
|
||||
getObject(std::string_view prefix, std::optional<std::size_t> idx = std::nullopt) const;
|
||||
|
||||
/**
|
||||
* @brief Returns the specified ValueView object associated with the key
|
||||
*
|
||||
* @param fullKey The config key to search for
|
||||
* @return ValueView associated with the given key
|
||||
*/
|
||||
[[nodiscard]] ValueView
|
||||
getValue(std::string_view fullKey) const;
|
||||
|
||||
/**
|
||||
* @brief Returns the specified ValueView object in an array with a given index
|
||||
*
|
||||
* @param fullKey The config key to search for
|
||||
* @param index The index of the config value inside the Array to get
|
||||
* @return ValueView associated with the given key
|
||||
*/
|
||||
[[nodiscard]] ValueView
|
||||
getValueInArray(std::string_view fullKey, std::size_t index) const;
|
||||
|
||||
/**
|
||||
* @brief Returns the specified Array object from ClioConfigDefinition
|
||||
*
|
||||
* @param prefix The prefix to search config keys from
|
||||
* @return ArrayView with all key-value pairs where key starts with "prefix"
|
||||
*/
|
||||
[[nodiscard]] ArrayView
|
||||
getArray(std::string_view prefix) const;
|
||||
|
||||
/**
|
||||
* @brief Checks if a key is present in the configuration map.
|
||||
*
|
||||
* @param key The key to search for in the configuration map.
|
||||
* @return True if the key is present, false otherwise.
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
contains(std::string_view key) const;
|
||||
|
||||
/**
|
||||
* @brief Checks if any key in config starts with "key"
|
||||
*
|
||||
* @param key The key to search for in the configuration map.
|
||||
* @return True if the any key in config starts with "key", false otherwise.
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
hasItemsWithPrefix(std::string_view key) const;
|
||||
|
||||
/**
|
||||
* @brief Returns the Array object associated with the specified key.
|
||||
*
|
||||
* @param key The key whose associated Array object is to be returned.
|
||||
* @return The Array object associated with the specified key.
|
||||
*/
|
||||
[[nodiscard]] Array const&
|
||||
asArray(std::string_view key) const;
|
||||
|
||||
/**
|
||||
* @brief Returns the size of an Array
|
||||
*
|
||||
* @param prefix The prefix whose associated Array object is to be returned.
|
||||
* @return The size of the array associated with the specified prefix.
|
||||
*/
|
||||
[[nodiscard]] std::size_t
|
||||
arraySize(std::string_view prefix) const;
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator to the beginning of the configuration map.
|
||||
*
|
||||
* @return A constant iterator to the beginning of the map.
|
||||
*/
|
||||
[[nodiscard]] auto
|
||||
begin() const
|
||||
{
|
||||
return map_.begin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator to the end of the configuration map.
|
||||
*
|
||||
* @return A constant iterator to the end of the map.
|
||||
*/
|
||||
[[nodiscard]] auto
|
||||
end() const
|
||||
{
|
||||
return map_.end();
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief returns the iterator of key-value pair with key fullKey
|
||||
*
|
||||
* @param fullKey Key to search for
|
||||
* @return iterator of map
|
||||
*/
|
||||
[[nodiscard]] auto
|
||||
getArrayIterator(std::string_view key) const
|
||||
{
|
||||
auto const fullKey = addBracketsForArrayKey(key);
|
||||
auto const it = std::ranges::find_if(map_, [&fullKey](auto pair) { return pair.first == fullKey; });
|
||||
|
||||
ASSERT(it != map_.end(), "key {} does not exist in config", fullKey);
|
||||
ASSERT(std::holds_alternative<Array>(it->second), "Value of {} is not an array", fullKey);
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Used for all Array API's; check to make sure "[]" exists, if not, append to end
|
||||
*
|
||||
* @param key key to check for
|
||||
* @return the key with "[]" appended to the end
|
||||
*/
|
||||
[[nodiscard]] static std::string
|
||||
addBracketsForArrayKey(std::string_view key)
|
||||
{
|
||||
std::string fullKey = std::string(key);
|
||||
if (!key.contains(".[]"))
|
||||
fullKey += ".[]";
|
||||
return fullKey;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string_view, std::variant<ConfigValue, Array>> map_;
|
||||
};
|
||||
|
||||
} // namespace util::config
|
||||
125
src/util/newconfig/ConfigDescription.hpp
Normal file
125
src/util/newconfig/ConfigDescription.hpp
Normal file
@@ -0,0 +1,125 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/Assert.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <string_view>
|
||||
|
||||
namespace util::config {
|
||||
|
||||
/**
|
||||
* @brief All the config description are stored and extracted from this class
|
||||
*
|
||||
* Represents all the possible config description
|
||||
*/
|
||||
struct ClioConfigDescription {
|
||||
public:
|
||||
/** @brief Struct to represent a key-value pair*/
|
||||
struct KV {
|
||||
std::string_view key;
|
||||
std::string_view value;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Constructs a new Clio Config Description based on pre-existing descriptions
|
||||
*
|
||||
* Config Keys and it's corresponding descriptions are all predefined. Used to generate markdown file
|
||||
*/
|
||||
constexpr ClioConfigDescription() = default;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the description for a given key
|
||||
*
|
||||
* @param key The key to look up the description for
|
||||
* @return The description associated with the key, or "Not Found" if the key does not exist
|
||||
*/
|
||||
[[nodiscard]] static constexpr std::string_view
|
||||
get(std::string_view key)
|
||||
{
|
||||
auto const itr = std::ranges::find_if(configDescription, [&](auto const& v) { return v.key == key; });
|
||||
ASSERT(itr != configDescription.end(), "Key {} doesn't exist in config", key);
|
||||
return itr->value;
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr auto configDescription = std::array{
|
||||
KV{"database.type", "Type of database to use."},
|
||||
KV{"database.cassandra.contact_points", "Comma-separated list of contact points for Cassandra nodes."},
|
||||
KV{"database.cassandra.port", "Port number to connect to Cassandra."},
|
||||
KV{"database.cassandra.keyspace", "Keyspace to use in Cassandra."},
|
||||
KV{"database.cassandra.replication_factor", "Number of replicated nodes for Scylladb."},
|
||||
KV{"database.cassandra.table_prefix", "Prefix for Cassandra table names."},
|
||||
KV{"database.cassandra.max_write_requests_outstanding", "Maximum number of outstanding write requests."},
|
||||
KV{"database.cassandra.max_read_requests_outstanding", "Maximum number of outstanding read requests."},
|
||||
KV{"database.cassandra.threads", "Number of threads for Cassandra operations."},
|
||||
KV{"database.cassandra.core_connections_per_host", "Number of core connections per host for Cassandra."},
|
||||
KV{"database.cassandra.queue_size_io", "Queue size for I/O operations in Cassandra."},
|
||||
KV{"database.cassandra.write_batch_size", "Batch size for write operations in Cassandra."},
|
||||
KV{"etl_source.[].ip", "IP address of the ETL source."},
|
||||
KV{"etl_source.[].ws_port", "WebSocket port of the ETL source."},
|
||||
KV{"etl_source.[].grpc_port", "gRPC port of the ETL source."},
|
||||
KV{"forwarding.cache_timeout", "Timeout duration for the forwarding cache used in Rippled communication."},
|
||||
KV{"forwarding.request_timeout", "Timeout duration for the forwarding request used in Rippled communication."},
|
||||
KV{"dos_guard.[].whitelist", "List of IP addresses to whitelist for DOS protection."},
|
||||
KV{"dos_guard.max_fetches", "Maximum number of fetch operations allowed by DOS guard."},
|
||||
KV{"dos_guard.max_connections", "Maximum number of concurrent connections allowed by DOS guard."},
|
||||
KV{"dos_guard.max_requests", "Maximum number of requests allowed by DOS guard."},
|
||||
KV{"dos_guard.sweep_interval", "Interval in seconds for DOS guard to sweep/clear its state."},
|
||||
KV{"cache.peers.[].ip", "IP address of peer nodes to cache."},
|
||||
KV{"cache.peers.[].port", "Port number of peer nodes to cache."},
|
||||
KV{"server.ip", "IP address of the Clio HTTP server."},
|
||||
KV{"server.port", "Port number of the Clio HTTP server."},
|
||||
KV{"server.max_queue_size", "Maximum size of the server's request queue."},
|
||||
KV{"server.local_admin", "Indicates if the server should run with admin privileges."},
|
||||
KV{"prometheus.enabled", "Enable or disable Prometheus metrics."},
|
||||
KV{"prometheus.compress_reply", "Enable or disable compression of Prometheus responses."},
|
||||
KV{"io_threads", "Number of I/O threads."},
|
||||
KV{"cache.num_diffs", "Number of diffs to cache."},
|
||||
KV{"cache.num_markers", "Number of markers to cache."},
|
||||
KV{"cache.num_cursors_from_diff", "Num of cursors that are different."},
|
||||
KV{"cache.num_cursors_from_account", "Number of cursors from an account."},
|
||||
KV{"cache.page_fetch_size", "Page fetch size for cache operations."},
|
||||
KV{"cache.load", "Cache loading strategy ('sync' or 'async')."},
|
||||
KV{"log_channels.[].channel", "Name of the log channel."},
|
||||
KV{"log_channels.[].log_level", "Log level for the log channel."},
|
||||
KV{"log_level", "General logging level of Clio."},
|
||||
KV{"log_format", "Format string for log messages."},
|
||||
KV{"log_to_console", "Enable or disable logging to console."},
|
||||
KV{"log_directory", "Directory path for log files."},
|
||||
KV{"log_rotation_size", "Log rotation size in megabytes."},
|
||||
KV{"log_directory_max_size", "Maximum size of the log directory in megabytes."},
|
||||
KV{"log_rotation_hour_interval", "Interval in hours for log rotation."},
|
||||
KV{"log_tag_style", "Style for log tags."},
|
||||
KV{"extractor_threads", "Number of extractor threads."},
|
||||
KV{"read_only", "Indicates if the server should have read-only privileges."},
|
||||
KV{"txn_threshold", "Transaction threshold value."},
|
||||
KV{"start_sequence", "Starting ledger index."},
|
||||
KV{"finish_sequence", "Ending ledger index."},
|
||||
KV{"ssl_cert_file", "Path to the SSL certificate file."},
|
||||
KV{"ssl_key_file", "Path to the SSL key file."},
|
||||
KV{"api_version.min", "Minimum API version."},
|
||||
KV{"api_version.max", "Maximum API version."}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace util::config
|
||||
66
src/util/newconfig/ConfigFileInterface.hpp
Normal file
66
src/util/newconfig/ConfigFileInterface.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/newconfig/ConfigValue.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace util::config {
|
||||
|
||||
/**
|
||||
* @brief The interface for configuration files.
|
||||
*
|
||||
* This class defines the interface for handling configuration files,
|
||||
* which can be implemented for different formats such as JSON or YAML.
|
||||
*/
|
||||
class ConfigFileInterface {
|
||||
public:
|
||||
virtual ~ConfigFileInterface() = default;
|
||||
/**
|
||||
* @brief Parses the provided path of user clio configuration data
|
||||
*
|
||||
* @param filePath The path to the Clio Config data
|
||||
*/
|
||||
virtual void
|
||||
parse(std::string_view filePath) = 0;
|
||||
|
||||
/**
|
||||
* @brief Retrieves a configuration value.
|
||||
*
|
||||
* @param key The key of the configuration value.
|
||||
* @return An optional containing the configuration value if found, otherwise std::nullopt.
|
||||
*/
|
||||
virtual std::optional<ConfigValue>
|
||||
getValue(std::string_view key) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Retrieves an array of configuration values.
|
||||
*
|
||||
* @param key The key of the configuration array.
|
||||
* @return An optional containing a vector of configuration values if found, otherwise std::nullopt.
|
||||
*/
|
||||
virtual std::optional<std::vector<ConfigValue>>
|
||||
getArray(std::string_view key) const = 0;
|
||||
};
|
||||
|
||||
} // namespace util::config
|
||||
216
src/util/newconfig/ConfigValue.hpp
Normal file
216
src/util/newconfig/ConfigValue.hpp
Normal file
@@ -0,0 +1,216 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/Assert.hpp"
|
||||
#include "util/UnsupportedType.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
|
||||
namespace util::config {
|
||||
|
||||
/** @brief Custom clio config types */
|
||||
enum class ConfigType { Integer, String, Double, Boolean };
|
||||
|
||||
/**
|
||||
* @brief Get the corresponding clio config type
|
||||
*
|
||||
* @tparam Type The type to get the corresponding ConfigType for
|
||||
* @return The corresponding ConfigType
|
||||
*/
|
||||
template <typename Type>
|
||||
constexpr ConfigType
|
||||
getType()
|
||||
{
|
||||
if constexpr (std::is_same_v<Type, int64_t>) {
|
||||
return ConfigType::Integer;
|
||||
} else if constexpr (std::is_same_v<Type, std::string>) {
|
||||
return ConfigType::String;
|
||||
} else if constexpr (std::is_same_v<Type, double>) {
|
||||
return ConfigType::Double;
|
||||
} else if constexpr (std::is_same_v<Type, bool>) {
|
||||
return ConfigType::Boolean;
|
||||
} else {
|
||||
static_assert(util::Unsupported<Type>, "Wrong config type");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Represents the config values for Json/Yaml config
|
||||
*
|
||||
* Used in ClioConfigDefinition to indicate the required type of value and
|
||||
* whether it is mandatory to specify in the configuration
|
||||
*/
|
||||
class ConfigValue {
|
||||
public:
|
||||
using Type = std::variant<int64_t, std::string, bool, double>;
|
||||
|
||||
/**
|
||||
* @brief Constructor initializing with the config type
|
||||
*
|
||||
* @param type The type of the config value
|
||||
*/
|
||||
constexpr ConfigValue(ConfigType type) : type_(type)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the default value for the config
|
||||
*
|
||||
* @param value The default value
|
||||
* @return Reference to this ConfigValue
|
||||
*/
|
||||
[[nodiscard]] ConfigValue&
|
||||
defaultValue(Type value)
|
||||
{
|
||||
setValue(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the config type
|
||||
*
|
||||
* @return The config type
|
||||
*/
|
||||
[[nodiscard]] constexpr ConfigType
|
||||
type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the minimum value for the config
|
||||
*
|
||||
* @param min The minimum value
|
||||
* @return Reference to this ConfigValue
|
||||
*/
|
||||
[[nodiscard]] constexpr ConfigValue&
|
||||
min(std::uint32_t min)
|
||||
{
|
||||
min_ = min;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the maximum value for the config
|
||||
*
|
||||
* @param max The maximum value
|
||||
* @return Reference to this ConfigValue
|
||||
*/
|
||||
[[nodiscard]] constexpr ConfigValue&
|
||||
max(std::uint32_t max)
|
||||
{
|
||||
max_ = max;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the config value as optional, meaning the user doesn't have to provide the value in their config
|
||||
*
|
||||
* @return Reference to this ConfigValue
|
||||
*/
|
||||
[[nodiscard]] constexpr ConfigValue&
|
||||
optional()
|
||||
{
|
||||
optional_ = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if configValue is optional
|
||||
*
|
||||
* @return true if optional, false otherwise
|
||||
*/
|
||||
[[nodiscard]] constexpr bool
|
||||
isOptional() const
|
||||
{
|
||||
return optional_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if value is optional
|
||||
*
|
||||
* @return if value is optiona, false otherwise
|
||||
*/
|
||||
[[nodiscard]] constexpr bool
|
||||
hasValue() const
|
||||
{
|
||||
return value_.has_value();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the value of config
|
||||
*
|
||||
* @return Config Value
|
||||
*/
|
||||
[[nodiscard]] Type const&
|
||||
getValue() const
|
||||
{
|
||||
return value_.value();
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Checks if the value type is consistent with the specified ConfigType
|
||||
*
|
||||
* @param type The config type
|
||||
* @param value The config value
|
||||
*/
|
||||
static void
|
||||
checkTypeConsistency(ConfigType type, Type value)
|
||||
{
|
||||
if (std::holds_alternative<std::string>(value)) {
|
||||
ASSERT(type == ConfigType::String, "Value does not match type string");
|
||||
} else if (std::holds_alternative<bool>(value)) {
|
||||
ASSERT(type == ConfigType::Boolean, "Value does not match type boolean");
|
||||
} else if (std::holds_alternative<double>(value)) {
|
||||
ASSERT(type == ConfigType::Double, "Value does not match type double");
|
||||
} else if (std::holds_alternative<int64_t>(value)) {
|
||||
ASSERT(type == ConfigType::Integer, "Value does not match type integer");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the value for the config
|
||||
*
|
||||
* @param value The value to set
|
||||
* @return The value that was set
|
||||
*/
|
||||
Type
|
||||
setValue(Type value)
|
||||
{
|
||||
checkTypeConsistency(type_, value);
|
||||
value_ = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
ConfigType type_{};
|
||||
bool optional_{false};
|
||||
std::optional<Type> value_;
|
||||
std::optional<std::uint32_t> min_;
|
||||
std::optional<std::uint32_t> max_;
|
||||
};
|
||||
|
||||
} // namespace util::config
|
||||
33
src/util/newconfig/Errors.hpp
Normal file
33
src/util/newconfig/Errors.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace util::config {
|
||||
|
||||
/** @brief todo: Will display the different errors when parsing config */
|
||||
struct Error {
|
||||
std::string_view key;
|
||||
std::string_view error;
|
||||
};
|
||||
|
||||
} // namespace util::config
|
||||
101
src/util/newconfig/ObjectView.cpp
Normal file
101
src/util/newconfig/ObjectView.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/ObjectView.hpp"
|
||||
|
||||
#include "util/Assert.hpp"
|
||||
#include "util/newconfig/ArrayView.hpp"
|
||||
#include "util/newconfig/ConfigDefinition.hpp"
|
||||
#include "util/newconfig/ValueView.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
namespace util::config {
|
||||
|
||||
ObjectView::ObjectView(std::string_view prefix, ClioConfigDefinition const& clioConfig)
|
||||
: prefix_{prefix}, clioConfig_{clioConfig}
|
||||
{
|
||||
}
|
||||
|
||||
ObjectView::ObjectView(std::string_view prefix, std::size_t arrayIndex, ClioConfigDefinition const& clioConfig)
|
||||
: prefix_{prefix}, arrayIndex_{arrayIndex}, clioConfig_{clioConfig}
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
ObjectView::containsKey(std::string_view key) const
|
||||
{
|
||||
return clioConfig_.get().contains(getFullKey(key));
|
||||
}
|
||||
|
||||
ValueView
|
||||
ObjectView::getValue(std::string_view key) const
|
||||
{
|
||||
auto const fullKey = getFullKey(key);
|
||||
if (arrayIndex_.has_value()) {
|
||||
return clioConfig_.get().getArray(fullKey).valueAt(arrayIndex_.value());
|
||||
}
|
||||
return clioConfig_.get().getValue(fullKey);
|
||||
}
|
||||
|
||||
ObjectView
|
||||
ObjectView::getObject(std::string_view key) const
|
||||
{
|
||||
auto const fullKey = getFullKey(key);
|
||||
if (startsWithKey(fullKey) && !arrayIndex_.has_value()) {
|
||||
return clioConfig_.get().getObject(fullKey);
|
||||
}
|
||||
if (startsWithKey(fullKey) && arrayIndex_.has_value()) {
|
||||
return ObjectView(fullKey, arrayIndex_.value(), clioConfig_);
|
||||
}
|
||||
ASSERT(false, "Key {} does not exist in object", fullKey);
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
ArrayView
|
||||
ObjectView::getArray(std::string_view key) const
|
||||
{
|
||||
auto fullKey = getFullKey(key);
|
||||
if (!fullKey.contains(".[]"))
|
||||
fullKey += ".[]";
|
||||
|
||||
ASSERT(clioConfig_.get().hasItemsWithPrefix(fullKey), "Key {} does not exist in object", fullKey);
|
||||
return clioConfig_.get().getArray(fullKey);
|
||||
}
|
||||
|
||||
std::string
|
||||
ObjectView::getFullKey(std::string_view key) const
|
||||
{
|
||||
return fmt::format("{}.{}", prefix_, key);
|
||||
}
|
||||
|
||||
bool
|
||||
ObjectView::startsWithKey(std::string_view key) const
|
||||
{
|
||||
return std::ranges::any_of(clioConfig_.get(), [&key](auto const& pair) { return pair.first.starts_with(key); });
|
||||
}
|
||||
|
||||
} // namespace util::config
|
||||
122
src/util/newconfig/ObjectView.hpp
Normal file
122
src/util/newconfig/ObjectView.hpp
Normal file
@@ -0,0 +1,122 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/newconfig/ConfigValue.hpp"
|
||||
#include "util/newconfig/ValueView.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace util::config {
|
||||
|
||||
class ClioConfigDefinition;
|
||||
class ArrayView;
|
||||
|
||||
/**
|
||||
* @brief Provides a view into a subset of configuration data defined by a prefix
|
||||
*
|
||||
* Allows querying and accessing configuration values based on the provided prefix
|
||||
*/
|
||||
class ObjectView {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs an ObjectView for the specified prefix. The view must be of type object
|
||||
*
|
||||
* @param prefix The prefix indicating the subset of configuration data to view
|
||||
* @param clioConfig Reference to the ClioConfigDefinition containing all the configuration data
|
||||
*/
|
||||
ObjectView(std::string_view prefix, ClioConfigDefinition const& clioConfig);
|
||||
|
||||
/**
|
||||
* @brief Constructs an ObjectView for an indexed array within the specified prefix
|
||||
*
|
||||
* @param prefix The prefix indicating the subset of configuration data to view
|
||||
* @param arrayIndex The index of the array object element to view
|
||||
* @param clioConfig Reference to the ClioConfigDefinition containing all the configuration data
|
||||
*/
|
||||
ObjectView(std::string_view prefix, std::size_t arrayIndex, ClioConfigDefinition const& clioConfig);
|
||||
|
||||
/**
|
||||
* @brief Checks if prefix_.key (fullkey) exists in ClioConfigDefinition
|
||||
*
|
||||
* @param key The suffix of the key
|
||||
* @return true if the full key exists, otherwise false
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
containsKey(std::string_view key) const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the value associated with the specified prefix._key in ClioConfigDefinition
|
||||
*
|
||||
* @param key The suffix of the key
|
||||
* @return A ValueView object representing the value associated with the key
|
||||
*/
|
||||
[[nodiscard]] ValueView
|
||||
getValue(std::string_view key) const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves an ObjectView in ClioConfigDefinition with key that starts with prefix_.key. The view must be of
|
||||
* type object
|
||||
*
|
||||
* @param key The suffix of the key
|
||||
* @return An ObjectView representing the subset of configuration data
|
||||
*/
|
||||
[[nodiscard]] ObjectView
|
||||
getObject(std::string_view key) const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves an ArrayView in ClioConfigDefinition with key that starts with prefix_.key. The view must be of
|
||||
* type object
|
||||
*
|
||||
* @param key The suffix of the key
|
||||
* @return An ObjectView representing the subset of configuration data
|
||||
*/
|
||||
[[nodiscard]] ArrayView
|
||||
getArray(std::string_view key) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief returns the full key (prefix.key)
|
||||
*
|
||||
* @param key The suffix of the key
|
||||
* @return the full string of the key
|
||||
*/
|
||||
[[nodiscard]] std::string
|
||||
getFullKey(std::string_view key) const;
|
||||
|
||||
/**
|
||||
* @brief Checks if any key in ClioConfigDefinition starts with prefix_.key
|
||||
*
|
||||
* @param key The suffix of the key
|
||||
* @return true if at least one key starts with the specified prefix_.key, otherwise false
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
startsWithKey(std::string_view key) const;
|
||||
|
||||
std::string prefix_;
|
||||
std::optional<size_t> arrayIndex_;
|
||||
std::reference_wrapper<ClioConfigDefinition const> clioConfig_;
|
||||
};
|
||||
|
||||
} // namespace util::config
|
||||
82
src/util/newconfig/ValueView.cpp
Normal file
82
src/util/newconfig/ValueView.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/ValueView.hpp"
|
||||
|
||||
#include "util/Assert.hpp"
|
||||
#include "util/newconfig/ConfigValue.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
namespace util::config {
|
||||
|
||||
ValueView::ValueView(ConfigValue const& configVal) : configVal_{configVal}
|
||||
{
|
||||
}
|
||||
|
||||
std::string_view
|
||||
ValueView::asString() const
|
||||
{
|
||||
if (this->type() == ConfigType::String && configVal_.get().hasValue())
|
||||
return std::get<std::string>(configVal_.get().getValue());
|
||||
ASSERT(false, "Value view is not of String type");
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
bool
|
||||
ValueView::asBool() const
|
||||
{
|
||||
if (type() == ConfigType::Boolean && configVal_.get().hasValue())
|
||||
return std::get<bool>(configVal_.get().getValue());
|
||||
ASSERT(false, "Value view is not of Bool type");
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
double
|
||||
ValueView::asDouble() const
|
||||
{
|
||||
if (configVal_.get().hasValue()) {
|
||||
if (type() == ConfigType::Double) {
|
||||
return std::get<double>(configVal_.get().getValue());
|
||||
}
|
||||
if (type() == ConfigType::Integer)
|
||||
return static_cast<double>(std::get<int64_t>(configVal_.get().getValue()));
|
||||
}
|
||||
ASSERT(false, "Value view is not of Double type");
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
float
|
||||
ValueView::asFloat() const
|
||||
{
|
||||
if (configVal_.get().hasValue()) {
|
||||
if (type() == ConfigType::Double) {
|
||||
return static_cast<float>(std::get<double>(configVal_.get().getValue()));
|
||||
}
|
||||
if (type() == ConfigType::Integer)
|
||||
return static_cast<float>(std::get<int64_t>(configVal_.get().getValue()));
|
||||
}
|
||||
ASSERT(false, "Value view is not of Float type");
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
} // namespace util::config
|
||||
146
src/util/newconfig/ValueView.hpp
Normal file
146
src/util/newconfig/ValueView.hpp
Normal file
@@ -0,0 +1,146 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/Assert.hpp"
|
||||
#include "util/newconfig/ConfigValue.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <string_view>
|
||||
|
||||
namespace util::config {
|
||||
|
||||
class ClioConfigDefinition;
|
||||
|
||||
/**
|
||||
* @brief Provides view into ConfigValues that represents values in Clio Config
|
||||
*/
|
||||
class ValueView {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a ValueView object
|
||||
*
|
||||
* @param configVal the config Value to view
|
||||
*/
|
||||
ValueView(ConfigValue const& configVal);
|
||||
|
||||
/**
|
||||
* @brief Retrieves the value as a string
|
||||
*
|
||||
* @return The value as a string
|
||||
* @throws std::bad_variant_access if the value is not a string
|
||||
*/
|
||||
[[nodiscard]] std::string_view
|
||||
asString() const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the value as a boolean
|
||||
*
|
||||
* @return The value as a boolean
|
||||
* @throws std::bad_variant_access if the value is not a boolean
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
asBool() const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves any type of "int" value (uint_32, int64_t etc)
|
||||
*
|
||||
* @return The value with user requested type (if convertible)
|
||||
* @throws std::logic_error if the int < 0 and user requested unsigned int
|
||||
* @throws std::bad_variant_access if the value is not of type int
|
||||
*/
|
||||
template <typename T>
|
||||
[[nodiscard]] T
|
||||
asIntType() const
|
||||
{
|
||||
if ((type() == ConfigType::Integer) && configVal_.get().hasValue()) {
|
||||
auto const val = std::get<int64_t>(configVal_.get().getValue());
|
||||
if (std::is_unsigned_v<T> && val < 0)
|
||||
ASSERT(false, "Int {} cannot be converted to the specified unsigned type", val);
|
||||
|
||||
if (std::is_convertible_v<decltype(val), T>) {
|
||||
return static_cast<T>(val);
|
||||
}
|
||||
}
|
||||
ASSERT(false, "Value view is not of any Int type");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves the value as a double
|
||||
*
|
||||
* @return The value as a double
|
||||
* @throws std::bad_variant_access if the value cannot be retrieved as a Double
|
||||
*/
|
||||
[[nodiscard]] double
|
||||
asDouble() const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the value as a float
|
||||
*
|
||||
* @return The value as a float
|
||||
* @throws std::bad_variant_access if the value cannot be retrieved as a float
|
||||
*/
|
||||
[[nodiscard]] float
|
||||
asFloat() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the config type
|
||||
*
|
||||
* @return The config type
|
||||
*/
|
||||
[[nodiscard]] constexpr ConfigType
|
||||
type() const
|
||||
{
|
||||
return configVal_.get().type();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if Config Value exists
|
||||
*
|
||||
* @return true if exists, false otherwise
|
||||
*/
|
||||
[[nodiscard]] constexpr bool
|
||||
hasValue() const
|
||||
{
|
||||
return configVal_.get().hasValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if config value is optional
|
||||
*
|
||||
* @return true if optional, false otherwise
|
||||
*/
|
||||
[[nodiscard]] constexpr bool
|
||||
isOptional() const
|
||||
{
|
||||
return configVal_.get().isOptional();
|
||||
}
|
||||
|
||||
private:
|
||||
std::reference_wrapper<ConfigValue const> configVal_;
|
||||
};
|
||||
|
||||
} // namespace util::config
|
||||
95
tests/common/util/newconfig/FakeConfigData.hpp
Normal file
95
tests/common/util/newconfig/FakeConfigData.hpp
Normal file
@@ -0,0 +1,95 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/newconfig/Array.hpp"
|
||||
#include "util/newconfig/ConfigDefinition.hpp"
|
||||
#include "util/newconfig/ConfigValue.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace util::config;
|
||||
|
||||
inline ClioConfigDefinition
|
||||
generateConfig()
|
||||
{
|
||||
return ClioConfigDefinition{
|
||||
{"header.text1", ConfigValue{ConfigType::String}.defaultValue("value")},
|
||||
{"header.port", ConfigValue{ConfigType::Integer}.defaultValue(123)},
|
||||
{"header.admin", ConfigValue{ConfigType::Boolean}.defaultValue(true)},
|
||||
{"header.sub.sub2Value", ConfigValue{ConfigType::String}.defaultValue("TSM")},
|
||||
{"ip", ConfigValue{ConfigType::Double}.defaultValue(444.22)},
|
||||
{"array.[].sub",
|
||||
Array{
|
||||
ConfigValue{ConfigType::Double}.defaultValue(111.11), ConfigValue{ConfigType::Double}.defaultValue(4321.55)
|
||||
}},
|
||||
{"array.[].sub2",
|
||||
Array{
|
||||
ConfigValue{ConfigType::String}.defaultValue("subCategory"),
|
||||
ConfigValue{ConfigType::String}.defaultValue("temporary")
|
||||
}},
|
||||
{"higher.[].low.section", Array{ConfigValue{ConfigType::String}.defaultValue("true")}},
|
||||
{"higher.[].low.admin", Array{ConfigValue{ConfigType::Boolean}.defaultValue(false)}},
|
||||
{"dosguard.whitelist.[]",
|
||||
Array{
|
||||
ConfigValue{ConfigType::String}.defaultValue("125.5.5.2"),
|
||||
ConfigValue{ConfigType::String}.defaultValue("204.2.2.2")
|
||||
}},
|
||||
{"dosguard.port", ConfigValue{ConfigType::Integer}.defaultValue(55555)}
|
||||
};
|
||||
}
|
||||
|
||||
/* The config definition above would look like this structure in config.json:
|
||||
"header": {
|
||||
"text1": "value",
|
||||
"port": 123,
|
||||
"admin": true,
|
||||
"sub": {
|
||||
"sub2Value": "TSM"
|
||||
}
|
||||
},
|
||||
"ip": 444.22,
|
||||
"array": [
|
||||
{
|
||||
"sub": 111.11,
|
||||
"sub2": "subCategory"
|
||||
},
|
||||
{
|
||||
"sub": 4321.55,
|
||||
"sub2": "temporary"
|
||||
}
|
||||
],
|
||||
"higher": [
|
||||
{
|
||||
"low": {
|
||||
"section": "true",
|
||||
"admin": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"dosguard": {
|
||||
"whitelist": [
|
||||
"125.5.5.2", "204.2.2.2"
|
||||
],
|
||||
"port" : 55555
|
||||
},
|
||||
|
||||
|
||||
*/
|
||||
@@ -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