xref: /aosp_15_r20/external/leveldb/issues/issue320_test.cc (revision 9507f98c5f32dee4b5f9e4a38cd499f3ff5c4490)
1 // Copyright (c) 2019 The LevelDB Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. See the AUTHORS file for names of contributors.
4 
5 #include <cstdint>
6 #include <cstdlib>
7 #include <iostream>
8 #include <memory>
9 #include <string>
10 #include <vector>
11 
12 #include "gtest/gtest.h"
13 #include "leveldb/db.h"
14 #include "leveldb/write_batch.h"
15 #include "util/testutil.h"
16 
17 namespace leveldb {
18 
19 namespace {
20 
21 // Creates a random number in the range of [0, max).
GenerateRandomNumber(int max)22 int GenerateRandomNumber(int max) { return std::rand() % max; }
23 
CreateRandomString(int32_t index)24 std::string CreateRandomString(int32_t index) {
25   static const size_t len = 1024;
26   char bytes[len];
27   size_t i = 0;
28   while (i < 8) {
29     bytes[i] = 'a' + ((index >> (4 * i)) & 0xf);
30     ++i;
31   }
32   while (i < sizeof(bytes)) {
33     bytes[i] = 'a' + GenerateRandomNumber(26);
34     ++i;
35   }
36   return std::string(bytes, sizeof(bytes));
37 }
38 
39 }  // namespace
40 
TEST(Issue320,Test)41 TEST(Issue320, Test) {
42   std::srand(0);
43 
44   bool delete_before_put = false;
45   bool keep_snapshots = true;
46 
47   std::vector<std::unique_ptr<std::pair<std::string, std::string>>> test_map(
48       10000);
49   std::vector<Snapshot const*> snapshots(100, nullptr);
50 
51   DB* db;
52   Options options;
53   options.create_if_missing = true;
54 
55   std::string dbpath = testing::TempDir() + "leveldb_issue320_test";
56   ASSERT_LEVELDB_OK(DB::Open(options, dbpath, &db));
57 
58   uint32_t target_size = 10000;
59   uint32_t num_items = 0;
60   uint32_t count = 0;
61   std::string key;
62   std::string value, old_value;
63 
64   WriteOptions writeOptions;
65   ReadOptions readOptions;
66   while (count < 200000) {
67     if ((++count % 1000) == 0) {
68       std::cout << "count: " << count << std::endl;
69     }
70 
71     int index = GenerateRandomNumber(test_map.size());
72     WriteBatch batch;
73 
74     if (test_map[index] == nullptr) {
75       num_items++;
76       test_map[index].reset(new std::pair<std::string, std::string>(
77           CreateRandomString(index), CreateRandomString(index)));
78       batch.Put(test_map[index]->first, test_map[index]->second);
79     } else {
80       ASSERT_LEVELDB_OK(
81           db->Get(readOptions, test_map[index]->first, &old_value));
82       if (old_value != test_map[index]->second) {
83         std::cout << "ERROR incorrect value returned by Get" << std::endl;
84         std::cout << "  count=" << count << std::endl;
85         std::cout << "  old value=" << old_value << std::endl;
86         std::cout << "  test_map[index]->second=" << test_map[index]->second
87                   << std::endl;
88         std::cout << "  test_map[index]->first=" << test_map[index]->first
89                   << std::endl;
90         std::cout << "  index=" << index << std::endl;
91         ASSERT_EQ(old_value, test_map[index]->second);
92       }
93 
94       if (num_items >= target_size && GenerateRandomNumber(100) > 30) {
95         batch.Delete(test_map[index]->first);
96         test_map[index] = nullptr;
97         --num_items;
98       } else {
99         test_map[index]->second = CreateRandomString(index);
100         if (delete_before_put) batch.Delete(test_map[index]->first);
101         batch.Put(test_map[index]->first, test_map[index]->second);
102       }
103     }
104 
105     ASSERT_LEVELDB_OK(db->Write(writeOptions, &batch));
106 
107     if (keep_snapshots && GenerateRandomNumber(10) == 0) {
108       int i = GenerateRandomNumber(snapshots.size());
109       if (snapshots[i] != nullptr) {
110         db->ReleaseSnapshot(snapshots[i]);
111       }
112       snapshots[i] = db->GetSnapshot();
113     }
114   }
115 
116   for (Snapshot const* snapshot : snapshots) {
117     if (snapshot) {
118       db->ReleaseSnapshot(snapshot);
119     }
120   }
121 
122   delete db;
123   DestroyDB(dbpath, options);
124 }
125 
126 }  // namespace leveldb
127 
main(int argc,char ** argv)128 int main(int argc, char** argv) {
129   testing::InitGoogleTest(&argc, argv);
130   return RUN_ALL_TESTS();
131 }
132