Bitcoin Core  27.99.0
P2P Digital Currency
flatfile_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2019-2022 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 <common/args.h>
7 #include <flatfile.h>
8 #include <streams.h>
10 
11 #include <boost/test/unit_test.hpp>
12 
13 BOOST_FIXTURE_TEST_SUITE(flatfile_tests, BasicTestingSetup)
14 
15 BOOST_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  // Check default constructor IsNull
29 }
30 
31 BOOST_AUTO_TEST_CASE(flatfile_open)
32 {
33  const auto data_dir = m_args.GetDataDirBase();
34  FlatFileSeq seq(data_dir, "a", 16 * 1024);
35 
36  std::string line1("A purely peer-to-peer version of electronic cash would allow online "
37  "payments to be sent directly from one party to another without going "
38  "through a financial institution.");
39  std::string line2("Digital signatures provide part of the solution, but the main benefits are "
40  "lost if a trusted third party is still required to prevent double-spending.");
41 
42  size_t pos1 = 0;
43  size_t pos2 = pos1 + GetSerializeSize(line1);
44 
45  // Write first line to file.
46  {
47  AutoFile file{seq.Open(FlatFilePos(0, pos1))};
48  file << LIMITED_STRING(line1, 256);
49  }
50 
51  // Attempt to append to file opened in read-only mode.
52  {
53  AutoFile file{seq.Open(FlatFilePos(0, pos2), true)};
54  BOOST_CHECK_THROW(file << LIMITED_STRING(line2, 256), std::ios_base::failure);
55  }
56 
57  // Append second line to file.
58  {
59  AutoFile file{seq.Open(FlatFilePos(0, pos2))};
60  file << LIMITED_STRING(line2, 256);
61  }
62 
63  // Read text from file in read-only mode.
64  {
65  std::string text;
66  AutoFile file{seq.Open(FlatFilePos(0, pos1), true)};
67 
68  file >> LIMITED_STRING(text, 256);
69  BOOST_CHECK_EQUAL(text, line1);
70 
71  file >> LIMITED_STRING(text, 256);
72  BOOST_CHECK_EQUAL(text, line2);
73  }
74 
75  // Read text from file with position offset.
76  {
77  std::string text;
78  AutoFile file{seq.Open(FlatFilePos(0, pos2))};
79 
80  file >> LIMITED_STRING(text, 256);
81  BOOST_CHECK_EQUAL(text, line2);
82  }
83 
84  // Ensure another file in the sequence has no data.
85  {
86  std::string text;
87  AutoFile file{seq.Open(FlatFilePos(1, pos2))};
88  BOOST_CHECK_THROW(file >> LIMITED_STRING(text, 256), std::ios_base::failure);
89  }
90 }
91 
92 BOOST_AUTO_TEST_CASE(flatfile_allocate)
93 {
94  const auto data_dir = m_args.GetDataDirBase();
95  FlatFileSeq seq(data_dir, "a", 100);
96 
97  bool out_of_space;
98 
99  BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 0), 1, out_of_space), 100U);
100  BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 0))), 100U);
101  BOOST_CHECK(!out_of_space);
102 
103  BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 99), 1, out_of_space), 0U);
104  BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 99))), 100U);
105  BOOST_CHECK(!out_of_space);
106 
107  BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 99), 2, out_of_space), 101U);
108  BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 99))), 200U);
109  BOOST_CHECK(!out_of_space);
110 }
111 
112 BOOST_AUTO_TEST_CASE(flatfile_flush)
113 {
114  const auto data_dir = m_args.GetDataDirBase();
115  FlatFileSeq seq(data_dir, "a", 100);
116 
117  bool out_of_space;
118  seq.Allocate(FlatFilePos(0, 0), 1, out_of_space);
119 
120  // Flush without finalize should not truncate file.
121  seq.Flush(FlatFilePos(0, 1));
122  BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 1))), 100U);
123 
124  // Flush with finalize should truncate file.
125  seq.Flush(FlatFilePos(0, 1), true);
126  BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 1))), 1U);
127 }
128 
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:389
FlatFileSeq represents a sequence of numbered files storing raw data.
Definition: flatfile.h:46
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
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(flatfile_filename)
#define BOOST_CHECK_THROW(stmt, excMatch)
Definition: object.cpp:19
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
#define BOOST_CHECK(expr)
Definition: object.cpp:17
size_t GetSerializeSize(const T &t)
Definition: serialize.h:1101
#define LIMITED_STRING(obj, n)
Definition: serialize.h:500
Basic testing setup.
Definition: setup_common.h:60
bool IsNull() const
Definition: flatfile.h:36
assert(!tx.IsCoinBase())