LCOV - code coverage report
Current view: top level - src/test - dbwrapper_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 194 199 97.5 %
Date: 2025-02-23 09:33:43 Functions: 14 15 93.3 %

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

Generated by: LCOV version 1.14