Remove redundant semicolons
[bitcoinplatinum.git] / src / test / dbwrapper_tests.cpp
blobe5cb48ffcf48d59c95df2a8537d73c7a9d10a255
1 // Copyright (c) 2012-2016 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.
5 #include "dbwrapper.h"
6 #include "uint256.h"
7 #include "random.h"
8 #include "test/test_bitcoin.h"
10 #include <boost/assign/std/vector.hpp> // for 'operator+=()'
11 #include <boost/assert.hpp>
12 #include <boost/test/unit_test.hpp>
14 // Test if a string consists entirely of null characters
15 bool is_null_key(const std::vector<unsigned char>& key) {
16 bool isnull = true;
18 for (unsigned int i = 0; i < key.size(); i++)
19 isnull &= (key[i] == '\x00');
21 return isnull;
24 BOOST_FIXTURE_TEST_SUITE(dbwrapper_tests, BasicTestingSetup)
26 BOOST_AUTO_TEST_CASE(dbwrapper)
28 // Perform tests both obfuscated and non-obfuscated.
29 for (int i = 0; i < 2; i++) {
30 bool obfuscate = (bool)i;
31 boost::filesystem::path ph = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
32 CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
33 char key = 'k';
34 uint256 in = GetRandHash();
35 uint256 res;
37 // Ensure that we're doing real obfuscation when obfuscate=true
38 BOOST_CHECK(obfuscate != is_null_key(dbwrapper_private::GetObfuscateKey(dbw)));
40 BOOST_CHECK(dbw.Write(key, in));
41 BOOST_CHECK(dbw.Read(key, res));
42 BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
46 // Test batch operations
47 BOOST_AUTO_TEST_CASE(dbwrapper_batch)
49 // Perform tests both obfuscated and non-obfuscated.
50 for (int i = 0; i < 2; i++) {
51 bool obfuscate = (bool)i;
52 boost::filesystem::path ph = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
53 CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
55 char key = 'i';
56 uint256 in = GetRandHash();
57 char key2 = 'j';
58 uint256 in2 = GetRandHash();
59 char key3 = 'k';
60 uint256 in3 = GetRandHash();
62 uint256 res;
63 CDBBatch batch(dbw);
65 batch.Write(key, in);
66 batch.Write(key2, in2);
67 batch.Write(key3, in3);
69 // Remove key3 before it's even been written
70 batch.Erase(key3);
72 dbw.WriteBatch(batch);
74 BOOST_CHECK(dbw.Read(key, res));
75 BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
76 BOOST_CHECK(dbw.Read(key2, res));
77 BOOST_CHECK_EQUAL(res.ToString(), in2.ToString());
79 // key3 never should've been written
80 BOOST_CHECK(dbw.Read(key3, res) == false);
84 BOOST_AUTO_TEST_CASE(dbwrapper_iterator)
86 // Perform tests both obfuscated and non-obfuscated.
87 for (int i = 0; i < 2; i++) {
88 bool obfuscate = (bool)i;
89 boost::filesystem::path ph = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
90 CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
92 // The two keys are intentionally chosen for ordering
93 char key = 'j';
94 uint256 in = GetRandHash();
95 BOOST_CHECK(dbw.Write(key, in));
96 char key2 = 'k';
97 uint256 in2 = GetRandHash();
98 BOOST_CHECK(dbw.Write(key2, in2));
100 std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper*>(&dbw)->NewIterator());
102 // Be sure to seek past the obfuscation key (if it exists)
103 it->Seek(key);
105 char key_res;
106 uint256 val_res;
108 it->GetKey(key_res);
109 it->GetValue(val_res);
110 BOOST_CHECK_EQUAL(key_res, key);
111 BOOST_CHECK_EQUAL(val_res.ToString(), in.ToString());
113 it->Next();
115 it->GetKey(key_res);
116 it->GetValue(val_res);
117 BOOST_CHECK_EQUAL(key_res, key2);
118 BOOST_CHECK_EQUAL(val_res.ToString(), in2.ToString());
120 it->Next();
121 BOOST_CHECK_EQUAL(it->Valid(), false);
125 // Test that we do not obfuscation if there is existing data.
126 BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate)
128 // We're going to share this boost::filesystem::path between two wrappers
129 boost::filesystem::path ph = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
130 create_directories(ph);
132 // Set up a non-obfuscated wrapper to write some initial data.
133 CDBWrapper* dbw = new CDBWrapper(ph, (1 << 10), false, false, false);
134 char key = 'k';
135 uint256 in = GetRandHash();
136 uint256 res;
138 BOOST_CHECK(dbw->Write(key, in));
139 BOOST_CHECK(dbw->Read(key, res));
140 BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
142 // Call the destructor to free leveldb LOCK
143 delete dbw;
145 // Now, set up another wrapper that wants to obfuscate the same directory
146 CDBWrapper odbw(ph, (1 << 10), false, false, true);
148 // Check that the key/val we wrote with unobfuscated wrapper exists and
149 // is readable.
150 uint256 res2;
151 BOOST_CHECK(odbw.Read(key, res2));
152 BOOST_CHECK_EQUAL(res2.ToString(), in.ToString());
154 BOOST_CHECK(!odbw.IsEmpty()); // There should be existing data
155 BOOST_CHECK(is_null_key(dbwrapper_private::GetObfuscateKey(odbw))); // The key should be an empty string
157 uint256 in2 = GetRandHash();
158 uint256 res3;
160 // Check that we can write successfully
161 BOOST_CHECK(odbw.Write(key, in2));
162 BOOST_CHECK(odbw.Read(key, res3));
163 BOOST_CHECK_EQUAL(res3.ToString(), in2.ToString());
166 // Ensure that we start obfuscating during a reindex.
167 BOOST_AUTO_TEST_CASE(existing_data_reindex)
169 // We're going to share this boost::filesystem::path between two wrappers
170 boost::filesystem::path ph = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
171 create_directories(ph);
173 // Set up a non-obfuscated wrapper to write some initial data.
174 CDBWrapper* dbw = new CDBWrapper(ph, (1 << 10), false, false, false);
175 char key = 'k';
176 uint256 in = GetRandHash();
177 uint256 res;
179 BOOST_CHECK(dbw->Write(key, in));
180 BOOST_CHECK(dbw->Read(key, res));
181 BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
183 // Call the destructor to free leveldb LOCK
184 delete dbw;
186 // Simulate a -reindex by wiping the existing data store
187 CDBWrapper odbw(ph, (1 << 10), false, true, true);
189 // Check that the key/val we wrote with unobfuscated wrapper doesn't exist
190 uint256 res2;
191 BOOST_CHECK(!odbw.Read(key, res2));
192 BOOST_CHECK(!is_null_key(dbwrapper_private::GetObfuscateKey(odbw)));
194 uint256 in2 = GetRandHash();
195 uint256 res3;
197 // Check that we can write successfully
198 BOOST_CHECK(odbw.Write(key, in2));
199 BOOST_CHECK(odbw.Read(key, res3));
200 BOOST_CHECK_EQUAL(res3.ToString(), in2.ToString());
203 BOOST_AUTO_TEST_CASE(iterator_ordering)
205 boost::filesystem::path ph = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
206 CDBWrapper dbw(ph, (1 << 20), true, false, false);
207 for (int x=0x00; x<256; ++x) {
208 uint8_t key = x;
209 uint32_t value = x*x;
210 BOOST_CHECK(dbw.Write(key, value));
213 std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper*>(&dbw)->NewIterator());
214 for (int c=0; c<2; ++c) {
215 int seek_start;
216 if (c == 0)
217 seek_start = 0x00;
218 else
219 seek_start = 0x80;
220 it->Seek((uint8_t)seek_start);
221 for (int x=seek_start; x<256; ++x) {
222 uint8_t key;
223 uint32_t value;
224 BOOST_CHECK(it->Valid());
225 if (!it->Valid()) // Avoid spurious errors about invalid iterator's key and value in case of failure
226 break;
227 BOOST_CHECK(it->GetKey(key));
228 BOOST_CHECK(it->GetValue(value));
229 BOOST_CHECK_EQUAL(key, x);
230 BOOST_CHECK_EQUAL(value, x*x);
231 it->Next();
233 BOOST_CHECK(!it->Valid());
237 struct StringContentsSerializer {
238 // Used to make two serialized objects the same while letting them have a different lengths
239 // This is a terrible idea
240 std::string str;
241 StringContentsSerializer() {}
242 StringContentsSerializer(const std::string& inp) : str(inp) {}
244 StringContentsSerializer& operator+=(const std::string& s) {
245 str += s;
246 return *this;
248 StringContentsSerializer& operator+=(const StringContentsSerializer& s) { return *this += s.str; }
250 ADD_SERIALIZE_METHODS;
252 template <typename Stream, typename Operation>
253 inline void SerializationOp(Stream& s, Operation ser_action) {
254 if (ser_action.ForRead()) {
255 str.clear();
256 char c = 0;
257 while (true) {
258 try {
259 READWRITE(c);
260 str.push_back(c);
261 } catch (const std::ios_base::failure& e) {
262 break;
265 } else {
266 for (size_t i = 0; i < str.size(); i++)
267 READWRITE(str[i]);
272 BOOST_AUTO_TEST_CASE(iterator_string_ordering)
274 char buf[10];
276 boost::filesystem::path ph = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
277 CDBWrapper dbw(ph, (1 << 20), true, false, false);
278 for (int x=0x00; x<10; ++x) {
279 for (int y = 0; y < 10; y++) {
280 sprintf(buf, "%d", x);
281 StringContentsSerializer key(buf);
282 for (int z = 0; z < y; z++)
283 key += key;
284 uint32_t value = x*x;
285 BOOST_CHECK(dbw.Write(key, value));
289 std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper*>(&dbw)->NewIterator());
290 for (int c=0; c<2; ++c) {
291 int seek_start;
292 if (c == 0)
293 seek_start = 0;
294 else
295 seek_start = 5;
296 sprintf(buf, "%d", seek_start);
297 StringContentsSerializer seek_key(buf);
298 it->Seek(seek_key);
299 for (int x=seek_start; x<10; ++x) {
300 for (int y = 0; y < 10; y++) {
301 sprintf(buf, "%d", x);
302 std::string exp_key(buf);
303 for (int z = 0; z < y; z++)
304 exp_key += exp_key;
305 StringContentsSerializer key;
306 uint32_t value;
307 BOOST_CHECK(it->Valid());
308 if (!it->Valid()) // Avoid spurious errors about invalid iterator's key and value in case of failure
309 break;
310 BOOST_CHECK(it->GetKey(key));
311 BOOST_CHECK(it->GetValue(value));
312 BOOST_CHECK_EQUAL(key.str, exp_key);
313 BOOST_CHECK_EQUAL(value, x*x);
314 it->Next();
317 BOOST_CHECK(!it->Valid());
323 BOOST_AUTO_TEST_SUITE_END()