10#include <boost/test/unit_test.hpp>
21#include <system_error>
37inline std::ostream&
operator<<(std::ostream& os,
const std::pair<std::string, common::SettingsValue>& kv)
40 out.pushKVEnd(kv.first, kv.second);
56 fs::path path = m_args.GetDataDirBase() /
"settings.json";
65 std::map<std::string, common::SettingsValue> expected{
73 std::map<std::string, common::SettingsValue>
values;
74 std::vector<std::string> errors;
76 BOOST_CHECK_EQUAL_COLLECTIONS(
values.begin(),
values.end(), expected.begin(), expected.end());
92 BOOST_CHECK_EQUAL_COLLECTIONS(errors.begin(), errors.end(), dup_keys.begin(), dup_keys.end());
98 std::vector<std::string> non_kv = {strprintf("Found non-object value \"non-kv\" in settings file %s",
fs::PathToString(path))};
99 BOOST_CHECK_EQUAL_COLLECTIONS(errors.begin(), errors.end(), non_kv.begin(), non_kv.end());
104 std::vector<std::string> fail_parse = {strprintf("Settings file %s does not contain valid JSON. This is probably caused by disk corruption or a crash, "
105 "and can be fixed by removing the file, which will reset settings to default values.",
107 BOOST_CHECK_EQUAL_COLLECTIONS(errors.begin(), errors.end(), fail_parse.begin(), fail_parse.end());
115 for (
const auto& item :
GetSettingsList(settings,
"section",
"name",
false)) {
128 settings.
ro_config[
"section"][
"name"].emplace_back(2);
131 CheckValues(settings, R
"("val2")", R"(["val1","val2",2])");
134 settings2.ro_config["section"][
"name"].emplace_back(
"val2");
135 settings2.
ro_config[
"section"][
"name"].emplace_back(
"val3");
138 CheckValues(settings2, R
"("val2")", R"(["val2","val3"])");
166 template <
typename Fn>
174 for (
bool force_set : {
false,
true}) {
175 for (
bool ignore_default_section_config : {
false,
true}) {
176 fn(arg_actions, conf_actions, force_set, ignore_default_section_config);
191 FILE* out_file =
nullptr;
192 if (
const char* out_path = getenv(
"SETTINGS_MERGE_TEST_OUT")) {
194 if (!out_file)
throw std::system_error(errno, std::generic_category(),
"fopen failed");
198 ForEachMergeSetup([&](
const ActionList& arg_actions,
const ActionList& conf_actions,
bool force_set,
199 bool ignore_default_section_config) {
201 int value_suffix = 0;
204 const std::string&
name = ignore_default_section_config ?
"wallet" :
"server";
205 auto push_values = [&](Action action,
const char* value_prefix,
const std::string& name_prefix,
206 std::vector<common::SettingsValue>& dest) {
207 if (action == SET || action == SECTION_SET) {
208 for (
int i = 0; i < 2; ++i) {
209 dest.emplace_back(value_prefix +
ToString(++value_suffix));
210 desc +=
" " + name_prefix +
name +
"=" + dest.back().get_str();
212 }
else if (action == NEGATE || action == SECTION_NEGATE) {
213 dest.emplace_back(
false);
214 desc +=
" " + name_prefix +
"no" +
name;
220 desc +=
" " +
name +
"=forced";
222 for (Action arg_action : arg_actions) {
225 for (Action conf_action : conf_actions) {
226 bool use_section = conf_action == SECTION_SET || conf_action == SECTION_NEGATE;
227 push_values(conf_action,
"c", use_section ? network +
"." :
"",
232 desc +=
GetSetting(settings, network,
name, ignore_default_section_config,
false,
false).
write();
244 BOOST_REQUIRE(fwrite(desc.data(), 1, desc.size(), out_file) == desc.size());
249 if (fclose(out_file))
throw std::system_error(errno, std::generic_category(),
"fclose failed");
255 std::string out_sha_hex =
HexStr(out_sha_bytes);
266 BOOST_CHECK_EQUAL(out_sha_hex,
"79db02d74e3e193196541b67c068b40ebd0c124a24b3ecbe9cbf7e85b1c4ba7a");
std::string ChainTypeToString(ChainType chain)
A hasher class for Bitcoin's 256-bit hash (double SHA-256).
void Finalize(Span< unsigned char > output)
CHash256 & Write(Span< const unsigned char > input)
static const size_t OUTPUT_SIZE
void push_back(UniValue val)
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
bool ReadSettings(const fs::path &path, std::map< std::string, SettingsValue > &values, std::vector< std::string > &errors)
Read settings file.
SettingsValue GetSetting(const Settings &settings, const std::string §ion, const std::string &name, bool ignore_default_section_config, bool ignore_nonpersistent, bool get_chain_type)
Get settings value from combined sources: forced settings, command line arguments,...
std::vector< SettingsValue > GetSettingsList(const Settings &settings, const std::string §ion, const std::string &name, bool ignore_default_section_config)
Get combined setting value similar to GetSetting(), except if setting was specified multiple times,...
bool OnlyHasDefaultSectionSetting(const Settings &settings, const std::string §ion, const std::string &name)
Return true if a setting is set in the default config file section, and not overridden by a higher pr...
static std::string PathToString(const path &path)
Convert path object to a byte string.
FILE * fopen(const fs::path &p, const char *mode)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
#define BOOST_CHECK_EQUAL(v1, v2)
#define BOOST_CHECK(expr)
static const int64_t values[]
A selection of numbers that do not trigger int64_t overflow when added/subtracted.
BOOST_AUTO_TEST_CASE(ReadWrite)
static void CheckValues(const common::Settings &settings, const std::string &single_val, const std::string &list_val)
Check settings struct contents against expected json strings.
void WriteText(const fs::path &path, const std::string &text)
BOOST_FIXTURE_TEST_CASE(Merge, MergeTestingSetup)
bool operator==(const common::SettingsValue &a, const common::SettingsValue &b)
std::ostream & operator<<(std::ostream &os, const common::SettingsValue &value)
constexpr auto MakeUCharSpan(V &&v) -> decltype(UCharSpanCast(Span{std::forward< V >(v)}))
Like the Span constructor, but for (const) unsigned char member types only.
void ForEachNoDup(CharType(&string)[StringLength], CharType min_char, CharType max_char, Fn &&fn)
Iterate over string values and call function for each string without successive duplicate characters.
void ForEachMergeSetup(Fn &&fn)
Enumerate all possible test configurations.
Action[MAX_ACTIONS] ActionList
static constexpr int MAX_ACTIONS
Max number of actions to sequence together.
std::map< std::string, std::map< std::string, std::vector< SettingsValue > > > ro_config
Map of config section name and setting name to list of config file values.
std::map< std::string, SettingsValue > forced_settings
Map of setting name to forced setting value.
std::map< std::string, std::vector< SettingsValue > > command_line_options
Map of setting name to list of command line values.