YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rocksdb/db/user_op_id_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 <memory>
15
#include <sstream>
16
#include <string>
17
18
#include <gtest/gtest.h>
19
20
#include "yb/rocksdb/db/write_batch_internal.h"
21
#include "yb/rocksdb/env.h"
22
#include "yb/rocksdb/util/testutil.h"
23
24
#include "yb/util/test_macros.h"
25
26
using std::string;
27
28
namespace rocksdb {
29
30
namespace {
31
32
struct UserOpIdTestHandler : public WriteBatch::Handler {
33
  Status PutCF(
34
      uint32_t column_family_id,
35
      const SliceParts& key,
36
15
      const SliceParts& value) override {
37
15
    StartOutputLine(__FUNCTION__);
38
15
    OutputField("key", key.TheOnlyPart());
39
15
    OutputField("value", value.TheOnlyPart());
40
15
    FinishOutputLine();
41
15
    return Status::OK();
42
15
  }
43
44
  Status DeleteCF(
45
      uint32_t column_family_id,
46
13
      const Slice& key) override {
47
13
    StartOutputLine(__FUNCTION__);
48
13
    OutputField("key", key);
49
13
    FinishOutputLine();
50
13
    return Status::OK();
51
13
  }
52
53
  Status SingleDeleteCF(
54
      uint32_t column_family_id,
55
0
      const Slice& key) override {
56
0
    StartOutputLine(__FUNCTION__);
57
0
    OutputField("key", key);
58
0
    FinishOutputLine();
59
0
    return Status::OK();
60
0
  }
61
62
  Status MergeCF(
63
      uint32_t column_family_id,
64
      const Slice& key,
65
2
      const Slice& value) override {
66
2
    StartOutputLine(__FUNCTION__);
67
2
    OutputField("key", key);
68
2
    OutputField("value", value);
69
2
    FinishOutputLine();
70
2
    return Status::OK();
71
2
  }
72
73
14
  Status Frontiers(const UserFrontiers& frontier) override {
74
14
    out_ << "frontiers=" << frontier.ToString() << std::endl;
75
14
    return Status::OK();
76
14
  }
77
78
20
  std::string str() const {
79
20
    return out_.str();
80
20
  }
81
82
 private:
83
30
  void StartOutputLine(const char* name) {
84
30
    out_ << name << "(";
85
30
    need_separator_ = false;
86
30
  }
87
47
  void OutputField(const char* field_name, const Slice& value) {
88
47
    if (need_separator_) {
89
17
      out_ << ", ";
90
17
    }
91
47
    need_separator_ = true,
92
47
    out_ << field_name << "='" << value.ToString() << "'";
93
47
  }
94
30
  void FinishOutputLine() {
95
30
    out_ << ")" << std::endl;
96
30
  }
97
98
  std::stringstream out_;
99
  bool need_separator_ = false;
100
};
101
102
20
std::string WriteBatchToString(const WriteBatch& b) {
103
20
  UserOpIdTestHandler handler;
104
20
  EXPECT_OK(b.Iterate(&handler));
105
20
  return handler.str();
106
20
}
107
108
} // namespace
109
110
class UserOpIdTest : public RocksDBTest {
111
 protected:
112
3
  WriteBatch CreateDummyWriteBatch() {
113
3
    WriteBatch b;
114
3
    b.SetFrontiers(&frontiers_);
115
3
    b.Put("A", "B");
116
3
    b.Delete("C");
117
3
    return b;
118
3
  }
119
120
  test::TestUserFrontiers frontiers_{1, 123};
121
};
122
123
1
TEST_F(UserOpIdTest, Empty) {
124
1
  WriteBatch batch;
125
1
  ASSERT_EQ(0, WriteBatchInternal::Count(&batch));
126
1
  ASSERT_EQ(0, batch.Count());
127
1
}
128
129
130
1
TEST_F(UserOpIdTest, Append) {
131
1
  WriteBatch b1, b2;
132
1
  WriteBatchInternal::SetSequence(&b1, 200);
133
1
  WriteBatchInternal::SetSequence(&b2, 300);
134
1
  WriteBatchInternal::Append(&b1, &b2);
135
1
  ASSERT_EQ(0, b1.Count());
136
1
  b2.Put("a", "va");
137
1
  WriteBatchInternal::Append(&b1, &b2);
138
1
  ASSERT_EQ(1, b1.Count());
139
1
  b2.Clear();
140
1
  b2.Put("b", "vb");
141
1
  WriteBatchInternal::Append(&b1, &b2);
142
1
  ASSERT_EQ(2, b1.Count());
143
1
  b2.Delete("foo");
144
1
  WriteBatchInternal::Append(&b1, &b2);
145
1
  ASSERT_EQ(4, b1.Count());
146
1
}
147
148
1
TEST_F(UserOpIdTest, SetUserSequenceNumber) {
149
1
  WriteBatch b;
150
151
1
  ASSERT_FALSE(b.Frontiers());
152
1
  test::TestUserFrontiers range(1, 77701);
153
1
  b.SetFrontiers(&range);
154
1
  b.Put("k1", "v1");
155
1
  ASSERT_FALSE(!b.Frontiers());
156
157
1
  b.Put("k2", "v2");
158
159
1
  b.Delete("k3");
160
161
1
  b.Merge("k4", "v4");
162
163
1
  ASSERT_FALSE(!b.Frontiers());
164
165
1
  ASSERT_EQ(
166
1
    "frontiers={ smallest: { value: 1 } largest: { value: 77701 } }\n"
167
1
    "PutCF(key='k1', value='v1')\n"
168
1
    "PutCF(key='k2', value='v2')\n"
169
1
    "DeleteCF(key='k3')\n"
170
1
    "MergeCF(key='k4', value='v4')\n",
171
1
    WriteBatchToString(b));
172
1
}
173
174
1
TEST_F(UserOpIdTest, AppendBatchesWithUserSequenceNumbers) {
175
1
  WriteBatch dst;
176
1
  test::TestUserFrontiers range(1, 1200);
177
1
  dst.SetFrontiers(&range);
178
1
  dst.Put("my_key", "my_value");
179
180
1
  dst.Merge("my_merge_key", "my_merge_value");
181
182
1
  WriteBatch src;
183
1
  src.Delete("my_key");
184
185
1
  WriteBatchInternal::Append(&dst, &src);
186
1
  ASSERT_EQ(
187
1
      "frontiers={ smallest: { value: 1 } largest: { value: 1200 } }\n"
188
1
      "PutCF(key='my_key', value='my_value')\n"
189
1
      "MergeCF(key='my_merge_key', value='my_merge_value')\n"
190
1
      "DeleteCF(key='my_key')\n",
191
1
      WriteBatchToString(dst));
192
1
}
193
194
// This is based on WriteBatchTest.SavePointsTest
195
1
TEST_F(UserOpIdTest, SavePointTest) {
196
1
  Status s;
197
1
  WriteBatch batch;
198
1
  batch.SetSavePoint();
199
200
1
  test::TestUserFrontiers range(1, 1000);
201
1
  batch.SetFrontiers(&range);
202
1
  batch.Put("A", "a");
203
1
  batch.Put("B", "b");
204
1
  batch.SetSavePoint();
205
206
1
  batch.Put("C", "c");
207
1
  batch.Delete("A");
208
1
  batch.SetSavePoint();
209
1
  batch.SetSavePoint();
210
211
1
  ASSERT_OK(batch.RollbackToSavePoint());
212
1
  ASSERT_EQ(
213
1
      "frontiers={ smallest: { value: 1 } largest: { value: 1000 } }\n"
214
1
      "PutCF(key='A', value='a')\n"
215
1
      "PutCF(key='B', value='b')\n"
216
1
      "PutCF(key='C', value='c')\n"
217
1
      "DeleteCF(key='A')\n",
218
1
      WriteBatchToString(batch));
219
1
  ASSERT_FALSE(!batch.Frontiers());
220
221
1
  ASSERT_OK(batch.RollbackToSavePoint());
222
1
  ASSERT_FALSE(!batch.Frontiers());
223
224
1
  ASSERT_OK(batch.RollbackToSavePoint());
225
1
  ASSERT_EQ(
226
1
      "frontiers={ smallest: { value: 1 } largest: { value: 1000 } }\n"
227
1
      "PutCF(key='A', value='a')\n"
228
1
      "PutCF(key='B', value='b')\n",
229
1
      WriteBatchToString(batch));
230
1
  ASSERT_FALSE(!batch.Frontiers());
231
232
1
  batch.Delete("A");
233
1
  batch.Put("B", "bb");
234
1
  ASSERT_FALSE(!batch.Frontiers());
235
236
1
  ASSERT_OK(batch.RollbackToSavePoint());
237
1
  ASSERT_EQ("", WriteBatchToString(batch));
238
1
  ASSERT_FALSE(batch.Frontiers());
239
240
1
  s = batch.RollbackToSavePoint();
241
1
  ASSERT_TRUE(s.IsNotFound());
242
1
  ASSERT_EQ("", WriteBatchToString(batch));
243
244
1
  test::TestUserFrontiers range2(1, 1001);
245
1
  batch.SetFrontiers(&range2);
246
1
  batch.Put("D", "d");
247
1
  batch.Delete("A");
248
249
1
  batch.SetSavePoint();
250
251
1
  batch.Put("A", "aaa");
252
253
1
  ASSERT_EQ(range2, *batch.Frontiers());
254
255
1
  ASSERT_OK(batch.RollbackToSavePoint());
256
1
  ASSERT_EQ(range2, *batch.Frontiers());
257
258
1
  ASSERT_EQ(
259
1
      "frontiers={ smallest: { value: 1 } largest: { value: 1001 } }\n"
260
1
      "PutCF(key='D', value='d')\n"
261
1
      "DeleteCF(key='A')\n",
262
1
      WriteBatchToString(batch));
263
264
1
  batch.SetSavePoint();
265
266
1
  batch.Put("D", "d");
267
1
  batch.Delete("A");
268
269
1
  ASSERT_OK(batch.RollbackToSavePoint());
270
1
  ASSERT_EQ(
271
1
      "frontiers={ smallest: { value: 1 } largest: { value: 1001 } }\n"
272
1
      "PutCF(key='D', value='d')\n"
273
1
      "DeleteCF(key='A')\n",
274
1
      WriteBatchToString(batch));
275
276
1
  s = batch.RollbackToSavePoint();
277
1
  ASSERT_TRUE(s.IsNotFound());
278
1
  ASSERT_EQ(
279
1
      "frontiers={ smallest: { value: 1 } largest: { value: 1001 } }\n"
280
1
      "PutCF(key='D', value='d')\n"
281
1
      "DeleteCF(key='A')\n",
282
1
      WriteBatchToString(batch));
283
1
}
284
285
1
TEST_F(UserOpIdTest, SavePointTest2) {
286
1
  WriteBatch b;
287
288
1
  Status s = b.RollbackToSavePoint();
289
1
  ASSERT_TRUE(s.IsNotFound());
290
1
  ASSERT_EQ("", WriteBatchToString(b));
291
292
1
  test::TestUserFrontiers range2(1, 1002);
293
1
  b.SetFrontiers(&range2);
294
1
  b.Delete("A");
295
1
  b.SetSavePoint();
296
297
1
  s = b.RollbackToSavePoint();
298
1
  ASSERT_OK(s);
299
1
  ASSERT_EQ("frontiers={ smallest: { value: 1 } largest: { value: 1002 } }\nDeleteCF(key='A')\n",
300
1
            WriteBatchToString(b));
301
302
1
  b.Clear();
303
1
  ASSERT_EQ("", WriteBatchToString(b));
304
305
1
  b.SetSavePoint();
306
307
1
  test::TestUserFrontiers range3(1, 1003);
308
1
  b.SetFrontiers(&range3);
309
1
  b.Delete("B");
310
1
  ASSERT_EQ("frontiers={ smallest: { value: 1 } largest: { value: 1003 } }\nDeleteCF(key='B')\n",
311
1
            WriteBatchToString(b));
312
313
1
  b.SetSavePoint();
314
1
  s = b.RollbackToSavePoint();
315
1
  ASSERT_OK(s);
316
1
  ASSERT_EQ("frontiers={ smallest: { value: 1 } largest: { value: 1003 } }\nDeleteCF(key='B')\n",
317
1
            WriteBatchToString(b));
318
319
1
  s = b.RollbackToSavePoint();
320
1
  ASSERT_OK(s);
321
1
  ASSERT_EQ("", WriteBatchToString(b));
322
323
1
  s = b.RollbackToSavePoint();
324
1
  ASSERT_TRUE(s.IsNotFound());
325
1
  ASSERT_EQ("", WriteBatchToString(b));
326
1
}
327
328
1
TEST_F(UserOpIdTest, CopyConstructorAndAssignmentOperator) {
329
1
  WriteBatch b = CreateDummyWriteBatch();
330
1
  WriteBatch b_copy(b);
331
1
  WriteBatch b_assigned = b;
332
1
  auto expected_str =
333
1
      "frontiers={ smallest: { value: 1 } largest: { value: 123 } }\n"
334
1
      "PutCF(key='A', value='B')\n"
335
1
      "DeleteCF(key='C')\n";
336
1
  ASSERT_EQ(expected_str, WriteBatchToString(b_copy));
337
1
  ASSERT_EQ(expected_str, WriteBatchToString(b_assigned));
338
1
}
339
340
1
TEST_F(UserOpIdTest, MoveConstructor) {
341
1
  auto temp = CreateDummyWriteBatch();
342
1
  WriteBatch b_moved(std::move(temp));
343
1
  temp = CreateDummyWriteBatch();
344
1
  WriteBatch b_move_assigned = std::move(temp);
345
1
  auto expected_str =
346
1
      "frontiers={ smallest: { value: 1 } largest: { value: 123 } }\n"
347
1
      "PutCF(key='A', value='B')\n"
348
1
      "DeleteCF(key='C')\n";
349
1
  ASSERT_EQ(expected_str, WriteBatchToString(b_moved));
350
1
  ASSERT_EQ(expected_str, WriteBatchToString(b_move_assigned));
351
1
}
352
353
}  // namespace rocksdb
354
355
13.2k
int main(int argc, char** argv) {
356
13.2k
  ::testing::InitGoogleTest(&argc, argv);
357
13.2k
  return RUN_ALL_TESTS();
358
13.2k
}