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};
126 AutoFile xor_file{raw_file(
"wbx"), obfuscation};
127 xor_file <<
test1 << test2;
129 BOOST_REQUIRE_EQUAL(xor_file.fclose(), 0);
133 AutoFile non_xor_file{raw_file(
"rb")};
134 std::vector<std::byte> raw(7);
135 non_xor_file >> std::span{raw};
142 AutoFile xor_file{raw_file(
"rb"), obfuscation};
143 std::vector<std::byte> read1, read2;
144 xor_file >> read1 >> read2;
152 AutoFile xor_file{raw_file(
"rb"), obfuscation};
153 std::vector<std::byte> read2;
169 unsigned char bytes[] = {3, 4, 5, 6};
170 std::vector<unsigned char> vch;
177 BOOST_CHECK((vch == std::vector<unsigned char>{{1, 2}}));
179 BOOST_CHECK((vch == std::vector<unsigned char>{{1, 2}}));
183 BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 1, 2}}));
185 BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 1, 2}}));
190 BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 1, 2, 0}}));
192 BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 1, 2, 0}}));
197 BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 1, 2}}));
199 BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 1, 2}}));
204 BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 0, 1, 2}}));
206 BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 0, 1, 2}}));
210 BOOST_CHECK((vch == std::vector<unsigned char>{{3, 4, 5, 6}}));
212 BOOST_CHECK((vch == std::vector<unsigned char>{{3, 4, 5, 6}}));
217 BOOST_CHECK((vch == std::vector<unsigned char>{{8, 8, 1, 3, 4, 5, 6, 2}}));
219 BOOST_CHECK((vch == std::vector<unsigned char>{{8, 8, 1, 3, 4, 5, 6, 2}}));
227 unsigned char bytes[] = {3, 4, 5, 6};
228 std::array<std::byte, 8> arr{};
236 SpanWriter{std::span{arr}.subspan(2), a, bytes, b};
240 std::array<std::byte, 1> small{};
247 std::vector<unsigned char> vch = {1, 255, 3, 4, 5, 6};
292 std::vector<uint8_t>
data{0x82, 0xa7, 0x31};
306 bit_writer.Write(0, 1);
307 bit_writer.Write(2, 2);
308 bit_writer.Write(6, 3);
309 bit_writer.Write(11, 4);
310 bit_writer.Write(1, 5);
311 bit_writer.Write(32, 6);
312 bit_writer.Write(7, 7);
313 bit_writer.Write(30497, 16);
317 uint32_t serialized_int1;
318 data >> serialized_int1;
320 uint16_t serialized_int2;
321 data >> serialized_int2;
346 const Obfuscation obfuscation{
"ffffffffffffffff"_hex};
354 const Obfuscation obfuscation{
"ff0fff0fff0fff0f"_hex};
364 fs::path streams_test_filename = m_args.GetDataDirBase() /
"streams_test_tmp";
368 for (uint8_t j = 0; j < 40; ++j) {
371 file.seek(0, SEEK_SET);
411 for (uint8_t j = 3; j < 10; ++j) {
444 for (uint8_t j = 0; j <
sizeof(a); ++j) {
468 BOOST_REQUIRE_EQUAL(file.fclose(), 0);
470 fs::remove(streams_test_filename);
475 fs::path streams_test_filename = m_args.GetDataDirBase() /
"streams_test_tmp";
478 for (uint8_t j = 0; j < 40; ++j) {
481 file.seek(0, SEEK_SET);
513 BOOST_REQUIRE_EQUAL(file.fclose(), 0);
514 fs::remove(streams_test_filename);
522 fs::path streams_test_filename = m_args.GetDataDirBase() /
"streams_test_tmp";
523 for (
int rep = 0; rep < 50; ++rep) {
525 size_t fileSize = m_rng.randrange(256);
526 for (uint8_t i = 0; i < fileSize; ++i) {
529 file.seek(0, SEEK_SET);
531 size_t bufSize = m_rng.randrange(300) + 1;
532 size_t rewindSize = m_rng.randrange(bufSize);
534 size_t currentPos = 0;
536 for (
int step = 0; step < 100; ++step) {
537 if (currentPos >= fileSize)
548 switch (m_rng.randrange(6)) {
551 if (currentPos + 1 > fileSize)
553 bf.SetLimit(currentPos + 1);
555 for (uint8_t i = 0; i < 1; ++i) {
563 if (currentPos + 2 > fileSize)
565 bf.SetLimit(currentPos + 2);
567 for (uint8_t i = 0; i < 2; ++i) {
575 if (currentPos + 5 > fileSize)
577 bf.SetLimit(currentPos + 5);
579 for (uint8_t i = 0; i < 5; ++i) {
588 size_t skip_length{
static_cast<size_t>(m_rng.randrange(5))};
589 if (currentPos + skip_length > fileSize)
continue;
590 bf.SetLimit(currentPos + skip_length);
591 bf.SkipTo(currentPos + skip_length);
592 currentPos += skip_length;
597 size_t find = currentPos + m_rng.randrange(8);
598 if (find >= fileSize)
600 bf.FindByte(std::byte(find));
605 bf.SetLimit(currentPos + 1);
613 size_t requestPos = m_rng.randrange(maxPos + 4);
614 bool okay = bf.SetPos(requestPos);
619 currentPos = bf.GetPos();
622 if (requestPos <= maxPos &&
623 maxPos > rewindSize &&
624 requestPos >= maxPos - rewindSize) {
631 if (maxPos < currentPos)
634 BOOST_REQUIRE_EQUAL(file.fclose(), 0);
636 fs::remove(streams_test_filename);
641 const size_t file_size{1 + m_rng.randrange<
size_t>(1 << 17)};
642 const size_t buf_size{1 + m_rng.randrange(file_size)};
650 AutoFile f{test_file.Open(pos,
false), obfuscation};
651 f.
write(m_rng.randbytes<std::byte>(file_size));
652 BOOST_REQUIRE_EQUAL(f.fclose(), 0);
657 AutoFile direct_file{test_file.Open(pos,
true), obfuscation};
659 AutoFile buffered_file{test_file.Open(pos,
true), obfuscation};
660 BufferedReader buffered_reader{std::move(buffered_file), buf_size};
662 for (
size_t total_read{0}; total_read < file_size;) {
663 const size_t read{
Assert(std::min(1 + m_rng.randrange(m_rng.randbool() ? buf_size : 2 * buf_size), file_size - total_read))};
666 direct_file.read(direct_file_buffer);
669 buffered_reader.read(buffered_buffer);
671 BOOST_CHECK_EQUAL_COLLECTIONS(
672 direct_file_buffer.begin(), direct_file_buffer.end(),
673 buffered_buffer.begin(), buffered_buffer.end()
690 fs::remove(test_file.FileName(pos));
695 const size_t file_size{1 + m_rng.randrange<
size_t>(1 << 17)};
696 const size_t buf_size{1 + m_rng.randrange(file_size)};
704 DataBuffer test_data{m_rng.randbytes<std::byte>(file_size)};
706 AutoFile direct_file{test_direct.Open(pos,
false), obfuscation};
708 AutoFile buffered_file{test_buffered.Open(pos,
false), obfuscation};
712 for (
size_t total_written{0}; total_written < file_size;) {
713 const size_t write_size{
Assert(std::min(1 + m_rng.randrange(m_rng.randbool() ? buf_size : 2 * buf_size), file_size - total_written))};
715 auto current_span = std::span{test_data}.subspan(total_written, write_size);
716 direct_file.write(current_span);
717 buffered.write(current_span);
719 total_written += write_size;
722 BOOST_REQUIRE_EQUAL(buffered_file.fclose(), 0);
723 BOOST_REQUIRE_EQUAL(direct_file.fclose(), 0);
729 AutoFile verify_direct{test_direct.Open(pos,
true), obfuscation};
730 verify_direct.
read(direct_result);
738 AutoFile verify_buffered{test_buffered.Open(pos,
true), obfuscation};
739 verify_buffered.
read(buffered_result);
745 BOOST_CHECK_EQUAL_COLLECTIONS(
746 direct_result.begin(), direct_result.end(),
747 buffered_result.begin(), buffered_result.end()
750 fs::remove(test_direct.FileName(pos));
751 fs::remove(test_buffered.FileName(pos));
756 const uint32_t v1{m_rng.rand32()}, v2{m_rng.rand32()}, v3{m_rng.rand32()};
757 const fs::path test_file{m_args.GetDataDirBase() /
"test_buffered_write_read.bin"};
764 f.
write(std::as_bytes(std::span{&v3, 1}));
766 BOOST_REQUIRE_EQUAL(file.fclose(), 0);
770 uint32_t _v1{0}, _v2{0}, _v3{0};
772 BufferedReader f(std::move(file),
sizeof(v1) +
sizeof(v2) +
sizeof(v3));
774 f.
read(std::as_writable_bytes(std::span{&_v3, 1}));
783 fs::remove(test_file);
790 const std::string
data{
"bitcoin"};
795 hash_verifier >> result;
802 const fs::path path = m_args.GetDataDirBase() /
"size_pos_test.bin";
804 for (uint8_t j = 0; j < 10; ++j) {
833 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.