YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/server/doc_hybrid_time-test.cc
Line
Count
Source
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 "yb/common/doc_hybrid_time.h"
17
18
#include "yb/gutil/ref_counted.h"
19
20
#include "yb/server/hybrid_clock.h"
21
22
#include "yb/util/bytes_formatter.h"
23
#include "yb/util/string_trim.h"
24
#include "yb/util/test_macros.h"
25
#include "yb/util/test_util.h"
26
27
using std::string;
28
using std::vector;
29
using std::tuple;
30
using std::cout;
31
using std::endl;
32
33
using yb::server::HybridClock;
34
using yb::FormatBytesAsStr;
35
using yb::util::sgn;
36
using strings::Substitute;
37
38
namespace yb {
39
40
1
TEST(DocHybridTimeTest, TestDocDbFormatEncodeDecode) {
41
1
  auto clock = make_scoped_refptr<HybridClock>(new HybridClock());
42
1
  ASSERT_OK(clock->Init());
43
1
  vector<DocHybridTime> timestamps;
44
1
  vector<string> encoded_timestamps;
45
1
  unsigned int seed = SeedRandom();
46
47
  // Increase this to e.g. an extreme value of 100 to test how big timestamps will become in the
48
  // future.
49
1
  constexpr int kAddNumYears = 0;
50
51
10.0k
  for (int i = 0; i < 10000; ++i) {
52
10.0k
    const IntraTxnWriteId write_id = rand_r(&seed) % 1000 + 1;
53
54
10.0k
    timestamps.emplace_back(
55
10.0k
        HybridClock::AddPhysicalTimeToHybridTime(
56
10.0k
            clock->Now(),
57
10.0k
            MonoDelta::FromSeconds(kAddNumYears * 3600 * 24 * 365)),
58
10.0k
        write_id);
59
10.0k
    timestamps.pop_back();
60
10.0k
    timestamps.push_back(DocHybridTime(1492469267789800, 0, 1));
61
62
10.0k
    const DocHybridTime& last_ts = timestamps.back();
63
10.0k
    encoded_timestamps.emplace_back(timestamps.back().EncodedInDocDbFormat());
64
10.0k
    const string& last_ts_encoded = encoded_timestamps.back();
65
10.0k
    const auto encoded_size = encoded_timestamps.back().size();
66
    // Encoded size will sometimes be only 6 bytes if both logical component and write id are zero.
67
10.0k
    ASSERT_GE(encoded_size, 6);
68
10.0k
    ASSERT_LE(encoded_size, 12);
69
    // We store the encoded length of the whole DocHybridTime into its last 5 bits.
70
10.0k
    ASSERT_EQ(encoded_size, last_ts_encoded.back() & 0x1f);
71
10.0k
    DocHybridTime decoded_ts;
72
10.0k
    ASSERT_OK_PREPEND(
73
10.0k
        decoded_ts.FullyDecodeFrom(last_ts_encoded),
74
10.0k
        Substitute("Could not decode from $0", FormatBytesAsStr(last_ts_encoded)));
75
10.0k
    ASSERT_EQ(last_ts, decoded_ts);
76
10.0k
  }
77
78
10.0k
  for (int iteration = 0; iteration < 10000; ++iteration) {
79
10.0k
    const int i = rand_r(&seed) % timestamps.size();
80
10.0k
    const int j = rand_r(&seed) % timestamps.size();
81
10.0k
    const auto& ts1 = timestamps[i];
82
10.0k
    const auto& ts2 = timestamps[j];
83
10.0k
    const auto& encoded1 = encoded_timestamps[i];
84
10.0k
    const auto& encoded2 = encoded_timestamps[j];
85
    // Encoded representations of timestamps should compare in the reverse order of decoded ones.
86
10.0k
    ASSERT_EQ(sgn(ts1.CompareTo(ts2)), -sgn(encoded1.compare(encoded2)));
87
10.0k
  }
88
1
}
89
90
1
TEST(DocHybridTimeTest, TestToString) {
91
1
  ASSERT_EQ("HT{ physical: 100200300400 }",
92
1
            DocHybridTime(100200300400, 0, kMinWriteId).ToString());
93
1
  ASSERT_EQ("HT{ physical: 100200300400 logical: 4095 }",
94
1
            DocHybridTime(100200300400, 4095, 0).ToString());
95
1
  ASSERT_EQ("HT{ physical: 100200300400 w: 123 }",
96
1
            DocHybridTime(100200300400, 0, 123).ToString());
97
1
  ASSERT_EQ("HT{ physical: 100200300400 logical: 2222 w: 123 }",
98
1
            DocHybridTime(100200300400, 2222, 123).ToString());
99
1
}
100
101
1
TEST(DocHybridTimeTest, TestExactByteRepresentation) {
102
1
  const auto kYugaEpoch = kYugaByteMicrosecondEpoch;
103
104
1
  struct TestDesc {
105
1
    string expected_bytes_str;
106
1
    MicrosTime micros;
107
1
    LogicalTimeComponent logical;
108
1
    IntraTxnWriteId write_id;
109
110
112
    DocHybridTime ToHybridTime() const {
111
112
      return DocHybridTime (micros, logical, write_id);
112
112
    }
113
114
32
    string ActualFormattedByteStr() const {
115
32
      return FormatBytesAsStr(ToHybridTime().EncodedInDocDbFormat());
116
32
    }
117
1
  };
118
1
  using std::get;
119
120
1
  vector<TestDesc> test_descriptions{
121
1
      TestDesc{ R"#("\x80\x07\xc4e5\xff\x80H")#",
122
1
                kYugaEpoch + 1000000000, 0, kMinWriteId },
123
124
1
      TestDesc{ R"#("\x80\x10\xbd\xbf;-\x03\xdf\xff\xff\xff\xec")#",
125
1
                kYugaEpoch + 1000000, 1234, 4294967295 },
126
127
1
      TestDesc{ R"#("\x80\x10\xbd\xbf;-G")#",
128
1
                kYugaEpoch + 1000000, 1234, kMinWriteId },
129
130
1
      TestDesc{ R"#("\x80\x10\xbd\xbf\x80\x03\xdf\xff\xff\xff\xeb")#",
131
1
                kYugaEpoch + 1000000, 0, 4294967295 },
132
133
1
      TestDesc{ R"#("\x80\x10\xbd\xbf\x80F")#",
134
1
                kYugaEpoch + 1000000, 0, kMinWriteId },
135
136
1
      TestDesc{ R"#("\x80<\x17\x80E")#",
137
1
                kYugaEpoch + 1000, 0, kMinWriteId },
138
139
1
      TestDesc{ R"#("\x80?\x0b=\xbfF")#",
140
1
                kYugaEpoch, 1000000, kMinWriteId },
141
142
1
      TestDesc{ R"#("\x80\x80<\x17E")#",
143
1
                kYugaEpoch, 1000, kMinWriteId },
144
145
1
      TestDesc{ R"#("\x80\x80\x80\x0e\x17\xb7\xc7")#",
146
1
                kYugaEpoch, 0, 1000000 },
147
148
1
      TestDesc{ R"#("\x80\x80\x80\x1f\x82\xc6")#",
149
1
                kYugaEpoch, 0, 1000 },
150
151
1
      TestDesc{ R"#("\x80\x80\x80D")#",
152
1
                kYugaEpoch, 0, kMinWriteId },
153
154
1
      TestDesc{ R"#("\x80\xc3\xe8\x80E")#",
155
1
                kYugaEpoch - 1000, 0, kMinWriteId },
156
157
1
      TestDesc{ R"#("\x80\xefB@\x80F")#",
158
1
                kYugaEpoch - 1000000, 0, kMinWriteId },
159
160
1
      TestDesc{ R"#("\x80\xf8;\x9a\xca\x00\x80H")#",
161
1
                kYugaEpoch - 1000000000, 0, kMinWriteId },
162
163
1
      TestDesc{ R"#("\x80\xff\x01\xc6\xbfRc@\x00\x80K")#",
164
1
                1000000000000000LL, 0, kMinWriteId },
165
166
1
      TestDesc{ R"#("\x80\xff\x05T=\xf7)\xc0\x00\x80K")#",
167
1
                kYugaEpoch - 1500000000000000, 0, kMinWriteId },
168
1
  };
169
170
  // Sort so that the copy-and-paste-able correct answers always come out in the sorted order.
171
1
  sort(test_descriptions.begin(), test_descriptions.end(),
172
32
       [](const TestDesc& a, const TestDesc& b) -> bool {
173
         // Sort in reverse order (latest timestamps first).
174
32
         return a.ToHybridTime() > b.ToHybridTime();
175
32
       });
176
177
  // Generate expected answers that can be copied and pasted into the code above.
178
16
  for (const auto& t : test_descriptions) {
179
16
    string micros_str;
180
16
    const auto micros = t.micros;
181
16
    if (llabs(static_cast<int64_t>(micros) - static_cast<int64_t>(kYugaEpoch)) <= 1000000000) {
182
14
      if (micros == kYugaEpoch) {
183
5
        micros_str = "kYugaEpoch";
184
9
      } else if (micros > kYugaEpoch) {
185
6
        micros_str = Substitute("kYugaEpoch + $0", micros - kYugaByteMicrosecondEpoch);
186
3
      } else {
187
3
        micros_str = Substitute("kYugaEpoch - $0", kYugaByteMicrosecondEpoch - micros);
188
3
      }
189
2
    } else {
190
2
      micros_str = std::to_string(micros) + "LL";
191
2
    }
192
16
    cout << Substitute("TestDesc{ R\"#($0)#\",\n"
193
16
                       "          $1, $2, $3 },\n",
194
16
                       t.ActualFormattedByteStr(), micros_str, t.logical,
195
12
                       t.write_id == kMinWriteId ? "kMinWriteId" : std::to_string(t.write_id))
196
16
         << endl;
197
16
  }
198
199
16
  for (const auto& t : test_descriptions) {
200
16
    SCOPED_TRACE(t.ToHybridTime().ToString());
201
16
    EXPECT_STR_EQ_VERBOSE_TRIMMED(t.expected_bytes_str, t.ActualFormattedByteStr());
202
16
  }
203
1
}
204
205
1
TEST(DocHybridTimeTest, DefaultConstructionAndComparison) {
206
1
  const auto default_value = DocHybridTime();
207
1
  EXPECT_EQ(kInvalidHybridTimeValue, default_value.hybrid_time().value());
208
1
  EXPECT_EQ(kMinWriteId, default_value.write_id());
209
210
1
  ASSERT_EQ(DocHybridTime(0, 0, 0), DocHybridTime(0, 0, 0));
211
212
1
  EXPECT_LE(DocHybridTime(0, 0, 0), DocHybridTime(0, 0, 0));
213
1
  EXPECT_GE(DocHybridTime(0, 0, 0), DocHybridTime(0, 0, 0));
214
215
1
  EXPECT_LT(DocHybridTime(0, 0, 0), DocHybridTime(1, 0, 0));
216
1
  EXPECT_LT(DocHybridTime(0, 0, 0), DocHybridTime(0, 1, 0));
217
1
  EXPECT_LT(DocHybridTime(0, 0, 0), DocHybridTime(0, 0, 1));
218
1
  EXPECT_LE(DocHybridTime(0, 0, 0), DocHybridTime(1, 0, 0));
219
1
  EXPECT_LE(DocHybridTime(0, 0, 0), DocHybridTime(0, 1, 0));
220
1
  EXPECT_LE(DocHybridTime(0, 0, 0), DocHybridTime(0, 0, 1));
221
222
1
  EXPECT_GT(DocHybridTime(0, 0, 1), DocHybridTime(0, 0, 0));
223
1
  EXPECT_GT(DocHybridTime(0, 1, 0), DocHybridTime(0, 0, 0));
224
1
  EXPECT_GT(DocHybridTime(1, 0, 0), DocHybridTime(0, 0, 0));
225
1
  EXPECT_GE(DocHybridTime(0, 0, 1), DocHybridTime(0, 0, 0));
226
1
  EXPECT_GE(DocHybridTime(0, 1, 0), DocHybridTime(0, 0, 0));
227
1
  EXPECT_GE(DocHybridTime(1, 0, 0), DocHybridTime(0, 0, 0));
228
229
1
  EXPECT_NE(DocHybridTime(0, 0, 0), DocHybridTime(1, 0, 0));
230
1
  EXPECT_NE(DocHybridTime(0, 0, 0), DocHybridTime(0, 1, 0));
231
1
  EXPECT_NE(DocHybridTime(0, 0, 0), DocHybridTime(0, 0, 1));
232
233
1
  EXPECT_LT(DocHybridTime(10, 20, 0), DocHybridTime(20, 10, 0));
234
1
  EXPECT_LT(DocHybridTime(0, 10, 20), DocHybridTime(0, 20, 10));
235
1
  EXPECT_LT(DocHybridTime(10, 0, 20), DocHybridTime(20, 0, 10));
236
1
  EXPECT_LE(DocHybridTime(10, 20, 0), DocHybridTime(20, 10, 0));
237
1
  EXPECT_LE(DocHybridTime(0, 10, 20), DocHybridTime(0, 20, 10));
238
1
  EXPECT_LE(DocHybridTime(10, 0, 20), DocHybridTime(20, 0, 10));
239
240
1
  EXPECT_GT(DocHybridTime(20, 10, 0), DocHybridTime(10, 20, 0));
241
1
  EXPECT_GT(DocHybridTime(0, 20, 10), DocHybridTime(0, 10, 20));
242
1
  EXPECT_GT(DocHybridTime(20, 0, 10), DocHybridTime(10, 0, 20));
243
1
  EXPECT_GE(DocHybridTime(20, 10, 0), DocHybridTime(10, 20, 0));
244
1
  EXPECT_GE(DocHybridTime(0, 20, 10), DocHybridTime(0, 10, 20));
245
1
  EXPECT_GE(DocHybridTime(20, 0, 10), DocHybridTime(10, 0, 20));
246
1
}
247
248
}  // namespace yb