YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rocksdb/tools/db_sanity_test.cc
Line
Count
Source (jump to first uncovered line)
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
//  This source code is licensed under the BSD-style license found in the
3
//  LICENSE file in the root directory of this source tree. An additional grant
4
//  of patent rights can be found in the PATENTS file in the same directory.
5
//
6
// The following only applies to changes made to this file as part of YugaByte development.
7
//
8
// Portions Copyright (c) YugaByte, Inc.
9
//
10
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
11
// in compliance with the License.  You may obtain a copy of the License at
12
//
13
// http://www.apache.org/licenses/LICENSE-2.0
14
//
15
// Unless required by applicable law or agreed to in writing, software distributed under the License
16
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17
// or implied.  See the License for the specific language governing permissions and limitations
18
// under the License.
19
//
20
21
#include <vector>
22
#include <memory>
23
24
#include "yb/rocksdb/db.h"
25
#include "yb/rocksdb/options.h"
26
#include "yb/rocksdb/env.h"
27
#include "yb/util/slice.h"
28
#include "yb/rocksdb/status.h"
29
#include "yb/rocksdb/comparator.h"
30
#include "yb/rocksdb/table.h"
31
#include "yb/rocksdb/slice_transform.h"
32
#include "yb/rocksdb/filter_policy.h"
33
#include "yb/util/string_util.h"
34
35
namespace rocksdb {
36
37
class SanityTest {
38
 public:
39
  explicit SanityTest(const std::string& path)
40
0
      : env_(Env::Default()), path_(path) {
41
0
    CHECK_OK(env_->CreateDirIfMissing(path));
42
0
  }
43
0
  virtual ~SanityTest() {}
44
45
  virtual std::string Name() const = 0;
46
  virtual Options GetOptions() const = 0;
47
48
0
  Status Create() {
49
0
    Options options = GetOptions();
50
0
    options.create_if_missing = true;
51
0
    std::string dbname = path_ + Name();
52
0
    CHECK_OK(DestroyDB(dbname, options));
53
0
    DB* db = nullptr;
54
0
    Status s = DB::Open(options, dbname, &db);
55
0
    std::unique_ptr<DB> db_guard(db);
56
0
    if (!s.ok()) {
57
0
      return s;
58
0
    }
59
0
    for (int i = 0; i < 1000000; ++i) {
60
0
      std::string k = "key" + ToString(i);
61
0
      std::string v = "value" + ToString(i);
62
0
      s = db->Put(WriteOptions(), Slice(k), Slice(v));
63
0
      if (!s.ok()) {
64
0
        return s;
65
0
      }
66
0
    }
67
0
    return db->Flush(FlushOptions());
68
0
  }
69
0
  Status Verify() {
70
0
    DB* db = nullptr;
71
0
    std::string dbname = path_ + Name();
72
0
    Status s = DB::Open(GetOptions(), dbname, &db);
73
0
    std::unique_ptr<DB> db_guard(db);
74
0
    if (!s.ok()) {
75
0
      return s;
76
0
    }
77
0
    for (int i = 0; i < 1000000; ++i) {
78
0
      std::string k = "key" + ToString(i);
79
0
      std::string v = "value" + ToString(i);
80
0
      std::string result;
81
0
      s = db->Get(ReadOptions(), Slice(k), &result);
82
0
      if (!s.ok()) {
83
0
        return s;
84
0
      }
85
0
      if (result != v) {
86
0
        return STATUS(Corruption, "Unexpected value for key " + k);
87
0
      }
88
0
    }
89
0
    return Status::OK();
90
0
  }
91
92
 private:
93
  Env* env_;
94
  std::string const path_;
95
};
96
97
class SanityTestBasic : public SanityTest {
98
 public:
99
0
  explicit SanityTestBasic(const std::string& path) : SanityTest(path) {}
100
0
  Options GetOptions() const override {
101
0
    Options options;
102
0
    options.create_if_missing = true;
103
0
    return options;
104
0
  }
105
0
  std::string Name() const override { return "Basic"; }
106
};
107
108
class SanityTestSpecialComparator : public SanityTest {
109
 public:
110
  explicit SanityTestSpecialComparator(const std::string& path)
111
0
      : SanityTest(path) {
112
0
    options_.comparator = new NewComparator();
113
0
  }
114
0
  ~SanityTestSpecialComparator() { delete options_.comparator; }
115
0
  Options GetOptions() const override { return options_; }
116
0
  std::string Name() const override { return "SpecialComparator"; }
117
118
 private:
119
  class NewComparator : public Comparator {
120
   public:
121
0
    const char* Name() const override {
122
0
      return "rocksdb.NewComparator";
123
0
    }
124
0
    int Compare(const Slice& a, const Slice& b) const override {
125
0
      return BytewiseComparator()->Compare(a, b);
126
0
    }
127
    virtual void FindShortestSeparator(std::string* s,
128
0
                                       const Slice& l) const override {
129
0
      BytewiseComparator()->FindShortestSeparator(s, l);
130
0
    }
131
0
    void FindShortSuccessor(std::string* key) const override {
132
0
      BytewiseComparator()->FindShortSuccessor(key);
133
0
    }
134
  };
135
  Options options_;
136
};
137
138
class SanityTestZlibCompression : public SanityTest {
139
 public:
140
  explicit SanityTestZlibCompression(const std::string& path)
141
0
      : SanityTest(path) {
142
0
    options_.compression = kZlibCompression;
143
0
  }
144
0
  Options GetOptions() const override { return options_; }
145
0
  std::string Name() const override { return "ZlibCompression"; }
146
147
 private:
148
  Options options_;
149
};
150
151
class SanityTestZlibCompressionVersion2 : public SanityTest {
152
 public:
153
  explicit SanityTestZlibCompressionVersion2(const std::string& path)
154
0
      : SanityTest(path) {
155
0
    options_.compression = kZlibCompression;
156
0
    BlockBasedTableOptions table_options;
157
0
    table_options.format_version = 2;
158
0
    options_.table_factory.reset(NewBlockBasedTableFactory(table_options));
159
0
  }
160
0
  Options GetOptions() const override { return options_; }
161
0
  std::string Name() const override {
162
0
    return "ZlibCompressionVersion2";
163
0
  }
164
165
 private:
166
  Options options_;
167
};
168
169
class SanityTestLZ4Compression : public SanityTest {
170
 public:
171
  explicit SanityTestLZ4Compression(const std::string& path)
172
0
      : SanityTest(path) {
173
0
    options_.compression = kLZ4Compression;
174
0
  }
175
0
  Options GetOptions() const override { return options_; }
176
0
  std::string Name() const override { return "LZ4Compression"; }
177
178
 private:
179
  Options options_;
180
};
181
182
class SanityTestLZ4HCCompression : public SanityTest {
183
 public:
184
  explicit SanityTestLZ4HCCompression(const std::string& path)
185
0
      : SanityTest(path) {
186
0
    options_.compression = kLZ4HCCompression;
187
0
  }
188
0
  Options GetOptions() const override { return options_; }
189
0
  std::string Name() const override { return "LZ4HCCompression"; }
190
191
 private:
192
  Options options_;
193
};
194
195
class SanityTestZSTDCompression : public SanityTest {
196
 public:
197
  explicit SanityTestZSTDCompression(const std::string& path)
198
0
      : SanityTest(path) {
199
0
    options_.compression = kZSTDNotFinalCompression;
200
0
  }
201
0
  Options GetOptions() const override { return options_; }
202
0
  std::string Name() const override { return "ZSTDCompression"; }
203
204
 private:
205
  Options options_;
206
};
207
208
#ifndef ROCKSDB_LITE
209
class SanityTestPlainTableFactory : public SanityTest {
210
 public:
211
  explicit SanityTestPlainTableFactory(const std::string& path)
212
0
      : SanityTest(path) {
213
0
    options_.table_factory.reset(NewPlainTableFactory());
214
0
    options_.prefix_extractor.reset(NewFixedPrefixTransform(2));
215
0
    options_.allow_mmap_reads = true;
216
0
  }
217
0
  ~SanityTestPlainTableFactory() {}
218
0
  Options GetOptions() const override { return options_; }
219
0
  std::string Name() const override { return "PlainTable"; }
220
221
 private:
222
  Options options_;
223
};
224
#endif  // ROCKSDB_LITE
225
226
class SanityTestBloomFilter : public SanityTest {
227
 public:
228
0
  explicit SanityTestBloomFilter(const std::string& path) : SanityTest(path) {
229
0
    BlockBasedTableOptions table_options;
230
0
    table_options.filter_policy.reset(NewBloomFilterPolicy(10));
231
0
    options_.table_factory.reset(NewBlockBasedTableFactory(table_options));
232
0
  }
233
0
  ~SanityTestBloomFilter() {}
234
0
  Options GetOptions() const override { return options_; }
235
0
  std::string Name() const override { return "BloomFilter"; }
236
237
 private:
238
  Options options_;
239
};
240
241
namespace {
242
0
bool RunSanityTests(const std::string& command, const std::string& path) {
243
0
  std::vector<SanityTest*> sanity_tests = {
244
0
      new SanityTestBasic(path),
245
0
      new SanityTestSpecialComparator(path),
246
0
      new SanityTestZlibCompression(path),
247
0
      new SanityTestZlibCompressionVersion2(path),
248
0
      new SanityTestLZ4Compression(path),
249
0
      new SanityTestLZ4HCCompression(path),
250
0
      new SanityTestZSTDCompression(path),
251
0
#ifndef ROCKSDB_LITE
252
0
      new SanityTestPlainTableFactory(path),
253
0
#endif  // ROCKSDB_LITE
254
0
      new SanityTestBloomFilter(path)};
255
256
0
  if (command == "create") {
257
0
    fprintf(stderr, "Creating...\n");
258
0
  } else {
259
0
    fprintf(stderr, "Verifying...\n");
260
0
  }
261
0
  bool result = true;
262
0
  for (auto sanity_test : sanity_tests) {
263
0
    Status s;
264
0
    fprintf(stderr, "%s -- ", sanity_test->Name().c_str());
265
0
    if (command == "create") {
266
0
      s = sanity_test->Create();
267
0
    } else {
268
0
      assert(command == "verify");
269
0
      s = sanity_test->Verify();
270
0
    }
271
0
    fprintf(stderr, "%s\n", s.ToString().c_str());
272
0
    if (!s.ok()) {
273
0
      fprintf(stderr, "FAIL\n");
274
0
      result = false;
275
0
    }
276
277
0
    delete sanity_test;
278
0
  }
279
0
  return result;
280
0
}
281
}  // namespace
282
283
}  // namespace rocksdb
284
285
int main(int argc, char** argv) {
286
  std::string path, command;
287
  bool ok = (argc == 3);
288
  if (ok) {
289
    path = std::string(argv[1]);
290
    command = std::string(argv[2]);
291
    ok = (command == "create" || command == "verify");
292
  }
293
  if (!ok) {
294
    fprintf(stderr, "Usage: %s <path> [create|verify] \n", argv[0]);
295
    exit(1);
296
  }
297
  if (path.back() != '/') {
298
    path += "/";
299
  }
300
301
  bool sanity_ok = rocksdb::RunSanityTests(command, path);
302
303
  return sanity_ok ? 0 : 1;
304
}