YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rocksdb/util/testutil.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
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
21
// Use of this source code is governed by a BSD-style license that can be
22
// found in the LICENSE file. See the AUTHORS file for names of contributors.
23
24
#include "yb/rocksdb/util/testutil.h"
25
26
#include <boost/functional/hash.hpp>
27
28
#include <gtest/gtest.h>
29
30
#include "yb/gutil/casts.h"
31
32
#include "yb/rocksdb/port/port.h"
33
#include "yb/rocksdb/util/file_reader_writer.h"
34
35
namespace rocksdb {
36
namespace test {
37
38
295k
extern std::string RandomHumanReadableString(Random* rnd, int len) {
39
295k
  std::string ret;
40
295k
  ret.resize(len);
41
11.2M
  for (int i = 0; i < len; ++i) {
42
10.9M
    ret[i] = static_cast<char>('a' + rnd->Uniform(26));
43
10.9M
  }
44
295k
  return ret;
45
295k
}
46
47
2.77M
std::string RandomKey(Random* rnd, int len, RandomKeyType type) {
48
  // Make sure to generate a wide variety of characters so we
49
  // test the boundary conditions for short-key optimizations.
50
2.77M
  static const char kTestChars[] = {
51
2.77M
    '\0', '\1', 'a', 'b', 'c', 'd', 'e', '\xfd', '\xfe', '\xff'
52
2.77M
  };
53
2.77M
  std::string result;
54
11.5M
  for (int i = 0; i < len; i++) {
55
8.76M
    std::size_t indx = 0;
56
8.76M
    switch (type) {
57
8.76M
      case RandomKeyType::RANDOM:
58
8.76M
        indx = rnd->Uniform(sizeof(kTestChars));
59
8.76M
        break;
60
0
      case RandomKeyType::LARGEST:
61
0
        indx = sizeof(kTestChars) - 1;
62
0
        break;
63
0
      case RandomKeyType::MIDDLE:
64
0
        indx = sizeof(kTestChars) / 2;
65
0
        break;
66
0
      case RandomKeyType::SMALLEST:
67
0
        indx = 0;
68
0
        break;
69
8.76M
    }
70
8.76M
    result += kTestChars[indx];
71
8.76M
  }
72
2.77M
  return result;
73
2.77M
}
74
75
76
4.07k
WritableFileWriter* GetWritableFileWriter(WritableFile* wf) {
77
4.07k
  unique_ptr<WritableFile> file(wf);
78
4.07k
  return new WritableFileWriter(std::move(file), EnvOptions());
79
4.07k
}
80
81
4.04k
RandomAccessFileReader* GetRandomAccessFileReader(RandomAccessFile* raf) {
82
4.04k
  unique_ptr<RandomAccessFile> file(raf);
83
4.04k
  return new RandomAccessFileReader(std::move(file));
84
4.04k
}
85
86
112
SequentialFileReader* GetSequentialFileReader(SequentialFile* se) {
87
112
  unique_ptr<SequentialFile> file(se);
88
112
  return new SequentialFileReader(std::move(file));
89
112
}
90
91
804
void CorruptKeyType(InternalKey* ikey) {
92
804
  std::string keystr = ikey->Encode().ToString();
93
804
  keystr[keystr.size() - 8] = kTypeLogData;
94
804
  *ikey = InternalKey::DecodeFrom(Slice(keystr.data(), keystr.size()));
95
804
}
96
97
std::string KeyStr(const std::string& user_key, const SequenceNumber& seq,
98
10
                   const ValueType& t, bool corrupt) {
99
10
  InternalKey k(user_key, seq, t);
100
10
  if (corrupt) {
101
4
    CorruptKeyType(&k);
102
4
  }
103
10
  return k.Encode().ToString();
104
10
}
105
106
98
std::string RandomName(Random* rnd, const size_t len) {
107
98
  std::stringstream ss;
108
1.07k
  for (size_t i = 0; i < len; ++i) {
109
980
    ss << static_cast<char>(rnd->Uniform(26) + 'a');
110
980
  }
111
98
  return ss.str();
112
98
}
113
114
1.10k
CompressionType RandomCompressionType(Random* rnd) {
115
1.10k
  return static_cast<CompressionType>(rnd->Uniform(6));
116
1.10k
}
117
118
void RandomCompressionTypeVector(const size_t count,
119
                                 std::vector<CompressionType>* types,
120
22
                                 Random* rnd) {
121
22
  types->clear();
122
1.10k
  for (size_t i = 0; i < count; ++i) {
123
1.08k
    types->emplace_back(RandomCompressionType(rnd));
124
1.08k
  }
125
22
}
126
127
30
const SliceTransform* RandomSliceTransform(Random* rnd, int pre_defined) {
128
26
  int random_num = pre_defined >= 0 ? pre_defined : rnd->Uniform(4);
129
30
  switch (random_num) {
130
6
    case 0:
131
6
      return NewFixedPrefixTransform(rnd->Uniform(20) + 1);
132
14
    case 1:
133
14
      return NewCappedPrefixTransform(rnd->Uniform(20) + 1);
134
6
    case 2:
135
6
      return NewNoopTransform();
136
4
    default:
137
4
      return nullptr;
138
30
  }
139
30
}
140
141
0
BlockBasedTableOptions RandomBlockBasedTableOptions(Random* rnd) {
142
0
  BlockBasedTableOptions opt;
143
0
  opt.cache_index_and_filter_blocks = rnd->Uniform(2);
144
0
  opt.index_type = static_cast<IndexType>(rnd->Uniform(kElementsInIndexType));
145
0
  opt.hash_index_allow_collision = rnd->Uniform(2);
146
0
  opt.checksum = static_cast<ChecksumType>(rnd->Uniform(3));
147
0
  opt.block_size = rnd->Uniform(10000000);
148
0
  opt.block_size_deviation = rnd->Uniform(100);
149
0
  opt.block_restart_interval = rnd->Uniform(100);
150
0
  opt.index_block_restart_interval = rnd->Uniform(100);
151
0
  opt.whole_key_filtering = rnd->Uniform(2);
152
153
0
  return opt;
154
0
}
155
156
27
TableFactory* RandomTableFactory(Random* rnd, int pre_defined) {
157
22
  int random_num = pre_defined >= 0 ? pre_defined : rnd->Uniform(2);
158
27
  switch (random_num) {
159
14
    case 0:
160
14
      return NewPlainTableFactory();
161
13
    default:
162
13
      return NewBlockBasedTableFactory();
163
27
  }
164
27
}
165
166
32
MergeOperator* RandomMergeOperator(Random* rnd) {
167
32
  return new ChanglingMergeOperator(RandomName(rnd, 10));
168
32
}
169
170
27
CompactionFilter* RandomCompactionFilter(Random* rnd) {
171
27
  return new ChanglingCompactionFilter(RandomName(rnd, 10));
172
27
}
173
174
27
CompactionFilterFactory* RandomCompactionFilterFactory(Random* rnd) {
175
27
  return new ChanglingCompactionFilterFactory(RandomName(rnd, 10));
176
27
}
177
178
5
void RandomInitDBOptions(DBOptions* db_opt, Random* rnd) {
179
  // boolean options
180
5
  db_opt->advise_random_on_open = rnd->Uniform(2);
181
5
  db_opt->allow_mmap_reads = rnd->Uniform(2);
182
5
  db_opt->allow_mmap_writes = rnd->Uniform(2);
183
5
  db_opt->allow_os_buffer = rnd->Uniform(2);
184
5
  db_opt->create_if_missing = rnd->Uniform(2);
185
5
  db_opt->create_missing_column_families = rnd->Uniform(2);
186
5
  db_opt->disableDataSync = rnd->Uniform(2);
187
5
  db_opt->enable_thread_tracking = false;
188
5
  db_opt->error_if_exists = rnd->Uniform(2);
189
5
  db_opt->is_fd_close_on_exec = rnd->Uniform(2);
190
5
  db_opt->paranoid_checks = rnd->Uniform(2);
191
5
  db_opt->skip_log_error_on_recovery = rnd->Uniform(2);
192
5
  db_opt->skip_stats_update_on_db_open = rnd->Uniform(2);
193
5
  db_opt->use_adaptive_mutex = rnd->Uniform(2);
194
5
  db_opt->use_fsync = rnd->Uniform(2);
195
5
  db_opt->recycle_log_file_num = rnd->Uniform(2);
196
197
  // int options
198
5
  db_opt->max_background_compactions = rnd->Uniform(100);
199
5
  db_opt->max_background_flushes = rnd->Uniform(100);
200
5
  db_opt->max_file_opening_threads = rnd->Uniform(100);
201
5
  db_opt->max_open_files = rnd->Uniform(100);
202
5
  db_opt->table_cache_numshardbits = rnd->Uniform(100);
203
204
  // size_t options
205
5
  db_opt->db_write_buffer_size = rnd->Uniform(10000);
206
5
  db_opt->keep_log_file_num = rnd->Uniform(10000);
207
5
  db_opt->log_file_time_to_roll = rnd->Uniform(10000);
208
5
  db_opt->manifest_preallocation_size = rnd->Uniform(10000);
209
5
  db_opt->max_log_file_size = rnd->Uniform(10000);
210
211
  // std::string options
212
5
  db_opt->db_log_dir = "path/to/db_log_dir";
213
5
  db_opt->wal_dir = "path/to/wal_dir";
214
215
  // uint32_t options
216
5
  db_opt->max_subcompactions = rnd->Uniform(100000);
217
218
  // uint64_t options
219
5
  static const uint64_t uint_max = static_cast<uint64_t>(UINT_MAX);
220
5
  db_opt->WAL_size_limit_MB = uint_max + rnd->Uniform(100000);
221
5
  db_opt->WAL_ttl_seconds = uint_max + rnd->Uniform(100000);
222
5
  db_opt->bytes_per_sync = uint_max + rnd->Uniform(100000);
223
5
  db_opt->delayed_write_rate = uint_max + rnd->Uniform(100000);
224
5
  db_opt->delete_obsolete_files_period_micros = uint_max + rnd->Uniform(100000);
225
5
  db_opt->max_manifest_file_size = uint_max + rnd->Uniform(100000);
226
5
  db_opt->max_total_wal_size = uint_max + rnd->Uniform(100000);
227
5
  db_opt->wal_bytes_per_sync = uint_max + rnd->Uniform(100000);
228
229
  // unsigned int options
230
5
  db_opt->stats_dump_period_sec = rnd->Uniform(100000);
231
5
}
232
233
22
void RandomInitCFOptions(ColumnFamilyOptions* cf_opt, Random* rnd) {
234
22
  cf_opt->compaction_style = (CompactionStyle)(rnd->Uniform(4));
235
236
  // boolean options
237
22
  cf_opt->compaction_measure_io_stats = rnd->Uniform(2);
238
22
  cf_opt->disable_auto_compactions = rnd->Uniform(2);
239
22
  cf_opt->filter_deletes = rnd->Uniform(2);
240
22
  cf_opt->inplace_update_support = rnd->Uniform(2);
241
22
  cf_opt->level_compaction_dynamic_level_bytes = rnd->Uniform(2);
242
22
  cf_opt->optimize_filters_for_hits = rnd->Uniform(2);
243
22
  cf_opt->paranoid_file_checks = rnd->Uniform(2);
244
22
  cf_opt->purge_redundant_kvs_while_flush = rnd->Uniform(2);
245
22
  cf_opt->verify_checksums_in_compaction = rnd->Uniform(2);
246
247
  // double options
248
22
  cf_opt->hard_rate_limit = static_cast<double>(rnd->Uniform(10000)) / 13;
249
22
  cf_opt->soft_rate_limit = static_cast<double>(rnd->Uniform(10000)) / 13;
250
251
  // int options
252
22
  cf_opt->expanded_compaction_factor = rnd->Uniform(100);
253
22
  cf_opt->level0_file_num_compaction_trigger = rnd->Uniform(100);
254
22
  cf_opt->level0_slowdown_writes_trigger = rnd->Uniform(100);
255
22
  cf_opt->level0_stop_writes_trigger = rnd->Uniform(100);
256
22
  cf_opt->max_bytes_for_level_multiplier = rnd->Uniform(100);
257
22
  cf_opt->max_grandparent_overlap_factor = rnd->Uniform(100);
258
22
  cf_opt->max_mem_compaction_level = rnd->Uniform(100);
259
22
  cf_opt->max_write_buffer_number = rnd->Uniform(100);
260
22
  cf_opt->max_write_buffer_number_to_maintain = rnd->Uniform(100);
261
22
  cf_opt->min_write_buffer_number_to_merge = rnd->Uniform(100);
262
22
  cf_opt->num_levels = rnd->Uniform(100);
263
22
  cf_opt->source_compaction_factor = rnd->Uniform(100);
264
22
  cf_opt->target_file_size_multiplier = rnd->Uniform(100);
265
266
  // size_t options
267
22
  cf_opt->arena_block_size = rnd->Uniform(10000);
268
22
  cf_opt->inplace_update_num_locks = rnd->Uniform(10000);
269
22
  cf_opt->max_successive_merges = rnd->Uniform(10000);
270
22
  cf_opt->memtable_prefix_bloom_huge_page_tlb_size = rnd->Uniform(10000);
271
22
  cf_opt->write_buffer_size = rnd->Uniform(10000);
272
273
  // uint32_t options
274
22
  cf_opt->bloom_locality = rnd->Uniform(10000);
275
22
  cf_opt->memtable_prefix_bloom_bits = rnd->Uniform(10000);
276
22
  cf_opt->memtable_prefix_bloom_probes = rnd->Uniform(10000);
277
22
  cf_opt->min_partial_merge_operands = rnd->Uniform(10000);
278
22
  cf_opt->max_bytes_for_level_base = rnd->Uniform(10000);
279
280
  // uint64_t options
281
22
  static const uint64_t uint_max = static_cast<uint64_t>(UINT_MAX);
282
22
  cf_opt->max_sequential_skip_in_iterations = uint_max + rnd->Uniform(10000);
283
22
  cf_opt->target_file_size_base = uint_max + rnd->Uniform(10000);
284
285
  // unsigned int options
286
22
  cf_opt->rate_limit_delay_max_milliseconds = rnd->Uniform(10000);
287
288
  // pointer typed options
289
22
  cf_opt->prefix_extractor.reset(RandomSliceTransform(rnd));
290
22
  cf_opt->table_factory.reset(RandomTableFactory(rnd));
291
22
  cf_opt->merge_operator.reset(RandomMergeOperator(rnd));
292
22
  if (cf_opt->compaction_filter) {
293
5
    delete cf_opt->compaction_filter;
294
5
  }
295
22
  cf_opt->compaction_filter = RandomCompactionFilter(rnd);
296
22
  cf_opt->compaction_filter_factory.reset(RandomCompactionFilterFactory(rnd));
297
298
  // custom typed options
299
22
  cf_opt->compression = RandomCompressionType(rnd);
300
22
  RandomCompressionTypeVector(cf_opt->num_levels,
301
22
                              &cf_opt->compression_per_level, rnd);
302
22
}
303
304
namespace {
305
306
enum TestBoundaryUserValueTag {
307
  TAG_INT_VALUE,
308
  TAG_STRING_VALUE,
309
};
310
311
566
Slice EncodeValue(const int64_t &value) {
312
566
  return Slice(reinterpret_cast<const char *>(&value), sizeof(value));
313
566
}
314
315
104k
int CompareValues(int64_t lhs, int64_t rhs) {
316
52.5k
  return lhs > rhs ? 1 : (lhs == rhs ? 0 : -1);
317
104k
}
318
319
104k
int CompareValues(const std::string& lhs, const std::string& rhs) {
320
104k
  return lhs.compare(rhs);
321
104k
}
322
323
566
Slice EncodeValue(const std::string &value) {
324
566
  return value;
325
566
}
326
327
template<UserBoundaryTag TAG, class T>
328
class TestBoundaryUserValue : public UserBoundaryValue {
329
 public:
330
104k
  explicit TestBoundaryUserValue(T value) : value_(value) {}
testutil.cc:_ZN7rocksdb4test12_GLOBAL__N_121TestBoundaryUserValueILj0ExEC2Ex
Line
Count
Source
330
52.3k
  explicit TestBoundaryUserValue(T value) : value_(value) {}
testutil.cc:_ZN7rocksdb4test12_GLOBAL__N_121TestBoundaryUserValueILj1ENSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEC2ES9_
Line
Count
Source
330
52.3k
  explicit TestBoundaryUserValue(T value) : value_(value) {}
331
332
523k
  UserBoundaryTag Tag() override { return TAG; }
testutil.cc:_ZN7rocksdb4test12_GLOBAL__N_121TestBoundaryUserValueILj0ExE3TagEv
Line
Count
Source
332
313k
  UserBoundaryTag Tag() override { return TAG; }
testutil.cc:_ZN7rocksdb4test12_GLOBAL__N_121TestBoundaryUserValueILj1ENSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEE3TagEv
Line
Count
Source
332
209k
  UserBoundaryTag Tag() override { return TAG; }
333
334
1.13k
  Slice Encode() override {
335
1.13k
    return EncodeValue(value_);
336
1.13k
  }
testutil.cc:_ZN7rocksdb4test12_GLOBAL__N_121TestBoundaryUserValueILj0ExE6EncodeEv
Line
Count
Source
334
566
  Slice Encode() override {
335
566
    return EncodeValue(value_);
336
566
  }
testutil.cc:_ZN7rocksdb4test12_GLOBAL__N_121TestBoundaryUserValueILj1ENSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEE6EncodeEv
Line
Count
Source
334
566
  Slice Encode() override {
335
566
    return EncodeValue(value_);
336
566
  }
337
338
208k
  int CompareTo(const UserBoundaryValue& rhs) override {
339
208k
    return CompareValues(value_, static_cast<const TestBoundaryUserValue<TAG, T>*>(&rhs)->value_);
340
208k
  }
testutil.cc:_ZN7rocksdb4test12_GLOBAL__N_121TestBoundaryUserValueILj0ExE9CompareToERKNS_17UserBoundaryValueE
Line
Count
Source
338
104k
  int CompareTo(const UserBoundaryValue& rhs) override {
339
104k
    return CompareValues(value_, static_cast<const TestBoundaryUserValue<TAG, T>*>(&rhs)->value_);
340
104k
  }
testutil.cc:_ZN7rocksdb4test12_GLOBAL__N_121TestBoundaryUserValueILj1ENSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEE9CompareToERKNS_17UserBoundaryValueE
Line
Count
Source
338
104k
  int CompareTo(const UserBoundaryValue& rhs) override {
339
104k
    return CompareValues(value_, static_cast<const TestBoundaryUserValue<TAG, T>*>(&rhs)->value_);
340
104k
  }
341
342
16
  const T& value() const {
343
16
    return value_;
344
16
  }
testutil.cc:_ZNK7rocksdb4test12_GLOBAL__N_121TestBoundaryUserValueILj0ExE5valueEv
Line
Count
Source
342
8
  const T& value() const {
343
8
    return value_;
344
8
  }
testutil.cc:_ZNK7rocksdb4test12_GLOBAL__N_121TestBoundaryUserValueILj1ENSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEE5valueEv
Line
Count
Source
342
8
  const T& value() const {
343
8
    return value_;
344
8
  }
345
346
104k
  virtual ~TestBoundaryUserValue() {}
testutil.cc:_ZN7rocksdb4test12_GLOBAL__N_121TestBoundaryUserValueILj0ExED2Ev
Line
Count
Source
346
52.3k
  virtual ~TestBoundaryUserValue() {}
testutil.cc:_ZN7rocksdb4test12_GLOBAL__N_121TestBoundaryUserValueILj1ENSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEED2Ev
Line
Count
Source
346
52.3k
  virtual ~TestBoundaryUserValue() {}
347
 private:
348
  T value_;
349
};
350
351
// Use some weird logic to extract int value from key.
352
102k
int64_t ExtractIntValue(Slice key) {
353
102k
  return boost::hash_range(key.data(), key.end());
354
102k
}
355
356
// Use some weird logic to extract string value from key.
357
102k
std::string ExtractStringValue(Slice key) {
358
102k
  std::string temp = key.ToBuffer();
359
102k
  std::reverse(temp.begin(), temp.end());
360
102k
  return temp;
361
102k
}
362
363
typedef TestBoundaryUserValue<TAG_INT_VALUE, int64_t> IntValue;
364
typedef TestBoundaryUserValue<TAG_STRING_VALUE, std::string> StringValue;
365
366
class TestBoundaryValuesExtractor: public BoundaryValuesExtractor {
367
 public:
368
60
  Status Decode(UserBoundaryTag tag, Slice data, UserBoundaryValuePtr *value) override {
369
60
    switch (static_cast<TestBoundaryUserValueTag>(tag)) {
370
30
      case TAG_INT_VALUE: {
371
30
        if (sizeof(int64_t) != data.size()) {
372
0
          return STATUS(Corruption, "Invalid size of data " + std::to_string(data.size()));
373
0
        }
374
375
30
        int64_t temp;
376
30
        memcpy(&temp, data.data(), sizeof(temp));
377
30
        *value = std::make_shared<IntValue>(temp);
378
30
        break;
379
30
      }
380
30
      case TAG_STRING_VALUE:
381
30
        *value = std::make_shared<StringValue>(data.ToBuffer());
382
30
        break;
383
60
    }
384
60
    return Status::OK();
385
60
  }
386
387
0
  Status Extract(Slice user_key, Slice value, UserBoundaryValues *values) override {
388
0
    values->push_back(MakeIntBoundaryValue(ExtractIntValue(user_key)));
389
0
    values->push_back(MakeStringBoundaryValue(ExtractStringValue(user_key)));
390
0
    return Status::OK();
391
0
  }
392
393
35
  UserFrontierPtr CreateFrontier() override {
394
35
    return new TestUserFrontier(0);
395
35
  }
396
397
34
  virtual ~TestBoundaryValuesExtractor() {}
398
 private:
399
};
400
401
} // namespace
402
403
84
std::string TestUserFrontier::ToString() const {
404
84
  return YB_CLASS_TO_STRING(value);
405
84
}
406
407
0
int64_t GetBoundaryInt(const UserBoundaryValues& values) {
408
0
  auto value = UserValueWithTag(values, TAG_INT_VALUE);
409
0
  EXPECT_NE(value, nullptr);
410
0
  auto* int_value = down_cast<IntValue*>(value.get());
411
0
  return int_value ? int_value->value() : 0;
412
0
}
413
414
0
std::string GetBoundaryString(const UserBoundaryValues& values) {
415
0
  auto value = UserValueWithTag(values, TAG_STRING_VALUE);
416
0
  EXPECT_NE(value, nullptr);
417
0
  auto* string_value = down_cast<StringValue*>(value.get());
418
0
  return string_value ? string_value->value() : std::string();
419
0
}
420
421
34
std::shared_ptr<BoundaryValuesExtractor> MakeBoundaryValuesExtractor() {
422
34
  return std::make_shared<TestBoundaryValuesExtractor>();
423
34
}
424
425
52.2k
UserBoundaryValuePtr MakeIntBoundaryValue(int64_t value) {
426
52.2k
  return std::make_shared<TestBoundaryUserValue<TAG_INT_VALUE, int64_t>>(value);
427
52.2k
}
428
429
52.2k
UserBoundaryValuePtr MakeStringBoundaryValue(std::string value) {
430
52.2k
  return std::make_shared<TestBoundaryUserValue<TAG_STRING_VALUE, std::string>>(std::move(value));
431
52.2k
}
432
433
50.2k
void BoundaryTestValues::Feed(Slice key) {
434
50.2k
  auto int_value = ExtractIntValue(key);
435
50.2k
  min_int = std::min(min_int, int_value);
436
50.2k
  max_int = std::max(max_int, int_value);
437
50.2k
  auto string_value = ExtractStringValue(key);
438
50.2k
  if (min_string.empty()) {
439
44
    min_string = string_value;
440
44
    max_string = std::move(string_value);
441
50.1k
  } else {
442
50.1k
    if (string_value < min_string) {
443
4
      min_string = std::move(string_value);
444
50.1k
    } else if (string_value > max_string) {
445
249
      max_string = std::move(string_value);
446
249
    }
447
50.1k
  }
448
50.2k
}
449
450
void BoundaryTestValues::Check(const FileBoundaryValues<InternalKey>& smallest,
451
1
                               const FileBoundaryValues<InternalKey>& largest) {
452
1
  ASSERT_EQ(min_int, GetBoundaryInt(smallest.user_values));
453
1
  ASSERT_EQ(max_int, GetBoundaryInt(largest.user_values));
454
1
  ASSERT_EQ(min_string, GetBoundaryString(smallest.user_values));
455
1
  ASSERT_EQ(max_string, GetBoundaryString(largest.user_values));
456
1
}
457
458
459
}  // namespace test
460
}  // namespace rocksdb