YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/docdb/consensus_frontier-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
#include <google/protobuf/any.pb.h>
14
15
#include "yb/docdb/consensus_frontier.h"
16
#include "yb/docdb/docdb.pb.h"
17
#include "yb/gutil/casts.h"
18
#include "yb/rocksdb/metadata.h"
19
#include "yb/util/test_util.h"
20
21
using rocksdb::UpdateUserValueType;
22
23
namespace yb {
24
namespace docdb {
25
26
class ConsensusFrontierTest : public YBTest {
27
};
28
29
namespace {
30
31
0
std::string PbToString(const ConsensusFrontierPB& pb) {
32
0
  google::protobuf::Any any;
33
0
  any.PackFrom(pb);
34
0
  ConsensusFrontier frontier;
35
0
  frontier.FromPB(any);
36
0
  return frontier.ToString();
37
0
}
38
39
}  // anonymous namespace
40
41
TEST_F(ConsensusFrontierTest, TestUpdates) {
42
  {
43
    ConsensusFrontier frontier;
44
    EXPECT_TRUE(frontier.Equals(frontier));
45
    EXPECT_EQ(
46
        "{ op_id: 0.0 hybrid_time: <invalid> history_cutoff: <invalid> "
47
        "hybrid_time_filter: <invalid> max_value_level_ttl_expiration_time: <invalid> }",
48
        frontier.ToString());
49
    EXPECT_TRUE(frontier.IsUpdateValid(frontier, UpdateUserValueType::kLargest));
50
    EXPECT_TRUE(frontier.IsUpdateValid(frontier, UpdateUserValueType::kSmallest));
51
52
    ConsensusFrontier opid1{{0, 1}, HybridTime::kInvalid, HybridTime::kInvalid};
53
    EXPECT_TRUE(frontier.IsUpdateValid(opid1, UpdateUserValueType::kLargest));
54
  }
55
56
  {
57
    ConsensusFrontier frontier{{1, 1}, 1000_usec_ht, 500_usec_ht};
58
    EXPECT_EQ(
59
        "{ op_id: 1.1 hybrid_time: { physical: 1000 } history_cutoff: { physical: 500 } "
60
        "hybrid_time_filter: <invalid> max_value_level_ttl_expiration_time: <invalid> }",
61
        frontier.ToString());
62
    ConsensusFrontier higher_idx{{1, 2}, 1000_usec_ht, 500_usec_ht};
63
    ConsensusFrontier higher_ht{{1, 1}, 1001_usec_ht, 500_usec_ht};
64
    ConsensusFrontier higher_cutoff{{1, 1}, 1000_usec_ht, 501_usec_ht};
65
    ConsensusFrontier higher_idx_lower_ht{{1, 2}, 999_usec_ht, 500_usec_ht};
66
67
    EXPECT_TRUE(higher_idx.Dominates(frontier, UpdateUserValueType::kLargest));
68
    EXPECT_TRUE(higher_ht.Dominates(frontier, UpdateUserValueType::kLargest));
69
    EXPECT_TRUE(higher_cutoff.Dominates(frontier, UpdateUserValueType::kLargest));
70
    EXPECT_FALSE(higher_idx.Dominates(frontier, UpdateUserValueType::kSmallest));
71
    EXPECT_FALSE(higher_ht.Dominates(frontier, UpdateUserValueType::kSmallest));
72
    EXPECT_FALSE(higher_cutoff.Dominates(frontier, UpdateUserValueType::kSmallest));
73
    EXPECT_FALSE(frontier.Dominates(higher_idx, UpdateUserValueType::kLargest));
74
    EXPECT_FALSE(frontier.Dominates(higher_ht, UpdateUserValueType::kLargest));
75
    EXPECT_FALSE(frontier.Dominates(higher_cutoff, UpdateUserValueType::kLargest));
76
    EXPECT_TRUE(frontier.Dominates(higher_idx, UpdateUserValueType::kSmallest));
77
    EXPECT_TRUE(frontier.Dominates(higher_ht, UpdateUserValueType::kSmallest));
78
    EXPECT_TRUE(frontier.Dominates(higher_cutoff, UpdateUserValueType::kSmallest));
79
80
    // frontier and higher_idx_lower_ht are "incomparable" according to the "dominates" ordering.
81
    EXPECT_FALSE(frontier.Dominates(higher_idx_lower_ht, UpdateUserValueType::kSmallest));
82
    EXPECT_FALSE(frontier.Dominates(higher_idx_lower_ht, UpdateUserValueType::kLargest));
83
    EXPECT_FALSE(higher_idx_lower_ht.Dominates(frontier, UpdateUserValueType::kSmallest));
84
    EXPECT_FALSE(higher_idx_lower_ht.Dominates(frontier, UpdateUserValueType::kLargest));
85
86
    EXPECT_TRUE(frontier.IsUpdateValid(higher_idx, UpdateUserValueType::kLargest));
87
    EXPECT_TRUE(frontier.IsUpdateValid(higher_ht, UpdateUserValueType::kLargest));
88
    EXPECT_FALSE(higher_idx.IsUpdateValid(frontier, UpdateUserValueType::kLargest));
89
    EXPECT_FALSE(higher_ht.IsUpdateValid(frontier, UpdateUserValueType::kLargest));
90
    EXPECT_FALSE(frontier.IsUpdateValid(higher_idx, UpdateUserValueType::kSmallest));
91
    EXPECT_FALSE(frontier.IsUpdateValid(higher_ht, UpdateUserValueType::kSmallest));
92
    EXPECT_TRUE(higher_idx.IsUpdateValid(frontier, UpdateUserValueType::kSmallest));
93
    EXPECT_TRUE(higher_ht.IsUpdateValid(frontier, UpdateUserValueType::kSmallest));
94
95
    EXPECT_FALSE(higher_idx_lower_ht.IsUpdateValid(frontier, UpdateUserValueType::kLargest));
96
    EXPECT_FALSE(frontier.IsUpdateValid(higher_idx_lower_ht, UpdateUserValueType::kSmallest));
97
98
    // It is OK if a later compaction runs at a lower history_cutoff.
99
    EXPECT_TRUE(frontier.IsUpdateValid(higher_cutoff, UpdateUserValueType::kLargest));
100
    EXPECT_TRUE(frontier.IsUpdateValid(higher_cutoff, UpdateUserValueType::kSmallest));
101
    EXPECT_TRUE(higher_cutoff.IsUpdateValid(frontier, UpdateUserValueType::kLargest));
102
    EXPECT_TRUE(higher_cutoff.IsUpdateValid(frontier, UpdateUserValueType::kSmallest));
103
104
    // Zero OpId should be considered as an undefined value, not causing any errors.
105
    ConsensusFrontier zero_op_id{{0, 0}, HybridTime::kInvalid, HybridTime::kInvalid};
106
    EXPECT_TRUE(frontier.IsUpdateValid(zero_op_id, UpdateUserValueType::kLargest));
107
    EXPECT_TRUE(frontier.IsUpdateValid(zero_op_id, UpdateUserValueType::kSmallest));
108
    EXPECT_TRUE(zero_op_id.IsUpdateValid(frontier, UpdateUserValueType::kLargest));
109
    EXPECT_TRUE(zero_op_id.IsUpdateValid(frontier, UpdateUserValueType::kSmallest));
110
  }
111
112
  ConsensusFrontierPB pb;
113
  pb.mutable_op_id()->set_term(0);
114
  pb.mutable_op_id()->set_index(0);
115
  EXPECT_EQ(
116
      PbToString(pb),
117
      "{ op_id: 0.0 hybrid_time: <min> history_cutoff: <invalid> "
118
      "hybrid_time_filter: <invalid> max_value_level_ttl_expiration_time: <invalid> }");
119
120
  pb.mutable_op_id()->set_term(2);
121
  pb.mutable_op_id()->set_index(3);
122
  EXPECT_EQ(
123
      PbToString(pb),
124
      "{ op_id: 2.3 hybrid_time: <min> history_cutoff: <invalid> "
125
      "hybrid_time_filter: <invalid> max_value_level_ttl_expiration_time: <invalid> }");
126
127
  pb.set_hybrid_time(100000);
128
  EXPECT_EQ(
129
      PbToString(pb),
130
      "{ op_id: 2.3 hybrid_time: { physical: 24 logical: 1696 } history_cutoff: <invalid> "
131
      "hybrid_time_filter: <invalid> max_value_level_ttl_expiration_time: <invalid> }");
132
133
  pb.set_history_cutoff(200000);
134
  EXPECT_EQ(
135
      PbToString(pb),
136
      "{ op_id: 2.3 hybrid_time: { physical: 24 logical: 1696 } "
137
      "history_cutoff: { physical: 48 logical: 3392 } "
138
      "hybrid_time_filter: <invalid> max_value_level_ttl_expiration_time: <invalid> }");
139
}
140
141
TEST_F(ConsensusFrontierTest, TestUpdateExpirationTime) {
142
  const HybridTime smallHT = 1000_usec_ht;
143
  const HybridTime largeHT = 2000_usec_ht;
144
  const HybridTime maxHT = HybridTime::kMax;
145
146
  // Three frontiers with the same op_id, ht, and history_cuttoff,
147
  // but different expiration times.
148
  ConsensusFrontier noExpiry{{1, 1}, 1000_usec_ht, 500_usec_ht};
149
  EXPECT_EQ(noExpiry.max_value_level_ttl_expiration_time(), HybridTime::kInvalid);
150
151
  ConsensusFrontier smallExpiry{{1, 1}, 1000_usec_ht, 500_usec_ht};
152
  smallExpiry.set_max_value_level_ttl_expiration_time(smallHT);
153
  EXPECT_EQ(smallExpiry.max_value_level_ttl_expiration_time(), smallHT);
154
155
  ConsensusFrontier largeExpiry{{1, 1}, 1000_usec_ht, 500_usec_ht};
156
  largeExpiry.set_max_value_level_ttl_expiration_time(largeHT);
157
  EXPECT_EQ(largeExpiry.max_value_level_ttl_expiration_time(), largeHT);
158
159
  ConsensusFrontier maxExpiry{{1, 1}, 1000_usec_ht, 500_usec_ht};
160
  maxExpiry.set_max_value_level_ttl_expiration_time(maxHT);
161
  EXPECT_EQ(maxExpiry.max_value_level_ttl_expiration_time(), maxHT);
162
163
  // Update no expiration frontier with another invalid expiration.
164
  auto expiryClone = noExpiry.Clone();
165
  ConsensusFrontier noExpiry2 = {{2, 2}, 2000_usec_ht, 1000_usec_ht};
166
  expiryClone->Update(noExpiry2, UpdateUserValueType::kLargest);
167
  auto consensusClone = down_cast<ConsensusFrontier&>(*expiryClone);
168
  EXPECT_EQ(consensusClone.max_value_level_ttl_expiration_time(), HybridTime::kInvalid);
169
170
  // Update frontier with no expiration with one with an expiration.
171
  expiryClone->Update(smallExpiry, UpdateUserValueType::kLargest);
172
  consensusClone = down_cast<ConsensusFrontier&>(*expiryClone);
173
  EXPECT_EQ(consensusClone.max_value_level_ttl_expiration_time(), smallHT);
174
175
  // Update same frontier with a larger expiration
176
  expiryClone->Update(largeExpiry, UpdateUserValueType::kLargest);
177
  consensusClone = down_cast<ConsensusFrontier&>(*expiryClone);
178
  EXPECT_EQ(consensusClone.max_value_level_ttl_expiration_time(), largeHT);
179
180
  // Try to update same frontier with the smaller expiration. Should keep the higher expiration.
181
  expiryClone->Update(smallExpiry, UpdateUserValueType::kLargest);
182
  consensusClone = down_cast<ConsensusFrontier&>(*expiryClone);
183
  EXPECT_EQ(consensusClone.max_value_level_ttl_expiration_time(), largeHT);
184
185
  // Update with the maximum expiration.
186
  expiryClone->Update(maxExpiry, UpdateUserValueType::kLargest);
187
  consensusClone = down_cast<ConsensusFrontier&>(*expiryClone);
188
  EXPECT_EQ(consensusClone.max_value_level_ttl_expiration_time(), maxHT);
189
190
  // Update with another invalid expiration time.
191
  expiryClone->Update(noExpiry2, UpdateUserValueType::kLargest);
192
  consensusClone = down_cast<ConsensusFrontier&>(*expiryClone);
193
  EXPECT_EQ(consensusClone.max_value_level_ttl_expiration_time(), maxHT);
194
}
195
196
}  // namespace docdb
197
}  // namespace yb