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);
73 std::vector<std::byte> key_out;
75 ds_out << obfuscation;
87 const Obfuscation non_null_obf{
"ff00ff00ff00ff00"_hex};
96 stream << uint8_t{42};
97 BOOST_CHECK_GT(stream.
size(), 0U);
103 stream << uint16_t{42};
104 BOOST_CHECK_GT(stream.
size(), 0U);
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)
561 for (uint8_t i = 0; i < 1; ++i) {
569 if (currentPos + 2 > fileSize)
573 for (uint8_t i = 0; i < 2; ++i) {
581 if (currentPos + 5 > fileSize)
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)
619 size_t requestPos = m_rng.randrange(maxPos + 4);
620 bool okay = bf.
SetPos(requestPos);
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)};
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);
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);
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 seek(int64_t offset, int origin)
Wrapper around fseek().
int64_t size()
Return the size of the file.
void write(std::span< const std::byte > src)
void read(std::span< std::byte > dst)
void Write(uint64_t data, int nbits)
Write the nbits least significant bits of a 64-bit int to the output stream.
void Flush()
Flush any unwritten bits to the output stream, padding with 0's to the next byte boundary.
Wrapper around an AutoFile& that implements a ring buffer to deserialize from.
bool eof() const
check whether we're at the end of the source file
bool SetLimit(uint64_t nPos=std::numeric_limits< uint64_t >::max())
uint64_t GetPos() const
return the current reading position
void SkipTo(const uint64_t file_pos)
void FindByte(std::byte byte)
search for a given byte in the stream, and remain positioned on it
bool SetPos(uint64_t nPos)
rewind to a given reading 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.
FILE * Open(const FlatFilePos &pos, bool read_only=false) const
Open a handle to the file at the given position.
fs::path FileName(const FlatFilePos &pos) const
Get the name of the file at the given position.
BOOST_CHECK_EXCEPTION predicates to check the specific validation error.
Reads data from an underlying stream, while hashing the read data.
uint256 GetHash()
Compute the double-SHA256 hash of all data written to this object.
Writes data to an underlying source stream, while hashing the written data.
std::string HexKey() const
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.
SpanWriter(std::span< std::byte > dest)
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_EXCEPTION(req.LoadBody(reader), std::runtime_error, HasReason{"Cannot parse Content-Length value"})
LineReader reader("GET / HTTP/1.0\r\nHost: ", MAX_HEADERS_SIZE)
BOOST_AUTO_TEST_CASE(ipc_tests)
FILE * fopen(const fs::path &p, const char *mode)
constexpr unsigned int BLOCKFILE_CHUNK_SIZE
The pre-allocation chunk size for blk?
""_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_EQUAL(v1, v2)
#define BOOST_CHECK(expr)
std::vector< std::byte > DataBuffer
@ ZEROS
Seed with a compile time constant of zeros.
BOOST_CHECK_EQUAL_COLLECTIONS(R1L.begin(), R1L.end(), R1Array, R1Array+uint256::size())