1#include <test/jtx/TestSuite.h>
2#include <test/unit_test/FileDirGuard.h>
4#include <xrpld/core/Config.h>
6#include <xrpl/basics/FileUtilities.h>
7#include <xrpl/beast/unit_test/suite.h>
8#include <xrpl/config/BasicConfig.h>
9#include <xrpl/config/Constants.h>
10#include <xrpl/protocol/SystemParameters.h>
11#include <xrpl/server/Port.h>
13#include <boost/lexical_cast/bad_lexical_cast.hpp>
38 static constexpr char const* kConfigContentsTemplate = R
"xrpldConfig(
66#-------------------------------------------------------------------------------
71# This is primary persistent datastore for xrpld. This includes transaction
72# metadata, account states, and ledger headers. Helpful information can be
73# found on https://xrpl.org/capacity-planning.html#node-db-type
74# delete old ledgers while maintaining at least 2000. Do not require an
75# external administrative command to initiate deletion.
78path=/Users/dummy/xrpld/config/db/rocksdb
89# This needs to be an absolute directory reference, not a relative one.
90# Modify this value as required.
92/Users/dummy/xrpld/config/log/debug.log
100# Where to find some other servers speaking the XRPL protocol.
105# Turn down default logging to save disk space in the long run.
106# Valid values here are trace, debug, info, warning, error, and fatal
108{{ "command": "log_level", "severity": "warning" }}
110# Defaults to 1 ("yes") so that certificates will be validated. To allow the use
111# of self-signed certificates for development or internal use, set to 0 ("no").
119 std::string dbPathSection = dbPath.empty() ? "" :
"[database_path]\n" + dbPath;
121 validatorsFile.
empty() ?
"" :
"[validators_file]\n" + validatorsFile;
122 return std::format(kConfigContentsTemplate, dbPathSection, valFileSection);
144 bool useCounter =
true,
194 using namespace std::filesystem;
198 catch (std::exception& e)
211n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7
212n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj
213n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C
214n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS
215n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA
218nHUhG1PgAG8H8myUENypM35JgfqXAKNQvRVVAFDRzJrny5eZN8d5
219nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8
220nHUPDdcdb2Y5DZAJne4c2iabFuAP3F34xZUgYQT2NH7qfkdapgnz
222[validator_list_sites]
223recommended-xrpl-validators.com
224more-xrpl-validators.net
22703E74EE14CB525AFBB9F1B7D86CD58ECC4B91452294B42AB4E78F260BD905C091D
228030775A669685BD6ABCEBD80385921C7851783D991A8055FD21D2F3966C96F1B56
230[validator_list_threshold]
243 beast::unit_test::Suite& test,
245 path const& validatorsFileName,
246 bool useCounter =
true)
250 path(validatorsFileName.
empty() ? Config::kValidatorsFileName : validatorsFileName),
262 [[nodiscard]] std::string
302 BEAST_EXPECT(c.
legacy(
"not_in_file").empty());
303 c.
legacy(
"not_in_file",
"new_value");
304 BEAST_EXPECT(c.
legacy(
"not_in_file") ==
"new_value");
318 for (
auto const& configFile : configFiles)
323 path const f = td.file(std::string{configFile});
324 std::ofstream o(f.
string());
330 c.
setup(
"",
true,
false,
true);
334 "/Users/dummy/xrpld/config/log/debug.log");
338#if BOOST_OS_LINUX || BOOST_OS_MACOS
339 for (
auto const& configFile : configFiles)
354 char const* h =
getenv(
"HOME");
355 setenv(
"HOME", tc.path().c_str(), 1);
356 char const* x =
getenv(
"XDG_CONFIG_HOME");
357 setenv(
"XDG_CONFIG_HOME", tc.path().c_str(), 1);
362 p = tc.file(
systemName() +
"/" + std::string{configFile});
363 std::ofstream o(p.
string());
369 c.setup(
"",
true,
false,
true);
373 "/Users/dummy/xrpld/config/log/debug.log");
376 (h !=
nullptr) ? setenv(
"HOME", h, 1) : unsetenv(
"HOME");
377 (x !=
nullptr) ? setenv(
"XDG_CONFIG_HOME", x, 1) : unsetenv(
"XDG_CONFIG_HOME");
386 char const* h =
getenv(
"HOME");
387 setenv(
"HOME", tc.path().c_str(), 1);
388 char const* x =
getenv(
"XDG_CONFIG_HOME");
389 unsetenv(
"XDG_CONFIG_HOME");
392 std::string s =
".config";
398 p = tc.file(s +
"/" + std::string{configFile});
399 std::ofstream o(p.
string());
405 c.setup(
"",
true,
false,
true);
409 "/Users/dummy/xrpld/config/log/debug.log");
412 (h !=
nullptr) ? setenv(
"HOME", h, 1) : unsetenv(
"HOME");
414 setenv(
"XDG_CONFIG_HOME", x, 1);
427 using namespace std::filesystem;
429 constexpr char const* cc =
"[database_path]\n{}\n";
432 path const dataDirRel(
"test_data_dir");
433 path const dataDirAbs(cwd / dataDirRel);
437 c.loadFromString(
std::format(cc, dataDirAbs.string()));
443 c.loadFromString(
std::format(cc, dataDirRel.string()));
451 c.loadFromString(
"");
458 detail::DirGuard
const g0(*
this,
"test_db");
459 path const dataDirRel(
"test_data_dir");
460 path const dataDirAbs(cwd / g0.subdir() / dataDirRel);
461 detail::FileCfgGuard
const g(
463 auto const& c(g.config());
464 BEAST_EXPECT(g.dataDirExists());
465 BEAST_EXPECT(g.configFileExists());
470 std::string
const dbPath(
"my_db");
472 auto const& c(g.config());
473 std::string
const nativeDbPath =
absolute(
path(dbPath)).string();
474 BEAST_EXPECT(g.dataDirExists());
475 BEAST_EXPECT(g.configFileExists());
481 auto const& c(g.config());
482 std::string
const nativeDbPath =
484 BEAST_EXPECT(g.dataDirExists());
485 BEAST_EXPECT(g.configFileExists());
498 "eyJ2YWxpZGF0aW9uX3ByaXZhdGVfa2V5IjoiOWVkNDVmODY2MjQxY2MxOGEyNzQ3Yj"
499 "U0Mzg3YzA2MjU5MDc5NzJmNGU3MTkwMjMxZmFhOTM3NDU3ZmE5ZGFmNiIsIm1hbmlm"
500 "ZXN0IjoiSkFBQUFBRnhJZTFGdHdtaW12R3RIMmlDY01KcUM5Z1ZGS2lsR2Z3MS92Q3"
501 "hIWFhMcGxjMkduTWhBa0UxYWdxWHhCd0R3RGJJRDZPTVNZdU0wRkRBbHBBZ05rOFNL"
502 "Rm43TU8yZmRrY3dSUUloQU9uZ3U5c0FLcVhZb3VKK2wyVjBXK3NBT2tWQitaUlM2UF"
503 "NobEpBZlVzWGZBaUJzVkpHZXNhYWRPSmMvYUFab2tTMXZ5bUdtVnJsSFBLV1gzWXl3"
504 "dTZpbjhIQVNRS1B1Z0JENjdrTWFSRkd2bXBBVEhsR0tKZHZERmxXUFl5NUFxRGVkRn"
505 "Y1VEphMncwaTIxZXEzTVl5d0xWSlpuRk9yN0Mwa3cyQWlUelNDakl6ZGl0UTg9In0"
510 static constexpr char const* kConfigTemplate = R
"xrpldConfig(
518 auto const expectedError =
519 "Cannot have both [validation_seed] "
520 "and [validator_token] config sections";
529 BEAST_EXPECT(error == expectedError);
541 c.loadFromString(R
"xrpldConfig(
546 catch (std::runtime_error
const& e)
551 BEAST_EXPECT(error.
empty());
552 BEAST_EXPECT(c.networkId == 0);
556 c.loadFromString(R
"xrpldConfig(
559 catch (std::runtime_error
const& e)
564 BEAST_EXPECT(error.
empty());
565 BEAST_EXPECT(c.networkId == 0);
569 c.loadFromString(R
"xrpldConfig(
574 catch (std::runtime_error
const& e)
579 BEAST_EXPECT(error.
empty());
580 BEAST_EXPECT(c.networkId == 255);
584 c.loadFromString(R
"xrpldConfig(
594 BEAST_EXPECT(error.
empty());
595 BEAST_EXPECT(c.networkId == 10000);
603 using namespace std::filesystem;
606 constexpr char const* cc =
"[validators_file]\n{}\n";
608 std::string
const missingPath =
"/no/way/this/path/exists";
609 auto const expectedError =
610 "The file specified in [validators_file] does not exist: " + missingPath;
616 catch (std::runtime_error
const& e)
620 BEAST_EXPECT(error == expectedError);
624 detail::ValidatorsTxtGuard
const vtg(*
this,
"test_cfg",
"validators.cfg");
626 constexpr char const* cc =
"[validators_file]\n{}\n";
628 auto const expectedError =
629 "Invalid file specified in [validators_file]: " + invalidFile.
string();
635 catch (std::runtime_error
const& e)
639 BEAST_EXPECT(error == expectedError);
644 std::string
const toLoad(R
"xrpldConfig(
646n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7
647n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj
648n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C
651nHUhG1PgAG8H8myUENypM35JgfqXAKNQvRVVAFDRzJrny5eZN8d5
652nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8
654 c.loadFromString(toLoad);
657 BEAST_EXPECT(c.validatorListThreshold == std::nullopt);
662 std::string
const toLoad(R
"xrpldConfig(
663[validator_list_sites]
665trust-these-validators.gov
668021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
670[validator_list_threshold]
673 c.loadFromString(toLoad);
679 "trust-these-validators.gov");
683 "021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801"
687 BEAST_EXPECT(c.validatorListThreshold == std::size_t(1));
692 std::string
const toLoad(R
"xrpldConfig(
693[validator_list_sites]
695trust-these-validators.gov
698021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
700[validator_list_threshold]
703 c.loadFromString(toLoad);
709 "trust-these-validators.gov");
713 "021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801"
717 BEAST_EXPECT(c.validatorListThreshold == std::nullopt);
723 std::string
const toLoad(R
"xrpldConfig(
724[validator_list_sites]
726trust-these-validators.gov
729021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
731[validator_list_threshold]
735 auto const expectedError =
736 "Value in config section [validator_list_threshold] exceeds "
737 "the number of configured list keys";
740 c.loadFromString(toLoad);
743 catch (std::runtime_error
const& e)
747 BEAST_EXPECT(error == expectedError);
752 std::string
const toLoad(R
"xrpldConfig(
753[validator_list_sites]
755trust-these-validators.gov
758021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
760[validator_list_threshold]
764 auto const expectedError =
765 "Config section [validator_list_threshold] should contain "
769 c.loadFromString(toLoad);
772 catch (std::runtime_error
const& e)
776 BEAST_EXPECT(error == expectedError);
781 std::string
const toLoad(R
"xrpldConfig(
782[validator_list_sites]
784trust-these-validators.gov
787021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
789[validator_list_threshold]
795 c.loadFromString(toLoad);
798 catch (std::bad_cast& e)
808 std::string
const toLoad(R
"xrpldConfig(
809[validator_list_sites]
811trust-these-validators.gov
814 auto const expectedError =
"[validator_list_keys] config section is missing";
817 c.loadFromString(toLoad);
820 catch (std::runtime_error
const& e)
824 BEAST_EXPECT(error == expectedError);
828 detail::ValidatorsTxtGuard
const vtg(*
this,
"test_cfg",
"validators.cfg");
829 BEAST_EXPECT(vtg.validatorsFileExists());
831 constexpr char const* cc =
"[validators_file]\n{}\n";
832 c.loadFromString(
std::format(cc, vtg.validatorsFile()));
838 BEAST_EXPECT(c.validatorListThreshold == 2);
843 std::string
const valFileName =
"validators.txt";
844 detail::ValidatorsTxtGuard
const vtg(*
this,
"test_cfg", valFileName);
845 detail::FileCfgGuard
const rcg(
847 BEAST_EXPECT(vtg.validatorsFileExists());
848 BEAST_EXPECT(rcg.configFileExists());
849 auto const& c(rcg.config());
855 BEAST_EXPECT(c.validatorListThreshold == 2);
860 detail::ValidatorsTxtGuard
const vtg(*
this,
"test_cfg",
"validators.txt");
861 auto const valFilePath =
".." / vtg.subdir() /
"validators.txt";
862 detail::FileCfgGuard
const rcg(
864 BEAST_EXPECT(vtg.validatorsFileExists());
865 BEAST_EXPECT(rcg.configFileExists());
866 auto const& c(rcg.config());
872 BEAST_EXPECT(c.validatorListThreshold == 2);
876 detail::ValidatorsTxtGuard
const vtg(*
this,
"test_cfg",
"validators.txt");
877 detail::FileCfgGuard
const rcg(
879 BEAST_EXPECT(vtg.validatorsFileExists());
880 BEAST_EXPECT(rcg.configFileExists());
881 auto const& c(rcg.config());
887 BEAST_EXPECT(c.validatorListThreshold == 2);
893 BEAST_EXPECT(vtg.validatorsFileExists());
895 *
this, vtg.subdir(),
"validators.txt",
false);
896 BEAST_EXPECT(vtgDefault.validatorsFileExists());
899 BEAST_EXPECT(rcg.configFileExists());
900 auto const& c(rcg.config());
906 BEAST_EXPECT(c.validatorListThreshold == 2);
911 constexpr char const* cc = R
"xrpldConfig(
916n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7
917n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj
918n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C
919n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS
920n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA
923nHB1X37qrniVugfQcuBTAjswphC1drx7QjFFojJPZwKHHnt8kU7v
924nHUkAWDR4cB8AgPg7VXMX6et8xRTQb2KJfgv1aBEXozwrawRKgMB
926[validator_list_sites]
928trust-these-validators.gov
931021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
933 detail::ValidatorsTxtGuard const vtg(*
this,
"test_cfg",
"validators.cfg");
934 BEAST_EXPECT(vtg.validatorsFileExists());
936 c.loadFromString(
std::format(cc, vtg.validatorsFile()));
942 BEAST_EXPECT(c.validatorListThreshold == 2);
947 constexpr char const* cc = R
"xrpldConfig(
951[validator_list_threshold]
955 detail::ValidatorsTxtGuard const vtg(*
this,
"test_cfg",
"validators.cfg");
956 BEAST_EXPECT(vtg.validatorsFileExists());
957 auto const expectedError =
958 "Config section [validator_list_threshold] should contain "
963 c.loadFromString(
std::format(cc, vtg.validatorsFile()));
966 catch (std::runtime_error
const& e)
970 BEAST_EXPECT(error == expectedError);
977 constexpr char const* cc =
"[validators_file]\n{}\n";
979 detail::ValidatorsTxtGuard
const vtg(*
this,
"test_cfg",
"validators.cfg");
980 BEAST_EXPECT(vtg.validatorsFileExists());
981 auto const expectedError =
982 "The file specified in [validators_file] does not contain a "
983 "[validators], [validator_keys] or [validator_list_keys] "
985 vtg.validatorsFile();
986 std::ofstream
const o(vtg.validatorsFile());
990 c2.loadFromString(
std::format(cc, vtg.validatorsFile()));
992 catch (std::runtime_error
const& e)
996 BEAST_EXPECT(error == expectedError);
1016 BEAST_EXPECT(!config.
quiet());
1017 BEAST_EXPECT(!config.
silent());
1029 BEAST_EXPECT(config.
quiet());
1030 BEAST_EXPECT(!config.
silent());
1042 BEAST_EXPECT(config.quiet());
1043 BEAST_EXPECT(config.silent());
1044 BEAST_EXPECT(!config.standalone());
1045 BEAST_EXPECT(config.ledgerHistory == 256);
1055 BEAST_EXPECT(config.
quiet());
1056 BEAST_EXPECT(config.
silent());
1068 BEAST_EXPECT(!config.quiet());
1069 BEAST_EXPECT(!config.silent());
1070 BEAST_EXPECT(config.standalone());
1071 BEAST_EXPECT(config.ledgerHistory == 0);
1081 BEAST_EXPECT(config.
quiet());
1082 BEAST_EXPECT(!config.
silent());
1094 BEAST_EXPECT(config.quiet());
1095 BEAST_EXPECT(config.silent());
1096 BEAST_EXPECT(config.standalone());
1097 BEAST_EXPECT(config.ledgerHistory == 0);
1107 BEAST_EXPECT(config.quiet());
1108 BEAST_EXPECT(config.silent());
1109 BEAST_EXPECT(config.standalone());
1110 BEAST_EXPECT(config.ledgerHistory == 0);
1119 auto const& conf = cfg.
config();
1127 BEAST_EXPECT(
rpc.adminNetsV4.size() +
rpc.adminNetsV6.size() == 2);
1144 BEAST_EXPECT(
false);
1159 std::string
const toLoad(
1182 cfg.loadFromString(toLoad);
1222 anotherserversansport
1223 anotherserverwithport:12
1233 2001:db8:3333:4444:5555:6666:7777:8888:12345
1234 [2001:db8:3333:4444:5555:6666:7777:8888]:1
1238 cfg.loadFromString(toLoad);
1249 BEAST_EXPECT(cfg.ips[0] == "r.ripple.com 51235");
1251 BEAST_EXPECT(cfg.ipsFixed[0] ==
"s1.ripple.com 51235");
1252 BEAST_EXPECT(cfg.ipsFixed[1] ==
"s2.ripple.com 51235");
1253 BEAST_EXPECT(cfg.ipsFixed[2] ==
"anotherserversansport");
1254 BEAST_EXPECT(cfg.ipsFixed[3] ==
"anotherserverwithport 12");
1255 BEAST_EXPECT(cfg.ipsFixed[4] ==
"1.1.1.1 1");
1256 BEAST_EXPECT(cfg.ipsFixed[5] ==
"1.1.1.1 1");
1257 BEAST_EXPECT(cfg.ipsFixed[6] ==
"12.34.12.123 12345");
1258 BEAST_EXPECT(cfg.ipsFixed[7] ==
"12.34.12.123 12345");
1261 BEAST_EXPECT(cfg.ipsFixed[8] ==
"::");
1262 BEAST_EXPECT(cfg.ipsFixed[9] ==
"2001:db8::");
1263 BEAST_EXPECT(cfg.ipsFixed[10] ==
"::1");
1264 BEAST_EXPECT(cfg.ipsFixed[11] ==
"::1:12345");
1265 BEAST_EXPECT(cfg.ipsFixed[12] ==
"[::1]:12345");
1266 BEAST_EXPECT(cfg.ipsFixed[13] ==
"2001:db8:3333:4444:5555:6666:7777:8888:12345");
1267 BEAST_EXPECT(cfg.ipsFixed[14] ==
"[2001:db8:3333:4444:5555:6666:7777:8888]:1");
1273 struct TestCommentData
1282 {{.line =
"password = aaaa\\#bbbb",
1283 .field =
"password",
1284 .expect =
"aaaa#bbbb",
1285 .hadComment =
false},
1286 {.line =
"password = aaaa#bbbb",
1287 .field =
"password",
1289 .hadComment =
true},
1290 {.line =
"password = aaaa #bbbb",
1291 .field =
"password",
1293 .hadComment =
true},
1295 {.line =
"password = #aaaa #bbbb",
1297 .expect =
"password =",
1298 .hadComment =
true},
1299 {.line =
"password = aaaa\\# #bbbb",
1300 .field =
"password",
1302 .hadComment =
true},
1303 {.line =
"password = aaaa\\##bbbb",
1304 .field =
"password",
1306 .hadComment =
true},
1307 {.line =
"aaaa#bbbb", .field =
"", .expect =
"aaaa", .hadComment =
true},
1308 {.line =
"aaaa\\#bbbb", .field =
"", .expect =
"aaaa#bbbb", .hadComment =
false},
1309 {.line =
"aaaa\\##bbbb", .field =
"", .expect =
"aaaa#", .hadComment =
true},
1310 {.line =
"aaaa #bbbb", .field =
"", .expect =
"aaaa", .hadComment =
true},
1311 {.line =
"1 #comment", .field =
"", .expect =
"1", .hadComment =
true},
1312 {.line =
"#whole thing is comment", .field =
"", .expect =
"", .hadComment =
false},
1313 {.line =
" #whole comment with space",
1316 .hadComment =
false}}};
1318 for (
auto const& t : tests)
1321 s.
append(std::string(t.line));
1322 BEAST_EXPECT(s.hadTrailingComments() == t.hadComment);
1323 if (t.field.empty())
1325 BEAST_EXPECTS(s.legacy() == t.expect, s.legacy());
1330 BEAST_EXPECTS(
set(field, std::string(t.field), s), t.line);
1331 BEAST_EXPECTS(field == t.expect, t.line);
1337 s.append(
"online_delete = 3000");
1338 std::uint32_t od = 0;
1346 s.append(
"online_delete = 2000 #my comment on this");
1347 std::uint32_t od = 0;
1357 using namespace std::string_literals;
1359 s.
append(
"a_string = mystring");
1360 s.
append(
"positive_int = 2");
1361 s.
append(
"negative_int = -3");
1362 s.
append(
"bool_ish = 1");
1365 auto val1 =
"value 1"s;
1366 BEAST_EXPECT(
set(val1,
"a_string", s));
1367 BEAST_EXPECT(val1 ==
"mystring");
1369 auto val2 =
"value 2"s;
1370 BEAST_EXPECT(!
set(val2,
"not_a_key", s));
1371 BEAST_EXPECT(val2 ==
"value 2");
1372 BEAST_EXPECT(!
set(val2,
"default"s,
"not_a_key", s));
1373 BEAST_EXPECT(val2 ==
"default");
1376 BEAST_EXPECT(val3 ==
"mystring");
1378 BEAST_EXPECT(val4.empty());
1380 BEAST_EXPECT(val5 ==
"default");
1382 auto val6 =
"value 6"s;
1384 BEAST_EXPECT(val6 ==
"mystring");
1386 auto val7 =
"value 7"s;
1388 BEAST_EXPECT(val7 ==
"value 7");
1393 BEAST_EXPECT(
set(val1,
"positive_int", s));
1394 BEAST_EXPECT(val1 == 2);
1397 BEAST_EXPECT(
set(val2,
"negative_int", s));
1398 BEAST_EXPECT(val2 == -3);
1401 BEAST_EXPECT(!
set(val3,
"a_string", s));
1402 BEAST_EXPECT(val3 == 3);
1404 auto val4 =
get<int>(s,
"positive_int");
1405 BEAST_EXPECT(val4 == 2);
1406 auto val5 =
get<int>(s,
"not_a_key");
1407 BEAST_EXPECT(val5 == 0);
1408 auto val6 =
get<int>(s,
"not_a_key", 5);
1409 BEAST_EXPECT(val6 == 5);
1410 auto val7 =
get<int>(s,
"a_string", 6);
1411 BEAST_EXPECT(val7 == 6);
1414 BEAST_EXPECT(
getIfExists(s,
"positive_int", val8));
1415 BEAST_EXPECT(val8 == 2);
1419 BEAST_EXPECT(val9 == 9);
1423 BEAST_EXPECT(val10 == 10);
1425 BEAST_EXPECT(s.
get<
int>(
"not_a_key") == std::nullopt);
1428 [[maybe_unused]]
auto _ = s.
get<
int>(
"a_string");
1431 catch (boost::bad_lexical_cast&)
1440 BEAST_EXPECT(flag1 ==
true);
1443 BEAST_EXPECT(!
getIfExists(s,
"not_a_key", flag2));
1444 BEAST_EXPECT(flag2 ==
false);
1455 std::uint32_t numSeconds;
1456 std::uint32_t configVal;
1460 std::vector<ConfigUnit>
const units = {
1461 {.unit =
"seconds", .numSeconds = 1, .configVal = 15 * 60, .shouldPass =
false},
1462 {.unit =
"minutes", .numSeconds = 60, .configVal = 14, .shouldPass =
false},
1463 {.unit =
"minutes", .numSeconds = 60, .configVal = 15, .shouldPass =
true},
1464 {.unit =
"hours", .numSeconds = 3600, .configVal = 10, .shouldPass =
true},
1465 {.unit =
"days", .numSeconds = 86400, .configVal = 10, .shouldPass =
true},
1466 {.unit =
"weeks", .numSeconds = 604800, .configVal = 2, .shouldPass =
true},
1467 {.unit =
"months", .numSeconds = 2592000, .configVal = 1, .shouldPass =
false},
1468 {.unit =
"years", .numSeconds = 31536000, .configVal = 1, .shouldPass =
false}};
1471 for (
auto& [unit, sec, val, shouldPass] : units)
1474 std::string toLoad(R
"xrpldConfig(
1475[amendment_majority_time]
1483 c.loadFromString(toLoad);
1486 BEAST_EXPECT(c.amendmentMajorityTime.count() == val * sec);
1493 catch (std::runtime_error
const&)
1526 BEAST_EXPECT(!testUnknown(
"none"));
1527 BEAST_EXPECT(!testUnknown(
"0.5"));
1528 BEAST_EXPECT(!testUnknown(
"180 seconds"));
1529 BEAST_EXPECT(!testUnknown(
"9 minutes"));
1532 BEAST_EXPECT(!testUnknown(
"299"));
1536 BEAST_EXPECT(testUnknown(
"301") == std::chrono::seconds{301});
1537 BEAST_EXPECT(testUnknown(
"1799") == std::chrono::seconds{1799});
1538 BEAST_EXPECT(testUnknown(
"1800") == std::chrono::seconds{1800});
1541 BEAST_EXPECT(!testUnknown(
"1801"));
1543 testcase(
"overlay: diverged time");
1546 auto testDiverged = [](std::string value) -> std::optional<std::chrono::seconds> {
1550 c.loadFromString(
"[overlay]\nmax_diverged_time=" + value);
1551 return c.maxDivergedTime;
1553 catch (std::runtime_error
const&)
1560 BEAST_EXPECT(!testDiverged(
"none"));
1561 BEAST_EXPECT(!testDiverged(
"0.5"));
1562 BEAST_EXPECT(!testDiverged(
"180 seconds"));
1563 BEAST_EXPECT(!testDiverged(
"9 minutes"));
1566 BEAST_EXPECT(!testDiverged(
"0"));
1567 BEAST_EXPECT(!testDiverged(
"59"));
1570 BEAST_EXPECT(testDiverged(
"60") == std::chrono::seconds{60});
1571 BEAST_EXPECT(testDiverged(
"61") == std::chrono::seconds{61});
1572 BEAST_EXPECT(testDiverged(
"899") == std::chrono::seconds{899});
1573 BEAST_EXPECT(testDiverged(
"900") == std::chrono::seconds{900});
1576 BEAST_EXPECT(!testDiverged(
"901"));
1578 testcase(
"overlay: manifest counts");
1582 auto testCount = [](std::string
const& key,
1583 std::string
const& value) -> std::optional<std::size_t> {
1587 c.loadFromString(
"[overlay]\n" + key +
"=" + value);
1588 return key ==
"max_trusted_count" ? c.maxTrustedCount : c.maxUntrustedCount;
1590 catch (std::runtime_error
const&)
1596 for (
auto const* key : {
"max_untrusted_count",
"max_trusted_count"})
1600 BEAST_EXPECT(!testCount(key,
"none"));
1601 BEAST_EXPECT(!testCount(key,
"0.5"));
1602 BEAST_EXPECT(!testCount(key,
"400 manifests"));
1603 BEAST_EXPECT(!testCount(key,
"-1"));
1606 BEAST_EXPECT(!testCount(key,
"0"));
1607 BEAST_EXPECT(!testCount(key,
"49"));
1610 BEAST_EXPECT(testCount(key,
"50") == 50);
1611 BEAST_EXPECT(testCount(key,
"51") == 51);
1612 BEAST_EXPECT(testCount(key,
"300") == 300);
1613 BEAST_EXPECT(testCount(key,
"400") == 400);
1614 BEAST_EXPECT(testCount(key,
"999") == 999);
1615 BEAST_EXPECT(testCount(key,
"1000") == 1000);
1618 BEAST_EXPECT(!testCount(key,
"1001"));
1624 c.loadFromString(
"[overlay]\nmax_untrusted_count=500");
1625 BEAST_EXPECT(c.maxUntrustedCount == 500);
1626 BEAST_EXPECT(!c.maxTrustedCount);
1630 c.loadFromString(
"[overlay]\nmax_trusted_count=500");
1631 BEAST_EXPECT(c.maxTrustedCount == 500);
1632 BEAST_EXPECT(!c.maxUntrustedCount);
1638 c.loadFromString(
"[overlay]\nmax_untrusted_count=250\nmax_trusted_count=750");
1639 BEAST_EXPECT(c.maxUntrustedCount == 250);
1640 BEAST_EXPECT(c.maxTrustedCount == 750);
1646 c.loadFromString(
"[overlay]\nip_limit=64");
1647 BEAST_EXPECT(!c.maxUntrustedCount);
1648 BEAST_EXPECT(!c.maxTrustedCount);
1654 c.loadFromString(
"");
1655 BEAST_EXPECT(!c.maxUntrustedCount);
1656 BEAST_EXPECT(!c.maxTrustedCount);
bool unexcept(F &&f, String const &reason)
void pass()
Record a successful test condition.
void fail(String const &reason, char const *file, int line)
Record a failure.
LogOs< char > log
Logging output stream.
TestcaseT testcase
Memberspace for declaring test cases.
void legacy(std::string const §ion, std::string value)
Set a value that is not a key/value pair.
void testSetup(bool explicitPath)
void run() override
Runs the suite.
void testValidatorsFile()
std::filesystem::path path
void setup(std::string const &strConf, bool bQuiet, bool bSilent, bool bStandalone)
std::chrono::seconds maxUnknownTime
static char const *const kDatabaseDirName
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
static char const *const kConfigLegacyName
static char const *const kConfigFileName
std::uint32_t ledgerHistory
Holds a collection of configuration values.
std::optional< T > get(std::string const &name) const
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
bool expectException(Functor f, std::string const &message="")
beast::unit_test::Suite & test_
path const & subdir() const
std::filesystem::path path
auto rmDir(path const &toRm)
Write an xrpld config file and remove when done.
Config const & config() const
std::string configFile() const
bool configFileExists() const
bool dataDirExists() const
FileCfgGuard(beast::unit_test::Suite &test, path subDir, path const &dbPath, path const &configFile, path const &validatorsFile, bool useCounter=true, std::string confContents="")
Write a file in a directory and remove when done.
path const & file() const
FileDirGuard(beast::unit_test::Suite &test, path subDir, path file, std::string const &contents, bool useCounter=true, bool create=true)
Write a validators.txt file and remove when done.
std::string validatorsFile() const
bool validatorsFileExists() const
~ValidatorsTxtGuard()=default
ValidatorsTxtGuard(beast::unit_test::Suite &test, path subDir, path const &validatorsFileName, bool useCounter=true)
T create_directory(T... args)
T current_path(T... args)
T is_directory(T... args)
std::string valFileContents()
std::string configContents(std::string const &dbPath, std::string const &validatorsFile)
API version numbers used in later API versions.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool set(T &target, std::string const &name, Section const §ion)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
void parsePort(ParsedPort &port, Section const §ion, std::ostream &log)
T get(Section const §ion, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
bool getIfExists(Section const §ion, std::string const &name, T &v)
static std::string const & systemName()
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, xrpl)
static std::optional< Seed > validationSeed(json::Value const ¶ms)
T regex_replace(T... args)
static constexpr auto kOnlineDelete
std::vector< boost::asio::ip::network_v4 > adminNetsV4
std::vector< boost::asio::ip::network_v6 > adminNetsV6
static constexpr auto kIps
static constexpr auto kPortWssAdmin
static constexpr auto kValidatorListThreshold
static constexpr auto kValidators
static constexpr auto kValidatorListKeys
static constexpr auto kServer
static constexpr auto kPortRpc
static constexpr auto kSslVerify
static constexpr auto kValidatorsFile
static constexpr auto kIpsFixed
static constexpr auto kDatabasePath
static constexpr auto kDebugLogfile
static constexpr auto kValidatorListSites