1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #ifndef OMIT_MULTI_VER
16 #include <gtest/gtest.h>
17 #include <ctime>
18 #include <cmath>
19 #include <random>
20 #include <chrono>
21 #include <fstream>
22 #include <string>
23
24 #include "distributeddb_data_generator.h"
25 #include "distributed_test_tools.h"
26 #include "distributeddb_nb_test_tools.h"
27 #include "kv_store_delegate.h"
28 #include "kv_store_delegate_manager.h"
29
30 using namespace std;
31 using namespace chrono;
32 using namespace testing;
33 #if defined TESTCASES_USING_GTEST_EXT
34 using namespace testing::ext;
35 #endif
36 using namespace DistributedDB;
37 using namespace DistributedDBDataGenerator;
38
39 namespace DistributeddbKvRealdel {
40 static std::condition_variable g_kvBackupVar;
41 class DistributeddbKvRealdelTest : public testing::Test {
42 public:
43 static void SetUpTestCase(void);
44 static void TearDownTestCase(void);
45 void SetUp();
46 void TearDown();
47 private:
48 };
49
50 KvStoreDelegate *g_kvBackupDelegate = nullptr; // the delegate used in this suit.
51 KvStoreDelegateManager *g_manager = nullptr;
SetUpTestCase(void)52 void DistributeddbKvRealdelTest::SetUpTestCase(void)
53 {
54 }
55
TearDownTestCase(void)56 void DistributeddbKvRealdelTest::TearDownTestCase(void)
57 {
58 }
59
SetUp(void)60 void DistributeddbKvRealdelTest::SetUp(void)
61 {
62 UnitTest *test = UnitTest::GetInstance();
63 ASSERT_NE(test, nullptr);
64 const TestInfo *testinfo = test->current_test_info();
65 ASSERT_NE(testinfo, nullptr);
66 string testCaseName = string(testinfo->name());
67 MST_LOG("[SetUp] test case %s is start to run", testCaseName.c_str());
68
69 KvOption option = g_kvOption;
70 g_kvBackupDelegate = DistributedTestTools::GetDelegateSuccess(g_manager, g_kvdbParameter1, option);
71 ASSERT_TRUE(g_manager != nullptr && g_kvBackupDelegate != nullptr);
72 }
73
TearDown(void)74 void DistributeddbKvRealdelTest::TearDown(void)
75 {
76 MST_LOG("TearDown after case.");
77 EXPECT_TRUE(g_manager->CloseKvStore(g_kvBackupDelegate) == OK);
78 g_kvBackupDelegate = nullptr;
79 DBStatus status = g_manager->DeleteKvStore(STORE_ID_1);
80 EXPECT_TRUE(status == DistributedDB::DBStatus::OK) << "fail to delete exist kvdb";
81 delete g_manager;
82 g_manager = nullptr;
83 }
84
85 /*
86 * @tc.name: KvDeleteAll 001
87 * @tc.desc: test that delete interface will real delete data.
88 * @tc.type: FUNC
89 * @tc.require: SR000D4878
90 * @tc.author: fengxiaoyun
91 */
92 #ifdef KV_REALDEL
93 HWTEST_F(DistributeddbKvRealdelTest, KvDeleteAll001, TestSize.Level1)
94 {
95 /**
96 * @tc.steps: step1. put (k1, v1), (k2, v2) to db, and update (k1, v1) to (k1, v2).
97 * @tc.expected: step1. put successfully.
98 */
99 EXPECT_EQ(g_kvBackupDelegate->Put(KEY_1, VALUE_1), OK);
100 EXPECT_EQ(g_kvBackupDelegate->Put(KEY_2, VALUE_2), OK);
101 EXPECT_EQ(g_kvBackupDelegate->Put(KEY_1, VALUE_2), OK);
102 /**
103 * @tc.steps: step2. use sqlite to open the db and check the data of k1.
104 * @tc.expected: step2. there is only one data of k1 in db.
105 */
106 std::string identifier = g_kvdbParameter1.userId + "-" + g_kvdbParameter1.appId + "-" + g_kvdbParameter1.storeId;
107 std::string hashIdentifierRes = TransferStringToHashHexString(identifier);
108 const std::string kvDbName = DIRECTOR + hashIdentifierRes + KVMULTIDB;
109 std::vector<DistributedDB::Key> keyS1, keyS2;
110 keyS1.push_back(KEY_1);
111 int count = 0;
__anon13c9df4a0102()112 EXPECT_TRUE(DistributedTestTools::RepeatCheckAsyncResult([&kvDbName, &count, &keyS1]()->bool {
113 DistributedTestTools::GetRecordCntByKey(kvDbName.c_str(), QUERY_SQL, keyS1, g_kvOption, count);
114 return count == ONE_RECORD;
115 }, 5, 500)); // query 5 times every 500 ms.
116 /**
117 * @tc.steps: step3. delete k1 and then check data of k1 and k2;
118 * @tc.expected: step3. can't find k1, but can find the value of k2 is v2.
119 */
120 EXPECT_EQ(g_kvBackupDelegate->Delete(KEY_1), OK);
121 Value realValue;
122 realValue = DistributedTestTools::Get(*g_kvBackupDelegate, KEY_1);
123 EXPECT_TRUE(realValue.size() == 0);
124 realValue = DistributedTestTools::Get(*g_kvBackupDelegate, KEY_2);
125 EXPECT_TRUE(realValue == VALUE_2);
126 /**
127 * @tc.steps: step4. wait for some seconds and check the data of k1;
128 * @tc.expected: step4. can't find k1.
129 */
__anon13c9df4a0202()130 EXPECT_TRUE(DistributedTestTools::RepeatCheckAsyncResult([&kvDbName, &count, &keyS1]()->bool {
131 DistributedTestTools::GetRecordCntByKey(kvDbName.c_str(), QUERY_SQL, keyS1, g_kvOption, count);
132 return count == 0;
133 }, 5, 500)); // query 5 times every 500 ms.
134 }
135
136 /*
137 * @tc.name: KvDeleteAll 002
138 * @tc.desc: test that deleteBatch interface will real delete data.
139 * @tc.type: FUNC
140 * @tc.require: SR000D4878
141 * @tc.author: fengxiaoyun
142 */
143 HWTEST_F(DistributeddbKvRealdelTest, KvDeleteAll002, TestSize.Level1)
144 {
145 /**
146 * @tc.steps: step1. put (k1, v1), (k2, v2), (k3, v3) to db and use deletebatch interface to delete k1, k2.
147 * @tc.expected: step1. put and delete successfully.
148 */
149 EXPECT_EQ(g_kvBackupDelegate->Put(KEY_1, VALUE_1), OK);
150 EXPECT_EQ(g_kvBackupDelegate->Put(KEY_2, VALUE_2), OK);
151 EXPECT_EQ(g_kvBackupDelegate->Put(KEY_3, VALUE_3), OK);
152 std::vector<DistributedDB::Key> keyS;
153 keyS.push_back(KEY_1);
154 keyS.push_back(KEY_2);
155 EXPECT_EQ(g_kvBackupDelegate->DeleteBatch(keyS), OK);
156 /**
157 * @tc.steps: step2. open the db and check the data of k1, k2, k3.
158 * @tc.expected: step2. there is only k3 in db and can't get k1, k2.
159 */
160 Value realValue;
161 realValue = DistributedTestTools::Get(*g_kvBackupDelegate, KEY_1);
162 EXPECT_TRUE(realValue.size() == 0);
163 realValue = DistributedTestTools::Get(*g_kvBackupDelegate, KEY_2);
164 EXPECT_TRUE(realValue.size() == 0);
165 realValue = DistributedTestTools::Get(*g_kvBackupDelegate, KEY_3);
166 EXPECT_TRUE(realValue == VALUE_3);
167 /**
168 * @tc.steps: step3. wait for some seconds and check the data of k1, k2 by sqlite;
169 * @tc.expected: step3. can't find k1, k2.
170 */
171 std::string identifier = g_kvdbParameter1.userId + "-" + g_kvdbParameter1.appId + "-" + g_kvdbParameter1.storeId;
172 std::string hashIdentifierRes = TransferStringToHashHexString(identifier);
173 const std::string kvDbName = DIRECTOR + hashIdentifierRes + KVMULTIDB;
174 int count = 0;
__anon13c9df4a0302()175 EXPECT_TRUE(DistributedTestTools::RepeatCheckAsyncResult([&kvDbName, &count, &keyS]()->bool {
176 DistributedTestTools::GetRecordCntByKey(kvDbName.c_str(), MULTI_KEY_QUERY_SQL, keyS, g_kvOption, count);
177 return count == 0;
178 }, 5, 500)); // query 5 times every 500 ms.
179 }
180
181 /*
182 * @tc.name: KvDeleteAll 003
183 * @tc.desc: test that clear interface will real delete data.
184 * @tc.type: FUNC
185 * @tc.require: SR000D4878
186 * @tc.author: fengxiaoyun
187 */
188 HWTEST_F(DistributeddbKvRealdelTest, KvDeleteAll003, TestSize.Level1)
189 {
190 /**
191 * @tc.steps: step1. put (k1, v1), (k2, v2) to db and update (k1, v1) to (k1, v2).
192 * @tc.expected: step1. put and update successfully.
193 */
194 EXPECT_EQ(g_kvBackupDelegate->Put(KEY_1, VALUE_1), OK);
195 EXPECT_EQ(g_kvBackupDelegate->Put(KEY_2, VALUE_2), OK);
196 EXPECT_EQ(g_kvBackupDelegate->Put(KEY_1, VALUE_2), OK);
197 /**
198 * @tc.steps: step2. clear the db, and check the data of k1, k2.
199 * @tc.expected: step2. clear and can't find k1, k2.
200 */
201 EXPECT_EQ(g_kvBackupDelegate->Clear(), OK);
202 Value realValue;
203 realValue = DistributedTestTools::Get(*g_kvBackupDelegate, KEY_1);
204 EXPECT_TRUE(realValue.size() == 0);
205 realValue = DistributedTestTools::Get(*g_kvBackupDelegate, KEY_2);
206 EXPECT_TRUE(realValue.size() == 0);
207
208 /**
209 * @tc.steps: step3. wait for 5 seconds and check the data of k1, k2;
210 * @tc.expected: step3. can't find k1, k2.
211 */
212 std::string identifier = g_kvdbParameter1.userId + "-" + g_kvdbParameter1.appId + "-" + g_kvdbParameter1.storeId;
213 std::string hashIdentifierRes = TransferStringToHashHexString(identifier);
214 const std::string kvDbName = DIRECTOR + hashIdentifierRes + KVMULTIDB;
215 std::vector<DistributedDB::Key> keyS;
216 keyS.push_back(KEY_1);
217 keyS.push_back(KEY_2);
218 int count = 0;
__anon13c9df4a0402()219 EXPECT_TRUE(DistributedTestTools::RepeatCheckAsyncResult([&kvDbName, &count, &keyS]()->bool {
220 DistributedTestTools::GetRecordCntByKey(kvDbName.c_str(), MULTI_KEY_QUERY_SQL, keyS, g_kvOption, count);
221 return count == 0;
222 }, 5, 500)); // query 5 times every 500 ms.
223
224 EncrypteAttribute attribute = {g_kvOption.isEncryptedDb, g_kvOption.passwd};
__anon13c9df4a0502()225 EXPECT_TRUE(DistributedTestTools::RepeatCheckAsyncResult([&kvDbName, &attribute, &count]()->bool {
226 DistributedTestTools::QuerySpecifiedData(kvDbName, SYNC_MULTI_VER_QUERY_SQL, attribute, count);
227 return count == ONE_RECORD;
228 }, 5, 500)); // query 5 times every 500 ms.
229 }
230
231 /*
232 * @tc.name: KvDeleteAll 004
233 * @tc.desc: test that it can get record when snapshot is register, and can't get records after unregister snapshor.
234 * @tc.type: FUNC
235 * @tc.require: SR000D4878
236 * @tc.author: fengxiaoyun
237 */
238 HWTEST_F(DistributeddbKvRealdelTest, KvDeleteAll004, TestSize.Level2)
239 {
240 /**
241 * @tc.steps: step1. put (k1, v1), update (k1, v1) to (k1, v2).
242 * @tc.expected: step1. put and update successfully.
243 */
244 EXPECT_EQ(g_kvBackupDelegate->Put(KEY_1, VALUE_1), OK);
245 EXPECT_EQ(g_kvBackupDelegate->Put(KEY_1, VALUE_2), OK);
246 KvStoreObserverImpl observer;
247 KvStoreSnapshotDelegate *snapShot = DistributedTestTools::RegisterSnapObserver(g_kvBackupDelegate, &observer);
248 EXPECT_NE(snapShot, nullptr);
249 /**
250 * @tc.steps: step2. delete k1 and then check data of k1;
251 * @tc.expected: step2. there is only one records in the db.
252 */
253 EXPECT_EQ(g_kvBackupDelegate->Delete(KEY_1), OK);
254 std::this_thread::sleep_for(std::chrono::seconds(UNIQUE_SECOND));
255 std::string identifier = g_kvdbParameter1.userId + "-" + g_kvdbParameter1.appId + "-" + g_kvdbParameter1.storeId;
256 std::string hashIdentifierRes = TransferStringToHashHexString(identifier);
257 const std::string kvDbName = DIRECTOR + hashIdentifierRes + KVMULTIDB;
258
259 std::vector<DistributedDB::Key> keyS;
260 keyS.push_back(KEY_1);
261 int count = 0;
262 DistributedTestTools::GetRecordCntByKey(kvDbName.c_str(), QUERY_SQL, keyS, g_kvOption, count);
263 EXPECT_EQ(count, ONE_RECORD);
264
265 /**
266 * @tc.steps: step3. after release the snap shot query the records;
267 * @tc.expected: step3. can't find the k1 in db.
268 */
269 EXPECT_EQ(g_kvBackupDelegate->ReleaseKvStoreSnapshot(snapShot), OK);
270 std::this_thread::sleep_for(std::chrono::seconds(UNIQUE_SECOND));
271 DistributedTestTools::GetRecordCntByKey(kvDbName.c_str(), QUERY_SQL, keyS, g_kvOption, count);
272 EXPECT_TRUE(count == 0);
273 }
274
275 /*
276 * @tc.name: DeleteAll 006
277 * @tc.desc: value slices will be real deleted if reference count is 0 caused by clear.
278 * @tc.type: FUNC
279 * @tc.require: SR000D4878
280 * @tc.author: fengxiaoyun
281 */
282 HWTEST_F(DistributeddbKvRealdelTest, KvDeleteAll006, TestSize.Level2)
283 {
284 KvStoreDelegate *delegate2 = nullptr;
285 KvStoreDelegateManager *manager2 = nullptr;
286 delegate2 = DistributedTestTools::GetDelegateSuccess(manager2, g_kvdbParameter2, g_kvOption);
287 ASSERT_TRUE(manager2 != nullptr && delegate2 != nullptr);
288 /**
289 * @tc.steps: step1. put (k1,v1) and (k2,v2), each value of them are 4M.
290 * @tc.expected: step1. call successfully.
291 */
292 EntrySize entrySize = { KEY_SIX_BYTE, FOUR_M_LONG_STRING };
293 std::vector<DistributedDB::Entry> entries;
294 GenerateAppointPrefixAndSizeRecords(entries, entrySize, RECORDS_SMALL_CNT, { 'K' }, { 'v' });
295 for (auto entry : entries) {
296 EXPECT_EQ(delegate2->Put(entry.key, entry.value), OK);
297 }
298 /**
299 * @tc.steps: step2. clear and verify the records of ValueSlice by sqlite interface.
300 * @tc.expected: step1. count is 0.
301 */
302 EXPECT_EQ(delegate2->Clear(), OK);
303 std::this_thread::sleep_for(std::chrono::seconds(UNIQUE_SECOND));
304 std::string identifier = g_kvdbParameter2.userId + "-" + g_kvdbParameter2.appId +
305 "-" + g_kvdbParameter2.storeId;
306 std::string hashIdentifierRes = TransferStringToHashHexString(identifier);
307 const std::string dbName = DIRECTOR + hashIdentifierRes + MULTIDB;
308 int count = 0;
309 EncrypteAttribute attribute = {g_kvOption.isEncryptedDb, g_kvOption.passwd};
310 EXPECT_TRUE(DistributedTestTools::QuerySpecifiedData(dbName, SYNC_VALUE_SLICE_QUERY_SQL, attribute, count));
311 EXPECT_EQ(count, 0); // there are no ValueSlices in db.
312
313 EXPECT_EQ(manager2->CloseKvStore(delegate2), OK);
314 delegate2 = nullptr;
315 EXPECT_EQ(manager2->DeleteKvStore(STORE_ID_2), OK);
316 delete manager2;
317 manager2 = nullptr;
318 }
319
320 /*
321 * @tc.name: DeleteAll 007
322 * @tc.desc: value slices will be real deleted if reference count is 0 caused by clear.
323 * @tc.type: FUNC
324 * @tc.require: SR000D4878
325 * @tc.author: fengxiaoyun
326 */
327 HWTEST_F(DistributeddbKvRealdelTest, KvDeleteAll007, TestSize.Level2)
328 {
329 KvStoreDelegate *delegate2 = nullptr;
330 KvStoreDelegateManager *manager2 = nullptr;
331 delegate2 = DistributedTestTools::GetDelegateSuccess(manager2, g_kvdbParameter2, g_kvOption);
332 ASSERT_TRUE(manager2 != nullptr && delegate2 != nullptr);
333 /**
334 * @tc.steps: step1. put (k1,v1) and (k2,v1), each value of them are 4M.
335 * @tc.expected: step1. call successfully.
336 */
337 EntrySize entrySize = { KEY_SIX_BYTE, FOUR_M_LONG_STRING };
338 std::vector<DistributedDB::Entry> entries;
339 GenerateAppointPrefixAndSizeRecords(entries, entrySize, RECORDS_SMALL_CNT, { 'K' }, { 'v' });
340 entries[INDEX_FIRST].value = entries[INDEX_ZEROTH].value;
341 for (auto entry : entries) {
342 EXPECT_EQ(delegate2->Put(entry.key, entry.value), OK);
343 }
344 /**
345 * @tc.steps: step2. delete k1 and verify the records of ValueSlice by sqlite interface.
346 * @tc.expected: step1. count is not equal to 0.
347 */
348 std::string identifier = g_kvdbParameter2.userId + "-" + g_kvdbParameter2.appId +
349 "-" + g_kvdbParameter2.storeId;
350 std::string hashIdentifierRes = TransferStringToHashHexString(identifier);
351 const std::string dbName = DIRECTOR + hashIdentifierRes + MULTIDB;
352 EXPECT_EQ(delegate2->Delete(entries[INDEX_ZEROTH].key), OK);
353 std::this_thread::sleep_for(std::chrono::seconds(UNIQUE_SECOND));
354 int count = 0;
355 EncrypteAttribute attribute = {g_kvOption.isEncryptedDb, g_kvOption.passwd};
356 EXPECT_TRUE(DistributedTestTools::QuerySpecifiedData(dbName, SYNC_VALUE_SLICE_QUERY_SQL, attribute, count));
357 EXPECT_EQ(count, 0); // there are some ValueSlices in db.
358 /**
359 * @tc.steps: step3. delete k2 and verify the records of ValueSlice by sqlite interface.
360 * @tc.expected: step1. count is 0.
361 */
362 EXPECT_EQ(delegate2->Delete(entries[INDEX_FIRST].key), OK);
363 std::this_thread::sleep_for(std::chrono::seconds(UNIQUE_SECOND));
364 count = 0;
365 EXPECT_TRUE(DistributedTestTools::QuerySpecifiedData(dbName, SYNC_VALUE_SLICE_QUERY_SQL, attribute, count));
366 EXPECT_EQ(count, 0); // there are no ValueSlices in db.
367
368 EXPECT_EQ(manager2->CloseKvStore(delegate2), OK);
369 delegate2 = nullptr;
370 EXPECT_EQ(manager2->DeleteKvStore(STORE_ID_2), OK);
371 delete manager2;
372 manager2 = nullptr;
373 }
374 #endif
375 }
376 #endif // OMIT_MULTI_VER