1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
5
6 #include "rocksdb/slice.h"
7
8 #include "port/port.h"
9 #include "port/stack_trace.h"
10 #include "rocksdb/data_structure.h"
11 #include "rocksdb/types.h"
12 #include "test_util/testharness.h"
13 #include "test_util/testutil.h"
14
15 namespace ROCKSDB_NAMESPACE {
16
17 // Use this to keep track of the cleanups that were actually performed
Multiplier(void * arg1,void * arg2)18 void Multiplier(void* arg1, void* arg2) {
19 int* res = reinterpret_cast<int*>(arg1);
20 int* num = reinterpret_cast<int*>(arg2);
21 *res *= *num;
22 }
23
24 class PinnableSliceTest : public testing::Test {
25 public:
AssertSameData(const std::string & expected,const PinnableSlice & slice)26 void AssertSameData(const std::string& expected,
27 const PinnableSlice& slice) {
28 std::string got;
29 got.assign(slice.data(), slice.size());
30 ASSERT_EQ(expected, got);
31 }
32 };
33
34 // Test that the external buffer is moved instead of being copied.
TEST_F(PinnableSliceTest,MoveExternalBuffer)35 TEST_F(PinnableSliceTest, MoveExternalBuffer) {
36 Slice s("123");
37 std::string buf;
38 PinnableSlice v1(&buf);
39 v1.PinSelf(s);
40
41 PinnableSlice v2(std::move(v1));
42 ASSERT_EQ(buf.data(), v2.data());
43 ASSERT_EQ(&buf, v2.GetSelf());
44
45 PinnableSlice v3;
46 v3 = std::move(v2);
47 ASSERT_EQ(buf.data(), v3.data());
48 ASSERT_EQ(&buf, v3.GetSelf());
49 }
50
TEST_F(PinnableSliceTest,Move)51 TEST_F(PinnableSliceTest, Move) {
52 int n2 = 2;
53 int res = 1;
54 const std::string const_str1 = "123";
55 const std::string const_str2 = "ABC";
56 Slice slice1(const_str1);
57 Slice slice2(const_str2);
58
59 {
60 // Test move constructor on a pinned slice.
61 res = 1;
62 PinnableSlice v1;
63 v1.PinSlice(slice1, Multiplier, &res, &n2);
64 PinnableSlice v2(std::move(v1));
65
66 // Since v1's Cleanable has been moved to v2,
67 // no cleanup should happen in Reset.
68 v1.Reset();
69 ASSERT_EQ(1, res);
70
71 AssertSameData(const_str1, v2);
72 }
73 // v2 is cleaned up.
74 ASSERT_EQ(2, res);
75
76 {
77 // Test move constructor on an unpinned slice.
78 PinnableSlice v1;
79 v1.PinSelf(slice1);
80 PinnableSlice v2(std::move(v1));
81
82 AssertSameData(const_str1, v2);
83 }
84
85 {
86 // Test move assignment from a pinned slice to
87 // another pinned slice.
88 res = 1;
89 PinnableSlice v1;
90 v1.PinSlice(slice1, Multiplier, &res, &n2);
91 PinnableSlice v2;
92 v2.PinSlice(slice2, Multiplier, &res, &n2);
93 v2 = std::move(v1);
94
95 // v2's Cleanable will be Reset before moving
96 // anything from v1.
97 ASSERT_EQ(2, res);
98 // Since v1's Cleanable has been moved to v2,
99 // no cleanup should happen in Reset.
100 v1.Reset();
101 ASSERT_EQ(2, res);
102
103 AssertSameData(const_str1, v2);
104 }
105 // The Cleanable moved from v1 to v2 will be Reset.
106 ASSERT_EQ(4, res);
107
108 {
109 // Test move assignment from a pinned slice to
110 // an unpinned slice.
111 res = 1;
112 PinnableSlice v1;
113 v1.PinSlice(slice1, Multiplier, &res, &n2);
114 PinnableSlice v2;
115 v2.PinSelf(slice2);
116 v2 = std::move(v1);
117
118 // Since v1's Cleanable has been moved to v2,
119 // no cleanup should happen in Reset.
120 v1.Reset();
121 ASSERT_EQ(1, res);
122
123 AssertSameData(const_str1, v2);
124 }
125 // The Cleanable moved from v1 to v2 will be Reset.
126 ASSERT_EQ(2, res);
127
128 {
129 // Test move assignment from an upinned slice to
130 // another unpinned slice.
131 PinnableSlice v1;
132 v1.PinSelf(slice1);
133 PinnableSlice v2;
134 v2.PinSelf(slice2);
135 v2 = std::move(v1);
136
137 AssertSameData(const_str1, v2);
138 }
139
140 {
141 // Test move assignment from an upinned slice to
142 // a pinned slice.
143 res = 1;
144 PinnableSlice v1;
145 v1.PinSelf(slice1);
146 PinnableSlice v2;
147 v2.PinSlice(slice2, Multiplier, &res, &n2);
148 v2 = std::move(v1);
149
150 // v2's Cleanable will be Reset before moving
151 // anything from v1.
152 ASSERT_EQ(2, res);
153
154 AssertSameData(const_str1, v2);
155 }
156 // No Cleanable is moved from v1 to v2, so no more cleanup.
157 ASSERT_EQ(2, res);
158 }
159
160 // Unit test for SmallEnumSet
161 class SmallEnumSetTest : public testing::Test {
162 public:
SmallEnumSetTest()163 SmallEnumSetTest() {}
~SmallEnumSetTest()164 ~SmallEnumSetTest() {}
165 };
166
TEST_F(SmallEnumSetTest,SmallSetTest)167 TEST_F(SmallEnumSetTest, SmallSetTest) {
168 FileTypeSet fs;
169 ASSERT_TRUE(fs.Add(FileType::kIdentityFile));
170 ASSERT_FALSE(fs.Add(FileType::kIdentityFile));
171 ASSERT_TRUE(fs.Add(FileType::kInfoLogFile));
172 ASSERT_TRUE(fs.Contains(FileType::kIdentityFile));
173 ASSERT_FALSE(fs.Contains(FileType::kDBLockFile));
174 }
175
176 } // namespace ROCKSDB_NAMESPACE
177
main(int argc,char ** argv)178 int main(int argc, char** argv) {
179 ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
180 ::testing::InitGoogleTest(&argc, argv);
181 return RUN_ALL_TESTS();
182 }
183