YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/docdb/doc_kv_util-test.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) YugaByte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
//
13
14
#include <string>
15
16
#include <gtest/gtest.h>
17
18
#include "yb/common/schema.h"
19
20
#include "yb/docdb/doc_kv_util.h"
21
#include "yb/docdb/doc_ttl_util.h"
22
#include "yb/docdb/value.h"
23
24
#include "yb/rocksdb/util/random.h"
25
26
#include "yb/util/monotime.h"
27
#include "yb/util/slice.h"
28
#include "yb/util/test_macros.h"
29
30
using namespace std::literals;
31
using std::string;
32
33
namespace yb {
34
namespace docdb {
35
36
TEST(DocKVUtilTest, KeyBelongsToDocKeyInTest) {
37
  string actual_key = "mydockey";
38
  actual_key.push_back('\x0');
39
  const string actual_key_with_one_zero = actual_key;
40
  actual_key.push_back('\x0');
41
  ASSERT_TRUE(KeyBelongsToDocKeyInTest(rocksdb::Slice(actual_key), "mydockey"));
42
  ASSERT_FALSE(KeyBelongsToDocKeyInTest(rocksdb::Slice(actual_key_with_one_zero), "mydockey"));
43
  ASSERT_FALSE(KeyBelongsToDocKeyInTest(rocksdb::Slice("mydockey"), "mydockey"));
44
  ASSERT_FALSE(KeyBelongsToDocKeyInTest(rocksdb::Slice(""), ""));
45
46
  string just_two_zeros;
47
  just_two_zeros.push_back('\x0');
48
  just_two_zeros.push_back('\x0');
49
  ASSERT_TRUE(KeyBelongsToDocKeyInTest(rocksdb::Slice(just_two_zeros), ""));
50
  ASSERT_FALSE(KeyBelongsToDocKeyInTest(rocksdb::Slice(just_two_zeros), just_two_zeros));
51
}
52
53
0
TEST(DocKVUtilTest, EncodeAndDecodeHybridTimeInKey) {
54
0
  string initial_str;
55
0
  HybridTimeRepr cur_ht_value = 0;
56
0
  for (int i = 0; i < 10; ++i) {
57
0
    initial_str.push_back('a');
58
0
    string buf = initial_str;
59
0
    static constexpr int kNumHTValuesToTry = 10;
60
0
    for (int j = 0; j < kNumHTValuesToTry ; ++j) {
61
0
      static constexpr int kNumWriteIdsToTry = 10;
62
0
      for (int k = 0; k < kNumWriteIdsToTry; ++k) {
63
0
        const auto write_id = std::numeric_limits<IntraTxnWriteId>::max() / kNumWriteIdsToTry * k;
64
0
        const auto htw = DocHybridTime(HybridTime(cur_ht_value), write_id);
65
0
        htw.AppendEncodedInDocDbFormat(&buf);
66
0
        rocksdb::Slice slice(buf);
67
0
        DocHybridTime decoded_ht;
68
0
        ASSERT_OK(DecodeHybridTimeFromEndOfKey(slice, &decoded_ht));
69
0
        ASSERT_EQ(htw, decoded_ht);
70
0
      }
71
0
      cur_ht_value += std::numeric_limits<uint64_t>::max() / kNumHTValuesToTry;
72
0
    }
73
0
  }
74
0
}
75
76
TEST(DocKVUtilTest, AppendZeroEncodedStrToKey) {
77
  KeyBuffer buf("a"s);
78
  AppendZeroEncodedStrToKey("bc", &buf);
79
  ASSERT_EQ("abc", buf.ToStringBuffer());
80
  string str_with_embedded_zeros = "f";
81
  str_with_embedded_zeros.push_back('\x0');
82
  str_with_embedded_zeros.push_back('g');
83
  AppendZeroEncodedStrToKey(str_with_embedded_zeros, &buf);
84
  ASSERT_EQ(7, buf.size());
85
  ASSERT_EQ('f', buf[3]);
86
  ASSERT_EQ('\x00', buf[4]);
87
  ASSERT_EQ('\x01', buf[5]);
88
  ASSERT_EQ('g', buf[6]);
89
}
90
91
TEST(DocKVUtilTest, TerminateZeroEncodedKeyStr) {
92
  KeyBuffer buf("a"s);
93
  TerminateZeroEncodedKeyStr(&buf);
94
  ASSERT_EQ(3, buf.size());
95
  ASSERT_EQ('a', buf[0]);
96
  ASSERT_EQ('\x0', buf[1]);
97
  ASSERT_EQ('\x0', buf[2]);
98
}
99
100
0
TEST(DocKVUtilTest, ZeroEncodingAndDecoding) {
101
0
  rocksdb::Random rng(12345); // initialize with a fixed seed
102
0
  for (int i = 0; i < 1000; ++i) {
103
0
    int len = rng.Next() % 200;
104
0
    string s;
105
0
    s.reserve(len);
106
0
    for (int j = 0; j < len; ++j) {
107
0
      s.push_back(static_cast<char>(rng.Next()));
108
0
    }
109
0
    string encoded_str = ZeroEncodeStr(s);
110
0
    size_t expected_size_when_no_zeros = s.size() + kEncodedKeyStrTerminatorSize;
111
0
    if (s.find('\0') == string::npos) {
112
0
      ASSERT_EQ(expected_size_when_no_zeros, encoded_str.size());
113
0
    } else {
114
0
      ASSERT_LT(expected_size_when_no_zeros, encoded_str.size());
115
0
    }
116
0
    string decoded_str = DecodeZeroEncodedStr(encoded_str);
117
0
    ASSERT_EQ(s, decoded_str);
118
0
  }
119
0
}
120
121
0
TEST(DocKVUtilTest, TableTTL) {
122
0
  Schema schema;
123
0
  EXPECT_TRUE(TableTTL(schema).Equals(Value::kMaxTtl));
124
125
0
  schema.SetDefaultTimeToLive(1000);
126
0
  EXPECT_TRUE(MonoDelta::FromMilliseconds(1000).Equals(TableTTL(schema)));
127
0
}
128
129
0
TEST(DocKVUtilTest, ComputeTTL) {
130
0
  Schema schema;
131
0
  schema.SetDefaultTimeToLive(1000);
132
133
0
  MonoDelta value_ttl = MonoDelta::FromMilliseconds(2000);
134
135
0
  EXPECT_TRUE(MonoDelta::FromMilliseconds(2000).Equals(ComputeTTL(value_ttl, schema)));
136
0
  EXPECT_TRUE(MonoDelta::FromMilliseconds(1000).Equals(ComputeTTL(Value::kMaxTtl, schema)));
137
138
0
  MonoDelta reset_ttl = MonoDelta::FromMilliseconds(0);
139
0
  EXPECT_TRUE(ComputeTTL(reset_ttl, schema).Equals(Value::kMaxTtl));
140
0
}
141
142
TEST(DocKVUtilTest, FileExpirationFromValueTTL) {
143
  HybridTime key_hybrid_time = 1000_usec_ht;
144
145
  MonoDelta value_ttl = Value::kMaxTtl;
146
  EXPECT_EQ(FileExpirationFromValueTTL(key_hybrid_time, value_ttl), kUseDefaultTTL);
147
148
  value_ttl = Value::kResetTtl;
149
  EXPECT_EQ(FileExpirationFromValueTTL(key_hybrid_time, value_ttl), kNoExpiration);
150
151
  value_ttl = MonoDelta::FromMicroseconds(1000);
152
  EXPECT_EQ(FileExpirationFromValueTTL(key_hybrid_time, value_ttl), 2000_usec_ht);
153
154
  key_hybrid_time = HybridTime::kInvalid;
155
  EXPECT_EQ(FileExpirationFromValueTTL(key_hybrid_time, value_ttl), kNoExpiration);
156
157
  key_hybrid_time = HybridTime::kMax;
158
  EXPECT_EQ(FileExpirationFromValueTTL(key_hybrid_time, value_ttl), kNoExpiration);
159
}
160
161
TEST(DocKVUtilTest, MaxExpirationFromValueAndTableTTL) {
162
  HybridTime key_ht = 1000_usec_ht;
163
  MonoDelta table_ttl;
164
  HybridTime val_expiry_ht;
165
166
  val_expiry_ht = 2000_usec_ht;
167
  table_ttl = Value::kMaxTtl;
168
  EXPECT_EQ(MaxExpirationFromValueAndTableTTL(key_ht, table_ttl, val_expiry_ht), val_expiry_ht);
169
  val_expiry_ht = kUseDefaultTTL;
170
  EXPECT_EQ(MaxExpirationFromValueAndTableTTL(key_ht, table_ttl, val_expiry_ht), kNoExpiration);
171
  val_expiry_ht = kNoExpiration;
172
  EXPECT_EQ(MaxExpirationFromValueAndTableTTL(key_ht, table_ttl, val_expiry_ht), kNoExpiration);
173
174
  table_ttl = MonoDelta::FromMicroseconds(500);
175
  val_expiry_ht = 2000_usec_ht;
176
  EXPECT_EQ(MaxExpirationFromValueAndTableTTL(key_ht, table_ttl, val_expiry_ht), val_expiry_ht);
177
  val_expiry_ht = 1100_usec_ht;
178
  EXPECT_EQ(MaxExpirationFromValueAndTableTTL(key_ht, table_ttl, val_expiry_ht), 1500_usec_ht);
179
  val_expiry_ht = kNoExpiration;
180
  EXPECT_EQ(MaxExpirationFromValueAndTableTTL(key_ht, table_ttl, val_expiry_ht), kNoExpiration);
181
  val_expiry_ht = kUseDefaultTTL;
182
  EXPECT_EQ(MaxExpirationFromValueAndTableTTL(key_ht, table_ttl, val_expiry_ht), 1500_usec_ht);
183
184
  key_ht = HybridTime::kMax;
185
  val_expiry_ht = 2000_usec_ht;
186
  EXPECT_EQ(MaxExpirationFromValueAndTableTTL(key_ht, table_ttl, val_expiry_ht), kNoExpiration);
187
  key_ht = HybridTime::kInvalid;
188
  EXPECT_EQ(MaxExpirationFromValueAndTableTTL(key_ht, table_ttl, val_expiry_ht), kNoExpiration);
189
}
190
191
0
TEST(DocKVUtilTest, FloatEncoding) {
192
0
  vector<float> numbers = {-123.45f, -0.00123f, -0.0f, 0.0f, 0.00123f, 123.45f};
193
0
  vector<string> strings;
194
0
  for (size_t i = 0; i < numbers.size(); i++) {
195
0
    string s;
196
0
    util::AppendFloatToKey(numbers[i], &s);
197
0
    strings.push_back(s);
198
0
    EXPECT_EQ(numbers[i], util::DecodeFloatFromKey(rocksdb::Slice(s)));
199
0
  }
200
0
  for (size_t i = 1; i < numbers.size(); i++) {
201
0
    EXPECT_LT(strings[i-1], strings[i]);
202
0
  }
203
0
}
204
205
0
TEST(DocKVUtilTest, DoubleEncoding) {
206
0
  vector<double> numbers = {-123.45f, -0.00123f, -0.0f, 0.0f, 0.00123f, 123.45f};
207
0
  vector<string> strings;
208
0
  for (size_t i = 0; i < numbers.size(); i++) {
209
0
    string s;
210
0
    util::AppendDoubleToKey(numbers[i], &s);
211
0
    strings.push_back(s);
212
0
    EXPECT_EQ(numbers[i], util::DecodeDoubleFromKey(rocksdb::Slice(s)));
213
0
  }
214
0
  for (size_t i = 1; i < numbers.size(); i++) {
215
0
    EXPECT_LT(strings[i-1], strings[i]);
216
0
  }
217
0
}
218
219
0
TEST(DocKVUtilTest, UInt64Encoding) {
220
0
  vector<uint64_t> numbers = {0, 1, 100, 9223372036854775807ULL, 18446744073709551615ULL};
221
0
  vector<string> strings;
222
0
  for (size_t i = 0; i < numbers.size(); i++) {
223
0
    string s;
224
0
    AppendUInt64ToKey(numbers[i], &s);
225
0
    strings.push_back(s);
226
0
    EXPECT_EQ(numbers[i], BigEndian::Load64(s.c_str()));
227
0
  }
228
0
  for (size_t i = 1; i < numbers.size(); i++) {
229
0
    EXPECT_LT(strings[i-1], strings[i]);
230
0
  }
231
0
}
232
233
}  // namespace docdb
234
}  // namespace yb