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.
501break;502}504case 1: {505if (kVerbose) fprintf(stderr, "SeekToFirst\n");506iter->SeekToFirst();507model_iter = data.begin();508ASSERT_EQ(ToString(data, model_iter), ToString(iter));509break;510}512case 2: {513std::string key = PickRandomKey(rnd, keys);514model_iter = data.lower_bound(key);515if (kVerbose)516fprintf(stderr, "Seek '%s'\n", EscapeString(key).c_str());517iter->Seek(Slice(key));518ASSERT_EQ(ToString(data, model_iter), ToString(iter));519break;520}522case 3: {523if (iter->Valid()) {524if (kVerbose) fprintf(stderr, "Prev\n");525iter->Prev();526if (model_iter == data.begin()) {527model_iter = data.end(); // Wrap around to invalid value528} else {529--model_iter;530}531ASSERT_EQ(ToString(data, model_iter), ToString(iter));532}533break;534}536case 4: {537if (kVerbose) fprintf(stderr, "SeekToLast\n");538iter->SeekToLast();539if (keys.empty()) {540model_iter = data.end();541} else {542std::string last = data.rbegin()->first;543model_iter = data.lower_bound(last);544}545ASSERT_EQ(ToString(data, model_iter), ToString(iter));546break;547}548}549}550delete iter;551}553std::string ToString(const KVMap& data, const KVMap::const_iterator& it) {554if (it == data.end()) {555return "END";556} else {557return "'" + it->first + "->" + it->second + "'";558}559}561std::string ToString(const KVMap& data,562const KVMap::const_reverse_iterator& it) {563if (it == data.rend()) {564return "END";565} else {566return "'" + it->first + "->" + it->second + "'";567}568}570std::string ToString(const Iterator* it) {571if (!it->Valid()) {572return "END";573} else {574return "'" + it->key().ToString() + "->" + it->value().ToString() + "'";575}576}578std::string PickRandomKey(Random* rnd, const std::vector<std::string>& keys) {579if (keys.empty()) {580return "foo";581} else {582const int index = rnd->Uniform(keys.size());583std::string result = keys[index];584switch (rnd->Uniform(3)) {585case 0:586// Return an existing key587break;588case 1: {589// Attempt to return something smaller than an existing key590if (!result.empty() && result[result.size() - 1] > '\0') {591result[result.size() - 1]--;592}593break;594}595case 2: {596// Return something larger than an existing key597Increment(options_.comparator, &result);598break;599}600}601return result;602}603}605// Returns nullptr if not running against a DB606DB* db() const { return constructor_->db(); }608private:609Options options_;610Constructor* constructor_;611};613// Test empty table/block.614TEST(Harness, Empty) {615for (int i = 0; i < kNumTestArgs; i++) {616Init(kTestArgList[i]);617Random rnd(test::RandomSeed() + 1);618Test(&rnd);619}620}622// Special test for a block with no restart entries. The C++ leveldb623// code never generates such blocks, but the Java version of leveldb624// seems to.625TEST(Harness, ZeroRestartPointsInBlock) {626char data[sizeof(uint32_t)];627memset(data, 0, sizeof(data));628BlockContents contents;629contents.data = Slice(data, sizeof(data));630contents.cachable = false;631contents.heap_allocated = false;632Block block(contents);633Iterator* iter = block.NewIterator(BytewiseComparator());634iter->SeekToFirst();635ASSERT_TRUE(!iter->Valid());636iter->SeekToLast();637ASSERT_TRUE(!iter->Valid());638iter->Seek("foo");639ASSERT_TRUE(!iter->Valid());640delete iter;641}643// Test the empty key644TEST(Harness, SimpleEmptyKey) {645for (int i = 0; i < kNumTestArgs; i++) {646Init(kTestArgList[i]);647Random rnd(test::RandomSeed() + 1);648Add("", "v");649Test(&rnd);650}651}653TEST(Harness, SimpleSingle) {654for (int i = 0; i < kNumTestArgs; i++) {655Init(kTestArgList[i]);656Random rnd(test::RandomSeed() + 2);657Add("abc", "v");658Test(&rnd);659}660}662TEST(Harness, SimpleMulti) {663for (int i = 0; i < kNumTestArgs; i++) {664Init(kTestArgList[i]);665Random rnd(test::RandomSeed() + 3);666Add("abc", "v");667Add("abcd", "v");668Add("ac", "v2");669Test(&rnd);670}671}673TEST(Harness, SimpleSpecialKey) {674for (int i = 0; i < kNumTestArgs; i++) {675Init(kTestArgList[i]);676Random rnd(test::RandomSeed() + 4);677Add("\xff\xff", "v3");678Test(&rnd);679}680}682TEST(Harness, Randomized) {683for (int i = 0; i < kNumTestArgs; i++) {684Init(kTestArgList[i]);685Random rnd(test::RandomSeed() + 5);686for (int num_entries = 0; num_entries < 2000;687num_entries += (num_entries < 50 ? 1 : 200)) {688if ((num_entries % 10) == 0) {689fprintf(stderr, "case %d of %d: num_entries = %d\n", (i + 1),690int(kNumTestArgs), num_entries);691}692for (int e = 0; e < num_entries; e++) {693std::string v;694Add(test::RandomKey(&rnd, rnd.Skewed(4)),695test::RandomString(&rnd, rnd.Skewed(5), &v).ToString());696}697Test(&rnd);698}699}700}702TEST(Harness, RandomizedLongDB) {703Random rnd(test::RandomSeed());704TestArgs args = {DB_TEST, false, 16};705Init(args);706int num_entries = 100000;707for (int e = 0; e < num_entries; e++) {708std::string v;709Add(test::RandomKey(&rnd, rnd.Skewed(4)),710test::RandomString(&rnd, rnd.Skewed(5), &v).ToString());711}712Test(&rnd);714// We must have created enough data to force merging715int files = 0;716for (int level = 0; level < config::kNumLevels; level++) {717std::string value;718char name[100];719snprintf(name, sizeof(name), "leveldb.num-files-at-level%d", level);720ASSERT_TRUE(db()->GetProperty(name, &value));721files += atoi(value.c_str());722}723ASSERT_GT(files, 0);724}726class MemTableTest {};728TEST(MemTableTest, Simple) {729InternalKeyComparator cmp(BytewiseComparator());730MemTable* memtable = new MemTable(cmp);731memtable->Ref();732WriteBatch batch;733WriteBatchInternal::SetSequence(&batch, 100);734batch.Put(std::string("k1"), std::string("v1"));735batch.Put(std::string("k2"), std::string("v2"));736batch.Put(std::string("k3"), std::string("v3"));737batch.Put(std::string("largekey"), std::string("vlarge"));738ASSERT_TRUE(WriteBatchInternal::InsertInto(&batch, memtable).ok());740Iterator* iter = memtable->NewIterator();741iter->SeekToFirst();742while (iter->Valid()) {743fprintf(stderr, "key: '%s' -> '%s'\n", iter->key().ToString().c_str(),744iter->value().ToString().c_str());745iter->Next();746}748delete iter;749memtable->Unref();750}
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.