1#include <xrpl/basics/ByteUtilities.h>
2#include <xrpl/basics/FileUtilities.h>
3#include <xrpl/beast/utility/Journal.h>
4#include <xrpl/config/BasicConfig.h>
5#include <xrpl/nodestore/DummyScheduler.h>
6#include <xrpl/nodestore/Manager.h>
8#include <gtest/gtest.h>
9#include <helpers/CaptureSink.h>
10#include <helpers/TestSink.h>
11#include <nodestore/TestBase.h>
26makeSection(std::string
const& path, std::string
const& blockSize =
"")
29 params.set(
"type",
"nudb");
30 params.set(
"path", path);
31 if (!blockSize.empty())
32 params.set(
"nudb_block_size", blockSize);
37runRoundTrip(Section
const& params, std::size_t expectedBlocksize)
44 ASSERT_EQ(backend->getBlockSize(), expectedBlocksize);
46 ASSERT_TRUE(backend->isOpen());
54 EXPECT_EQ(batch, copy);
62 auto const params = makeSection(tempDir.
path());
63 ASSERT_NO_FATAL_FAILURE(runRoundTrip(params, 4096));
68 auto const kValidSizes = std::to_array<std::size_t>({4096, 8192, 16384, 32768});
69 for (
auto const size : kValidSizes)
74 ASSERT_NO_FATAL_FAILURE(runRoundTrip(params, size));
80 auto const params = makeSection(tempDir.
path(),
"");
81 ASSERT_NO_FATAL_FAILURE(runRoundTrip(params, 4096));
101 for (
auto const& size : kInvalidSizes)
103 SCOPED_TRACE(
"size='" + size +
"'");
105 auto const params = makeSection(tempDir.
path(), size);
111 for (
auto const& size : kWhitespaceSizes)
113 SCOPED_TRACE(
"size='" + size +
"'");
115 auto const params = makeSection(tempDir.
path(), size);
125 auto const params = makeSection(tempDir.
path(),
"8192");
130 [[maybe_unused]]
auto backend =
133 EXPECT_TRUE(sink.
messages().contains(
"Using custom NuDB block size: 8192"));
139 auto const params = makeSection(tempDir.
path(),
"5000");
147 FAIL() <<
"expected exception for invalid block size 5000";
152 EXPECT_TRUE(what.contains(
"Invalid nudb_block_size: 5000"));
153 EXPECT_TRUE(what.contains(
"Must be power of 2 between 4096 and 32768"));
160 auto const params = makeSection(tempDir.
path(),
"invalid");
168 FAIL() <<
"expected exception for non-numeric block size";
173 EXPECT_TRUE(what.contains(
"Invalid nudb_block_size value: invalid"));
191 for (
auto const& [size, shouldWork] : kCASES)
193 SCOPED_TRACE(
"size=" + size +
" shouldWork=" + (shouldWork ?
"true" :
"false"));
195 auto const params = makeSection(tempDir.
path(), size);
203 EXPECT_TRUE(shouldWork);
210 EXPECT_FALSE(shouldWork);
212 EXPECT_TRUE(what.contains(
"Invalid nudb_block_size"));
220 auto const params = makeSection(tempDir.
path(),
"16384");
225 EXPECT_NE(backend1,
nullptr);
226 ASSERT_NO_FATAL_FAILURE(runRoundTrip(params, 16384));
239 auto const params = makeSection(tempDir.
path(),
"8192");
243 [[maybe_unused]]
auto backend =
245 EXPECT_TRUE(sink.
messages().contains(
"Using custom NuDB block size"));
250 for (
auto const& format : kWhitespaceFormats)
252 SCOPED_TRACE(
"format='" + format +
"'");
254 auto const params = makeSection(tempDir.
path(), format);
265 for (
auto const& size : kBlockSizes)
267 SCOPED_TRACE(
"size=" + size);
269 auto const params = makeSection(tempDir.
path(), size);
291 EXPECT_EQ(batch, copy);
A generic endpoint for log messages.
RAII temporary directory.
std::string path() const
Get the native path for the temporary directory.
static TestSink & instance()
Simple NodeStore Scheduler that just performs the tasks synchronously.
virtual std::unique_ptr< Backend > makeBackend(Section const ¶meters, std::size_t burstSize, Scheduler &scheduler, beast::Journal journal)=0
Create a backend.
static Manager & instance()
Returns the instance of the manager singleton.
std::string messages() const
TEST(NodeStoreBasics, predictable_batches)
Batch createPredictableBatch(std::size_t numObjects, std::uint64_t seed)
void storeBatch(Backend &backend, Batch const &batch)
Batch fetchCopyOfBatch(Backend &backend, Batch const &batch)
constexpr auto megabytes(T value) noexcept