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