xrpld
Loading...
Searching...
No Matches
DatabaseConfig_test.cpp
1#include <test/jtx/CheckMessageLogs.h>
2#include <test/jtx/Env.h>
3#include <test/jtx/envconfig.h>
4
5#include <xrpld/core/Config.h>
6
7#include <xrpl/beast/unit_test/suite.h>
8#include <xrpl/beast/utility/Journal.h>
9#include <xrpl/rdb/DatabaseCon.h>
10
11#include <memory>
12#include <utility>
13
14namespace xrpl::node_store {
15
17{
18public:
19 void
21 {
22 testcase("Config");
23
24 using namespace xrpl::test;
25 using namespace xrpl::test::jtx;
26
27 auto const integrityWarning =
28 "reducing the data integrity guarantees from the "
29 "default [sqlite] behavior is not recommended for "
30 "nodes storing large amounts of history, because of the "
31 "difficulty inherent in rebuilding corrupted data.";
32 {
33 // defaults
34 Env env(*this);
35
36 auto const s = setupDatabaseCon(env.app().config());
37
38 if (BEAST_EXPECT(s.globalPragma->size() == 3))
39 {
40 BEAST_EXPECT(s.globalPragma->at(0) == "PRAGMA journal_mode=wal;");
41 BEAST_EXPECT(s.globalPragma->at(1) == "PRAGMA synchronous=normal;");
42 BEAST_EXPECT(s.globalPragma->at(2) == "PRAGMA temp_store=file;");
43 }
44 }
45 {
46 // High safety level
48
49 bool found = false;
50 Env env = [&]() {
51 auto p = test::jtx::envconfig();
52 {
53 auto& section = p->section("sqlite");
54 section.set("safety_level", "high");
55 }
56 p->ledgerHistory = 100'000'000;
57
58 return Env(
59 *this,
60 std::move(p),
61 std::make_unique<CheckMessageLogs>(integrityWarning, &found),
63 }();
64
65 BEAST_EXPECT(!found);
66 auto const s = setupDatabaseCon(env.app().config());
67 if (BEAST_EXPECT(s.globalPragma->size() == 3))
68 {
69 BEAST_EXPECT(s.globalPragma->at(0) == "PRAGMA journal_mode=wal;");
70 BEAST_EXPECT(s.globalPragma->at(1) == "PRAGMA synchronous=normal;");
71 BEAST_EXPECT(s.globalPragma->at(2) == "PRAGMA temp_store=file;");
72 }
73 }
74 {
75 // Low safety level
77
78 bool found = false;
79 Env env = [&]() {
80 auto p = test::jtx::envconfig();
81 {
82 auto& section = p->section("sqlite");
83 section.set("safety_level", "low");
84 }
85 p->ledgerHistory = 100'000'000;
86
87 return Env(
88 *this,
89 std::move(p),
90 std::make_unique<CheckMessageLogs>(integrityWarning, &found),
92 }();
93
94 BEAST_EXPECT(found);
95 auto const s = setupDatabaseCon(env.app().config());
96 if (BEAST_EXPECT(s.globalPragma->size() == 3))
97 {
98 BEAST_EXPECT(s.globalPragma->at(0) == "PRAGMA journal_mode=memory;");
99 BEAST_EXPECT(s.globalPragma->at(1) == "PRAGMA synchronous=off;");
100 BEAST_EXPECT(s.globalPragma->at(2) == "PRAGMA temp_store=memory;");
101 }
102 }
103 {
104 // Override individual settings
106
107 bool found = false;
108 Env env = [&]() {
109 auto p = test::jtx::envconfig();
110 {
111 auto& section = p->section("sqlite");
112 section.set("journal_mode", "off");
113 section.set("synchronous", "extra");
114 section.set("temp_store", "default");
115 }
116
117 return Env(
118 *this,
119 std::move(p),
120 std::make_unique<CheckMessageLogs>(integrityWarning, &found),
122 }();
123
124 // No warning, even though higher risk settings were used because
125 // ledgerHistory is small
126 BEAST_EXPECT(!found);
127 auto const s = setupDatabaseCon(env.app().config());
128 if (BEAST_EXPECT(s.globalPragma->size() == 3))
129 {
130 BEAST_EXPECT(s.globalPragma->at(0) == "PRAGMA journal_mode=off;");
131 BEAST_EXPECT(s.globalPragma->at(1) == "PRAGMA synchronous=extra;");
132 BEAST_EXPECT(s.globalPragma->at(2) == "PRAGMA temp_store=default;");
133 }
134 }
135 {
136 // Override individual settings with large history
138
139 bool found = false;
140 Env env = [&]() {
141 auto p = test::jtx::envconfig();
142 {
143 auto& section = p->section("sqlite");
144 section.set("journal_mode", "off");
145 section.set("synchronous", "extra");
146 section.set("temp_store", "default");
147 }
148 p->ledgerHistory = 50'000'000;
149
150 return Env(
151 *this,
152 std::move(p),
153 std::make_unique<CheckMessageLogs>(integrityWarning, &found),
155 }();
156
157 // No warning, even though higher risk settings were used because
158 // ledgerHistory is small
159 BEAST_EXPECT(found);
160 auto const s = setupDatabaseCon(env.app().config());
161 if (BEAST_EXPECT(s.globalPragma->size() == 3))
162 {
163 BEAST_EXPECT(s.globalPragma->at(0) == "PRAGMA journal_mode=off;");
164 BEAST_EXPECT(s.globalPragma->at(1) == "PRAGMA synchronous=extra;");
165 BEAST_EXPECT(s.globalPragma->at(2) == "PRAGMA temp_store=default;");
166 }
167 }
168 {
169 // Error: Mix safety_level and individual settings
171 auto const expected =
172 "Failed to initialize SQL databases: "
173 "Configuration file may not define both \"safety_level\" and "
174 "\"journal_mode\"";
175 bool found = false;
176
177 auto p = test::jtx::envconfig();
178 {
179 auto& section = p->section("sqlite");
180 section.set("safety_level", "low");
181 section.set("journal_mode", "off");
182 section.set("synchronous", "extra");
183 section.set("temp_store", "default");
184 }
185
186 try
187 {
188 Env const env(
189 *this,
190 std::move(p),
191 std::make_unique<CheckMessageLogs>(expected, &found),
193 fail();
194 }
195 catch (...)
196 {
197 BEAST_EXPECT(found);
198 }
199 }
200 {
201 // Error: Mix safety_level and one setting (gotta catch 'em all)
203 auto const expected =
204 "Failed to initialize SQL databases: Configuration file may "
205 "not define both \"safety_level\" and \"journal_mode\"";
206 bool found = false;
207
208 auto p = test::jtx::envconfig();
209 {
210 auto& section = p->section("sqlite");
211 section.set("safety_level", "high");
212 section.set("journal_mode", "off");
213 }
214
215 try
216 {
217 Env const env(
218 *this,
219 std::move(p),
220 std::make_unique<CheckMessageLogs>(expected, &found),
222 fail();
223 }
224 catch (...)
225 {
226 BEAST_EXPECT(found);
227 }
228 }
229 {
230 // Error: Mix safety_level and one setting (gotta catch 'em all)
232 auto const expected =
233 "Failed to initialize SQL databases: Configuration file may "
234 "not define both \"safety_level\" and \"synchronous\"";
235 bool found = false;
236
237 auto p = test::jtx::envconfig();
238 {
239 auto& section = p->section("sqlite");
240 section.set("safety_level", "low");
241 section.set("synchronous", "extra");
242 }
243
244 try
245 {
246 Env const env(
247 *this,
248 std::move(p),
249 std::make_unique<CheckMessageLogs>(expected, &found),
251 fail();
252 }
253 catch (...)
254 {
255 BEAST_EXPECT(found);
256 }
257 }
258 {
259 // Error: Mix safety_level and one setting (gotta catch 'em all)
261 auto const expected =
262 "Failed to initialize SQL databases: Configuration file may "
263 "not define both \"safety_level\" and \"temp_store\"";
264 bool found = false;
265
266 auto p = test::jtx::envconfig();
267 {
268 auto& section = p->section("sqlite");
269 section.set("safety_level", "high");
270 section.set("temp_store", "default");
271 }
272
273 try
274 {
275 Env const env(
276 *this,
277 std::move(p),
278 std::make_unique<CheckMessageLogs>(expected, &found),
280 fail();
281 }
282 catch (...)
283 {
284 BEAST_EXPECT(found);
285 }
286 }
287 {
288 // Error: Invalid value
290 auto const expected =
291 "Failed to initialize SQL databases: Invalid safety_level "
292 "value: slow";
293 bool found = false;
294
295 auto p = test::jtx::envconfig();
296 {
297 auto& section = p->section("sqlite");
298 section.set("safety_level", "slow");
299 }
300
301 try
302 {
303 Env const env(
304 *this,
305 std::move(p),
306 std::make_unique<CheckMessageLogs>(expected, &found),
308 fail();
309 }
310 catch (...)
311 {
312 BEAST_EXPECT(found);
313 }
314 }
315 {
316 // Error: Invalid value
318 auto const expected =
319 "Failed to initialize SQL databases: Invalid journal_mode "
320 "value: fast";
321 bool found = false;
322
323 auto p = test::jtx::envconfig();
324 {
325 auto& section = p->section("sqlite");
326 section.set("journal_mode", "fast");
327 }
328
329 try
330 {
331 Env const env(
332 *this,
333 std::move(p),
334 std::make_unique<CheckMessageLogs>(expected, &found),
336 fail();
337 }
338 catch (...)
339 {
340 BEAST_EXPECT(found);
341 }
342 }
343 {
344 // Error: Invalid value
346 auto const expected =
347 "Failed to initialize SQL databases: Invalid synchronous "
348 "value: instant";
349 bool found = false;
350
351 auto p = test::jtx::envconfig();
352 {
353 auto& section = p->section("sqlite");
354 section.set("synchronous", "instant");
355 }
356
357 try
358 {
359 Env const env(
360 *this,
361 std::move(p),
362 std::make_unique<CheckMessageLogs>(expected, &found),
364 fail();
365 }
366 catch (...)
367 {
368 BEAST_EXPECT(found);
369 }
370 }
371 {
372 // Error: Invalid value
374 auto const expected =
375 "Failed to initialize SQL databases: Invalid temp_store "
376 "value: network";
377 bool found = false;
378
379 auto p = test::jtx::envconfig();
380 {
381 auto& section = p->section("sqlite");
382 section.set("temp_store", "network");
383 }
384
385 try
386 {
387 Env const env(
388 *this,
389 std::move(p),
390 std::make_unique<CheckMessageLogs>(expected, &found),
392 fail();
393 }
394 catch (...)
395 {
396 BEAST_EXPECT(found);
397 }
398 }
399 {
400 // N/A: Default values
401 Env env(*this);
402 auto const s = setupDatabaseCon(env.app().config());
403 if (BEAST_EXPECT(s.txPragma.size() == 4))
404 {
405 BEAST_EXPECT(s.txPragma.at(0) == "PRAGMA page_size=4096;");
406 BEAST_EXPECT(s.txPragma.at(1) == "PRAGMA journal_size_limit=1582080;");
407 BEAST_EXPECT(s.txPragma.at(2) == "PRAGMA max_page_count=4294967294;");
408 BEAST_EXPECT(s.txPragma.at(3) == "PRAGMA mmap_size=17179869184;");
409 }
410 }
411 {
412 // Success: Valid values
413 Env env = [&]() {
414 auto p = test::jtx::envconfig();
415 {
416 auto& section = p->section("sqlite");
417 section.set("page_size", "512");
418 section.set("journal_size_limit", "2582080");
419 }
420 return Env(*this, std::move(p));
421 }();
422 auto const s = setupDatabaseCon(env.app().config());
423 if (BEAST_EXPECT(s.txPragma.size() == 4))
424 {
425 BEAST_EXPECT(s.txPragma.at(0) == "PRAGMA page_size=512;");
426 BEAST_EXPECT(s.txPragma.at(1) == "PRAGMA journal_size_limit=2582080;");
427 BEAST_EXPECT(s.txPragma.at(2) == "PRAGMA max_page_count=4294967294;");
428 BEAST_EXPECT(s.txPragma.at(3) == "PRAGMA mmap_size=17179869184;");
429 }
430 }
431 {
432 // Error: Invalid values
433 auto const expected = "Invalid page_size. Must be between 512 and 65536.";
434 bool found = false;
435 auto p = test::jtx::envconfig();
436 {
437 auto& section = p->section("sqlite");
438 section.set("page_size", "256");
439 }
440 try
441 {
442 Env const env(
443 *this,
444 std::move(p),
445 std::make_unique<CheckMessageLogs>(expected, &found),
447 fail();
448 }
449 catch (...)
450 {
451 BEAST_EXPECT(found);
452 }
453 }
454 {
455 // Error: Invalid values
456 auto const expected = "Invalid page_size. Must be between 512 and 65536.";
457 bool found = false;
458 auto p = test::jtx::envconfig();
459 {
460 auto& section = p->section("sqlite");
461 section.set("page_size", "131072");
462 }
463 try
464 {
465 Env const env(
466 *this,
467 std::move(p),
468 std::make_unique<CheckMessageLogs>(expected, &found),
470 fail();
471 }
472 catch (...)
473 {
474 BEAST_EXPECT(found);
475 }
476 }
477 {
478 // Error: Invalid values
479 auto const expected = "Invalid page_size. Must be a power of 2.";
480 bool found = false;
481 auto p = test::jtx::envconfig();
482 {
483 auto& section = p->section("sqlite");
484 section.set("page_size", "513");
485 }
486 try
487 {
488 Env const env(
489 *this,
490 std::move(p),
491 std::make_unique<CheckMessageLogs>(expected, &found),
493 fail();
494 }
495 catch (...)
496 {
497 BEAST_EXPECT(found);
498 }
499 }
500 }
501
502 void
503 run() override
504 {
505 testConfig();
506 }
507};
508
509BEAST_DEFINE_TESTSUITE(DatabaseConfig, nodestore, xrpl);
510
511} // namespace xrpl::node_store
A testsuite class.
Definition suite.h:52
void fail(String const &reason, char const *file, int line)
Record a failure.
Definition suite.h:554
TestcaseT testcase
Memberspace for declaring test cases.
Definition suite.h:155
virtual Config & config()=0
A transaction testing environment.
Definition Env.h:161
Application & app()
Definition Env.h:300
T make_unique(T... args)
BEAST_DEFINE_TESTSUITE(DatabaseConfig, nodestore, xrpl)
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:37
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
DatabaseCon::Setup setupDatabaseCon(Config const &c, std::optional< beast::Journal > j=std::nullopt)
static std::unique_ptr< std::vector< std::string > const > globalPragma
Definition DatabaseCon.h:97