PIVX Core  5.6.99
P2P Digital Currency
dbwrapper_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2012-2013 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 "dbwrapper.h"
7 #include "uint256.h"
8 #include "random.h"
9 #include "test/test_pivx.h"
10 
11 #include <boost/test/unit_test.hpp>
12 
13 // Test if a string consists entirely of null characters
14 bool is_null_key(const std::vector<unsigned char>& key) {
15  bool isnull = true;
16 
17  for (unsigned int i = 0; i < key.size(); i++)
18  isnull &= (key[i] == '\x00');
19 
20  return isnull;
21 }
22 
24 
26 {
27  {
28  fs::path ph = SetDataDir(std::string("dbwrapper"));
29  CDBWrapper dbw(ph, (1 << 20), true, false);
30  char key = 'k';
31  uint256 in = GetRandHash();
32  uint256 res;
33 
34  BOOST_CHECK(dbw.Write(key, in));
35  BOOST_CHECK(dbw.Read(key, res));
36  BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
37  }
38 }
39 
40 BOOST_AUTO_TEST_CASE(dbwrapper_basic_data)
41 {
42  fs::path ph = SetDataDir(std::string("dbwrapper_basic_data"));
43  CDBWrapper dbw(ph, (1 << 20), false, true);
44 
45  uint256 res;
46  uint32_t res_uint_32;
47  bool res_bool;
48 
49  //Simulate block raw data - "b + block hash"
50  std::string key_block = "b" + InsecureRand256().ToString();
51 
52  uint256 in_block = InsecureRand256();
53  BOOST_CHECK(dbw.Write(key_block, in_block));
54  BOOST_CHECK(dbw.Read(key_block, res));
55  BOOST_CHECK_EQUAL(res.ToString(), in_block.ToString());
56 
57  //Simulate file raw data - "f + file_number"
58  std::string key_file = strprintf("f%04x", InsecureRand32());
59 
60  uint256 in_file_info = InsecureRand256();
61  BOOST_CHECK(dbw.Write(key_file, in_file_info));
62  BOOST_CHECK(dbw.Read(key_file, res));
63  BOOST_CHECK_EQUAL(res.ToString(), in_file_info.ToString());
64 
65  //Simulate transaction raw data - "t + transaction hash"
66  std::string key_transaction = "t" + InsecureRand256().ToString();
67 
68  uint256 in_transaction = InsecureRand256();
69  BOOST_CHECK(dbw.Write(key_transaction, in_transaction));
70  BOOST_CHECK(dbw.Read(key_transaction, res));
71  BOOST_CHECK_EQUAL(res.ToString(), in_transaction.ToString());
72 
73  //Simulate UTXO raw data - "c + transaction hash"
74  std::string key_utxo = "c" + InsecureRand256().ToString();
75 
76  uint256 in_utxo = InsecureRand256();
77  BOOST_CHECK(dbw.Write(key_utxo, in_utxo));
78  BOOST_CHECK(dbw.Read(key_utxo, res));
79  BOOST_CHECK_EQUAL(res.ToString(), in_utxo.ToString());
80 
81  //Simulate last block file number - "l"
82  char key_last_blockfile_number = 'l';
83  uint32_t lastblockfilenumber = InsecureRand32();
84  BOOST_CHECK(dbw.Write(key_last_blockfile_number, lastblockfilenumber));
85  BOOST_CHECK(dbw.Read(key_last_blockfile_number, res_uint_32));
86  BOOST_CHECK_EQUAL(lastblockfilenumber, res_uint_32);
87 
88  //Simulate Is Reindexing - "R"
89  char key_IsReindexing = 'R';
90  bool isInReindexing = InsecureRandBool();
91  BOOST_CHECK(dbw.Write(key_IsReindexing, isInReindexing));
92  BOOST_CHECK(dbw.Read(key_IsReindexing, res_bool));
93  BOOST_CHECK_EQUAL(isInReindexing, res_bool);
94 
95  //Simulate last block hash up to which UXTO covers - 'B'
96  char key_lastblockhash_uxto = 'B';
97  uint256 lastblock_hash = InsecureRand256();
98  BOOST_CHECK(dbw.Write(key_lastblockhash_uxto, lastblock_hash));
99  BOOST_CHECK(dbw.Read(key_lastblockhash_uxto, res));
100  BOOST_CHECK_EQUAL(lastblock_hash, res);
101 
102  //Simulate file raw data - "F + filename_number + filename"
103  std::string file_option_tag = "F";
104  uint8_t filename_length = InsecureRandBits(8);
105  std::string filename = "randomfilename";
106  std::string key_file_option = strprintf("%s%01x%s", file_option_tag,filename_length,filename);
107 
108  bool in_file_bool = InsecureRandBool();
109  BOOST_CHECK(dbw.Write(key_file_option, in_file_bool));
110  BOOST_CHECK(dbw.Read(key_file_option, res_bool));
111  BOOST_CHECK_EQUAL(res_bool, in_file_bool);
112 }
113 
114 // Test batch operations
115 BOOST_AUTO_TEST_CASE(dbwrapper_batch)
116 {
117  {
118  fs::path ph = SetDataDir(std::string("dbwrapper_batch"));
119  CDBWrapper dbw(ph, (1 << 20), true, false);
120 
121  char key = 'i';
122  uint256 in = GetRandHash();
123  char key2 = 'j';
124  uint256 in2 = GetRandHash();
125  char key3 = 'k';
126  uint256 in3 = GetRandHash();
127 
128  uint256 res;
129  CDBBatch batch(CLIENT_VERSION);
130 
131  batch.Write(key, in);
132  batch.Write(key2, in2);
133  batch.Write(key3, in3);
134 
135  // Remove key3 before it's even been written
136  batch.Erase(key3);
137 
138  dbw.WriteBatch(batch);
139 
140  BOOST_CHECK(dbw.Read(key, res));
141  BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
142  BOOST_CHECK(dbw.Read(key2, res));
143  BOOST_CHECK_EQUAL(res.ToString(), in2.ToString());
144 
145  // key3 never should've been written
146  BOOST_CHECK(dbw.Read(key3, res) == false);
147  }
148 }
149 
150 BOOST_AUTO_TEST_CASE(dbwrapper_iterator)
151 {
152  {
153  fs::path ph = SetDataDir(std::string("dbwrapper_iterator"));
154  CDBWrapper dbw(ph, (1 << 20), true, false);
155 
156  // The two keys are intentionally chosen for ordering
157  char key = 'j';
158  uint256 in = GetRandHash();
159  BOOST_CHECK(dbw.Write(key, in));
160  char key2 = 'k';
161  uint256 in2 = GetRandHash();
162  BOOST_CHECK(dbw.Write(key2, in2));
163 
164  std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper&>(dbw).NewIterator());
165 
166  // Be sure to seek past any earlier key (if it exists)
167  it->Seek(key);
168 
169  char key_res;
170  uint256 val_res;
171 
172  it->GetKey(key_res);
173  it->GetValue(val_res);
174  BOOST_CHECK_EQUAL(key_res, key);
175  BOOST_CHECK_EQUAL(val_res.ToString(), in.ToString());
176 
177  it->Next();
178 
179  it->GetKey(key_res);
180  it->GetValue(val_res);
181  BOOST_CHECK_EQUAL(key_res, key2);
182  BOOST_CHECK_EQUAL(val_res.ToString(), in2.ToString());
183 
184  it->Next();
185  BOOST_CHECK_EQUAL(it->Valid(), false);
186  }
187 }
188 
189 BOOST_AUTO_TEST_CASE(iterator_ordering)
190 {
191  fs::path ph = SetDataDir(std::string("iterator_ordering"));
192  CDBWrapper dbw(ph, (1 << 20), true, false);
193  for (int x=0x00; x<256; ++x) {
194  uint8_t key = x;
195  uint32_t value = x*x;
196  if (!(x & 1)) BOOST_CHECK(dbw.Write(key, value));
197  }
198 
199  // Check that creating an iterator creates a snapshot
200  std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper&>(dbw).NewIterator());
201 
202  for (int x=0x00; x<256; ++x) {
203  uint8_t key = x;
204  uint32_t value = x*x;
205  if (x & 1) BOOST_CHECK(dbw.Write(key, value));
206  }
207 
208  for (int seek_start : {0x00, 0x80}) {
209  it->Seek((uint8_t)seek_start);
210  for (int x=seek_start; x<255; ++x) {
211  uint8_t key;
212  uint32_t value;
213  BOOST_CHECK(it->Valid());
214  if (!it->Valid()) // Avoid spurious errors about invalid iterator's key and value in case of failure
215  break;
216  BOOST_CHECK(it->GetKey(key));
217  if (x & 1) {
218  BOOST_CHECK_EQUAL(key, x + 1);
219  continue;
220  }
221  BOOST_CHECK(it->GetValue(value));
222  BOOST_CHECK_EQUAL(key, x);
223  BOOST_CHECK_EQUAL(value, x*x);
224  it->Next();
225  }
226  BOOST_CHECK(!it->Valid());
227  }
228 }
229 
231  // Used to make two serialized objects the same while letting them have a different lengths
232  // This is a terrible idea
233  std::string str;
235  explicit StringContentsSerializer(const std::string& inp) : str(inp) {}
236 
237  StringContentsSerializer& operator+=(const std::string& s) {
238  str += s;
239  return *this;
240  }
242 
243  template<typename Stream>
244  void Serialize(Stream& s) const
245  {
246  for (size_t i = 0; i < str.size(); i++) {
247  s << str[i];
248  }
249  }
250 
251  template<typename Stream>
252  void Unserialize(Stream& s)
253  {
254  str.clear();
255  char c = 0;
256  while (true) {
257  try {
258  s >> c;
259  str.push_back(c);
260  } catch (const std::ios_base::failure&) {
261  break;
262  }
263  }
264  }
265 };
266 
267 BOOST_AUTO_TEST_CASE(iterator_string_ordering)
268 {
269  char buf[10];
270 
271  fs::path ph = SetDataDir(std::string("iterator_string_ordering"));
272  CDBWrapper dbw(ph, (1 << 20), true, false);
273  for (int x=0x00; x<10; ++x) {
274  for (int y = 0; y < 10; y++) {
275  snprintf(buf, sizeof(buf), "%d", x);
276  StringContentsSerializer key(buf);
277  for (int z = 0; z < y; z++)
278  key += key;
279  uint32_t value = x*x;
280  BOOST_CHECK(dbw.Write(key, value));
281  }
282  }
283 
284  boost::scoped_ptr<CDBIterator> it(const_cast<CDBWrapper*>(&dbw)->NewIterator());
285  for (int c=0; c<2; ++c) {
286  int seek_start;
287  if (c == 0)
288  seek_start = 0;
289  else
290  seek_start = 5;
291  snprintf(buf, sizeof(buf), "%d", seek_start);
292  StringContentsSerializer seek_key(buf);
293  it->Seek(seek_key);
294  for (int x=seek_start; x<10; ++x) {
295  for (int y = 0; y < 10; y++) {
296  snprintf(buf, sizeof(buf), "%d", x);
297  std::string exp_key(buf);
298  for (int z = 0; z < y; z++)
299  exp_key += exp_key;
301  uint32_t value;
302  BOOST_CHECK(it->Valid());
303  if (!it->Valid()) // Avoid spurious errors about invalid iterator's key and value in case of failure
304  break;
305  BOOST_CHECK(it->GetKey(key));
306  BOOST_CHECK(it->GetValue(value));
307  BOOST_CHECK_EQUAL(key.str, exp_key);
308  BOOST_CHECK_EQUAL(value, x*x);
309  it->Next();
310  }
311  }
312  BOOST_CHECK(!it->Valid());
313  }
314 }
315 
316 
317 
Batch of changes queued to be written to a CDBWrapper.
Definition: dbwrapper.h:46
void Erase(const K &key)
Definition: dbwrapper.h:100
void Write(const K &key, const V &value)
Definition: dbwrapper.h:69
bool WriteBatch(CDBBatch &batch, bool fSync=false)
Definition: dbwrapper.cpp:94
bool Read(const K &key, V &value) const
Definition: dbwrapper.h:260
bool Write(const K &key, const V &value, bool fSync=false)
Definition: dbwrapper.h:284
std::string ToString() const
Definition: uint256.cpp:65
256-bit opaque blob.
Definition: uint256.h:138
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(dbwrapper)
bool is_null_key(const std::vector< unsigned char > &key)
#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
uint256 GetRandHash() noexcept
Definition: random.cpp:596
Basic testing setup.
Definition: test_pivx.h:51
StringContentsSerializer & operator+=(const std::string &s)
StringContentsSerializer & operator+=(const StringContentsSerializer &s)
void Serialize(Stream &s) const
StringContentsSerializer(const std::string &inp)
#define strprintf
Definition: tinyformat.h:1056