Bitcoin Core 22.99.0
P2P Digital Currency
flatfile_tests.cpp
Go to the documentation of this file.
1// Copyright (c) 2019-2020 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <clientversion.h>
6#include <flatfile.h>
7#include <streams.h>
9#include <util/system.h>
10
11#include <boost/test/unit_test.hpp>
12
14
15BOOST_AUTO_TEST_CASE(flatfile_filename)
16{
17 const auto data_dir = m_args.GetDataDirBase();
18
19 FlatFilePos pos(456, 789);
20
21 FlatFileSeq seq1(data_dir, "a", 16 * 1024);
22 BOOST_CHECK_EQUAL(seq1.FileName(pos), data_dir / "a00456.dat");
23
24 FlatFileSeq seq2(data_dir / "a", "b", 16 * 1024);
25 BOOST_CHECK_EQUAL(seq2.FileName(pos), data_dir / "a" / "b00456.dat");
26}
27
29{
30 const auto data_dir = m_args.GetDataDirBase();
31 FlatFileSeq seq(data_dir, "a", 16 * 1024);
32
33 std::string line1("A purely peer-to-peer version of electronic cash would allow online "
34 "payments to be sent directly from one party to another without going "
35 "through a financial institution.");
36 std::string line2("Digital signatures provide part of the solution, but the main benefits are "
37 "lost if a trusted third party is still required to prevent double-spending.");
38
39 size_t pos1 = 0;
40 size_t pos2 = pos1 + GetSerializeSize(line1, CLIENT_VERSION);
41
42 // Write first line to file.
43 {
44 CAutoFile file(seq.Open(FlatFilePos(0, pos1)), SER_DISK, CLIENT_VERSION);
45 file << LIMITED_STRING(line1, 256);
46 }
47
48 // Attempt to append to file opened in read-only mode.
49 {
50 CAutoFile file(seq.Open(FlatFilePos(0, pos2), true), SER_DISK, CLIENT_VERSION);
51 BOOST_CHECK_THROW(file << LIMITED_STRING(line2, 256), std::ios_base::failure);
52 }
53
54 // Append second line to file.
55 {
56 CAutoFile file(seq.Open(FlatFilePos(0, pos2)), SER_DISK, CLIENT_VERSION);
57 file << LIMITED_STRING(line2, 256);
58 }
59
60 // Read text from file in read-only mode.
61 {
62 std::string text;
63 CAutoFile file(seq.Open(FlatFilePos(0, pos1), true), SER_DISK, CLIENT_VERSION);
64
65 file >> LIMITED_STRING(text, 256);
66 BOOST_CHECK_EQUAL(text, line1);
67
68 file >> LIMITED_STRING(text, 256);
69 BOOST_CHECK_EQUAL(text, line2);
70 }
71
72 // Read text from file with position offset.
73 {
74 std::string text;
75 CAutoFile file(seq.Open(FlatFilePos(0, pos2)), SER_DISK, CLIENT_VERSION);
76
77 file >> LIMITED_STRING(text, 256);
78 BOOST_CHECK_EQUAL(text, line2);
79 }
80
81 // Ensure another file in the sequence has no data.
82 {
83 std::string text;
84 CAutoFile file(seq.Open(FlatFilePos(1, pos2)), SER_DISK, CLIENT_VERSION);
85 BOOST_CHECK_THROW(file >> LIMITED_STRING(text, 256), std::ios_base::failure);
86 }
87}
88
89BOOST_AUTO_TEST_CASE(flatfile_allocate)
90{
91 const auto data_dir = m_args.GetDataDirBase();
92 FlatFileSeq seq(data_dir, "a", 100);
93
94 bool out_of_space;
95
96 BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 0), 1, out_of_space), 100U);
97 BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 0))), 100U);
98 BOOST_CHECK(!out_of_space);
99
100 BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 99), 1, out_of_space), 0U);
101 BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 99))), 100U);
102 BOOST_CHECK(!out_of_space);
103
104 BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 99), 2, out_of_space), 101U);
105 BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 99))), 200U);
106 BOOST_CHECK(!out_of_space);
107}
108
109BOOST_AUTO_TEST_CASE(flatfile_flush)
110{
111 const auto data_dir = m_args.GetDataDirBase();
112 FlatFileSeq seq(data_dir, "a", 100);
113
114 bool out_of_space;
115 seq.Allocate(FlatFilePos(0, 0), 1, out_of_space);
116
117 // Flush without finalize should not truncate file.
118 seq.Flush(FlatFilePos(0, 1));
119 BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 1))), 100U);
120
121 // Flush with finalize should truncate file.
122 seq.Flush(FlatFilePos(0, 1), true);
123 BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 1))), 1U);
124}
125
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:565
FlatFileSeq represents a sequence of numbered files storing raw data.
Definition: flatfile.h:47
fs::path FileName(const FlatFilePos &pos) const
Get the name of the file at the given position.
Definition: flatfile.cpp:28
size_t Allocate(const FlatFilePos &pos, size_t add_size, bool &out_of_space)
Allocate additional space in a file after the given starting position.
Definition: flatfile.cpp:55
bool Flush(const FlatFilePos &pos, bool finalize=false)
Commit a file to disk, and optionally truncate off extra pre-allocated bytes if final.
Definition: flatfile.cpp:81
FILE * Open(const FlatFilePos &pos, bool read_only=false)
Open a handle to the file at the given position.
Definition: flatfile.cpp:33
static const int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:33
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(flatfile_filename)
#define BOOST_CHECK_THROW(stmt, excMatch)
Definition: object.cpp:19
#define BOOST_FIXTURE_TEST_SUITE(a, b)
Definition: object.cpp:14
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
#define BOOST_CHECK(expr)
Definition: object.cpp:17
@ SER_DISK
Definition: serialize.h:139
#define LIMITED_STRING(obj, n)
Definition: serialize.h:445
size_t GetSerializeSize(const T &t, int nVersion=0)
Definition: serialize.h:1080
Basic testing setup.
Definition: setup_common.h:76