15#include <boost/test/unit_test.hpp>
17using namespace std::string_literals;
26 auto apply_random_xor_chunks{[&](std::span<std::byte> target,
const Obfuscation& obfuscation) {
27 for (
size_t offset{0}; offset < target.size();) {
28 const size_t chunk_size{1 + m_rng.randrange(target.size() - offset)};
29 obfuscation(target.subspan(offset, chunk_size), offset);
34 for (
size_t test{0}; test < 100; ++test) {
35 const size_t write_size{1 + m_rng.randrange(100U)};
36 const std::vector original{m_rng.randbytes<std::byte>(write_size)};
37 std::vector roundtrip{original};
39 const auto key_bytes{m_rng.randbool() ? m_rng.randbytes<
Obfuscation::KEY_SIZE>() : std::array<std::byte, Obfuscation::KEY_SIZE>{}};
41 apply_random_xor_chunks(roundtrip, obfuscation);
43 for (
size_t i{0}; i < original.size(); ++i) {
47 apply_random_xor_chunks(roundtrip, obfuscation);
48 BOOST_CHECK_EQUAL_COLLECTIONS(roundtrip.begin(), roundtrip.end(), original.begin(), original.end());
73 std::vector<std::byte> key_out;
75 ds_out << obfuscation;
79 BOOST_CHECK_EQUAL_COLLECTIONS(key_in.begin(), key_in.end(), key_out.begin(), key_out.end());
87 const Obfuscation non_null_obf{
"ff00ff00ff00ff00"_hex};
96 stream << uint8_t{42};
103 stream << uint16_t{42};
111 fs::path xor_path{m_args.GetDataDirBase() /
"test_xor.bin"};
112 auto raw_file{[&](
const auto& mode) {
return fsbridge::fopen(xor_path, mode); }};
113 const std::vector<uint8_t>
test1{1, 2, 3};
114 const std::vector<uint8_t> test2{4, 5};
115 const Obfuscation obfuscation{
"ff00ff00ff00ff00"_hex};
119 AutoFile xor_file{raw_file(
"rb"), obfuscation};
128 const char* mode =
"wb";
130 const char* mode =
"wbx";
132 AutoFile xor_file{raw_file(mode), obfuscation};
133 xor_file <<
test1 << test2;
135 BOOST_REQUIRE_EQUAL(xor_file.fclose(), 0);
139 AutoFile non_xor_file{raw_file(
"rb")};
140 std::vector<std::byte> raw(7);
141 non_xor_file >> std::span{raw};
148 AutoFile xor_file{raw_file(
"rb"), obfuscation};
149 std::vector<std::byte> read1, read2;
150 xor_file >> read1 >> read2;
158 AutoFile xor_file{raw_file(
"rb"), obfuscation};
159 std::vector<std::byte> read2;
175 unsigned char bytes[] = {3, 4, 5, 6};
176 std::vector<unsigned char> vch;
183 BOOST_CHECK((vch == std::vector<unsigned char>{{1, 2}}));
185 BOOST_CHECK((vch == std::vector<unsigned char>{{1, 2}}));
189 BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 1, 2}}));
191 BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 1, 2}}));
196 BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 1, 2, 0}}));
198 BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 1, 2, 0}}));
203 BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 1, 2}}));
205 BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 1, 2}}));
210 BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 0, 1, 2}}));
212 BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 0, 1, 2}}));
216 BOOST_CHECK((vch == std::vector<unsigned char>{{3, 4, 5, 6}}));
218 BOOST_CHECK((vch == std::vector<unsigned char>{{3, 4, 5, 6}}));
223 BOOST_CHECK((vch == std::vector<unsigned char>{{8, 8, 1, 3, 4, 5, 6, 2}}));
225 BOOST_CHECK((vch == std::vector<unsigned char>{{8, 8, 1, 3, 4, 5, 6, 2}}));
233 unsigned char bytes[] = {3, 4, 5, 6};
234 std::array<std::byte, 8> arr{};
242 SpanWriter{std::span{arr}.subspan(2), a, bytes, b};
246 std::array<std::byte, 1> small{};
253 std::vector<unsigned char> vch = {1, 255, 3, 4, 5, 6};
298 std::vector<uint8_t>
data{0x82, 0xa7, 0x31};
312 bit_writer.Write(0, 1);
313 bit_writer.Write(2, 2);
314 bit_writer.Write(6, 3);
315 bit_writer.Write(11, 4);
316 bit_writer.Write(1, 5);
317 bit_writer.Write(32, 6);
318 bit_writer.Write(7, 7);
319 bit_writer.Write(30497, 16);
323 uint32_t serialized_int1;
324 data >> serialized_int1;
326 uint16_t serialized_int2;
327 data >> serialized_int2;
352 const Obfuscation obfuscation{
"ffffffffffffffff"_hex};
360 const Obfuscation obfuscation{
"ff0fff0fff0fff0f"_hex};
370 fs::path streams_test_filename = m_args.GetDataDirBase() /
"streams_test_tmp";
374 for (uint8_t j = 0; j < 40; ++j) {
377 file.seek(0, SEEK_SET);
417 for (uint8_t j = 3; j < 10; ++j) {
450 for (uint8_t j = 0; j <
sizeof(a); ++j) {
474 BOOST_REQUIRE_EQUAL(file.fclose(), 0);
476 fs::remove(streams_test_filename);
481 fs::path streams_test_filename = m_args.GetDataDirBase() /
"streams_test_tmp";
484 for (uint8_t j = 0; j < 40; ++j) {
487 file.seek(0, SEEK_SET);
519 BOOST_REQUIRE_EQUAL(file.fclose(), 0);
520 fs::remove(streams_test_filename);
528 fs::path streams_test_filename = m_args.GetDataDirBase() /
"streams_test_tmp";
529 for (
int rep = 0; rep < 50; ++rep) {
531 size_t fileSize = m_rng.randrange(256);
532 for (uint8_t i = 0; i < fileSize; ++i) {
535 file.seek(0, SEEK_SET);
537 size_t bufSize = m_rng.randrange(300) + 1;
538 size_t rewindSize = m_rng.randrange(bufSize);
540 size_t currentPos = 0;
542 for (
int step = 0; step < 100; ++step) {
543 if (currentPos >= fileSize)
554 switch (m_rng.randrange(6)) {
557 if (currentPos + 1 > fileSize)
559 bf.SetLimit(currentPos + 1);
561 for (uint8_t i = 0; i < 1; ++i) {
569 if (currentPos + 2 > fileSize)
571 bf.SetLimit(currentPos + 2);
573 for (uint8_t i = 0; i < 2; ++i) {
581 if (currentPos + 5 > fileSize)
583 bf.SetLimit(currentPos + 5);
585 for (uint8_t i = 0; i < 5; ++i) {
594 size_t skip_length{
static_cast<size_t>(m_rng.randrange(5))};
595 if (currentPos + skip_length > fileSize)
continue;
596 bf.SetLimit(currentPos + skip_length);
597 bf.SkipTo(currentPos + skip_length);
598 currentPos += skip_length;
603 size_t find = currentPos + m_rng.randrange(8);
604 if (find >= fileSize)
606 bf.FindByte(std::byte(find));
611 bf.SetLimit(currentPos + 1);
619 size_t requestPos = m_rng.randrange(maxPos + 4);
620 bool okay = bf.SetPos(requestPos);
625 currentPos = bf.GetPos();
628 if (requestPos <= maxPos &&
629 maxPos > rewindSize &&
630 requestPos >= maxPos - rewindSize) {
637 if (maxPos < currentPos)
640 BOOST_REQUIRE_EQUAL(file.fclose(), 0);
642 fs::remove(streams_test_filename);
647 const size_t file_size{1 + m_rng.randrange<
size_t>(1 << 17)};
648 const size_t buf_size{1 + m_rng.randrange(file_size)};
656 AutoFile f{test_file.Open(pos,
false), obfuscation};
657 f.
write(m_rng.randbytes<std::byte>(file_size));
658 BOOST_REQUIRE_EQUAL(f.fclose(), 0);
663 AutoFile direct_file{test_file.Open(pos,
true), obfuscation};
665 AutoFile buffered_file{test_file.Open(pos,
true), obfuscation};
666 BufferedReader buffered_reader{std::move(buffered_file), buf_size};
668 for (
size_t total_read{0}; total_read < file_size;) {
669 const size_t read{
Assert(std::min(1 + m_rng.randrange(m_rng.randbool() ? buf_size : 2 * buf_size), file_size - total_read))};
672 direct_file.read(direct_file_buffer);
675 buffered_reader.read(buffered_buffer);
677 BOOST_CHECK_EQUAL_COLLECTIONS(
678 direct_file_buffer.begin(), direct_file_buffer.end(),
679 buffered_buffer.begin(), buffered_buffer.end()
696 fs::remove(test_file.FileName(pos));
701 const size_t file_size{1 + m_rng.randrange<
size_t>(1 << 17)};
702 const size_t buf_size{1 + m_rng.randrange(file_size)};
710 DataBuffer test_data{m_rng.randbytes<std::byte>(file_size)};
712 AutoFile direct_file{test_direct.Open(pos,
false), obfuscation};
714 AutoFile buffered_file{test_buffered.Open(pos,
false), obfuscation};
718 for (
size_t total_written{0}; total_written < file_size;) {
719 const size_t write_size{
Assert(std::min(1 + m_rng.randrange(m_rng.randbool() ? buf_size : 2 * buf_size), file_size - total_written))};
721 auto current_span = std::span{test_data}.subspan(total_written, write_size);
722 direct_file.write(current_span);
723 buffered.write(current_span);
725 total_written += write_size;
728 BOOST_REQUIRE_EQUAL(buffered_file.fclose(), 0);
729 BOOST_REQUIRE_EQUAL(direct_file.fclose(), 0);
735 AutoFile verify_direct{test_direct.Open(pos,
true), obfuscation};
736 verify_direct.
read(direct_result);
744 AutoFile verify_buffered{test_buffered.Open(pos,
true), obfuscation};
745 verify_buffered.
read(buffered_result);
751 BOOST_CHECK_EQUAL_COLLECTIONS(
752 direct_result.begin(), direct_result.end(),
753 buffered_result.begin(), buffered_result.end()
756 fs::remove(test_direct.FileName(pos));
757 fs::remove(test_buffered.FileName(pos));
762 const uint32_t v1{m_rng.rand32()}, v2{m_rng.rand32()}, v3{m_rng.rand32()};
763 const fs::path test_file{m_args.GetDataDirBase() /
"test_buffered_write_read.bin"};
770 f.
write(std::as_bytes(std::span{&v3, 1}));
772 BOOST_REQUIRE_EQUAL(file.fclose(), 0);
776 uint32_t _v1{0}, _v2{0}, _v3{0};
778 BufferedReader f(std::move(file),
sizeof(v1) +
sizeof(v2) +
sizeof(v3));
780 f.
read(std::as_writable_bytes(std::span{&_v3, 1}));
789 fs::remove(test_file);
796 const std::string
data{
"bitcoin"};
801 hash_verifier >> result;
808 const fs::path path = m_args.GetDataDirBase() /
"size_pos_test.bin";
810 for (uint8_t j = 0; j < 10; ++j) {
839 BOOST_REQUIRE_EQUAL(f.fclose(), 0);
#define Assert(val)
Identity function.
Non-refcounted RAII wrapper for FILE*.
void ignore(size_t nSize)
void write(std::span< const std::byte > src)
void read(std::span< std::byte > dst)
Wrapper around an AutoFile& that implements a ring buffer to deserialize from.
void SkipTo(const uint64_t file_pos)
Move the read position ahead in the stream to the given position.
Wrapper that buffers reads from an underlying stream.
void read(std::span< std::byte > dst)
Wrapper that buffers writes to an underlying stream.
void write(std::span< const std::byte > src)
Double ended buffer combining vector and stream-like interfaces.
FlatFileSeq represents a sequence of numbered files storing raw data.
BOOST_CHECK_EXCEPTION predicates to check the specific validation error.
Reads data from an underlying stream, while hashing the read data.
Writes data to an underlying source stream, while hashing the written data.
static constexpr size_t KEY_SIZE
Minimal stream for reading from an existing byte array by std::span.
Minimal stream for writing to an existing span of bytes.
static const PrecomputedData data
Precomputed COutPoint and CCoins values.
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
BOOST_CHECK_GT(excessive_headers.size(), MAX_HEADERS_SIZE)
BOOST_CHECK_EQUAL(headers.FindFirst("key"), "value")
BOOST_CHECK_EXCEPTION(HTTPHeaders{}.Read(reader), std::runtime_error, HasReason{"Empty HTTP header name"})
FILE * fopen(const fs::path &p, const char *mode)
constexpr unsigned int BLOCKFILE_CHUNK_SIZE
The pre-allocation chunk size for blk?????.dat files (since 0.8)
""_hex is a compile-time user-defined literal returning a std::array<std::byte>, equivalent to ParseH...
#define BOOST_CHECK_THROW(stmt, excMatch)
#define BOOST_CHECK(expr)
std::vector< std::byte > DataBuffer
BOOST_AUTO_TEST_CASE(xor_random_chunks)
@ ZEROS
Seed with a compile time constant of zeros.