20 #include <ripple/basics/contract.h>
21 #include <ripple/core/Config.h>
22 #include <ripple/core/ConfigSections.h>
23 #include <ripple/server/Port.h>
24 #include <boost/filesystem.hpp>
25 #include <boost/format.hpp>
28 #include <test/jtx/TestSuite.h>
29 #include <test/unit_test/FileDirGuard.h>
36 static boost::format configContentsTemplate(R
"rippleConfig(
45 admin = 127.0.0.1, ::1
64 #-------------------------------------------------------------------------------
69 # This is primary persistent datastore for rippled. This includes transaction
70 # metadata, account states, and ledger headers. Helpful information can be
71 # found on https://xrpl.org/capacity-planning.html#node-db-type
72 # delete old ledgers while maintaining at least 2000. Do not require an
73 # external administrative command to initiate deletion.
76 path=/Users/dummy/ripple/config/db/rocksdb
87 # This needs to be an absolute directory reference, not a relative one.
88 # Modify this value as required.
90 /Users/dummy/ripple/config/log/debug.log
98 # Where to find some other servers speaking the Ripple protocol.
103 # Turn down default logging to save disk space in the long run.
104 # Valid values here are trace, debug, info, warning, error, and fatal
106 { "command": "log_level", "severity": "warning" }
108 # Defaults to 1 ("yes") so that certificates will be validated. To allow the use
109 # of self-signed certificates for development or internal use, set to 0 ("no").
118 dbPath.empty() ? "" :
"[database_path]\n" + dbPath;
120 validatorsFile.
empty() ?
"" :
"[validators_file]\n" + validatorsFile;
121 return boost::str(configContentsTemplate % dbPathSection % valFileSection);
138 beast::unit_test::suite& test,
141 path const& validatorsFile,
142 bool useCounter =
true)
171 return file().string();
177 return boost::filesystem::is_directory(
dataDir_);
190 using namespace boost::filesystem;
207 n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7
208 n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj
209 n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C
210 n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS
211 n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA
214 nHUhG1PgAG8H8myUENypM35JgfqXAKNQvRVVAFDRzJrny5eZN8d5
215 nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8
216 nHUPDdcdb2Y5DZAJne4c2iabFuAP3F34xZUgYQT2NH7qfkdapgnz
218 [validator_list_sites]
219 recommendedripplevalidators.com
220 moreripplevalidators.net
222 [validator_list_keys]
223 03E74EE14CB525AFBB9F1B7D86CD58ECC4B91452294B42AB4E78F260BD905C091D
224 030775A669685BD6ABCEBD80385921C7851783D991A8055FD21D2F3966C96F1B56
236 beast::unit_test::suite& test,
238 path const& validatorsFileName,
239 bool useCounter =
true)
244 validatorsFileName.empty() ?
Config::validatorsFileName
245 : validatorsFileName),
260 return absolute(
file()).string();
272 using path = boost::filesystem::path;
294 BEAST_EXPECT(c.legacy("ssl_verify") ==
"0");
295 expectException([&c] { c.
legacy(
"server"); });
298 BEAST_EXPECT(c.
legacy(
"not_in_file") ==
"");
299 c.
legacy(
"not_in_file",
"new_value");
300 BEAST_EXPECT(c.
legacy(
"not_in_file") ==
"new_value");
305 testcase(
"database_path");
307 using namespace boost::filesystem;
309 boost::format cc(
"[database_path]\n%1%\n");
311 auto const cwd = current_path();
312 path const dataDirRel(
"test_data_dir");
313 path const dataDirAbs(cwd / dataDirRel);
318 BEAST_EXPECT(c.
legacy(
"database_path") == dataDirAbs.string());
324 BEAST_EXPECT(c.
legacy(
"database_path") == dataDirAbs.string());
332 BEAST_EXPECT(c.
legacy(
"database_path") ==
"");
337 auto const cwd = current_path();
339 path const dataDirRel(
"test_data_dir");
340 path const dataDirAbs(cwd / g0.
subdir() / dataDirRel);
342 *
this, g0.
subdir(), dataDirAbs,
"",
false);
343 auto const& c(g.
config());
346 BEAST_EXPECT(c.legacy(
"database_path") == dataDirAbs.string());
352 auto const& c(g.
config());
356 BEAST_EXPECT(c.legacy(
"database_path") == nativeDbPath);
361 auto const& c(g.
config());
366 BEAST_EXPECT(c.legacy(
"database_path") == nativeDbPath);
373 testcase(
"validator keys");
378 "eyJ2YWxpZGF0aW9uX3ByaXZhdGVfa2V5IjoiOWVkNDVmODY2MjQxY2MxOGEyNzQ3Yj"
379 "U0Mzg3YzA2MjU5MDc5NzJmNGU3MTkwMjMxZmFhOTM3NDU3ZmE5ZGFmNiIsIm1hbmlm"
380 "ZXN0IjoiSkFBQUFBRnhJZTFGdHdtaW12R3RIMmlDY01KcUM5Z1ZGS2lsR2Z3MS92Q3"
381 "hIWFhMcGxjMkduTWhBa0UxYWdxWHhCd0R3RGJJRDZPTVNZdU0wRkRBbHBBZ05rOFNL"
382 "Rm43TU8yZmRrY3dSUUloQU9uZ3U5c0FLcVhZb3VKK2wyVjBXK3NBT2tWQitaUlM2UF"
383 "NobEpBZlVzWGZBaUJzVkpHZXNhYWRPSmMvYUFab2tTMXZ5bUdtVnJsSFBLV1gzWXl3"
384 "dTZpbjhIQVNRS1B1Z0JENjdrTWFSRkd2bXBBVEhsR0tKZHZERmxXUFl5NUFxRGVkRn"
385 "Y1VEphMncwaTIxZXEzTVl5d0xWSlpuRk9yN0Mwa3cyQWlUelNDakl6ZGl0UTg9In0"
390 static boost::format configTemplate(R
"rippleConfig(
398 auto const expectedError =
399 "Cannot have both [validation_seed] "
400 "and [validator_token] config sections";
410 BEAST_EXPECT(error == expectedError);
417 testcase(
"validators_file");
419 using namespace boost::filesystem;
422 boost::format cc(
"[validators_file]\n%1%\n");
424 std::string const missingPath =
"/no/way/this/path/exists";
425 auto const expectedError =
426 "The file specified in [validators_file] does not exist: " +
437 BEAST_EXPECT(error == expectedError);
442 *
this,
"test_cfg",
"validators.cfg");
443 path const invalidFile = current_path() / vtg.
subdir();
444 boost::format cc(
"[validators_file]\n%1%\n");
446 auto const expectedError =
447 "Invalid file specified in [validators_file]: " +
448 invalidFile.string();
458 BEAST_EXPECT(error == expectedError);
465 n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7
466 n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj
467 n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C
470 nHUhG1PgAG8H8myUENypM35JgfqXAKNQvRVVAFDRzJrny5eZN8d5
471 nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8
474 BEAST_EXPECT(c.legacy("validators_file").empty());
481 [validator_list_sites]
483 trustthesevalidators.gov
485 [validator_list_keys]
486 021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
493 "ripplevalidators.com");
496 "trustthesevalidators.gov");
501 "021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801"
509 [validator_list_sites]
511 trustthesevalidators.gov
514 auto const expectedError =
515 "[validator_list_keys] config section is missing";
524 BEAST_EXPECT(error == expectedError);
529 *
this,
"test_cfg",
"validators.cfg");
532 boost::format cc(
"[validators_file]\n%1%\n");
546 *
this,
"test_cfg", valFileName);
548 *
this, vtg.
subdir(),
"", valFileName,
false);
551 auto const& c(rcg.
config());
552 BEAST_EXPECT(c.legacy(
"validators_file") == valFileName);
553 BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8);
555 c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
557 c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
563 *
this,
"test_cfg",
"validators.txt");
564 auto const valFilePath =
".." / vtg.
subdir() /
"validators.txt";
566 *
this, vtg.
subdir(),
"", valFilePath,
false);
569 auto const& c(rcg.
config());
570 BEAST_EXPECT(c.legacy(
"validators_file") == valFilePath);
571 BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8);
573 c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
575 c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
580 *
this,
"test_cfg",
"validators.txt");
582 *
this, vtg.
subdir(),
"",
"",
false);
585 auto const& c(rcg.
config());
586 BEAST_EXPECT(c.legacy(
"validators_file").empty());
587 BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8);
589 c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
591 c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
597 *
this,
"test_cfg",
"validators.cfg");
600 *
this, vtg.
subdir(),
"validators.txt",
false);
605 auto const& c(rcg.
config());
606 BEAST_EXPECT(c.legacy(
"validators_file") == vtg.
validatorsFile());
607 BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8);
609 c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
611 c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
616 boost::format cc(R
"rippleConfig(
621 n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7
622 n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj
623 n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C
624 n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS
625 n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA
628 nHB1X37qrniVugfQcuBTAjswphC1drx7QjFFojJPZwKHHnt8kU7v
629 nHUkAWDR4cB8AgPg7VXMX6et8xRTQb2KJfgv1aBEXozwrawRKgMB
631 [validator_list_sites]
633 trustthesevalidators.gov
635 [validator_list_keys]
636 021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
639 *
this,
"test_cfg",
"validators.cfg");
655 boost::format cc(
"[validators_file]\n%1%\n");
658 *
this,
"test_cfg",
"validators.cfg");
660 auto const expectedError =
661 "The file specified in [validators_file] does not contain a "
662 "[validators], [validator_keys] or [validator_list_keys] "
675 BEAST_EXPECT(error == expectedError);
683 *
this,
"testSetup", explicitPath ?
"test_db" :
"",
"");
695 BEAST_EXPECT(!config.
quiet());
696 BEAST_EXPECT(!config.
silent());
699 BEAST_EXPECT(!config.
legacy(
"database_path").empty());
708 BEAST_EXPECT(config.
quiet());
709 BEAST_EXPECT(!config.
silent());
712 BEAST_EXPECT(!config.
legacy(
"database_path").empty());
721 BEAST_EXPECT(config.
quiet());
722 BEAST_EXPECT(config.
silent());
725 BEAST_EXPECT(!config.
legacy(
"database_path").empty());
734 BEAST_EXPECT(config.
quiet());
735 BEAST_EXPECT(config.
silent());
738 BEAST_EXPECT(!config.
legacy(
"database_path").empty());
747 BEAST_EXPECT(!config.
quiet());
748 BEAST_EXPECT(!config.
silent());
752 config.
legacy(
"database_path").empty() == !explicitPath);
761 BEAST_EXPECT(config.
quiet());
762 BEAST_EXPECT(!config.
silent());
766 config.
legacy(
"database_path").empty() == !explicitPath);
775 BEAST_EXPECT(config.
quiet());
776 BEAST_EXPECT(config.
silent());
780 config.
legacy(
"database_path").empty() == !explicitPath);
789 BEAST_EXPECT(config.
quiet());
790 BEAST_EXPECT(config.
silent());
794 config.
legacy(
"database_path").empty() == !explicitPath);
802 auto const& conf = cfg.
config();
803 if (!BEAST_EXPECT(conf.exists(
"port_rpc")))
805 if (!BEAST_EXPECT(conf.exists(
"port_wss_admin")))
808 if (!unexcept([&]() {
parse_Port(rpc, conf[
"port_rpc"], log); }))
812 if (!unexcept([&]() {
parse_Port(wss, conf[
"port_wss_admin"], log); }))
850 cfg.exists(SECTION_IPS) &&
851 cfg.section(SECTION_IPS).lines().size() == 1 &&
852 cfg.section(SECTION_IPS).values().size() == 1);
854 cfg.exists(SECTION_IPS_FIXED) &&
855 cfg.section(SECTION_IPS_FIXED).lines().size() == 2 &&
856 cfg.section(SECTION_IPS_FIXED).values().size() == 2);
862 struct TestCommentData
871 {{
"password = aaaa\\#bbbb",
"password",
"aaaa#bbbb",
false},
872 {
"password = aaaa#bbbb",
"password",
"aaaa",
true},
873 {
"password = aaaa #bbbb",
"password",
"aaaa",
true},
875 {
"password = #aaaa #bbbb",
"",
"password =",
true},
876 {
"password = aaaa\\# #bbbb",
"password",
"aaaa#",
true},
877 {
"password = aaaa\\##bbbb",
"password",
"aaaa#",
true},
878 {
"aaaa#bbbb",
"",
"aaaa",
true},
879 {
"aaaa\\#bbbb",
"",
"aaaa#bbbb",
false},
880 {
"aaaa\\##bbbb",
"",
"aaaa#",
true},
881 {
"aaaa #bbbb",
"",
"aaaa",
true},
882 {
"1 #comment",
"",
"1",
true},
883 {
"#whole thing is comment",
"",
"",
false},
884 {
" #whole comment with space",
"",
"",
false}}};
886 for (
auto const& t : tests)
889 s.append(t.line.data());
890 BEAST_EXPECT(s.had_trailing_comments() == t.had_comment);
893 BEAST_EXPECTS(s.legacy() == t.expect, s.legacy());
898 BEAST_EXPECTS(
set(field, t.field.data(), s), t.line);
899 BEAST_EXPECTS(field == t.expect, t.line);
905 s.append(
"online_delete = 3000");
907 BEAST_EXPECT(
set(od,
"online_delete", s));
908 BEAST_EXPECTS(od == 3000, *(s.get<
std::string>(
"online_delete")));
913 s.
append(
"online_delete = 2000 #my comment on this");
915 BEAST_EXPECT(
set(od,
"online_delete", s));
916 BEAST_EXPECTS(od == 2000, *(s.
get<
std::string>(
"online_delete")));
923 using namespace std::string_literals;
924 Section s{
"MySection"};
925 s.append(
"a_string = mystring");
926 s.append(
"positive_int = 2");
927 s.append(
"negative_int = -3");
928 s.append(
"bool_ish = 1");
931 auto val_1 =
"value 1"s;
932 BEAST_EXPECT(
set(val_1,
"a_string", s));
933 BEAST_EXPECT(val_1 ==
"mystring");
935 auto val_2 =
"value 2"s;
936 BEAST_EXPECT(!
set(val_2,
"not_a_key", s));
937 BEAST_EXPECT(val_2 ==
"value 2");
938 BEAST_EXPECT(!
set(val_2,
"default"s,
"not_a_key", s));
939 BEAST_EXPECT(val_2 ==
"default");
941 auto val_3 = get<std::string>(s,
"a_string");
942 BEAST_EXPECT(val_3 ==
"mystring");
943 auto val_4 = get<std::string>(s,
"not_a_key");
944 BEAST_EXPECT(val_4 ==
"");
945 auto val_5 = get<std::string>(s,
"not_a_key",
"default");
946 BEAST_EXPECT(val_5 ==
"default");
948 auto val_6 =
"value 6"s;
950 BEAST_EXPECT(val_6 ==
"mystring");
952 auto val_7 =
"value 7"s;
954 BEAST_EXPECT(val_7 ==
"value 7");
959 BEAST_EXPECT(
set(val_1,
"positive_int", s));
960 BEAST_EXPECT(val_1 == 2);
963 BEAST_EXPECT(
set(val_2,
"negative_int", s));
964 BEAST_EXPECT(val_2 == -3);
967 BEAST_EXPECT(!
set(val_3,
"a_string", s));
968 BEAST_EXPECT(val_3 == 3);
970 auto val_4 = get<int>(s,
"positive_int");
971 BEAST_EXPECT(val_4 == 2);
972 auto val_5 = get<int>(s,
"not_a_key");
973 BEAST_EXPECT(val_5 == 0);
974 auto val_6 = get<int>(s,
"not_a_key", 5);
975 BEAST_EXPECT(val_6 == 5);
976 auto val_7 = get<int>(s,
"a_string", 6);
977 BEAST_EXPECT(val_7 == 6);
981 BEAST_EXPECT(val_8 == 2);
985 BEAST_EXPECT(val_9 == 9);
989 BEAST_EXPECT(val_10 == 10);
991 BEAST_EXPECT(s.get<
int>(
"not_a_key") == std::nullopt);
994 s.get<
int>(
"a_string");
997 catch (boost::bad_lexical_cast&)
1004 bool flag_1 =
false;
1006 BEAST_EXPECT(flag_1 ==
true);
1008 bool flag_2 =
false;
1010 BEAST_EXPECT(flag_2 ==
false);
1017 testcase(
"amendment");
1027 {
"seconds", 1, 15 * 60,
false},
1028 {
"minutes", 60, 14,
false},
1029 {
"minutes", 60, 15,
true},
1030 {
"hours", 3600, 10,
true},
1031 {
"days", 86400, 10,
true},
1032 {
"weeks", 604800, 2,
true},
1033 {
"months", 2592000, 1,
false},
1034 {
"years", 31536000, 1,
false}};
1037 for (
auto& [unit, sec, val, shouldPass] : units)
1041 [amendment_majority_time]
1048 c.loadFromString(toLoad);
1051 c.AMENDMENT_MAJORITY_TIME.count() == val * sec);
1068 testcase(
"overlay: unknown time");
1075 c.loadFromString(
"[overlay]\nmax_unknown_time=" + value);
1076 return c.MAX_UNKNOWN_TIME;
1085 BEAST_EXPECT(!testUnknown(
"none"));
1086 BEAST_EXPECT(!testUnknown(
"0.5"));
1087 BEAST_EXPECT(!testUnknown(
"180 seconds"));
1088 BEAST_EXPECT(!testUnknown(
"9 minutes"));
1091 BEAST_EXPECT(!testUnknown(
"299"));
1100 BEAST_EXPECT(!testUnknown(
"1801"));
1102 testcase(
"overlay: diverged time");
1110 c.loadFromString(
"[overlay]\nmax_diverged_time=" + value);
1111 return c.MAX_DIVERGED_TIME;
1120 BEAST_EXPECT(!testDiverged(
"none"));
1121 BEAST_EXPECT(!testDiverged(
"0.5"));
1122 BEAST_EXPECT(!testDiverged(
"180 seconds"));
1123 BEAST_EXPECT(!testDiverged(
"9 minutes"));
1126 BEAST_EXPECT(!testDiverged(
"0"));
1127 BEAST_EXPECT(!testDiverged(
"59"));
1136 BEAST_EXPECT(!testDiverged(
"901"));
1144 testValidatorKeys();
1145 testValidatorsFile();