LCOV - code coverage report
Current view: top level - src/test - dbwrapper_tests.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 0 250 0.0 %
Date: 2023-10-05 12:38:51 Functions: 0 55 0.0 %
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // Copyright (c) 2012-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 <dbwrapper.h>
       6                 :            : #include <test/util/random.h>
       7                 :            : #include <test/util/setup_common.h>
       8                 :            : #include <uint256.h>
       9                 :            : #include <util/string.h>
      10                 :            : 
      11                 :            : #include <memory>
      12                 :            : 
      13                 :            : #include <boost/test/unit_test.hpp>
      14                 :            : 
      15                 :            : // Test if a string consists entirely of null characters
      16                 :          0 : static bool is_null_key(const std::vector<unsigned char>& key) {
      17                 :          0 :     bool isnull = true;
      18                 :            : 
      19                 :          0 :     for (unsigned int i = 0; i < key.size(); i++)
      20                 :          0 :         isnull &= (key[i] == '\x00');
      21                 :            : 
      22                 :          0 :     return isnull;
      23                 :            : }
      24                 :            : 
      25                 :          0 : BOOST_FIXTURE_TEST_SUITE(dbwrapper_tests, BasicTestingSetup)
      26                 :            : 
      27                 :          0 : BOOST_AUTO_TEST_CASE(dbwrapper)
      28                 :            : {
      29                 :            :     // Perform tests both obfuscated and non-obfuscated.
      30                 :          0 :     for (const bool obfuscate : {false, true}) {
      31                 :          0 :         fs::path ph = m_args.GetDataDirBase() / (obfuscate ? "dbwrapper_obfuscate_true" : "dbwrapper_obfuscate_false");
      32                 :          0 :         CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = true, .wipe_data = false, .obfuscate = obfuscate});
      33                 :          0 :         uint8_t key{'k'};
      34                 :          0 :         uint256 in = InsecureRand256();
      35                 :          0 :         uint256 res;
      36                 :            : 
      37                 :            :         // Ensure that we're doing real obfuscation when obfuscate=true
      38                 :          0 :         BOOST_CHECK(obfuscate != is_null_key(dbwrapper_private::GetObfuscateKey(dbw)));
      39                 :            : 
      40                 :          0 :         BOOST_CHECK(dbw.Write(key, in));
      41                 :          0 :         BOOST_CHECK(dbw.Read(key, res));
      42                 :          0 :         BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
      43                 :          0 :     }
      44                 :          0 : }
      45                 :            : 
      46                 :          0 : BOOST_AUTO_TEST_CASE(dbwrapper_basic_data)
      47                 :            : {
      48                 :            :     // Perform tests both obfuscated and non-obfuscated.
      49                 :          0 :     for (bool obfuscate : {false, true}) {
      50                 :          0 :         fs::path ph = m_args.GetDataDirBase() / (obfuscate ? "dbwrapper_1_obfuscate_true" : "dbwrapper_1_obfuscate_false");
      51                 :          0 :         CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = false, .wipe_data = true, .obfuscate = obfuscate});
      52                 :            : 
      53                 :          0 :         uint256 res;
      54                 :            :         uint32_t res_uint_32;
      55                 :            :         bool res_bool;
      56                 :            : 
      57                 :            :         // Ensure that we're doing real obfuscation when obfuscate=true
      58                 :          0 :         BOOST_CHECK(obfuscate != is_null_key(dbwrapper_private::GetObfuscateKey(dbw)));
      59                 :            : 
      60                 :            :         //Simulate block raw data - "b + block hash"
      61                 :          0 :         std::string key_block = "b" + InsecureRand256().ToString();
      62                 :            : 
      63                 :          0 :         uint256 in_block = InsecureRand256();
      64                 :          0 :         BOOST_CHECK(dbw.Write(key_block, in_block));
      65                 :          0 :         BOOST_CHECK(dbw.Read(key_block, res));
      66                 :          0 :         BOOST_CHECK_EQUAL(res.ToString(), in_block.ToString());
      67                 :            : 
      68                 :            :         //Simulate file raw data - "f + file_number"
      69                 :          0 :         std::string key_file = strprintf("f%04x", InsecureRand32());
      70                 :            : 
      71                 :          0 :         uint256 in_file_info = InsecureRand256();
      72                 :          0 :         BOOST_CHECK(dbw.Write(key_file, in_file_info));
      73                 :          0 :         BOOST_CHECK(dbw.Read(key_file, res));
      74                 :          0 :         BOOST_CHECK_EQUAL(res.ToString(), in_file_info.ToString());
      75                 :            : 
      76                 :            :         //Simulate transaction raw data - "t + transaction hash"
      77                 :          0 :         std::string key_transaction = "t" + InsecureRand256().ToString();
      78                 :            : 
      79                 :          0 :         uint256 in_transaction = InsecureRand256();
      80                 :          0 :         BOOST_CHECK(dbw.Write(key_transaction, in_transaction));
      81                 :          0 :         BOOST_CHECK(dbw.Read(key_transaction, res));
      82                 :          0 :         BOOST_CHECK_EQUAL(res.ToString(), in_transaction.ToString());
      83                 :            : 
      84                 :            :         //Simulate UTXO raw data - "c + transaction hash"
      85                 :          0 :         std::string key_utxo = "c" + InsecureRand256().ToString();
      86                 :            : 
      87                 :          0 :         uint256 in_utxo = InsecureRand256();
      88                 :          0 :         BOOST_CHECK(dbw.Write(key_utxo, in_utxo));
      89                 :          0 :         BOOST_CHECK(dbw.Read(key_utxo, res));
      90                 :          0 :         BOOST_CHECK_EQUAL(res.ToString(), in_utxo.ToString());
      91                 :            : 
      92                 :            :         //Simulate last block file number - "l"
      93                 :          0 :         uint8_t key_last_blockfile_number{'l'};
      94                 :          0 :         uint32_t lastblockfilenumber = InsecureRand32();
      95                 :          0 :         BOOST_CHECK(dbw.Write(key_last_blockfile_number, lastblockfilenumber));
      96                 :          0 :         BOOST_CHECK(dbw.Read(key_last_blockfile_number, res_uint_32));
      97                 :          0 :         BOOST_CHECK_EQUAL(lastblockfilenumber, res_uint_32);
      98                 :            : 
      99                 :            :         //Simulate Is Reindexing - "R"
     100                 :          0 :         uint8_t key_IsReindexing{'R'};
     101                 :          0 :         bool isInReindexing = InsecureRandBool();
     102                 :          0 :         BOOST_CHECK(dbw.Write(key_IsReindexing, isInReindexing));
     103                 :          0 :         BOOST_CHECK(dbw.Read(key_IsReindexing, res_bool));
     104                 :          0 :         BOOST_CHECK_EQUAL(isInReindexing, res_bool);
     105                 :            : 
     106                 :            :         //Simulate last block hash up to which UXTO covers - 'B'
     107                 :          0 :         uint8_t key_lastblockhash_uxto{'B'};
     108                 :          0 :         uint256 lastblock_hash = InsecureRand256();
     109                 :          0 :         BOOST_CHECK(dbw.Write(key_lastblockhash_uxto, lastblock_hash));
     110                 :          0 :         BOOST_CHECK(dbw.Read(key_lastblockhash_uxto, res));
     111                 :          0 :         BOOST_CHECK_EQUAL(lastblock_hash, res);
     112                 :            : 
     113                 :            :         //Simulate file raw data - "F + filename_number + filename"
     114                 :          0 :         std::string file_option_tag = "F";
     115                 :          0 :         uint8_t filename_length = InsecureRandBits(8);
     116                 :          0 :         std::string filename = "randomfilename";
     117                 :          0 :         std::string key_file_option = strprintf("%s%01x%s", file_option_tag,filename_length,filename);
     118                 :            : 
     119                 :          0 :         bool in_file_bool = InsecureRandBool();
     120                 :          0 :         BOOST_CHECK(dbw.Write(key_file_option, in_file_bool));
     121                 :          0 :         BOOST_CHECK(dbw.Read(key_file_option, res_bool));
     122                 :          0 :         BOOST_CHECK_EQUAL(res_bool, in_file_bool);
     123                 :          0 :    }
     124                 :          0 : }
     125                 :            : 
     126                 :            : // Test batch operations
     127                 :          0 : BOOST_AUTO_TEST_CASE(dbwrapper_batch)
     128                 :            : {
     129                 :            :     // Perform tests both obfuscated and non-obfuscated.
     130                 :          0 :     for (const bool obfuscate : {false, true}) {
     131                 :          0 :         fs::path ph = m_args.GetDataDirBase() / (obfuscate ? "dbwrapper_batch_obfuscate_true" : "dbwrapper_batch_obfuscate_false");
     132                 :          0 :         CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = true, .wipe_data = false, .obfuscate = obfuscate});
     133                 :            : 
     134                 :          0 :         uint8_t key{'i'};
     135                 :          0 :         uint256 in = InsecureRand256();
     136                 :          0 :         uint8_t key2{'j'};
     137                 :          0 :         uint256 in2 = InsecureRand256();
     138                 :          0 :         uint8_t key3{'k'};
     139                 :          0 :         uint256 in3 = InsecureRand256();
     140                 :            : 
     141                 :          0 :         uint256 res;
     142                 :          0 :         CDBBatch batch(dbw);
     143                 :            : 
     144                 :          0 :         batch.Write(key, in);
     145                 :          0 :         batch.Write(key2, in2);
     146                 :          0 :         batch.Write(key3, in3);
     147                 :            : 
     148                 :            :         // Remove key3 before it's even been written
     149                 :          0 :         batch.Erase(key3);
     150                 :            : 
     151                 :          0 :         BOOST_CHECK(dbw.WriteBatch(batch));
     152                 :            : 
     153                 :          0 :         BOOST_CHECK(dbw.Read(key, res));
     154                 :          0 :         BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
     155                 :          0 :         BOOST_CHECK(dbw.Read(key2, res));
     156                 :          0 :         BOOST_CHECK_EQUAL(res.ToString(), in2.ToString());
     157                 :            : 
     158                 :            :         // key3 should've never been written
     159                 :          0 :         BOOST_CHECK(dbw.Read(key3, res) == false);
     160                 :          0 :     }
     161                 :          0 : }
     162                 :            : 
     163                 :          0 : BOOST_AUTO_TEST_CASE(dbwrapper_iterator)
     164                 :            : {
     165                 :            :     // Perform tests both obfuscated and non-obfuscated.
     166                 :          0 :     for (const bool obfuscate : {false, true}) {
     167                 :          0 :         fs::path ph = m_args.GetDataDirBase() / (obfuscate ? "dbwrapper_iterator_obfuscate_true" : "dbwrapper_iterator_obfuscate_false");
     168                 :          0 :         CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = true, .wipe_data = false, .obfuscate = obfuscate});
     169                 :            : 
     170                 :            :         // The two keys are intentionally chosen for ordering
     171                 :          0 :         uint8_t key{'j'};
     172                 :          0 :         uint256 in = InsecureRand256();
     173                 :          0 :         BOOST_CHECK(dbw.Write(key, in));
     174                 :          0 :         uint8_t key2{'k'};
     175                 :          0 :         uint256 in2 = InsecureRand256();
     176                 :          0 :         BOOST_CHECK(dbw.Write(key2, in2));
     177                 :            : 
     178                 :          0 :         std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper&>(dbw).NewIterator());
     179                 :            : 
     180                 :            :         // Be sure to seek past the obfuscation key (if it exists)
     181                 :          0 :         it->Seek(key);
     182                 :            : 
     183                 :            :         uint8_t key_res;
     184                 :          0 :         uint256 val_res;
     185                 :            : 
     186                 :          0 :         BOOST_REQUIRE(it->GetKey(key_res));
     187                 :          0 :         BOOST_REQUIRE(it->GetValue(val_res));
     188                 :          0 :         BOOST_CHECK_EQUAL(key_res, key);
     189                 :          0 :         BOOST_CHECK_EQUAL(val_res.ToString(), in.ToString());
     190                 :            : 
     191                 :          0 :         it->Next();
     192                 :            : 
     193                 :          0 :         BOOST_REQUIRE(it->GetKey(key_res));
     194                 :          0 :         BOOST_REQUIRE(it->GetValue(val_res));
     195                 :          0 :         BOOST_CHECK_EQUAL(key_res, key2);
     196                 :          0 :         BOOST_CHECK_EQUAL(val_res.ToString(), in2.ToString());
     197                 :            : 
     198                 :          0 :         it->Next();
     199                 :          0 :         BOOST_CHECK_EQUAL(it->Valid(), false);
     200                 :          0 :     }
     201                 :          0 : }
     202                 :            : 
     203                 :            : // Test that we do not obfuscation if there is existing data.
     204                 :          0 : BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate)
     205                 :            : {
     206                 :            :     // We're going to share this fs::path between two wrappers
     207                 :          0 :     fs::path ph = m_args.GetDataDirBase() / "existing_data_no_obfuscate";
     208                 :          0 :     fs::create_directories(ph);
     209                 :            : 
     210                 :            :     // Set up a non-obfuscated wrapper to write some initial data.
     211                 :          0 :     std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(DBParams{.path = ph, .cache_bytes = 1 << 10, .memory_only = false, .wipe_data = false, .obfuscate = false});
     212                 :          0 :     uint8_t key{'k'};
     213                 :          0 :     uint256 in = InsecureRand256();
     214                 :          0 :     uint256 res;
     215                 :            : 
     216                 :          0 :     BOOST_CHECK(dbw->Write(key, in));
     217                 :          0 :     BOOST_CHECK(dbw->Read(key, res));
     218                 :          0 :     BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
     219                 :            : 
     220                 :            :     // Call the destructor to free leveldb LOCK
     221                 :          0 :     dbw.reset();
     222                 :            : 
     223                 :            :     // Now, set up another wrapper that wants to obfuscate the same directory
     224                 :          0 :     CDBWrapper odbw({.path = ph, .cache_bytes = 1 << 10, .memory_only = false, .wipe_data = false, .obfuscate = true});
     225                 :            : 
     226                 :            :     // Check that the key/val we wrote with unobfuscated wrapper exists and
     227                 :          0 :     // is readable.
     228                 :          0 :     uint256 res2;
     229                 :          0 :     BOOST_CHECK(odbw.Read(key, res2));
     230                 :          0 :     BOOST_CHECK_EQUAL(res2.ToString(), in.ToString());
     231                 :            : 
     232                 :          0 :     BOOST_CHECK(!odbw.IsEmpty()); // There should be existing data
     233                 :          0 :     BOOST_CHECK(is_null_key(dbwrapper_private::GetObfuscateKey(odbw))); // The key should be an empty string
     234                 :            : 
     235                 :          0 :     uint256 in2 = InsecureRand256();
     236                 :          0 :     uint256 res3;
     237                 :            : 
     238                 :            :     // Check that we can write successfully
     239                 :          0 :     BOOST_CHECK(odbw.Write(key, in2));
     240                 :          0 :     BOOST_CHECK(odbw.Read(key, res3));
     241                 :          0 :     BOOST_CHECK_EQUAL(res3.ToString(), in2.ToString());
     242                 :          0 : }
     243                 :            : 
     244                 :            : // Ensure that we start obfuscating during a reindex.
     245                 :          0 : BOOST_AUTO_TEST_CASE(existing_data_reindex)
     246                 :            : {
     247                 :            :     // We're going to share this fs::path between two wrappers
     248                 :          0 :     fs::path ph = m_args.GetDataDirBase() / "existing_data_reindex";
     249                 :          0 :     fs::create_directories(ph);
     250                 :            : 
     251                 :            :     // Set up a non-obfuscated wrapper to write some initial data.
     252                 :          0 :     std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(DBParams{.path = ph, .cache_bytes = 1 << 10, .memory_only = false, .wipe_data = false, .obfuscate = false});
     253                 :          0 :     uint8_t key{'k'};
     254                 :          0 :     uint256 in = InsecureRand256();
     255                 :          0 :     uint256 res;
     256                 :            : 
     257                 :          0 :     BOOST_CHECK(dbw->Write(key, in));
     258                 :          0 :     BOOST_CHECK(dbw->Read(key, res));
     259                 :          0 :     BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
     260                 :            : 
     261                 :            :     // Call the destructor to free leveldb LOCK
     262                 :          0 :     dbw.reset();
     263                 :            : 
     264                 :            :     // Simulate a -reindex by wiping the existing data store
     265                 :          0 :     CDBWrapper odbw({.path = ph, .cache_bytes = 1 << 10, .memory_only = false, .wipe_data = true, .obfuscate = true});
     266                 :            : 
     267                 :            :     // Check that the key/val we wrote with unobfuscated wrapper doesn't exist
     268                 :          0 :     uint256 res2;
     269                 :          0 :     BOOST_CHECK(!odbw.Read(key, res2));
     270                 :          0 :     BOOST_CHECK(!is_null_key(dbwrapper_private::GetObfuscateKey(odbw)));
     271                 :            : 
     272                 :          0 :     uint256 in2 = InsecureRand256();
     273                 :          0 :     uint256 res3;
     274                 :            : 
     275                 :            :     // Check that we can write successfully
     276                 :          0 :     BOOST_CHECK(odbw.Write(key, in2));
     277                 :          0 :     BOOST_CHECK(odbw.Read(key, res3));
     278                 :          0 :     BOOST_CHECK_EQUAL(res3.ToString(), in2.ToString());
     279                 :          0 : }
     280                 :            : 
     281                 :          0 : BOOST_AUTO_TEST_CASE(iterator_ordering)
     282                 :            : {
     283                 :          0 :     fs::path ph = m_args.GetDataDirBase() / "iterator_ordering";
     284                 :          0 :     CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = true, .wipe_data = false, .obfuscate = false});
     285                 :          0 :     for (int x=0x00; x<256; ++x) {
     286                 :          0 :         uint8_t key = x;
     287                 :          0 :         uint32_t value = x*x;
     288                 :          0 :         if (!(x & 1)) BOOST_CHECK(dbw.Write(key, value));
     289                 :          0 :     }
     290                 :            : 
     291                 :            :     // Check that creating an iterator creates a snapshot
     292                 :          0 :     std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper&>(dbw).NewIterator());
     293                 :            : 
     294                 :          0 :     for (unsigned int x=0x00; x<256; ++x) {
     295                 :          0 :         uint8_t key = x;
     296                 :          0 :         uint32_t value = x*x;
     297                 :          0 :         if (x & 1) BOOST_CHECK(dbw.Write(key, value));
     298                 :          0 :     }
     299                 :            : 
     300                 :          0 :     for (const int seek_start : {0x00, 0x80}) {
     301                 :          0 :         it->Seek((uint8_t)seek_start);
     302                 :          0 :         for (unsigned int x=seek_start; x<255; ++x) {
     303                 :            :             uint8_t key;
     304                 :            :             uint32_t value;
     305                 :          0 :             BOOST_CHECK(it->Valid());
     306                 :          0 :             if (!it->Valid()) // Avoid spurious errors about invalid iterator's key and value in case of failure
     307                 :          0 :                 break;
     308                 :          0 :             BOOST_CHECK(it->GetKey(key));
     309                 :          0 :             if (x & 1) {
     310                 :          0 :                 BOOST_CHECK_EQUAL(key, x + 1);
     311                 :          0 :                 continue;
     312                 :            :             }
     313                 :          0 :             BOOST_CHECK(it->GetValue(value));
     314                 :          0 :             BOOST_CHECK_EQUAL(key, x);
     315                 :          0 :             BOOST_CHECK_EQUAL(value, x*x);
     316                 :          0 :             it->Next();
     317                 :          0 :         }
     318                 :          0 :         BOOST_CHECK(!it->Valid());
     319                 :            :     }
     320                 :          0 : }
     321                 :            : 
     322                 :            : struct StringContentsSerializer {
     323                 :            :     // Used to make two serialized objects the same while letting them have different lengths
     324                 :            :     // This is a terrible idea
     325                 :            :     std::string str;
     326                 :          0 :     StringContentsSerializer() = default;
     327                 :          0 :     explicit StringContentsSerializer(const std::string& inp) : str(inp) {}
     328                 :            : 
     329                 :            :     template<typename Stream>
     330                 :          0 :     void Serialize(Stream& s) const
     331                 :            :     {
     332                 :          0 :         for (size_t i = 0; i < str.size(); i++) {
     333                 :          0 :             s << uint8_t(str[i]);
     334                 :          0 :         }
     335                 :          0 :     }
     336                 :            : 
     337                 :            :     template<typename Stream>
     338                 :          0 :     void Unserialize(Stream& s)
     339                 :            :     {
     340                 :          0 :         str.clear();
     341                 :          0 :         uint8_t c{0};
     342                 :          0 :         while (!s.eof()) {
     343                 :          0 :             s >> c;
     344                 :          0 :             str.push_back(c);
     345                 :            :         }
     346                 :          0 :     }
     347                 :            : };
     348                 :            : 
     349                 :          0 : BOOST_AUTO_TEST_CASE(iterator_string_ordering)
     350                 :            : {
     351                 :          0 :     fs::path ph = m_args.GetDataDirBase() / "iterator_string_ordering";
     352                 :          0 :     CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = true, .wipe_data = false, .obfuscate = false});
     353                 :          0 :     for (int x = 0; x < 10; ++x) {
     354                 :          0 :         for (int y = 0; y < 10; ++y) {
     355                 :          0 :             std::string key{ToString(x)};
     356                 :          0 :             for (int z = 0; z < y; ++z)
     357                 :          0 :                 key += key;
     358                 :          0 :             uint32_t value = x*x;
     359                 :          0 :             BOOST_CHECK(dbw.Write(StringContentsSerializer{key}, value));
     360                 :          0 :         }
     361                 :          0 :     }
     362                 :            : 
     363                 :          0 :     std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper&>(dbw).NewIterator());
     364                 :          0 :     for (const int seek_start : {0, 5}) {
     365                 :          0 :         it->Seek(StringContentsSerializer{ToString(seek_start)});
     366                 :          0 :         for (unsigned int x = seek_start; x < 10; ++x) {
     367                 :          0 :             for (int y = 0; y < 10; ++y) {
     368                 :          0 :                 std::string exp_key{ToString(x)};
     369                 :          0 :                 for (int z = 0; z < y; ++z)
     370                 :          0 :                     exp_key += exp_key;
     371                 :          0 :                 StringContentsSerializer key;
     372                 :            :                 uint32_t value;
     373                 :          0 :                 BOOST_CHECK(it->Valid());
     374                 :          0 :                 if (!it->Valid()) // Avoid spurious errors about invalid iterator's key and value in case of failure
     375                 :          0 :                     break;
     376                 :          0 :                 BOOST_CHECK(it->GetKey(key));
     377                 :          0 :                 BOOST_CHECK(it->GetValue(value));
     378                 :          0 :                 BOOST_CHECK_EQUAL(key.str, exp_key);
     379                 :          0 :                 BOOST_CHECK_EQUAL(value, x*x);
     380                 :          0 :                 it->Next();
     381                 :          0 :             }
     382                 :          0 :         }
     383                 :          0 :         BOOST_CHECK(!it->Valid());
     384                 :            :     }
     385                 :          0 : }
     386                 :            : 
     387                 :          0 : BOOST_AUTO_TEST_CASE(unicodepath)
     388                 :            : {
     389                 :            :     // Attempt to create a database with a UTF8 character in the path.
     390                 :            :     // On Windows this test will fail if the directory is created using
     391                 :            :     // the ANSI CreateDirectoryA call and the code page isn't UTF8.
     392                 :            :     // It will succeed if created with CreateDirectoryW.
     393                 :          0 :     fs::path ph = m_args.GetDataDirBase() / "test_runner_₿_🏃_20191128_104644";
     394                 :          0 :     CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20});
     395                 :            : 
     396                 :          0 :     fs::path lockPath = ph / "LOCK";
     397                 :          0 :     BOOST_CHECK(fs::exists(lockPath));
     398                 :          0 : }
     399                 :            : 
     400                 :            : 
     401                 :          0 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.14