rippled
Config_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2015 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
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>
26 #include <fstream>
27 #include <iostream>
28 #include <test/jtx/TestSuite.h>
29 #include <test/unit_test/FileDirGuard.h>
30 
31 namespace ripple {
32 namespace detail {
34 configContents(std::string const& dbPath, std::string const& validatorsFile)
35 {
36  static boost::format configContentsTemplate(R"rippleConfig(
37 [server]
38 port_rpc
39 port_peer
40 port_wss_admin
41 
42 [port_rpc]
43 port = 5005
44 ip = 127.0.0.1
45 admin = 127.0.0.1, ::1
46 protocol = https
47 
48 [port_peer]
49 port = 51235
50 ip = 0.0.0.0
51 protocol = peer
52 
53 [port_wss_admin]
54 port = 6006
55 ip = 127.0.0.1
56 admin = 127.0.0.1
57 protocol = wss
58 
59 #[port_ws_public]
60 #port = 5005
61 #ip = 127.0.0.1
62 #protocol = wss
63 
64 #-------------------------------------------------------------------------------
65 
66 [node_size]
67 medium
68 
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.
74 [node_db]
75 type=memory
76 path=/Users/dummy/ripple/config/db/rocksdb
77 open_files=2000
78 filter_bits=12
79 cache_mb=256
80 file_size_mb=8
81 file_size_mult=2
82 
83 %1%
84 
85 %2%
86 
87 # This needs to be an absolute directory reference, not a relative one.
88 # Modify this value as required.
89 [debug_logfile]
90 /Users/dummy/ripple/config/log/debug.log
91 
92 [sntp_servers]
93 time.windows.com
94 time.apple.com
95 time.nist.gov
96 pool.ntp.org
97 
98 # Where to find some other servers speaking the Ripple protocol.
99 #
100 [ips]
101 r.ripple.com 51235
102 
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
105 [rpc_startup]
106 { "command": "log_level", "severity": "warning" }
107 
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").
110 [ssl_verify]
111 0
112 
113 [sqdb]
114 backend=sqlite
115 )rippleConfig");
116 
117  std::string dbPathSection =
118  dbPath.empty() ? "" : "[database_path]\n" + dbPath;
119  std::string valFileSection =
120  validatorsFile.empty() ? "" : "[validators_file]\n" + validatorsFile;
121  return boost::str(configContentsTemplate % dbPathSection % valFileSection);
122 }
123 
128 {
129 private:
131 
132  bool rmDataDir_{false};
133 
135 
136 public:
138  beast::unit_test::suite& test,
139  path subDir,
140  path const& dbPath,
141  path const& validatorsFile,
142  bool useCounter = true)
143  : FileDirGuard(
144  test,
145  std::move(subDir),
146  path(Config::configFileName),
147  configContents(dbPath.string(), validatorsFile.string()),
148  useCounter)
149  , dataDir_(dbPath)
150  {
151  if (dbPath.empty())
153 
154  rmDataDir_ = !exists(dataDir_);
155  config_.setup(
156  file_.string(),
157  /* bQuiet */ true,
158  /* bSilent */ false,
159  /* bStandalone */ false);
160  }
161 
162  Config const&
163  config() const
164  {
165  return config_;
166  }
167 
169  configFile() const
170  {
171  return file().string();
172  }
173 
174  bool
176  {
177  return boost::filesystem::is_directory(dataDir_);
178  }
179 
180  bool
182  {
183  return fileExists();
184  }
185 
187  {
188  try
189  {
190  using namespace boost::filesystem;
191  if (rmDataDir_)
192  rmDir(dataDir_);
193  }
194  catch (std::exception& e)
195  {
196  // if we throw here, just let it die.
197  test_.log << "Error in ~RippledCfgGuard: " << e.what() << std::endl;
198  };
199  }
200 };
201 
204 {
205  std::string configContents(R"rippleConfig(
206 [validators]
207 n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7
208 n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj
209 n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C
210 n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS
211 n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA
212 
213 [validator_keys]
214 nHUhG1PgAG8H8myUENypM35JgfqXAKNQvRVVAFDRzJrny5eZN8d5
215 nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8
216 nHUPDdcdb2Y5DZAJne4c2iabFuAP3F34xZUgYQT2NH7qfkdapgnz
217 
218 [validator_list_sites]
219 recommendedripplevalidators.com
220 moreripplevalidators.net
221 
222 [validator_list_keys]
223 03E74EE14CB525AFBB9F1B7D86CD58ECC4B91452294B42AB4E78F260BD905C091D
224 030775A669685BD6ABCEBD80385921C7851783D991A8055FD21D2F3966C96F1B56
225 )rippleConfig");
226  return configContents;
227 }
228 
233 {
234 public:
236  beast::unit_test::suite& test,
237  path subDir,
238  path const& validatorsFileName,
239  bool useCounter = true)
240  : FileDirGuard(
241  test,
242  std::move(subDir),
243  path(
244  validatorsFileName.empty() ? Config::validatorsFileName
245  : validatorsFileName),
246  valFileContents(),
247  useCounter)
248  {
249  }
250 
251  bool
253  {
254  return fileExists();
255  }
256 
259  {
260  return absolute(file()).string();
261  }
262 
264  {
265  }
266 };
267 } // namespace detail
268 
269 class Config_test final : public TestSuite
270 {
271 private:
272  using path = boost::filesystem::path;
273 
274 public:
275  void
277  {
278  testcase("legacy");
279 
280  Config c;
281 
282  std::string toLoad(R"rippleConfig(
283 [server]
284 port_rpc
285 port_peer
286 port_wss_admin
287 
288 [ssl_verify]
289 0
290 )rippleConfig");
291 
292  c.loadFromString(toLoad);
293 
294  BEAST_EXPECT(c.legacy("ssl_verify") == "0");
295  expectException([&c] { c.legacy("server"); }); // not a single line
296 
297  // set a legacy value
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");
301  }
302  void
304  {
305  testcase("database_path");
306 
307  using namespace boost::filesystem;
308  {
309  boost::format cc("[database_path]\n%1%\n");
310 
311  auto const cwd = current_path();
312  path const dataDirRel("test_data_dir");
313  path const dataDirAbs(cwd / dataDirRel);
314  {
315  // Dummy test - do we get back what we put in
316  Config c;
317  c.loadFromString(boost::str(cc % dataDirAbs.string()));
318  BEAST_EXPECT(c.legacy("database_path") == dataDirAbs.string());
319  }
320  {
321  // Rel paths should convert to abs paths
322  Config c;
323  c.loadFromString(boost::str(cc % dataDirRel.string()));
324  BEAST_EXPECT(c.legacy("database_path") == dataDirAbs.string());
325  }
326  {
327  // No db section.
328  // N.B. Config::setup will give database_path a default,
329  // load will not.
330  Config c;
331  c.loadFromString("");
332  BEAST_EXPECT(c.legacy("database_path") == "");
333  }
334  }
335  {
336  // read from file absolute path
337  auto const cwd = current_path();
338  ripple::test::detail::DirGuard const g0(*this, "test_db");
339  path const dataDirRel("test_data_dir");
340  path const dataDirAbs(cwd / g0.subdir() / dataDirRel);
341  detail::RippledCfgGuard const g(
342  *this, g0.subdir(), dataDirAbs, "", false);
343  auto const& c(g.config());
344  BEAST_EXPECT(g.dataDirExists());
345  BEAST_EXPECT(g.configFileExists());
346  BEAST_EXPECT(c.legacy("database_path") == dataDirAbs.string());
347  }
348  {
349  // read from file relative path
350  std::string const dbPath("my_db");
351  detail::RippledCfgGuard const g(*this, "test_db", dbPath, "");
352  auto const& c(g.config());
353  std::string const nativeDbPath = absolute(path(dbPath)).string();
354  BEAST_EXPECT(g.dataDirExists());
355  BEAST_EXPECT(g.configFileExists());
356  BEAST_EXPECT(c.legacy("database_path") == nativeDbPath);
357  }
358  {
359  // read from file no path
360  detail::RippledCfgGuard const g(*this, "test_db", "", "");
361  auto const& c(g.config());
362  std::string const nativeDbPath =
363  absolute(g.subdir() / path(Config::databaseDirName)).string();
364  BEAST_EXPECT(g.dataDirExists());
365  BEAST_EXPECT(g.configFileExists());
366  BEAST_EXPECT(c.legacy("database_path") == nativeDbPath);
367  }
368  }
369 
370  void
372  {
373  testcase("validator keys");
374 
375  std::string const validationSeed = "spA4sh1qTvwq92X715tYyGQKmAKfa";
376 
377  auto const token =
378  "eyJ2YWxpZGF0aW9uX3ByaXZhdGVfa2V5IjoiOWVkNDVmODY2MjQxY2MxOGEyNzQ3Yj"
379  "U0Mzg3YzA2MjU5MDc5NzJmNGU3MTkwMjMxZmFhOTM3NDU3ZmE5ZGFmNiIsIm1hbmlm"
380  "ZXN0IjoiSkFBQUFBRnhJZTFGdHdtaW12R3RIMmlDY01KcUM5Z1ZGS2lsR2Z3MS92Q3"
381  "hIWFhMcGxjMkduTWhBa0UxYWdxWHhCd0R3RGJJRDZPTVNZdU0wRkRBbHBBZ05rOFNL"
382  "Rm43TU8yZmRrY3dSUUloQU9uZ3U5c0FLcVhZb3VKK2wyVjBXK3NBT2tWQitaUlM2UF"
383  "NobEpBZlVzWGZBaUJzVkpHZXNhYWRPSmMvYUFab2tTMXZ5bUdtVnJsSFBLV1gzWXl3"
384  "dTZpbjhIQVNRS1B1Z0JENjdrTWFSRkd2bXBBVEhsR0tKZHZERmxXUFl5NUFxRGVkRn"
385  "Y1VEphMncwaTIxZXEzTVl5d0xWSlpuRk9yN0Mwa3cyQWlUelNDakl6ZGl0UTg9In0"
386  "=";
387 
388  {
389  Config c;
390  static boost::format configTemplate(R"rippleConfig(
391 [validation_seed]
392 %1%
393 
394 [validator_token]
395 %2%
396 )rippleConfig");
397  std::string error;
398  auto const expectedError =
399  "Cannot have both [validation_seed] "
400  "and [validator_token] config sections";
401  try
402  {
403  c.loadFromString(
404  boost::str(configTemplate % validationSeed % token));
405  }
406  catch (std::runtime_error& e)
407  {
408  error = e.what();
409  }
410  BEAST_EXPECT(error == expectedError);
411  }
412  }
413 
414  void
416  {
417  testcase("validators_file");
418 
419  using namespace boost::filesystem;
420  {
421  // load should throw for missing specified validators file
422  boost::format cc("[validators_file]\n%1%\n");
423  std::string error;
424  std::string const missingPath = "/no/way/this/path/exists";
425  auto const expectedError =
426  "The file specified in [validators_file] does not exist: " +
427  missingPath;
428  try
429  {
430  Config c;
431  c.loadFromString(boost::str(cc % missingPath));
432  }
433  catch (std::runtime_error& e)
434  {
435  error = e.what();
436  }
437  BEAST_EXPECT(error == expectedError);
438  }
439  {
440  // load should throw for invalid [validators_file]
441  detail::ValidatorsTxtGuard const vtg(
442  *this, "test_cfg", "validators.cfg");
443  path const invalidFile = current_path() / vtg.subdir();
444  boost::format cc("[validators_file]\n%1%\n");
445  std::string error;
446  auto const expectedError =
447  "Invalid file specified in [validators_file]: " +
448  invalidFile.string();
449  try
450  {
451  Config c;
452  c.loadFromString(boost::str(cc % invalidFile.string()));
453  }
454  catch (std::runtime_error& e)
455  {
456  error = e.what();
457  }
458  BEAST_EXPECT(error == expectedError);
459  }
460  {
461  // load validators from config into single section
462  Config c;
463  std::string toLoad(R"rippleConfig(
464 [validators]
465 n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7
466 n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj
467 n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C
468 
469 [validator_keys]
470 nHUhG1PgAG8H8myUENypM35JgfqXAKNQvRVVAFDRzJrny5eZN8d5
471 nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8
472 )rippleConfig");
473  c.loadFromString(toLoad);
474  BEAST_EXPECT(c.legacy("validators_file").empty());
475  BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 5);
476  }
477  {
478  // load validator list sites and keys from config
479  Config c;
480  std::string toLoad(R"rippleConfig(
481 [validator_list_sites]
482 ripplevalidators.com
483 trustthesevalidators.gov
484 
485 [validator_list_keys]
486 021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
487 )rippleConfig");
488  c.loadFromString(toLoad);
489  BEAST_EXPECT(
490  c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
491  BEAST_EXPECT(
492  c.section(SECTION_VALIDATOR_LIST_SITES).values()[0] ==
493  "ripplevalidators.com");
494  BEAST_EXPECT(
495  c.section(SECTION_VALIDATOR_LIST_SITES).values()[1] ==
496  "trustthesevalidators.gov");
497  BEAST_EXPECT(
498  c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 1);
499  BEAST_EXPECT(
500  c.section(SECTION_VALIDATOR_LIST_KEYS).values()[0] ==
501  "021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801"
502  "E566");
503  }
504  {
505  // load should throw if [validator_list_sites] is configured but
506  // [validator_list_keys] is not
507  Config c;
508  std::string toLoad(R"rippleConfig(
509 [validator_list_sites]
510 ripplevalidators.com
511 trustthesevalidators.gov
512 )rippleConfig");
513  std::string error;
514  auto const expectedError =
515  "[validator_list_keys] config section is missing";
516  try
517  {
518  c.loadFromString(toLoad);
519  }
520  catch (std::runtime_error& e)
521  {
522  error = e.what();
523  }
524  BEAST_EXPECT(error == expectedError);
525  }
526  {
527  // load from specified [validators_file] absolute path
528  detail::ValidatorsTxtGuard const vtg(
529  *this, "test_cfg", "validators.cfg");
530  BEAST_EXPECT(vtg.validatorsFileExists());
531  Config c;
532  boost::format cc("[validators_file]\n%1%\n");
533  c.loadFromString(boost::str(cc % vtg.validatorsFile()));
534  BEAST_EXPECT(c.legacy("validators_file") == vtg.validatorsFile());
535  BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8);
536  BEAST_EXPECT(
537  c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
538  BEAST_EXPECT(
539  c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
540  }
541  {
542  // load from specified [validators_file] file name
543  // in config directory
544  std::string const valFileName = "validators.txt";
545  detail::ValidatorsTxtGuard const vtg(
546  *this, "test_cfg", valFileName);
547  detail::RippledCfgGuard const rcg(
548  *this, vtg.subdir(), "", valFileName, false);
549  BEAST_EXPECT(vtg.validatorsFileExists());
550  BEAST_EXPECT(rcg.configFileExists());
551  auto const& c(rcg.config());
552  BEAST_EXPECT(c.legacy("validators_file") == valFileName);
553  BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8);
554  BEAST_EXPECT(
555  c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
556  BEAST_EXPECT(
557  c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
558  }
559  {
560  // load from specified [validators_file] relative path
561  // to config directory
562  detail::ValidatorsTxtGuard const vtg(
563  *this, "test_cfg", "validators.txt");
564  auto const valFilePath = ".." / vtg.subdir() / "validators.txt";
565  detail::RippledCfgGuard const rcg(
566  *this, vtg.subdir(), "", valFilePath, false);
567  BEAST_EXPECT(vtg.validatorsFileExists());
568  BEAST_EXPECT(rcg.configFileExists());
569  auto const& c(rcg.config());
570  BEAST_EXPECT(c.legacy("validators_file") == valFilePath);
571  BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8);
572  BEAST_EXPECT(
573  c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
574  BEAST_EXPECT(
575  c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
576  }
577  {
578  // load from validators file in default location
579  detail::ValidatorsTxtGuard const vtg(
580  *this, "test_cfg", "validators.txt");
581  detail::RippledCfgGuard const rcg(
582  *this, vtg.subdir(), "", "", false);
583  BEAST_EXPECT(vtg.validatorsFileExists());
584  BEAST_EXPECT(rcg.configFileExists());
585  auto const& c(rcg.config());
586  BEAST_EXPECT(c.legacy("validators_file").empty());
587  BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8);
588  BEAST_EXPECT(
589  c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
590  BEAST_EXPECT(
591  c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
592  }
593  {
594  // load from specified [validators_file] instead
595  // of default location
596  detail::ValidatorsTxtGuard const vtg(
597  *this, "test_cfg", "validators.cfg");
598  BEAST_EXPECT(vtg.validatorsFileExists());
599  detail::ValidatorsTxtGuard const vtgDefault(
600  *this, vtg.subdir(), "validators.txt", false);
601  BEAST_EXPECT(vtgDefault.validatorsFileExists());
602  detail::RippledCfgGuard const rcg(
603  *this, vtg.subdir(), "", vtg.validatorsFile(), false);
604  BEAST_EXPECT(rcg.configFileExists());
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);
608  BEAST_EXPECT(
609  c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
610  BEAST_EXPECT(
611  c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
612  }
613 
614  {
615  // load validators from both config and validators file
616  boost::format cc(R"rippleConfig(
617 [validators_file]
618 %1%
619 
620 [validators]
621 n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7
622 n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj
623 n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C
624 n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS
625 n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA
626 
627 [validator_keys]
628 nHB1X37qrniVugfQcuBTAjswphC1drx7QjFFojJPZwKHHnt8kU7v
629 nHUkAWDR4cB8AgPg7VXMX6et8xRTQb2KJfgv1aBEXozwrawRKgMB
630 
631 [validator_list_sites]
632 ripplevalidators.com
633 trustthesevalidators.gov
634 
635 [validator_list_keys]
636 021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
637 )rippleConfig");
638  detail::ValidatorsTxtGuard const vtg(
639  *this, "test_cfg", "validators.cfg");
640  BEAST_EXPECT(vtg.validatorsFileExists());
641  Config c;
642  c.loadFromString(boost::str(cc % vtg.validatorsFile()));
643  BEAST_EXPECT(c.legacy("validators_file") == vtg.validatorsFile());
644  BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 15);
645  BEAST_EXPECT(
646  c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 4);
647  BEAST_EXPECT(
648  c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 3);
649  }
650  {
651  // load should throw if [validators], [validator_keys] and
652  // [validator_list_keys] are missing from rippled cfg and
653  // validators file
654  Config c;
655  boost::format cc("[validators_file]\n%1%\n");
656  std::string error;
657  detail::ValidatorsTxtGuard const vtg(
658  *this, "test_cfg", "validators.cfg");
659  BEAST_EXPECT(vtg.validatorsFileExists());
660  auto const expectedError =
661  "The file specified in [validators_file] does not contain a "
662  "[validators], [validator_keys] or [validator_list_keys] "
663  "section: " +
664  vtg.validatorsFile();
665  std::ofstream o(vtg.validatorsFile());
666  try
667  {
668  Config c2;
669  c2.loadFromString(boost::str(cc % vtg.validatorsFile()));
670  }
671  catch (std::runtime_error& e)
672  {
673  error = e.what();
674  }
675  BEAST_EXPECT(error == expectedError);
676  }
677  }
678 
679  void
680  testSetup(bool explicitPath)
681  {
682  detail::RippledCfgGuard const cfg(
683  *this, "testSetup", explicitPath ? "test_db" : "", "");
684  /* RippledCfgGuard has a Config object that gets loaded on
685  construction, but Config::setup is not reentrant, so we
686  need a fresh config for every test case, so ignore it.
687  */
688  {
689  Config config;
690  config.setup(
691  cfg.configFile(),
692  /*bQuiet*/ false,
693  /* bSilent */ false,
694  /* bStandalone */ false);
695  BEAST_EXPECT(!config.quiet());
696  BEAST_EXPECT(!config.silent());
697  BEAST_EXPECT(!config.standalone());
698  BEAST_EXPECT(config.LEDGER_HISTORY == 256);
699  BEAST_EXPECT(!config.legacy("database_path").empty());
700  }
701  {
702  Config config;
703  config.setup(
704  cfg.configFile(),
705  /*bQuiet*/ true,
706  /* bSilent */ false,
707  /* bStandalone */ false);
708  BEAST_EXPECT(config.quiet());
709  BEAST_EXPECT(!config.silent());
710  BEAST_EXPECT(!config.standalone());
711  BEAST_EXPECT(config.LEDGER_HISTORY == 256);
712  BEAST_EXPECT(!config.legacy("database_path").empty());
713  }
714  {
715  Config config;
716  config.setup(
717  cfg.configFile(),
718  /*bQuiet*/ false,
719  /* bSilent */ true,
720  /* bStandalone */ false);
721  BEAST_EXPECT(config.quiet());
722  BEAST_EXPECT(config.silent());
723  BEAST_EXPECT(!config.standalone());
724  BEAST_EXPECT(config.LEDGER_HISTORY == 256);
725  BEAST_EXPECT(!config.legacy("database_path").empty());
726  }
727  {
728  Config config;
729  config.setup(
730  cfg.configFile(),
731  /*bQuiet*/ true,
732  /* bSilent */ true,
733  /* bStandalone */ false);
734  BEAST_EXPECT(config.quiet());
735  BEAST_EXPECT(config.silent());
736  BEAST_EXPECT(!config.standalone());
737  BEAST_EXPECT(config.LEDGER_HISTORY == 256);
738  BEAST_EXPECT(!config.legacy("database_path").empty());
739  }
740  {
741  Config config;
742  config.setup(
743  cfg.configFile(),
744  /*bQuiet*/ false,
745  /* bSilent */ false,
746  /* bStandalone */ true);
747  BEAST_EXPECT(!config.quiet());
748  BEAST_EXPECT(!config.silent());
749  BEAST_EXPECT(config.standalone());
750  BEAST_EXPECT(config.LEDGER_HISTORY == 0);
751  BEAST_EXPECT(
752  config.legacy("database_path").empty() == !explicitPath);
753  }
754  {
755  Config config;
756  config.setup(
757  cfg.configFile(),
758  /*bQuiet*/ true,
759  /* bSilent */ false,
760  /* bStandalone */ true);
761  BEAST_EXPECT(config.quiet());
762  BEAST_EXPECT(!config.silent());
763  BEAST_EXPECT(config.standalone());
764  BEAST_EXPECT(config.LEDGER_HISTORY == 0);
765  BEAST_EXPECT(
766  config.legacy("database_path").empty() == !explicitPath);
767  }
768  {
769  Config config;
770  config.setup(
771  cfg.configFile(),
772  /*bQuiet*/ false,
773  /* bSilent */ true,
774  /* bStandalone */ true);
775  BEAST_EXPECT(config.quiet());
776  BEAST_EXPECT(config.silent());
777  BEAST_EXPECT(config.standalone());
778  BEAST_EXPECT(config.LEDGER_HISTORY == 0);
779  BEAST_EXPECT(
780  config.legacy("database_path").empty() == !explicitPath);
781  }
782  {
783  Config config;
784  config.setup(
785  cfg.configFile(),
786  /*bQuiet*/ true,
787  /* bSilent */ true,
788  /* bStandalone */ true);
789  BEAST_EXPECT(config.quiet());
790  BEAST_EXPECT(config.silent());
791  BEAST_EXPECT(config.standalone());
792  BEAST_EXPECT(config.LEDGER_HISTORY == 0);
793  BEAST_EXPECT(
794  config.legacy("database_path").empty() == !explicitPath);
795  }
796  }
797 
798  void
800  {
801  detail::RippledCfgGuard const cfg(*this, "testPort", "", "");
802  auto const& conf = cfg.config();
803  if (!BEAST_EXPECT(conf.exists("port_rpc")))
804  return;
805  if (!BEAST_EXPECT(conf.exists("port_wss_admin")))
806  return;
807  ParsedPort rpc;
808  if (!unexcept([&]() { parse_Port(rpc, conf["port_rpc"], log); }))
809  return;
810  BEAST_EXPECT(rpc.admin_nets_v4.size() + rpc.admin_nets_v6.size() == 2);
811  ParsedPort wss;
812  if (!unexcept([&]() { parse_Port(wss, conf["port_wss_admin"], log); }))
813  return;
814  BEAST_EXPECT(wss.admin_nets_v4.size() + wss.admin_nets_v6.size() == 1);
815  }
816 
817  void
819  {
820  Config cfg;
821  /* NOTE: this string includes some explicit
822  * space chars in order to verify proper trimming */
823  std::string toLoad(R"(
824 [port_rpc])"
825  "\x20"
826  R"(
827 # comment
828  # indented comment
829 )"
830  "\x20\x20"
831  R"(
832 [ips])"
833  "\x20"
834  R"(
835 r.ripple.com 51235
836 
837  [ips_fixed])"
838  "\x20\x20"
839  R"(
840  # COMMENT
841  s1.ripple.com 51235
842  s2.ripple.com 51235
843 
844 )");
845  cfg.loadFromString(toLoad);
846  BEAST_EXPECT(
847  cfg.exists("port_rpc") && cfg.section("port_rpc").lines().empty() &&
848  cfg.section("port_rpc").values().empty());
849  BEAST_EXPECT(
850  cfg.exists(SECTION_IPS) &&
851  cfg.section(SECTION_IPS).lines().size() == 1 &&
852  cfg.section(SECTION_IPS).values().size() == 1);
853  BEAST_EXPECT(
854  cfg.exists(SECTION_IPS_FIXED) &&
855  cfg.section(SECTION_IPS_FIXED).lines().size() == 2 &&
856  cfg.section(SECTION_IPS_FIXED).values().size() == 2);
857  }
858 
859  void
860  testColons()
861  {
862  Config cfg;
863  /* NOTE: this string includes some explicit
864  * space chars in order to verify proper trimming */
865  std::string toLoad(R"(
866 [port_rpc])"
867  "\x20"
868  R"(
869 # comment
870  # indented comment
871 )"
872  "\x20\x20"
873  R"(
874 [ips])"
875  "\x20"
876  R"(
877 r.ripple.com:51235
878 
879  [ips_fixed])"
880  "\x20\x20"
881  R"(
882  # COMMENT
883  s1.ripple.com:51235
884  s2.ripple.com 51235
885  anotherserversansport
886  anotherserverwithport:12
887  1.1.1.1:1
888  1.1.1.1 1
889  12.34.12.123:12345
890  12.34.12.123 12345
891  ::
892  2001:db8::
893  ::1
894  ::1:12345
895  [::1]:12345
896  2001:db8:3333:4444:5555:6666:7777:8888:12345
897  [2001:db8:3333:4444:5555:6666:7777:8888]:1
898 
899 
900 )");
901  cfg.loadFromString(toLoad);
902  BEAST_EXPECT(
903  cfg.exists("port_rpc") && cfg.section("port_rpc").lines().empty() &&
904  cfg.section("port_rpc").values().empty());
905  BEAST_EXPECT(
906  cfg.exists(SECTION_IPS) &&
907  cfg.section(SECTION_IPS).lines().size() == 1 &&
908  cfg.section(SECTION_IPS).values().size() == 1);
909  BEAST_EXPECT(
910  cfg.exists(SECTION_IPS_FIXED) &&
911  cfg.section(SECTION_IPS_FIXED).lines().size() == 15 &&
912  cfg.section(SECTION_IPS_FIXED).values().size() == 15);
913  BEAST_EXPECT(cfg.IPS[0] == "r.ripple.com 51235");
914 
915  BEAST_EXPECT(cfg.IPS_FIXED[0] == "s1.ripple.com 51235");
916  BEAST_EXPECT(cfg.IPS_FIXED[1] == "s2.ripple.com 51235");
917  BEAST_EXPECT(cfg.IPS_FIXED[2] == "anotherserversansport");
918  BEAST_EXPECT(cfg.IPS_FIXED[3] == "anotherserverwithport 12");
919  BEAST_EXPECT(cfg.IPS_FIXED[4] == "1.1.1.1 1");
920  BEAST_EXPECT(cfg.IPS_FIXED[5] == "1.1.1.1 1");
921  BEAST_EXPECT(cfg.IPS_FIXED[6] == "12.34.12.123 12345");
922  BEAST_EXPECT(cfg.IPS_FIXED[7] == "12.34.12.123 12345");
923 
924  // all ipv6 should be ignored by colon replacer, howsoever formated
925  BEAST_EXPECT(cfg.IPS_FIXED[8] == "::");
926  BEAST_EXPECT(cfg.IPS_FIXED[9] == "2001:db8::");
927  BEAST_EXPECT(cfg.IPS_FIXED[10] == "::1");
928  BEAST_EXPECT(cfg.IPS_FIXED[11] == "::1:12345");
929  BEAST_EXPECT(cfg.IPS_FIXED[12] == "[::1]:12345");
930  BEAST_EXPECT(
931  cfg.IPS_FIXED[13] ==
932  "2001:db8:3333:4444:5555:6666:7777:8888:12345");
933  BEAST_EXPECT(
934  cfg.IPS_FIXED[14] == "[2001:db8:3333:4444:5555:6666:7777:8888]:1");
935  }
936 
937  void
938  testComments()
939  {
940  struct TestCommentData
941  {
942  std::string_view line;
943  std::string_view field;
944  std::string_view expect;
945  bool had_comment;
946  };
947 
949  {{"password = aaaa\\#bbbb", "password", "aaaa#bbbb", false},
950  {"password = aaaa#bbbb", "password", "aaaa", true},
951  {"password = aaaa #bbbb", "password", "aaaa", true},
952  // since the value is all comment, this doesn't parse as k=v :
953  {"password = #aaaa #bbbb", "", "password =", true},
954  {"password = aaaa\\# #bbbb", "password", "aaaa#", true},
955  {"password = aaaa\\##bbbb", "password", "aaaa#", true},
956  {"aaaa#bbbb", "", "aaaa", true},
957  {"aaaa\\#bbbb", "", "aaaa#bbbb", false},
958  {"aaaa\\##bbbb", "", "aaaa#", true},
959  {"aaaa #bbbb", "", "aaaa", true},
960  {"1 #comment", "", "1", true},
961  {"#whole thing is comment", "", "", false},
962  {" #whole comment with space", "", "", false}}};
963 
964  for (auto const& t : tests)
965  {
966  Section s;
967  s.append(t.line.data());
968  BEAST_EXPECT(s.had_trailing_comments() == t.had_comment);
969  if (t.field.empty())
970  {
971  BEAST_EXPECTS(s.legacy() == t.expect, s.legacy());
972  }
973  else
974  {
976  BEAST_EXPECTS(set(field, t.field.data(), s), t.line);
977  BEAST_EXPECTS(field == t.expect, t.line);
978  }
979  }
980 
981  {
982  Section s;
983  s.append("online_delete = 3000");
984  std::uint32_t od = 0;
985  BEAST_EXPECT(set(od, "online_delete", s));
986  BEAST_EXPECTS(od == 3000, *(s.get<std::string>("online_delete")));
987  }
988 
989  {
990  Section s;
991  s.append("online_delete = 2000 #my comment on this");
992  std::uint32_t od = 0;
993  BEAST_EXPECT(set(od, "online_delete", s));
994  BEAST_EXPECTS(od == 2000, *(s.get<std::string>("online_delete")));
995  }
996  }
997 
998  void
999  testGetters()
1000  {
1001  using namespace std::string_literals;
1002  Section s{"MySection"};
1003  s.append("a_string = mystring");
1004  s.append("positive_int = 2");
1005  s.append("negative_int = -3");
1006  s.append("bool_ish = 1");
1007 
1008  {
1009  auto val_1 = "value 1"s;
1010  BEAST_EXPECT(set(val_1, "a_string", s));
1011  BEAST_EXPECT(val_1 == "mystring");
1012 
1013  auto val_2 = "value 2"s;
1014  BEAST_EXPECT(!set(val_2, "not_a_key", s));
1015  BEAST_EXPECT(val_2 == "value 2");
1016  BEAST_EXPECT(!set(val_2, "default"s, "not_a_key", s));
1017  BEAST_EXPECT(val_2 == "default");
1018 
1019  auto val_3 = get<std::string>(s, "a_string");
1020  BEAST_EXPECT(val_3 == "mystring");
1021  auto val_4 = get<std::string>(s, "not_a_key");
1022  BEAST_EXPECT(val_4 == "");
1023  auto val_5 = get<std::string>(s, "not_a_key", "default");
1024  BEAST_EXPECT(val_5 == "default");
1025 
1026  auto val_6 = "value 6"s;
1027  BEAST_EXPECT(get_if_exists(s, "a_string", val_6));
1028  BEAST_EXPECT(val_6 == "mystring");
1029 
1030  auto val_7 = "value 7"s;
1031  BEAST_EXPECT(!get_if_exists(s, "not_a_key", val_7));
1032  BEAST_EXPECT(val_7 == "value 7");
1033  }
1034 
1035  {
1036  int val_1 = 1;
1037  BEAST_EXPECT(set(val_1, "positive_int", s));
1038  BEAST_EXPECT(val_1 == 2);
1039 
1040  int val_2 = 2;
1041  BEAST_EXPECT(set(val_2, "negative_int", s));
1042  BEAST_EXPECT(val_2 == -3);
1043 
1044  int val_3 = 3;
1045  BEAST_EXPECT(!set(val_3, "a_string", s));
1046  BEAST_EXPECT(val_3 == 3);
1047 
1048  auto val_4 = get<int>(s, "positive_int");
1049  BEAST_EXPECT(val_4 == 2);
1050  auto val_5 = get<int>(s, "not_a_key");
1051  BEAST_EXPECT(val_5 == 0);
1052  auto val_6 = get<int>(s, "not_a_key", 5);
1053  BEAST_EXPECT(val_6 == 5);
1054  auto val_7 = get<int>(s, "a_string", 6);
1055  BEAST_EXPECT(val_7 == 6);
1056 
1057  int val_8 = 8;
1058  BEAST_EXPECT(get_if_exists(s, "positive_int", val_8));
1059  BEAST_EXPECT(val_8 == 2);
1060 
1061  auto val_9 = 9;
1062  BEAST_EXPECT(!get_if_exists(s, "not_a_key", val_9));
1063  BEAST_EXPECT(val_9 == 9);
1064 
1065  auto val_10 = 10;
1066  BEAST_EXPECT(!get_if_exists(s, "a_string", val_10));
1067  BEAST_EXPECT(val_10 == 10);
1068 
1069  BEAST_EXPECT(s.get<int>("not_a_key") == std::nullopt);
1070  try
1071  {
1072  s.get<int>("a_string");
1073  fail();
1074  }
1075  catch (boost::bad_lexical_cast&)
1076  {
1077  pass();
1078  }
1079  }
1080 
1081  {
1082  bool flag_1 = false;
1083  BEAST_EXPECT(get_if_exists(s, "bool_ish", flag_1));
1084  BEAST_EXPECT(flag_1 == true);
1085 
1086  bool flag_2 = false;
1087  BEAST_EXPECT(!get_if_exists(s, "not_a_key", flag_2));
1088  BEAST_EXPECT(flag_2 == false);
1089  }
1090  }
1091 
1092  void
1093  testAmendment()
1094  {
1095  testcase("amendment");
1096  struct ConfigUnit
1097  {
1098  std::string unit;
1099  std::uint32_t numSeconds;
1100  std::uint32_t configVal;
1101  bool shouldPass;
1102  };
1103 
1104  std::vector<ConfigUnit> units = {
1105  {"seconds", 1, 15 * 60, false},
1106  {"minutes", 60, 14, false},
1107  {"minutes", 60, 15, true},
1108  {"hours", 3600, 10, true},
1109  {"days", 86400, 10, true},
1110  {"weeks", 604800, 2, true},
1111  {"months", 2592000, 1, false},
1112  {"years", 31536000, 1, false}};
1113 
1114  std::string space = "";
1115  for (auto& [unit, sec, val, shouldPass] : units)
1116  {
1117  Config c;
1118  std::string toLoad(R"rippleConfig(
1119 [amendment_majority_time]
1120 )rippleConfig");
1121  toLoad += std::to_string(val) + space + unit;
1122  space = space == "" ? " " : "";
1123 
1124  try
1125  {
1126  c.loadFromString(toLoad);
1127  if (shouldPass)
1128  BEAST_EXPECT(
1129  c.AMENDMENT_MAJORITY_TIME.count() == val * sec);
1130  else
1131  fail();
1132  }
1133  catch (std::runtime_error&)
1134  {
1135  if (!shouldPass)
1136  pass();
1137  else
1138  fail();
1139  }
1140  }
1141  }
1142 
1143  void
1144  testOverlay()
1145  {
1146  testcase("overlay: unknown time");
1147 
1148  auto testUnknown =
1150  try
1151  {
1152  Config c;
1153  c.loadFromString("[overlay]\nmax_unknown_time=" + value);
1154  return c.MAX_UNKNOWN_TIME;
1155  }
1156  catch (std::runtime_error&)
1157  {
1158  return {};
1159  }
1160  };
1161 
1162  // Failures
1163  BEAST_EXPECT(!testUnknown("none"));
1164  BEAST_EXPECT(!testUnknown("0.5"));
1165  BEAST_EXPECT(!testUnknown("180 seconds"));
1166  BEAST_EXPECT(!testUnknown("9 minutes"));
1167 
1168  // Below lower bound
1169  BEAST_EXPECT(!testUnknown("299"));
1170 
1171  // In bounds
1172  BEAST_EXPECT(testUnknown("300") == std::chrono::seconds{300});
1173  BEAST_EXPECT(testUnknown("301") == std::chrono::seconds{301});
1174  BEAST_EXPECT(testUnknown("1799") == std::chrono::seconds{1799});
1175  BEAST_EXPECT(testUnknown("1800") == std::chrono::seconds{1800});
1176 
1177  // Above upper bound
1178  BEAST_EXPECT(!testUnknown("1801"));
1179 
1180  testcase("overlay: diverged time");
1181 
1182  // In bounds:
1183  auto testDiverged =
1185  try
1186  {
1187  Config c;
1188  c.loadFromString("[overlay]\nmax_diverged_time=" + value);
1189  return c.MAX_DIVERGED_TIME;
1190  }
1191  catch (std::runtime_error&)
1192  {
1193  return {};
1194  }
1195  };
1196 
1197  // Failures
1198  BEAST_EXPECT(!testDiverged("none"));
1199  BEAST_EXPECT(!testDiverged("0.5"));
1200  BEAST_EXPECT(!testDiverged("180 seconds"));
1201  BEAST_EXPECT(!testDiverged("9 minutes"));
1202 
1203  // Below lower bound
1204  BEAST_EXPECT(!testDiverged("0"));
1205  BEAST_EXPECT(!testDiverged("59"));
1206 
1207  // In bounds
1208  BEAST_EXPECT(testDiverged("60") == std::chrono::seconds{60});
1209  BEAST_EXPECT(testDiverged("61") == std::chrono::seconds{61});
1210  BEAST_EXPECT(testDiverged("899") == std::chrono::seconds{899});
1211  BEAST_EXPECT(testDiverged("900") == std::chrono::seconds{900});
1212 
1213  // Above upper bound
1214  BEAST_EXPECT(!testDiverged("901"));
1215  }
1216 
1217  void
1218  run() override
1219  {
1220  testLegacy();
1221  testDbPath();
1222  testValidatorKeys();
1223  testValidatorsFile();
1224  testSetup(false);
1225  testSetup(true);
1226  testPort();
1227  testWhitespace();
1228  testColons();
1229  testComments();
1230  testGetters();
1231  testAmendment();
1232  testOverlay();
1233  }
1234 };
1235 
1236 BEAST_DEFINE_TESTSUITE(Config, core, ripple);
1237 
1238 } // namespace ripple
ripple::Config_test::testWhitespace
void testWhitespace()
Definition: Config_test.cpp:818
ripple::Config_test
Definition: Config_test.cpp:269
ripple::detail::RippledCfgGuard::RippledCfgGuard
RippledCfgGuard(beast::unit_test::suite &test, path subDir, path const &dbPath, path const &validatorsFile, bool useCounter=true)
Definition: Config_test.cpp:137
fstream
std::string
STL class.
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
ripple::detail::ValidatorsTxtGuard::ValidatorsTxtGuard
ValidatorsTxtGuard(beast::unit_test::suite &test, path subDir, path const &validatorsFileName, bool useCounter=true)
Definition: Config_test.cpp:235
std::exception
STL class.
std::string_view
STL class.
ripple::test::detail::DirGuard
Create a directory and remove it when it's done.
Definition: FileDirGuard.h:34
ripple::ParsedPort::admin_nets_v6
std::vector< boost::asio::ip::network_v6 > admin_nets_v6
Definition: Port.h:117
ripple::Config_test::testSetup
void testSetup(bool explicitPath)
Definition: Config_test.cpp:680
std::vector
STL class.
std::vector::size
T size(T... args)
ripple::detail::RippledCfgGuard::config_
Config config_
Definition: Config_test.cpp:134
std::chrono::seconds
ripple::Config::silent
bool silent() const
Definition: Config.h:326
ripple::detail::ValidatorsTxtGuard::validatorsFile
std::string validatorsFile() const
Definition: Config_test.cpp:258
ripple::Config_test::testDbPath
void testDbPath()
Definition: Config_test.cpp:303
ripple::parse_Port
void parse_Port(ParsedPort &port, Section const &section, std::ostream &log)
Definition: Port.cpp:199
ripple::Config_test::path
boost::filesystem::path path
Definition: Config_test.cpp:272
ripple::ParsedPort
Definition: Port.h:96
iostream
ripple::Config::quiet
bool quiet() const
Definition: Config.h:321
ripple::test::detail::DirGuard::subdir
path const & subdir() const
Definition: FileDirGuard.h:98
ripple::Section::values
std::vector< std::string > const & values() const
Returns all the values in the section.
Definition: BasicConfig.h:77
ripple::detail::RippledCfgGuard::~RippledCfgGuard
~RippledCfgGuard()
Definition: Config_test.cpp:186
ripple::get_if_exists
bool get_if_exists(Section const &section, std::string const &name, T &v)
Definition: BasicConfig.h:384
ripple::Config_test::testLegacy
void testLegacy()
Definition: Config_test.cpp:276
ripple::test::detail::FileDirGuard::file
path const & file() const
Definition: FileDirGuard.h:164
ripple::detail::ValidatorsTxtGuard::validatorsFileExists
bool validatorsFileExists() const
Definition: Config_test.cpp:252
ripple::Config::loadFromString
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition: Config.cpp:457
ripple::detail::RippledCfgGuard::configFile
std::string configFile() const
Definition: Config_test.cpp:169
ripple::Config
Definition: Config.h:89
std::ofstream
STL class.
ripple::Config_test::testPort
void testPort()
Definition: Config_test.cpp:799
ripple::Config::IPS_FIXED
std::vector< std::string > IPS_FIXED
Definition: Config.h:150
ripple::Config::standalone
bool standalone() const
Definition: Config.h:331
std::to_string
T to_string(T... args)
ripple::set
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
Definition: BasicConfig.h:313
std::array
STL class.
ripple::validationSeed
static std::optional< Seed > validationSeed(Json::Value const &params)
Definition: ValidationCreate.cpp:30
ripple::BasicConfig::legacy
void legacy(std::string const &section, std::string value)
Set a value that is not a key/value pair.
Definition: BasicConfig.cpp:164
ripple::Section::lines
std::vector< std::string > const & lines() const
Returns all the lines in the section.
Definition: BasicConfig.h:68
ripple::detail::valFileContents
std::string valFileContents()
Definition: Config_test.cpp:203
std::runtime_error
STL class.
ripple::test::detail::DirGuard::test_
beast::unit_test::suite & test_
Definition: FileDirGuard.h:44
std::uint32_t
ripple::Config::databaseDirName
static char const *const databaseDirName
Definition: Config.h:94
ripple::detail::RippledCfgGuard::configFileExists
bool configFileExists() const
Definition: Config_test.cpp:181
ripple::detail::RippledCfgGuard
Write a rippled config file and remove when done.
Definition: Config_test.cpp:127
ripple::Config::LEDGER_HISTORY
std::uint32_t LEDGER_HISTORY
Definition: Config.h:211
ripple::TestSuite
Definition: TestSuite.h:28
std::experimental::filesystem::space
T space(T... args)
beast::field
field_t< CharT, Traits, Allocator > field(std::basic_string< CharT, Traits, Allocator > const &text, int width=8, int pad=0, bool right=false)
Definition: iosformat.h:162
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::test::detail::FileDirGuard::FileDirGuard
FileDirGuard(beast::unit_test::suite &test, path subDir, path file, std::string const &contents, bool useCounter=true, bool create=true)
Definition: FileDirGuard.h:114
ripple::detail::RippledCfgGuard::rmDataDir_
bool rmDataDir_
Definition: Config_test.cpp:132
ripple::Config::setup
void setup(std::string const &strConf, bool bQuiet, bool bSilent, bool bStandalone)
Definition: Config.cpp:315
std::endl
T endl(T... args)
ripple::Config_test::testValidatorsFile
void testValidatorsFile()
Definition: Config_test.cpp:415
std
STL namespace.
std::string::empty
T empty(T... args)
std::optional
ripple::Config::IPS
std::vector< std::string > IPS
Definition: Config.h:149
ripple::test::detail::FileDirGuard::fileExists
bool fileExists() const
Definition: FileDirGuard.h:170
ripple::test::detail::FileDirGuard
Write a file in a directory and remove when done.
Definition: FileDirGuard.h:107
ripple::test::detail::DirGuard::rmDir
auto rmDir(path const &toRm)
Definition: FileDirGuard.h:47
ripple::Config_test::testValidatorKeys
void testValidatorKeys()
Definition: Config_test.cpp:371
ripple::test::detail::FileDirGuard::file_
const path file_
Definition: FileDirGuard.h:110
ripple::detail::RippledCfgGuard::dataDirExists
bool dataDirExists() const
Definition: Config_test.cpp:175
ripple::detail::ValidatorsTxtGuard
Write a validators.txt file and remove when done.
Definition: Config_test.cpp:232
ripple::detail::configContents
std::string configContents(std::string const &dbPath, std::string const &validatorsFile)
Definition: Config_test.cpp:34
ripple::detail::RippledCfgGuard::dataDir_
path dataDir_
Definition: Config_test.cpp:130
ripple::test::detail::DirGuard::path
boost::filesystem::path path
Definition: FileDirGuard.h:37
ripple::detail::ValidatorsTxtGuard::~ValidatorsTxtGuard
~ValidatorsTxtGuard()
Definition: Config_test.cpp:263
std::exception::what
T what(T... args)
ripple::BasicConfig::exists
bool exists(std::string const &name) const
Returns true if a section with the given name exists.
Definition: BasicConfig.cpp:121
ripple::BasicConfig::section
Section & section(std::string const &name)
Returns the section with the given name.
Definition: BasicConfig.cpp:127
ripple::Config::MAX_DIVERGED_TIME
std::chrono::seconds MAX_DIVERGED_TIME
Definition: Config.h:289
ripple::detail::RippledCfgGuard::config
Config const & config() const
Definition: Config_test.cpp:163
ripple::ParsedPort::admin_nets_v4
std::vector< boost::asio::ip::network_v4 > admin_nets_v4
Definition: Port.h:116