Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1501static const int kNum = 100000;1502Random rnd(test::RandomSeed());1503for (int i = 0; i < kNum; i++) {1504fflush(nullptr);1505ASSERT_OK(Put(RandomKey(&rnd), RandomString(&rnd, 100)));1506}1507}1509TEST(DBTest, ComparatorCheck) {1510class NewComparator : public Comparator {1511public:1512const char* Name() const override { return "leveldb.NewComparator"; }1513int Compare(const Slice& a, const Slice& b) const override {1514return BytewiseComparator()->Compare(a, b);1515}1516void FindShortestSeparator(std::string* s, const Slice& l) const override {1517BytewiseComparator()->FindShortestSeparator(s, l);1518}1519void FindShortSuccessor(std::string* key) const override {1520BytewiseComparator()->FindShortSuccessor(key);1521}1522};1523NewComparator cmp;1524Options new_options = CurrentOptions();1525new_options.comparator = &cmp;1526Status s = TryReopen(&new_options);1527ASSERT_TRUE(!s.ok());1528ASSERT_TRUE(s.ToString().find("comparator") != std::string::npos)1529<< s.ToString();1530}1532TEST(DBTest, CustomComparator) {1533class NumberComparator : public Comparator {1534public:1535const char* Name() const override { return "test.NumberComparator"; }1536int Compare(const Slice& a, const Slice& b) const override {1537return ToNumber(a) - ToNumber(b);1538}1539void FindShortestSeparator(std::string* s, const Slice& l) const override {1540ToNumber(*s); // Check format1541ToNumber(l); // Check format1542}1543void FindShortSuccessor(std::string* key) const override {1544ToNumber(*key); // Check format1545}1547private:1548static int ToNumber(const Slice& x) {1549// Check that there are no extra characters.1550ASSERT_TRUE(x.size() >= 2 && x[0] == '[' && x[x.size() - 1] == ']')1551<< EscapeString(x);1552int val;1553char ignored;1554ASSERT_TRUE(sscanf(x.ToString().c_str(), "[%i]%c", &val, &ignored) == 1)1555<< EscapeString(x);1556return val;1557}1558};1559NumberComparator cmp;1560Options new_options = CurrentOptions();1561new_options.create_if_missing = true;1562new_options.comparator = &cmp;1563new_options.filter_policy = nullptr; // Cannot use bloom filters1564new_options.write_buffer_size = 1000; // Compact more often1565DestroyAndReopen(&new_options);1566ASSERT_OK(Put("[10]", "ten"));1567ASSERT_OK(Put("[0x14]", "twenty"));1568for (int i = 0; i < 2; i++) {1569ASSERT_EQ("ten", Get("[10]"));1570ASSERT_EQ("ten", Get("[0xa]"));1571ASSERT_EQ("twenty", Get("[20]"));1572ASSERT_EQ("twenty", Get("[0x14]"));1573ASSERT_EQ("NOT_FOUND", Get("[15]"));1574ASSERT_EQ("NOT_FOUND", Get("[0xf]"));1575Compact("[0]", "[9999]");1576}1578for (int run = 0; run < 2; run++) {1579for (int i = 0; i < 1000; i++) {1580char buf[100];1581snprintf(buf, sizeof(buf), "[%d]", i * 10);1582ASSERT_OK(Put(buf, buf));1583}1584Compact("[0]", "[1000000]");1585}1586}1588TEST(DBTest, ManualCompaction) {1589ASSERT_EQ(config::kMaxMemCompactLevel, 2)1590<< "Need to update this test to match kMaxMemCompactLevel";1592MakeTables(3, "p", "q");1593ASSERT_EQ("1,1,1", FilesPerLevel());1595// Compaction range falls before files1596Compact("", "c");1597ASSERT_EQ("1,1,1", FilesPerLevel());1599// Compaction range falls after files1600Compact("r", "z");1601ASSERT_EQ("1,1,1", FilesPerLevel());1603// Compaction range overlaps files1604Compact("p1", "p9");1605ASSERT_EQ("0,0,1", FilesPerLevel());1607// Populate a different range1608MakeTables(3, "c", "e");1609ASSERT_EQ("1,1,2", FilesPerLevel());1611// Compact just the new range1612Compact("b", "f");1613ASSERT_EQ("0,0,2", FilesPerLevel());1615// Compact all1616MakeTables(1, "a", "z");1617ASSERT_EQ("0,1,2", FilesPerLevel());1618db_->CompactRange(nullptr, nullptr);1619ASSERT_EQ("0,0,1", FilesPerLevel());1620}1622TEST(DBTest, DBOpen_Options) {1623std::string dbname = test::TmpDir() + "/db_options_test";1624DestroyDB(dbname, Options());1626// Does not exist, and create_if_missing == false: error1627DB* db = nullptr;1628Options opts;1629opts.create_if_missing = false;1630Status s = DB::Open(opts, dbname, &db);1631ASSERT_TRUE(strstr(s.ToString().c_str(), "does not exist") != nullptr);1632ASSERT_TRUE(db == nullptr);1634// Does not exist, and create_if_missing == true: OK1635opts.create_if_missing = true;1636s = DB::Open(opts, dbname, &db);1637ASSERT_OK(s);1638ASSERT_TRUE(db != nullptr);1640delete db;1641db = nullptr;1643// Does exist, and error_if_exists == true: error1644opts.create_if_missing = false;1645opts.error_if_exists = true;1646s = DB::Open(opts, dbname, &db);1647ASSERT_TRUE(strstr(s.ToString().c_str(), "exists") != nullptr);1648ASSERT_TRUE(db == nullptr);1650// Does exist, and error_if_exists == false: OK1651opts.create_if_missing = true;1652opts.error_if_exists = false;1653s = DB::Open(opts, dbname, &db);1654ASSERT_OK(s);1655ASSERT_TRUE(db != nullptr);1657delete db;1658db = nullptr;1659}1661TEST(DBTest, DestroyEmptyDir) {1662std::string dbname = test::TmpDir() + "/db_empty_dir";1663TestEnv env(Env::Default());1664env.DeleteDir(dbname);1665ASSERT_TRUE(!env.FileExists(dbname));1667Options opts;1668opts.env = &env;1670ASSERT_OK(env.CreateDir(dbname));1671ASSERT_TRUE(env.FileExists(dbname));1672std::vector<std::string> children;1673ASSERT_OK(env.GetChildren(dbname, &children));1674// The stock Env's do not filter out '.' and '..' special files.1675ASSERT_EQ(2, children.size());1676ASSERT_OK(DestroyDB(dbname, opts));1677ASSERT_TRUE(!env.FileExists(dbname));1679// Should also be destroyed if Env is filtering out dot files.1680env.SetIgnoreDotFiles(true);1681ASSERT_OK(env.CreateDir(dbname));1682ASSERT_TRUE(env.FileExists(dbname));1683ASSERT_OK(env.GetChildren(dbname, &children));1684ASSERT_EQ(0, children.size());1685ASSERT_OK(DestroyDB(dbname, opts));1686ASSERT_TRUE(!env.FileExists(dbname));1687}1689TEST(DBTest, DestroyOpenDB) {1690std::string dbname = test::TmpDir() + "/open_db_dir";1691env_->DeleteDir(dbname);1692ASSERT_TRUE(!env_->FileExists(dbname));1694Options opts;1695opts.create_if_missing = true;1696DB* db = nullptr;1697ASSERT_OK(DB::Open(opts, dbname, &db));1698ASSERT_TRUE(db != nullptr);1700// Must fail to destroy an open db.1701ASSERT_TRUE(env_->FileExists(dbname));1702ASSERT_TRUE(!DestroyDB(dbname, Options()).ok());1703ASSERT_TRUE(env_->FileExists(dbname));1705delete db;1706db = nullptr;1708// Should succeed destroying a closed db.1709ASSERT_OK(DestroyDB(dbname, Options()));1710ASSERT_TRUE(!env_->FileExists(dbname));1711}1713TEST(DBTest, Locking) {1714DB* db2 = nullptr;1715Status s = DB::Open(CurrentOptions(), dbname_, &db2);1716ASSERT_TRUE(!s.ok()) << "Locking did not prevent re-opening db";1717}1719// Check that number of files does not grow when we are out of space1720TEST(DBTest, NoSpace) {1721Options options = CurrentOptions();1722options.env = env_;1723Reopen(&options);1725ASSERT_OK(Put("foo", "v1"));1726ASSERT_EQ("v1", Get("foo"));1727Compact("a", "z");1728const int num_files = CountFiles();1729// Force out-of-space errors.1730env_->no_space_.store(true, std::memory_order_release);1731for (int i = 0; i < 10; i++) {1732for (int level = 0; level < config::kNumLevels - 1; level++) {1733dbfull()->TEST_CompactRange(level, nullptr, nullptr);1734}1735}1736env_->no_space_.store(false, std::memory_order_release);1737ASSERT_LT(CountFiles(), num_files + 3);1738}1740TEST(DBTest, NonWritableFileSystem) {1741Options options = CurrentOptions();1742options.write_buffer_size = 1000;1743options.env = env_;1744Reopen(&options);1745ASSERT_OK(Put("foo", "v1"));1746// Force errors for new files.1747env_->non_writable_.store(true, std::memory_order_release);1748std::string big(100000, 'x');1749int errors = 0;1750for (int i = 0; i < 20; i++) {
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.