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 <cstdlib>
17 #include <ctime>
18 #include <gtest/gtest.h>
19 #include <openssl/rand.h>
20 #include <string>
21 #include <thread>
22
23 #include "db_common.h"
24 #include "db_constant.h"
25 #include "db_errno.h"
26 #include "default_factory.h"
27 #include "distributeddb_data_generate_unit_test.h"
28 #include "distributeddb_tools_unit_test.h"
29 #include "log_print.h"
30 #include "multi_ver_natural_store.h"
31 #include "multi_ver_natural_store_commit_storage.h"
32 #include "multi_ver_natural_store_connection.h"
33 #include "process_communicator_test_stub.h"
34 #include "sqlite_multi_ver_data_storage.h"
35
36 using namespace testing::ext;
37 using namespace DistributedDB;
38 using namespace DistributedDBUnitTest;
39 using namespace std;
40
41 namespace {
42 const int WAIT_TIME = 1000;
43 const uint64_t INVALID_TIMESTAMP = 0;
44 const uint64_t OPERATION_ADD = 1;
45 const uint64_t OPERATION_DELETE = 2;
46 const uint64_t OPERATION_CLEAR = 3;
47
48 string g_testDir;
49 KvDBProperties g_prop;
50 SQLiteMultiVerTransaction *g_transaction = nullptr;
51 MultiVerNaturalStore *g_naturalStore = nullptr;
52 MultiVerNaturalStoreConnection *g_naturalStoreConnection = nullptr;
53 Version g_version = 0;
54 const std::string CREATE_TABLE =
55 "CREATE TABLE IF NOT EXISTS version_data(key BLOB, value BLOB, oper_flag INTEGER, version INTEGER, " \
56 "timestamp INTEGER, ori_timestamp INTEGER, hash_key BLOB, " \
57 "PRIMARY key(hash_key, version));";
58 }
59
60 class DistributedDBStorageTransactionDataTest : public testing::Test {
61 public:
62 static void SetUpTestCase(void);
63 static void TearDownTestCase(void);
64 void SetUp();
65 void TearDown();
66 };
67
GetReadTransaction()68 static void GetReadTransaction()
69 {
70 if (g_transaction == nullptr) {
71 g_transaction = new (std::nothrow) SQLiteMultiVerTransaction();
72 ASSERT_NE(g_transaction, nullptr);
73 std::string dir = g_testDir + "/31/multi_ver/multi_ver_data.db";
74 LOGI("%s", dir.c_str());
75 CipherPassword passwd;
76 int errCode = g_transaction->Initialize(dir, true, CipherType::AES_256_GCM, passwd);
77 ASSERT_EQ(errCode, E_OK);
78 }
79 Version versionInfo;
80 ASSERT_EQ(g_transaction->GetMaxVersion(MultiVerDataType::ALL_TYPE, versionInfo), E_OK);
81 g_version = versionInfo;
82 g_transaction->SetVersion(versionInfo);
83 }
84
ValueEqual(const Value & read,const Value & origin)85 static void ValueEqual(const Value &read, const Value &origin)
86 {
87 EXPECT_EQ(read.size(), origin.size());
88 if (read.size() != origin.size()) {
89 DBCommon::PrintHexVector(origin, __LINE__, "Orig");
90 }
91
92 EXPECT_EQ(read, origin);
93 }
94
RunSyncMergeForOneCommit(std::vector<MultiVerKvEntry * > & entries)95 static int RunSyncMergeForOneCommit(std::vector<MultiVerKvEntry *> &entries)
96 {
97 MultiVerCommitNode multiVerCommit;
98 multiVerCommit.commitId.resize(20); // 20 as commit id size
99 RAND_bytes(multiVerCommit.commitId.data(), 20);
100 multiVerCommit.deviceInfo = DBCommon::TransferHashString("deviceB") + "deviceB1";
101
102 // Put the multiver commit of other device.
103 int errCode = g_naturalStore->PutCommitData(multiVerCommit, entries, "deviceB");
104 if (errCode != E_OK) {
105 return errCode;
106 }
107
108 std::vector<MultiVerCommitNode> multiVerCommits;
109 multiVerCommits.push_back(multiVerCommit);
110
111 // Merge the multiver commit of other device.
112 errCode = g_naturalStore->MergeSyncCommit(multiVerCommit, multiVerCommits);
113
114 for (auto &item : entries) {
115 if (item != nullptr) {
116 delete item;
117 item = nullptr;
118 }
119 }
120 entries.clear();
121
122 return errCode;
123 }
124
GetCommitTimestamp(const CommitID & commitId)125 static uint64_t GetCommitTimestamp(const CommitID& commitId)
126 {
127 MultiVerNaturalStoreCommitStorage *commitStorage = new (std::nothrow) MultiVerNaturalStoreCommitStorage();
128 if (commitStorage == nullptr) {
129 return 0;
130 }
131 Timestamp timestamp = INVALID_TIMESTAMP;
132 CommitID newCommitId;
133 IKvDBCommit *commit = nullptr;
134 IKvDBCommitStorage::Property property;
135 property.isNeedCreate = false;
136 property.path = g_testDir;
137 property.identifierName = "31";
138 int errCode = commitStorage->Open(property);
139 if (errCode != E_OK) {
140 goto END;
141 }
142
143 if (commitId.empty()) {
144 newCommitId = commitStorage->GetHeader(errCode);
145 if (newCommitId.empty()) {
146 return 0;
147 }
148 } else {
149 newCommitId = commitId;
150 }
151
152 commit = commitStorage->GetCommit(newCommitId, errCode);
153 if (commit == nullptr) {
154 LOGE("Can't get the commit:%d", errCode);
155 goto END;
156 }
157
158 timestamp = commit->GetTimestamp();
159 END:
160 if (commit != nullptr) {
161 commitStorage->ReleaseCommit(commit);
162 commit = nullptr;
163 }
164
165 delete commitStorage;
166 commitStorage = nullptr;
167
168 return timestamp;
169 }
170
GetMaxTimestamp()171 static uint64_t GetMaxTimestamp()
172 {
173 CommitID commitId;
174 return GetCommitTimestamp(commitId);
175 }
176
PutAndCommitEntry(const Key & key,const Value & value)177 static void PutAndCommitEntry(const Key &key, const Value &value)
178 {
179 EXPECT_EQ(g_naturalStoreConnection->StartTransaction(), E_OK);
180 IOption option;
181 EXPECT_EQ(g_naturalStoreConnection->Put(option, key, value), E_OK);
182 EXPECT_EQ(g_naturalStoreConnection->Commit(), E_OK);
183 }
184
PushOneEntry(uint64_t opr,uint64_t timestamp,const Key & key,const Value & value,std::vector<MultiVerKvEntry * > & entries)185 static void PushOneEntry(uint64_t opr, uint64_t timestamp, const Key &key, const Value &value,
186 std::vector<MultiVerKvEntry *> &entries)
187 {
188 GenericMultiVerKvEntry *entry = new (std::nothrow) GenericMultiVerKvEntry;
189 if (entry != nullptr) {
190 // set key
191 entry->SetKey(key);
192 // set value
193 MultiVerValueObject valueObject;
194 valueObject.SetValue(value);
195 Value objectSerial;
196 valueObject.GetSerialData(objectSerial);
197 entry->SetValue(objectSerial);
198 // set timestamp
199 entry->SetTimestamp(timestamp);
200
201 // set open_flag
202 entry->SetOperFlag(opr);
203 if (opr == OPERATION_DELETE) {
204 Key hashKey;
205 DBCommon::CalcValueHash(key, hashKey);
206 entry->SetKey(hashKey);
207 } else if (opr == OPERATION_CLEAR) {
208 Key clearKey = {'c', 'l', 'e', 'a', 'r'};
209 entry->SetKey(clearKey);
210 }
211
212 entries.push_back(entry);
213 }
214 }
215
ValueEqualByKey(const Key & key,const Value & value)216 static void ValueEqualByKey(const Key &key, const Value &value)
217 {
218 IOption option;
219 Value valueRead;
220 int errCode = g_naturalStoreConnection->Get(option, key, valueRead);
221 EXPECT_EQ(errCode, E_OK);
222 if (errCode != E_OK) {
223 DBCommon::PrintHexVector(key, __LINE__, "key");
224 }
225 ValueEqual(value, valueRead);
226 }
227
SetUpTestCase(void)228 void DistributedDBStorageTransactionDataTest::SetUpTestCase(void)
229 {
230 IKvDBFactory *factory = new (std::nothrow) DefaultFactory();
231 ASSERT_TRUE(factory != nullptr);
232 IKvDBFactory::Register(factory);
233 }
234
TearDownTestCase(void)235 void DistributedDBStorageTransactionDataTest::TearDownTestCase(void)
236 {
237 if (g_transaction != nullptr) {
238 delete g_transaction;
239 g_transaction = nullptr;
240 }
241 auto factory = IKvDBFactory::GetCurrent();
242 if (factory != nullptr) {
243 delete factory;
244 factory = nullptr;
245 }
246 IKvDBFactory::Register(nullptr);
247 }
248
SetUp(void)249 void DistributedDBStorageTransactionDataTest::SetUp(void)
250 {
251 DistributedDBToolsUnitTest::PrintTestCaseInfo();
252 DistributedDBToolsUnitTest::TestDirInit(g_testDir);
253
254 // KvDBProperties prop;
255 g_prop.SetStringProp(KvDBProperties::APP_ID, "app0");
256 g_prop.SetStringProp(KvDBProperties::STORE_ID, "store0");
257 g_prop.SetStringProp(KvDBProperties::USER_ID, "user0");
258 g_prop.SetStringProp(KvDBProperties::DATA_DIR, g_testDir);
259 g_prop.SetStringProp(KvDBProperties::IDENTIFIER_DIR, "31");
260 g_prop.SetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true);
261
262 g_naturalStore = new (std::nothrow) MultiVerNaturalStore();
263 ASSERT_NE(g_naturalStore, nullptr);
264 EXPECT_EQ(g_naturalStore->Open(g_prop), E_OK);
265
266 int errCode = 0;
267 IKvDBConnection *connection = g_naturalStore->GetDBConnection(errCode);
268 ASSERT_NE(connection, nullptr);
269 g_naturalStoreConnection = static_cast<MultiVerNaturalStoreConnection *>(connection);
270
271 LOGI("read directory :%s", g_testDir.c_str());
272 }
273
TearDown(void)274 void DistributedDBStorageTransactionDataTest::TearDown(void)
275 {
276 if (g_transaction != nullptr) {
277 delete g_transaction;
278 g_transaction = nullptr;
279 }
280
281 if (g_naturalStore != nullptr) {
282 if (g_naturalStoreConnection != nullptr) {
283 g_naturalStoreConnection->Close();
284 g_naturalStoreConnection = nullptr;
285 }
286 g_naturalStore->DecObjRef(g_naturalStore);
287 g_naturalStore = nullptr;
288 }
289 DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir + "/31/" + DBConstant::MULTI_SUB_DIR);
290 }
291
292 /**
293 * @tc.name: StorageInsert001
294 * @tc.desc: Put the non-empty key, non-empty value into the database.
295 * @tc.type: FUNC
296 * @tc.require: AR000C6TRV AR000CQDTM
297 * @tc.author: huangnaigu
298 */
299 HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsert001, TestSize.Level1)
300 {
301 /**
302 * @tc.steps: step1. Put the data(non-empty key, non-empty value) into the database.
303 * @tc.expected: step1. Put returns E_OK.
304 */
305 EXPECT_EQ(g_naturalStoreConnection->StartTransaction(), E_OK);
306 IOption option;
307 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_1, VALUE_1), E_OK);
308 EXPECT_EQ(g_naturalStoreConnection->Commit(), E_OK);
309 Value valueRead;
310 /**
311 * @tc.steps: step2. Get the data.
312 * @tc.expected: step2. Get returns E_OK and the value is equal to the put value.
313 */
314 EXPECT_EQ(g_naturalStoreConnection->Get(option, KEY_1, valueRead), E_OK);
315 ValueEqual(VALUE_1, valueRead);
316 /**
317 * @tc.steps: step3. Clear the data.
318 */
319 g_naturalStoreConnection->Clear(option);
320 /**
321 * @tc.steps: step4. Put another data(non-empty key, non-empty value) into the database.
322 * @tc.expected: step4. Put returns E_OK.
323 */
324 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_2, VALUE_2), E_OK);
325 EXPECT_NE(g_naturalStoreConnection->Commit(), E_OK);
326 /**
327 * @tc.steps: step5. Get the data.
328 * @tc.expected: step5. Get returns E_OK and the value is equal to the second put value.
329 */
330 EXPECT_EQ(g_naturalStoreConnection->Get(option, KEY_2, valueRead), E_OK);
331 ValueEqual(VALUE_2, valueRead);
332 }
333
334 /**
335 * @tc.name: StorageInsert002
336 * @tc.desc: Put the empty key, non-empty value into the database.
337 * @tc.type: FUNC
338 * @tc.require: AR000C6TRV AR000CQDTM
339 * @tc.author: huangnaigu
340 */
341 HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsert002, TestSize.Level1)
342 {
343 /**
344 * @tc.steps: step1. Put the data(empty key, non-empty value) into the database.
345 * @tc.expected: step1. Put returns -E_INVALID_ARGS.
346 */
347 EXPECT_EQ(g_naturalStoreConnection->StartTransaction(), E_OK);
348 IOption option;
349 EXPECT_EQ(g_naturalStoreConnection->Put(option, NULL_KEY_1, VALUE_1), -E_INVALID_ARGS);
350 EXPECT_EQ(g_naturalStoreConnection->Commit(), E_OK);
351 }
352
353 /**
354 * @tc.name: StorageInsert003
355 * @tc.desc: Put the non-empty key, empty value into the database.
356 * @tc.type: FUNC
357 * @tc.require: AR000C6TRV AR000CQDTM
358 * @tc.author: huangnaigu
359 */
360 HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsert003, TestSize.Level1)
361 {
362 /**
363 * @tc.steps: step1. Put the data(non-empty key, empty value) into the database.
364 * @tc.expected: step1. Put returns E_OK.
365 */
366 IOption option;
367 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_1, NULL_VALUE_1), E_OK);
368 GetReadTransaction();
369 Value valueRead;
370 Value valueTmp;
371 /**
372 * @tc.steps: step2. Get the data.
373 * @tc.expected: step2. Get returns E_OK and the value is empty.
374 */
375 EXPECT_EQ(g_naturalStoreConnection->Get(option, KEY_1, valueRead), E_OK);
376 ValueEqual(NULL_VALUE_1, valueRead);
377 }
378
379 /**
380 * @tc.name: StorageUpdate001
381 * @tc.desc: Update the value to non-empty
382 * @tc.type: FUNC
383 * @tc.require: AR000C6TRV AR000CQDTM
384 * @tc.author: huangnaigu
385 */
386 HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdate001, TestSize.Level1)
387 {
388 IOption option;
389 /**
390 * @tc.steps: step1. Put one valid data into the database.
391 * @tc.expected: step1. Put returns E_OK.
392 */
393 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_1, VALUE_1), E_OK);
394 /**
395 * @tc.steps: step2. Put another data whose key is same to the first put data and value(non-empty) is different.
396 * @tc.expected: step2. Put returns E_OK.
397 */
398 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_1, VALUE_2), E_OK);
399 GetReadTransaction();
400 Value valueRead;
401 /**
402 * @tc.steps: step3. Get the data.
403 * @tc.expected: step3. Get returns E_OK and the value is equal the second put value.
404 */
405 EXPECT_EQ(g_naturalStoreConnection->Get(option, KEY_1, valueRead), E_OK);
406 ValueEqual(VALUE_2, valueRead);
407 }
408
409 /**
410 * @tc.name: StorageUpdate002
411 * @tc.desc: Update the value to empty
412 * @tc.type: FUNC
413 * @tc.require: AR000C6TRV AR000CQDTM
414 * @tc.author: huangnaigu
415 */
416 HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdate002, TestSize.Level1)
417 {
418 IOption option;
419 /**
420 * @tc.steps: step1. Put one valid data into the database.
421 * @tc.expected: step1. Put returns E_OK.
422 */
423 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_1, VALUE_1), E_OK);
424 /**
425 * @tc.steps: step2. Put another data whose key is same to the first put data and value is empty.
426 * @tc.expected: step2. Put returns E_OK.
427 */
428 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_1, NULL_VALUE_1), E_OK);
429 Value valueRead;
430 /**
431 * @tc.steps: step3. Get the data.
432 * @tc.expected: step3. Get returns E_OK and the value is empty.
433 */
434 EXPECT_EQ(g_naturalStoreConnection->Get(option, KEY_1, valueRead), E_OK);
435 ValueEqual(NULL_VALUE_1, valueRead);
436 }
437
438 /**
439 * @tc.name: StorageDelete001
440 * @tc.desc: Delete the existed data
441 * @tc.type: FUNC
442 * @tc.require: AR000C6TRV AR000CQDTM
443 * @tc.author: huangnaigu
444 */
445 HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDelete001, TestSize.Level1)
446 {
447 IOption option;
448 /**
449 * @tc.steps: step1. Put one valid data.
450 */
451 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_1, VALUE_1), E_OK);
452 /**
453 * @tc.steps: step2. Delete the data.
454 */
455 EXPECT_EQ(g_naturalStoreConnection->Delete(option, KEY_1), E_OK);
456 GetReadTransaction();
457 Value valueRead;
458 /**
459 * @tc.steps: step3. Get the data.
460 * @tc.expected: step3. Get returns -E_NOT_FOUND.
461 */
462 EXPECT_EQ(g_transaction->Get(KEY_1, valueRead), -E_NOT_FOUND);
463 }
464
465 /**
466 * @tc.name: StorageDelete002
467 * @tc.desc: Delete the non-existed data
468 * @tc.type: FUNC
469 * @tc.require: AR000C6TRV AR000CQDTM
470 * @tc.author: huangnaigu
471 */
472 HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDelete002, TestSize.Level1)
473 {
474 /**
475 * @tc.steps: step1. Delete one non-existed data.
476 * @tc.expected: step1. Delete returns -E_NOT_FOUND.
477 */
478 IOption option;
479 EXPECT_EQ(g_naturalStoreConnection->Delete(option, KEY_1), -E_NOT_FOUND);
480 GetReadTransaction();
481 Value valueRead;
482 /**
483 * @tc.steps: step2. Get the non-existed data.
484 * @tc.expected: step2. Get returns -E_NOT_FOUND.
485 */
486 EXPECT_EQ(g_transaction->Get(KEY_1, valueRead), -E_NOT_FOUND);
487 }
488
489 /**
490 * @tc.name: StorageDelete003
491 * @tc.desc: Delete the invalid key data
492 * @tc.type: FUNC
493 * @tc.require: AR000C6TRV AR000CQDTM
494 * @tc.author: huangnaigu
495 */
496 HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDelete003, TestSize.Level1)
497 {
498 /**
499 * @tc.steps: step1. Delete the empty-key data.
500 * @tc.expected: step1. Delete returns not E_OK.
501 */
502 IOption option;
503 EXPECT_NE(g_naturalStoreConnection->Delete(option, NULL_KEY_1), E_OK);
504 }
505
506 /**
507 * @tc.name: StorageClear001
508 * @tc.desc: Clear the data
509 * @tc.type: FUNC
510 * @tc.require: AR000C6TRV AR000CQDTM
511 * @tc.author: huangnaigu
512 */
513 HWTEST_F(DistributedDBStorageTransactionDataTest, StorageClear001, TestSize.Level1)
514 {
515 /**
516 * @tc.steps: step1. put one data.
517 */
518 IOption option;
519 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_1, VALUE_1), E_OK);
520 /**
521 * @tc.steps: step2. clear the data.
522 * @tc.expected: step2. Returns E_OK.
523 */
524 EXPECT_EQ(g_naturalStoreConnection->Clear(option), E_OK);
525 GetReadTransaction();
526 /**
527 * @tc.steps: step3. Check the data.
528 * @tc.expected: step3. Getting the data result -E_NOT_FOUND.
529 */
530 Value valueRead;
531 EXPECT_EQ(g_transaction->Get(KEY_1, valueRead), -E_NOT_FOUND);
532 }
533
534 /**
535 * @tc.name: StorageInsertBatch001
536 * @tc.desc: Put the valid batch data
537 * @tc.type: FUNC
538 * @tc.require: AR000C6TRV AR000CQDTM
539 * @tc.author: huangnaigu
540 */
541 HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsertBatch001, TestSize.Level1)
542 {
543 /**
544 * @tc.steps: step1. Put the batch data.
545 * @tc.expected: step1. Returns E_OK.
546 */
547 std::vector<Entry> entries;
548 entries.push_back(KV_ENTRY_1);
549 entries.push_back(KV_ENTRY_2);
550 IOption option;
551 EXPECT_EQ(g_naturalStoreConnection->PutBatch(option, entries), E_OK);
552 Value valueRead;
553
554 /**
555 * @tc.steps: step2. Check the data.
556 * @tc.expected: step2. Get the data from the database and the value are equal to the data put before.
557 */
558 EXPECT_EQ(g_naturalStoreConnection->Get(option, KEY_1, valueRead), E_OK);
559 ValueEqual(VALUE_1, valueRead);
560 EXPECT_EQ(g_naturalStoreConnection->Get(option, KEY_2, valueRead), E_OK);
561 ValueEqual(VALUE_2, valueRead);
562 }
563
564 /**
565 * @tc.name: StorageInsertBatch002
566 * @tc.desc: Put the partially valid batch data
567 * @tc.type: FUNC
568 * @tc.require: AR000C6TRV AR000CQDTM
569 * @tc.author: huangnaigu
570 */
571 HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsertBatch002, TestSize.Level1)
572 {
573 /**
574 * @tc.steps: step1. Put the batch data(partially valid, partially invalid).
575 * @tc.expected: step1. Returns not E_OK.
576 */
577 std::vector<Entry> entries;
578 Entry entry;
579 entries.push_back(KV_ENTRY_1);
580 entries.push_back(entry);
581 IOption option;
582 EXPECT_NE(g_naturalStoreConnection->PutBatch(option, entries), E_OK);
583 GetReadTransaction();
584 Value valueRead;
585 /**
586 * @tc.steps: step2. Check the data.
587 * @tc.expected: step2. Getting the data results not E_OK.
588 */
589 EXPECT_NE(g_transaction->Get(KEY_1, valueRead), E_OK);
590 }
591
592 /**
593 * @tc.name: StorageUpdateBatch001
594 * @tc.desc: Update the batch data
595 * @tc.type: FUNC
596 * @tc.require: AR000C6TRV AR000CQDTM
597 * @tc.author: huangnaigu
598 */
599 HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdateBatch001, TestSize.Level1)
600 {
601 std::vector<Entry> entries1;
602 entries1.push_back(KV_ENTRY_1);
603 entries1.push_back(KV_ENTRY_2);
604
605 Entry kvEntry1 = {KEY_1, VALUE_2};
606 Entry kvEntry2 = {KEY_2, VALUE_1};
607 std::vector<Entry> entries2;
608 entries2.push_back(kvEntry1);
609 entries2.push_back(kvEntry2);
610
611 IOption option;
612 /**
613 * @tc.steps: step1. Put the batch data.
614 */
615 EXPECT_EQ(g_naturalStoreConnection->PutBatch(option, entries1), E_OK);
616 /**
617 * @tc.steps: step2. Update the batch data.
618 * @tc.expected: step2. Returns E_OK.
619 */
620 EXPECT_EQ(g_naturalStoreConnection->PutBatch(option, entries2), E_OK);
621 Value valueRead;
622 /**
623 * @tc.steps: step3. Check the data.
624 * @tc.expected: step3. Get the data from the database and check whether the data have been updated.
625 */
626 EXPECT_EQ(g_naturalStoreConnection->Get(option, KEY_1, valueRead), E_OK);
627 ValueEqual(VALUE_2, valueRead);
628 EXPECT_EQ(g_naturalStoreConnection->Get(option, KEY_2, valueRead), E_OK);
629 ValueEqual(VALUE_1, valueRead);
630 }
631
632 /**
633 * @tc.name: StorageUpdateBatch002
634 * @tc.desc: Update the batch data(partially invalid data)
635 * @tc.type: FUNC
636 * @tc.require: AR000C6TRV AR000CQDTM
637 * @tc.author: huangnaigu
638 */
639 HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdateBatch002, TestSize.Level1)
640 {
641 std::vector<Entry> entrys1;
642 entrys1.push_back(KV_ENTRY_1);
643 entrys1.push_back(KV_ENTRY_2);
644
645 Entry kvEntry1 = {KEY_1, VALUE_2};
646 Entry kvEntry;
647 Entry kvEntry2 = {KEY_2, VALUE_1};
648 std::vector<Entry> entrys2;
649 entrys2.push_back(kvEntry1);
650 entrys2.push_back(kvEntry);
651 entrys2.push_back(kvEntry2);
652
653 IOption option;
654 /**
655 * @tc.steps: step1. Put the batch data.
656 */
657 EXPECT_EQ(g_naturalStoreConnection->PutBatch(option, entrys1), E_OK);
658 /**
659 * @tc.steps: step2. Update the batch data(partially empty key).
660 * @tc.expected: step2. Returns not E_OK.
661 */
662 EXPECT_NE(g_naturalStoreConnection->PutBatch(option, entrys2), E_OK);
663 Value valueRead;
664 /**
665 * @tc.steps: step3. Check the data.
666 * @tc.expected: step3. The getting result data are the first put batch .
667 */
668 EXPECT_EQ(g_naturalStoreConnection->Get(option, KEY_1, valueRead), E_OK);
669 ValueEqual(VALUE_1, valueRead);
670 EXPECT_EQ(g_naturalStoreConnection->Get(option, KEY_2, valueRead), E_OK);
671 ValueEqual(VALUE_2, valueRead);
672 }
673
674 /**
675 * @tc.name: StorageDeleteBatch001
676 * @tc.desc: Delete the batch data
677 * @tc.type: FUNC
678 * @tc.require: AR000C6TRV AR000CQDTM
679 * @tc.author: huangnaigu
680 */
681 HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDeleteBatch001, TestSize.Level1)
682 {
683 std::vector<Entry> entries;
684 entries.push_back(KV_ENTRY_1);
685 entries.push_back(KV_ENTRY_2);
686 std::vector<Key> keys;
687 keys.push_back(KEY_1);
688 keys.push_back(KEY_2);
689
690 IOption option;
691 /**
692 * @tc.steps: step1. Put the batch data.
693 */
694 EXPECT_EQ(g_naturalStoreConnection->PutBatch(option, entries), E_OK);
695 /**
696 * @tc.steps: step2. Delete the batch data.
697 * @tc.expected: step2. Return E_OK.
698 */
699 EXPECT_EQ(g_naturalStoreConnection->DeleteBatch(option, keys), E_OK);
700 GetReadTransaction();
701 Value valueRead;
702 /**
703 * @tc.steps: step3. Check the data.
704 * @tc.expected: step3. Getting the data results -E_NOT_FOUND.
705 */
706 EXPECT_EQ(g_transaction->Get(KEY_1, valueRead), -E_NOT_FOUND);
707 EXPECT_EQ(g_transaction->Get(KEY_2, valueRead), -E_NOT_FOUND);
708 }
709
710 /**
711 * @tc.name: StorageDeleteBatch002
712 * @tc.desc: Delete the batch data(partially non-existed)
713 * @tc.type: FUNC
714 * @tc.require: AR000C6TRV AR000CQDTM
715 * @tc.author: huangnaigu
716 */
717 HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDeleteBatch002, TestSize.Level1)
718 {
719 std::vector<Entry> entries;
720 entries.push_back(KV_ENTRY_1);
721 entries.push_back(KV_ENTRY_2);
722 std::vector<Key> keys;
723 keys.push_back(KEY_1);
724 keys.push_back(KEY_2);
725 std::vector<uint8_t> k3 = {'3'};
726 keys.push_back(k3);
727
728 IOption option;
729 /**
730 * @tc.steps: step1. Put the batch data.
731 */
732 EXPECT_EQ(g_naturalStoreConnection->PutBatch(option, entries), E_OK);
733 /**
734 * @tc.steps: step2. Delete the batch data(partially non-existed).
735 * @tc.expected: step2. Return E_OK.
736 */
737 EXPECT_EQ(g_naturalStoreConnection->DeleteBatch(option, keys), E_OK);
738 GetReadTransaction();
739 Value valueRead;
740 /**
741 * @tc.steps: step3. Check the data.
742 * @tc.expected: step3. Cannot Get the delete data in the database.
743 */
744 EXPECT_NE(g_transaction->Get(KEY_1, valueRead), E_OK);
745 EXPECT_NE(g_transaction->Get(KEY_2, valueRead), E_OK);
746 }
747
748 /**
749 * @tc.name: StorageDeleteBatch003
750 * @tc.desc: Delete the batch data(partially invalid)
751 * @tc.type: FUNC
752 * @tc.require: AR000C6TRV AR000CQDTM
753 * @tc.author: huangnaigu
754 */
755 HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDeleteBatch003, TestSize.Level1)
756 {
757 std::vector<Entry> entries;
758 entries.push_back(KV_ENTRY_1);
759 entries.push_back(KV_ENTRY_2);
760 std::vector<Key> keys;
761 keys.push_back(KEY_1);
762 keys.push_back(KEY_2);
763 Key k3;
764 keys.push_back(k3);
765
766 IOption option;
767 /**
768 * @tc.steps: step1. Put the batch data.
769 */
770 EXPECT_EQ(g_naturalStoreConnection->PutBatch(option, entries), E_OK);
771 /**
772 * @tc.steps: step2. Delete the batch data(partially invalid).
773 * @tc.expected: step2. Return E_OK.
774 */
775 EXPECT_NE(g_naturalStoreConnection->DeleteBatch(option, keys), E_OK);
776 GetReadTransaction();
777 Value valueRead;
778 /**
779 * @tc.steps: step3. Check the data.
780 * @tc.expected: step3. Can get the put origined data.
781 */
782 EXPECT_EQ(g_transaction->Get(KEY_1, valueRead), E_OK);
783 EXPECT_EQ(g_transaction->Get(KEY_2, valueRead), E_OK);
784 }
785
786 /**
787 * @tc.name: StorageTransactionCombo001
788 * @tc.desc: Multiple operation within the transaction
789 * @tc.type: FUNC
790 * @tc.require: AR000C6TRV AR000CQDTM
791 * @tc.author: huangnaigu
792 */
793 HWTEST_F(DistributedDBStorageTransactionDataTest, StorageTransactionCombo001, TestSize.Level1)
794 {
795 Entry kvEntry3;
796 Entry kvEntry4;
797 kvEntry3.key = {'3'};
798 kvEntry4.key = {'4'};
799 kvEntry3.value = {'c'};
800 kvEntry4.value = {'d'};
801 // inserted data
802 std::vector<Entry> entrys1;
803 entrys1.push_back(KV_ENTRY_1);
804 entrys1.push_back(KV_ENTRY_2);
805 entrys1.push_back(kvEntry3);
806 entrys1.push_back(kvEntry4);
807
808 kvEntry3.value = {'e'};
809 kvEntry4.value = {'f'};
810 // updated data
811 std::vector<Entry> entrys2;
812 entrys2.push_back(kvEntry3);
813 entrys2.push_back(kvEntry4);
814
815 // deleted data
816 std::vector<Key> keys;
817 keys.push_back(KEY_1);
818 keys.push_back(KEY_2);
819
820 IOption option;
821 /**
822 * @tc.steps: step1. Start the transaction.
823 */
824 EXPECT_EQ(g_naturalStoreConnection->StartTransaction(), E_OK);
825 /**
826 * @tc.steps: step2. Put the batch data.
827 */
828 EXPECT_EQ(g_naturalStoreConnection->PutBatch(option, entrys1), E_OK);
829 /**
830 * @tc.steps: step3. Delete the batch data.
831 */
832 EXPECT_EQ(g_naturalStoreConnection->DeleteBatch(option, keys), E_OK);
833 /**
834 * @tc.steps: step4. Update the batch data.
835 */
836 EXPECT_EQ(g_naturalStoreConnection->PutBatch(option, entrys2), E_OK);
837 /**
838 * @tc.steps: step5. Commit the transaction.
839 */
840 EXPECT_EQ(g_naturalStoreConnection->Commit(), E_OK);
841 Value valueRead;
842 /**
843 * @tc.steps: step6. Check the data.
844 * @tc.expected: step6. Can get the updated data.
845 */
846 EXPECT_EQ(g_naturalStoreConnection->Get(option, kvEntry3.key, valueRead), E_OK);
847 ValueEqual(kvEntry3.value, valueRead);
848 EXPECT_EQ(g_naturalStoreConnection->Get(option, kvEntry4.key, valueRead), E_OK);
849 ValueEqual(kvEntry4.value, valueRead);
850 }
851
852 /**
853 * @tc.name: TransactionRollback001
854 * @tc.desc: Multiple operation within the transaction
855 * @tc.type: FUNC
856 * @tc.require: AR000C6TRV AR000CQDTM
857 * @tc.author: huangnaigu
858 */
859 HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionRollback001, TestSize.Level1)
860 {
861 std::vector<Entry> entries;
862 entries.push_back(KV_ENTRY_1);
863 entries.push_back(KV_ENTRY_2);
864 IOption option;
865 /**
866 * @tc.steps: step1. Start the transaction.
867 */
868 EXPECT_EQ(g_naturalStoreConnection->StartTransaction(), E_OK);
869 /**
870 * @tc.steps: step2. Put the batch data.
871 */
872 EXPECT_EQ(g_naturalStoreConnection->PutBatch(option, entries), E_OK);
873 /**
874 * @tc.steps: step3. Rollback the transaction.
875 */
876 EXPECT_EQ(g_naturalStoreConnection->RollBack(), E_OK);
877 Value valueRead;
878 /**
879 * @tc.steps: step4. Check the data.
880 * @tc.expected: step4. Couldn't find the data in the database.
881 */
882 EXPECT_EQ(g_naturalStoreConnection->Get(option, KEY_1, valueRead), -E_NOT_FOUND);
883 EXPECT_EQ(g_naturalStoreConnection->Get(option, KEY_2, valueRead), -E_NOT_FOUND);
884 }
885
886 /**
887 * @tc.name: TransactionGetCommitData001
888 * @tc.desc: Get the commit data of one transaction.
889 * @tc.type: FUNC
890 * @tc.require: AR000C6TRV AR000CQDTM
891 * @tc.author: huangnaigu
892 */
893 HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionGetCommitData001, TestSize.Level1)
894 {
895 std::vector<Entry> entries;
896 entries.push_back(KV_ENTRY_1);
897 entries.push_back(KV_ENTRY_2);
898 IOption option;
899 /**
900 * @tc.steps: step1. Put the batch data within in one transaction.
901 */
902 EXPECT_EQ(g_naturalStoreConnection->StartTransaction(), E_OK);
903 EXPECT_EQ(g_naturalStoreConnection->PutBatch(option, entries), E_OK);
904 EXPECT_EQ(g_naturalStoreConnection->Commit(), E_OK);
905
906 Value valueRead;
907 /**
908 * @tc.steps: step2. Check the put batch data, and could get the put data.
909 */
910 EXPECT_EQ(g_naturalStoreConnection->Get(option, KEY_1, valueRead), E_OK);
911 ValueEqual(valueRead, KV_ENTRY_1.value);
912 EXPECT_EQ(g_naturalStoreConnection->Get(option, KEY_2, valueRead), E_OK);
913 ValueEqual(valueRead, KV_ENTRY_2.value);
914 /**
915 * @tc.steps: step3. Get one commit data.
916 */
917 GetReadTransaction();
918 std::vector<MultiVerKvEntry *> multiVerKvEntries;
919 EXPECT_EQ(g_transaction->GetEntriesByVersion(g_version, multiVerKvEntries), OK);
920 ASSERT_EQ(multiVerKvEntries.size(), 2UL);
921 auto entry1 = static_cast<GenericMultiVerKvEntry *>(multiVerKvEntries[0]);
922 ASSERT_NE(entry1, nullptr);
923 valueRead.clear();
924 EXPECT_EQ(entry1->GetValue(valueRead), E_OK);
925 /**
926 * @tc.steps: step4. Check the commit data.
927 * @tc.expected: step4. Could find the batch put data in the commit data.
928 */
929 auto entry2 = static_cast<GenericMultiVerKvEntry *>(multiVerKvEntries[1]);
930 ASSERT_NE(entry2, nullptr);
931 valueRead.clear();
932 EXPECT_EQ(entry2->GetValue(valueRead), E_OK);
933 for (auto &item : multiVerKvEntries) {
934 delete item;
935 item = nullptr;
936 }
937 }
938
939 /**
940 * @tc.name: TransactionSqliteKvEntry001
941 * @tc.desc: Serialize the kv entry and deserialize the data.
942 * @tc.type: FUNC
943 * @tc.require: AR000C6TRV AR000CQDTM
944 * @tc.author: huangnaigu
945 */
946 HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionSqliteKvEntry001, TestSize.Level1)
947 {
948 GenericMultiVerKvEntry entry;
949 entry.SetOperFlag(17);
950 Key key;
951 DistributedDBToolsUnitTest::GetRandomKeyValue(key);
952 entry.SetKey(key);
953 Value value;
954 DistributedDBToolsUnitTest::GetRandomKeyValue(value, 20);
955 /**
956 * @tc.steps: step1. Initialize the multi version kv entry.
957 */
958 MultiVerValueObject valueObject;
959 valueObject.SetValue(value);
960 Value objectSerial;
961
962 valueObject.GetSerialData(objectSerial);
963 entry.SetValue(objectSerial);
964 /**
965 * @tc.steps: step2. Get the serial data of the entry.
966 */
967 std::vector<uint8_t> serialData;
968 EXPECT_EQ(entry.GetSerialData(serialData), E_OK);
969 /**
970 * @tc.steps: step3. Deserial the data.
971 */
972 GenericMultiVerKvEntry deEntry;
973 EXPECT_EQ(deEntry.DeSerialData(serialData), E_OK);
974 Key keyRead;
975 Value valueRead;
976 Value valueTmp;
977 uint64_t flag;
978 deEntry.GetKey(keyRead);
979 deEntry.GetValue(valueTmp);
980 deEntry.GetOperFlag(flag);
981 ValueEqual(keyRead, key);
982 MultiVerValueObject objectRead;
983 EXPECT_EQ(objectRead.DeSerialData(valueTmp), E_OK);
984 objectRead.GetValue(valueRead);
985 /**
986 * @tc.steps: step4. Check the deserialized data.
987 * @tc.expected: step4. the deserialized value is equal to the set value.
988 */
989 ValueEqual(valueRead, value);
990 EXPECT_EQ(flag, 17UL);
991 }
992
993 /**
994 * @tc.name: TransactionPutForeignData001
995 * @tc.desc: Put the remote commit data into the current device database.
996 * @tc.type: FUNC
997 * @tc.require: AR000C6TRV AR000CQDTM
998 * @tc.author: huangnaigu
999 */
1000 HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionPutForeignData001, TestSize.Level1)
1001 {
1002 GenericMultiVerKvEntry entry;
1003 entry.SetOperFlag(1);
1004 Key key;
1005 DistributedDBToolsUnitTest::GetRandomKeyValue(key);
1006 entry.SetKey(key);
1007 Value value;
1008 DistributedDBToolsUnitTest::GetRandomKeyValue(value);
1009 MultiVerValueObject valueObject;
1010 valueObject.SetValue(value);
1011 Value objectSerial;
1012 valueObject.GetSerialData(objectSerial);
1013 entry.SetValue(objectSerial);
1014
1015 std::vector<MultiVerKvEntry *> entries;
1016 entries.push_back(&entry);
1017 /**
1018 * @tc.steps: step1. Create the multiver commit.
1019 */
1020 MultiVerCommitNode multiVerCommit;
1021 multiVerCommit.commitId.resize(20); // commit id size
1022 RAND_bytes(multiVerCommit.commitId.data(), 20);
1023 multiVerCommit.deviceInfo = DBCommon::TransferHashString("deviceB") + "deviceB1";
1024 /**
1025 * @tc.steps: step2. Put the multiver commit of other device.
1026 */
1027 EXPECT_EQ(g_naturalStore->PutCommitData(multiVerCommit, entries, "deviceB"), E_OK);
1028 std::vector<MultiVerCommitNode> multiVerCommits;
1029 multiVerCommits.push_back(multiVerCommit);
1030 /**
1031 * @tc.steps: step3. Merge the multiver commit of other device.
1032 */
1033 EXPECT_EQ(g_naturalStore->MergeSyncCommit(multiVerCommit, multiVerCommits), E_OK);
1034
1035 /**
1036 * @tc.steps: step4. Get the commit data, the foreign synced data would be got from sync.
1037 */
1038 std::vector<MultiVerKvEntry *> readEntries;
1039 EXPECT_EQ(g_naturalStore->GetCommitData(multiVerCommit, readEntries), E_OK);
1040 ASSERT_EQ(readEntries.size(), 0UL);
1041 }
1042
1043 /**
1044 * @tc.name: DefaultConflictResolution001
1045 * @tc.desc: Merge data without conflicts
1046 * @tc.type: FUNC
1047 * @tc.require: AR000CQE13 AR000CQE14
1048 * @tc.author: wumin
1049 */
1050 HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution001, TestSize.Level1)
1051 {
1052 /**
1053 * @tc.steps: step1. Put the local data(KEY_1, VALUE_1) into the database.
1054 * @tc.expected: step1. Put returns E_OK.
1055 */
1056 PutAndCommitEntry(KEY_1, VALUE_1);
1057 /**
1058 * @tc.steps: step2. Put the external data(KEY_2, VALUE_2) into the database.
1059 * @tc.expected: step2. Put returns E_OK
1060 */
1061 std::vector<MultiVerKvEntry *> entries;
1062 PushOneEntry(OPERATION_ADD, 1, KEY_2, VALUE_2, entries);
1063 EXPECT_EQ(RunSyncMergeForOneCommit(entries), E_OK);
1064 /**
1065 * @tc.steps: step3. Get value1 and value2
1066 * @tc.expected: step3. Value1 and value2 are correct.
1067 */
1068 ValueEqualByKey(KEY_1, VALUE_1);
1069 ValueEqualByKey(KEY_2, VALUE_2);
1070 }
1071
1072 /**
1073 * @tc.name: DefaultConflictResolution002
1074 * @tc.desc: Merge data with conflicts ,no clear operation in the external data and local data
1075 * @tc.type: FUNC
1076 * @tc.require: AR000CQE13 AR000CQE14
1077 * @tc.author: wumin
1078 */
1079 HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution002, TestSize.Level1)
1080 {
1081 PutAndCommitEntry(KEY_1, VALUE_1);
1082 /**
1083 * @tc.steps: step1. Put the [KEY_2,V2] and [KEY_3,V3] into the database and delete [KEY_1,V1]
1084 * @tc.expected: step1. Both Put and Delete operation returns E_OK.
1085 */
1086 IOption option;
1087 EXPECT_EQ(g_naturalStoreConnection->StartTransaction(), E_OK);
1088 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_2, VALUE_2), E_OK);
1089 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_3, VALUE_3), E_OK);
1090 EXPECT_EQ(g_naturalStoreConnection->Delete(option, KEY_1), E_OK);
1091 EXPECT_EQ(g_naturalStoreConnection->Commit(), E_OK);
1092 /**
1093 * @tc.steps: step2. Get latest timestamp
1094 */
1095 Timestamp t1 = GetMaxTimestamp();
1096 EXPECT_TRUE(t1 > 0);
1097 /**
1098 * @tc.steps: step3. Put the external entry[KEY_2,VALUE_4,T2] into the database.
1099 * @tc.expected: step3. Put returns E_OK
1100 */
1101 std::vector<MultiVerKvEntry *> entriesV4;
1102 PushOneEntry(OPERATION_ADD, t1 - 1, KEY_2, VALUE_4, entriesV4);
1103 EXPECT_EQ(RunSyncMergeForOneCommit(entriesV4), E_OK);
1104 /**
1105 * @tc.steps: step4. Get value of K2
1106 * @tc.expected: step4. value of K2 is equals V2
1107 */
1108 ValueEqualByKey(KEY_2, VALUE_2);
1109 /**
1110 * @tc.steps: step5. Put the external entry[KEY_2,VALUE_5,T3] into the database.
1111 * @tc.expected: step5. Put returns E_OK
1112 */
1113 std::vector<MultiVerKvEntry *> entriesV5;
1114 PushOneEntry(OPERATION_ADD, t1 + 1, KEY_2, VALUE_5, entriesV5);
1115 EXPECT_EQ(RunSyncMergeForOneCommit(entriesV5), E_OK);
1116 /**
1117 * @tc.steps: step6. Get value of K2
1118 * @tc.expected: step6. value of K2 is equals V5
1119 */
1120 ValueEqualByKey(KEY_2, VALUE_5);
1121 /**
1122 * @tc.steps: step7. Put the external Delete entry[KEY_3,T2] into the database.
1123 * @tc.expected: step7. Put returns E_OK
1124 */
1125 std::vector<MultiVerKvEntry *> entriesV6;
1126 PushOneEntry(OPERATION_DELETE, t1 - 1, KEY_3, VALUE_6, entriesV6);
1127 EXPECT_EQ(RunSyncMergeForOneCommit(entriesV6), E_OK);
1128 /**
1129 * @tc.steps: step8. Get value of K3
1130 * @tc.expected: step8. value of K3 is equals V3
1131 */
1132 ValueEqualByKey(KEY_3, VALUE_3);
1133 /**
1134 * @tc.steps: step9. Put the external Delete entry[KEY_3,T2] into the database.
1135 * @tc.expected: step9. Put returns E_OK
1136 */
1137 std::vector<MultiVerKvEntry *> entriesV7;
1138 PushOneEntry(OPERATION_DELETE, t1 + 1, KEY_3, VALUE_7, entriesV7);
1139 EXPECT_EQ(RunSyncMergeForOneCommit(entriesV7), E_OK);
1140 /**
1141 * @tc.steps: step10. Get value of K3
1142 * @tc.expected: step10. Return NOT_FOUND
1143 */
1144 GetReadTransaction();
1145 Value valueTmp;
1146 EXPECT_EQ(g_transaction->Get(KEY_3, valueTmp), -E_NOT_FOUND);
1147 /**
1148 * @tc.steps: step11. Put the external entry[KEY_1,VALUE_6,T2] into the database.
1149 * @tc.expected: step11. Put returns E_OK
1150 */
1151 std::vector<MultiVerKvEntry *> entriesV8;
1152 PushOneEntry(OPERATION_ADD, t1 - 1, KEY_1, VALUE_6, entriesV8);
1153 EXPECT_EQ(RunSyncMergeForOneCommit(entriesV8), E_OK);
1154 /**
1155 * @tc.steps: step12. Get value of K1
1156 * @tc.expected: step12. Return NOT_FOUND
1157 */
1158 GetReadTransaction();
1159 EXPECT_EQ(g_transaction->Get(KEY_1, valueTmp), -E_NOT_FOUND);
1160 /**
1161 * @tc.steps: step13. Put the external entry[KEY_1,VALUE_7,T2] into the database.
1162 * @tc.expected: step13. Put returns E_OK
1163 */
1164 std::vector<MultiVerKvEntry *> entriesV9;
1165 PushOneEntry(OPERATION_ADD, t1 + 1, KEY_1, VALUE_7, entriesV9);
1166 EXPECT_EQ(RunSyncMergeForOneCommit(entriesV9), E_OK);
1167 /**
1168 * @tc.steps: step14. Get value of K1
1169 * @tc.expected: step14. value of K1 is V7
1170 */
1171 ValueEqualByKey(KEY_1, VALUE_7);
1172 }
1173
1174 /**
1175 * @tc.name: DefaultConflictResolution003
1176 * @tc.desc: Merge data with conflicts, clear operation is in the external data
1177 * @tc.type: FUNC
1178 * @tc.require: AR000CQE13 AR000CQE14
1179 * @tc.author: wumin
1180 */
1181 HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution003, TestSize.Level2)
1182 {
1183 /**
1184 * @tc.steps: step1. Put the local data(KEY_1, VALUE_1) into the database.
1185 * @tc.expected: step1. Put returns E_OK.
1186 */
1187 PutAndCommitEntry(KEY_1, VALUE_1);
1188 /**
1189 * @tc.steps: step2. Get timestampV1
1190 */
1191 Timestamp timestampV1 = GetMaxTimestamp();
1192 Timestamp timestampClear = timestampV1 + 1;
1193 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME));
1194 /**
1195 * @tc.steps: step3. Put the local data(KEY_2, VALUE_2) into the database.
1196 * @tc.expected: step3. Put returns E_OK.
1197 */
1198 PutAndCommitEntry(KEY_2, VALUE_2);
1199 /**
1200 * @tc.steps: step4. Get timestampV2
1201 */
1202 Timestamp timestampV2 = GetMaxTimestamp();
1203 /**
1204 * @tc.steps: step5. Put the external clear entry into the database.
1205 * @tc.expected: step5. Put returns E_OK
1206 */
1207 std::vector<MultiVerKvEntry *> entries;
1208 PushOneEntry(OPERATION_CLEAR, timestampClear, KEY_3, VALUE_3, entries);
1209 EXPECT_EQ(RunSyncMergeForOneCommit(entries), E_OK);
1210
1211 EXPECT_TRUE(timestampV1 < timestampClear);
1212 EXPECT_TRUE(timestampClear < timestampV2);
1213
1214 /**
1215 * @tc.steps: step6. Get value1 and value2
1216 * @tc.expected: step6. Get Value1 return NOT_FOUND , value2 is correct.
1217 */
1218 Value valueTmp;
1219 GetReadTransaction();
1220 EXPECT_EQ(g_transaction->Get(KEY_1, valueTmp), -E_NOT_FOUND);
1221
1222 ValueEqualByKey(KEY_2, VALUE_2);
1223 }
1224
1225 /**
1226 * @tc.name: DefaultConflictResolution004
1227 * @tc.desc: Merge data with conflicts, clear operation is in the local data
1228 * @tc.type: FUNC
1229 * @tc.require: AR000CQE13 AR000CQE14
1230 * @tc.author: wumin
1231 */
1232 HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution004, TestSize.Level2)
1233 {
1234 /**
1235 * @tc.steps: step1. Put the local data(KEY_1, VALUE_1) into the database and get the latest timestamp.
1236 * @tc.expected: step1. Put returns E_OK.
1237 */
1238 PutAndCommitEntry(KEY_1, VALUE_1);
1239 Timestamp t1 = GetMaxTimestamp();
1240 EXPECT_TRUE(t1 > 0);
1241 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME));
1242 /**
1243 * @tc.steps: step2. Put the local data(KEY_2, VALUE_2) into the database and get the latest timestamp.
1244 * @tc.expected: step2. Put returns E_OK.
1245 */
1246 PutAndCommitEntry(KEY_2, VALUE_2);
1247 Timestamp t2 = GetMaxTimestamp();
1248 /**
1249 * @tc.steps: step3. Execute Clear() operation and get the latest timestamp.
1250 */
1251 IOption option;
1252 g_naturalStoreConnection->Clear(option);
1253 Timestamp t3 = GetMaxTimestamp();
1254 EXPECT_TRUE(t3 > 0);
1255 /**
1256 * @tc.steps: step4. Put the local data(KEY_3, VALUE_3) into the database and get the latest timestamp.
1257 * @tc.expected: step4. Put returns E_OK.
1258 */
1259 PutAndCommitEntry(KEY_3, VALUE_3);
1260 /**
1261 * @tc.steps: step5. Put the external data [Clear, T5],[KEY_4,VALUE_4,T6],[KEY_5,VALUE_5,T7] into the database.
1262 * @tc.expected: step5. Put returns E_OK
1263 */
1264 EXPECT_TRUE(t1 + 1 < t2);
1265 std::vector<MultiVerKvEntry *> entries;
1266 // put clear entry
1267 PushOneEntry(OPERATION_CLEAR, t1 + 1, KEY_7, VALUE_7, entries);
1268 // put K4 entry
1269 PushOneEntry(OPERATION_ADD, t3 - 1, KEY_4, VALUE_4, entries);
1270 // put K5 entry
1271 PushOneEntry(OPERATION_ADD, t3 + 1, KEY_5, VALUE_5, entries);
1272 // merge data
1273 EXPECT_EQ(RunSyncMergeForOneCommit(entries), E_OK);
1274 /**
1275 * @tc.steps: step6. Get value of KEY_1,KEY_2,KEY_3,KEY_4,K5
1276 */
1277 GetReadTransaction();
1278 Value valueTmp;
1279 EXPECT_EQ(g_transaction->Get(KEY_1, valueTmp), -E_NOT_FOUND);
1280 EXPECT_EQ(g_transaction->Get(KEY_2, valueTmp), -E_NOT_FOUND);
1281 EXPECT_EQ(g_transaction->Get(KEY_4, valueTmp), -E_NOT_FOUND);
1282
1283 ValueEqualByKey(KEY_3, VALUE_3);
1284 ValueEqualByKey(KEY_5, VALUE_5);
1285 }
1286
1287 /**
1288 * @tc.name: CommitTimestamp001
1289 * @tc.desc: Test the timestamp of the native commit.
1290 * @tc.type: FUNC
1291 * @tc.require: AR000CQE11
1292 * @tc.author: wangbingquan
1293 */
1294 HWTEST_F(DistributedDBStorageTransactionDataTest, CommitTimestamp001, TestSize.Level2)
1295 {
1296 /**
1297 * @tc.steps: step1. Put in some data(non-empty key, non-empty value) within one transaction.
1298 */
1299 EXPECT_EQ(g_naturalStoreConnection->StartTransaction(), E_OK);
1300 IOption option;
1301 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_1, VALUE_1), E_OK);
1302 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_2, VALUE_2), E_OK);
1303 EXPECT_EQ(g_naturalStoreConnection->Commit(), E_OK);
1304
1305 /**
1306 * @tc.steps: step2. Add different operations(add,update,delete,clear) within one transaction.
1307 */
1308 std::srand(std::time(0)); // set the current time to the seed.
1309 EXPECT_EQ(g_naturalStoreConnection->StartTransaction(), E_OK);
1310 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_4, VALUE_4), E_OK); // add
1311 std::this_thread::sleep_for(std::chrono::milliseconds(std::rand() % 1000));
1312 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_1, VALUE_3), E_OK); // update
1313 std::this_thread::sleep_for(std::chrono::milliseconds(std::rand() % 1000));
1314 EXPECT_EQ(g_naturalStoreConnection->Delete(option, KEY_2), E_OK); // delete
1315 std::this_thread::sleep_for(std::chrono::milliseconds(std::rand() % 1000));
1316 EXPECT_EQ(g_naturalStoreConnection->Clear(option), E_OK); // clear
1317 std::this_thread::sleep_for(std::chrono::milliseconds(std::rand() % 1000));
1318 EXPECT_EQ(g_naturalStoreConnection->Commit(), E_OK);
1319
1320 /**
1321 * @tc.steps: step3. Get all the record data in the newest commit.
1322 */
1323 GetReadTransaction();
1324 std::vector<MultiVerKvEntry *> entries;
1325 g_transaction->GetEntriesByVersion(g_version, entries);
1326 ASSERT_EQ(entries.size(), 4UL); // add, update, delete and clear for 4 operation.
1327
1328 std::set<uint64_t> timeSet;
1329 for (auto item : entries) {
1330 uint64_t timestamp = 0;
1331 item->GetTimestamp(timestamp);
1332 timeSet.insert(timestamp);
1333 }
1334
1335 ASSERT_EQ(timeSet.size(), 1UL); // only one timestamp in one commit.
1336 // Tobe compare the timestamp.
1337 CommitID commitId;
1338 Timestamp commitTimestamp = GetCommitTimestamp(commitId);
1339 LOGD("TimeRecord:%" PRIu64 ", TimeCommit:%" PRIu64, *(timeSet.begin()), commitTimestamp);
1340 ASSERT_EQ(*(timeSet.begin()), commitTimestamp);
1341 ASSERT_NE(commitTimestamp, 0UL);
1342
1343 for (auto &item : entries) {
1344 g_naturalStore->ReleaseKvEntry(item);
1345 item = nullptr;
1346 }
1347 }
1348
PutFirstSyncCommitData(MultiVerCommitNode & multiVerCommit)1349 static bool PutFirstSyncCommitData(MultiVerCommitNode &multiVerCommit)
1350 {
1351 GenericMultiVerKvEntry entry;
1352 entry.SetOperFlag(1); // add the new data.
1353 entry.SetKey(KEY_2);
1354
1355 MultiVerValueObject valueObject;
1356 valueObject.SetValue(VALUE_2);
1357 Value objectSerial;
1358 valueObject.GetSerialData(objectSerial);
1359 entry.SetValue(objectSerial);
1360 entry.SetTimestamp(1000UL); // the first data timestamp.
1361
1362 std::vector<MultiVerKvEntry *> entries;
1363 entries.push_back(&entry);
1364 /**
1365 * @tc.steps: step1. Create the multiver commit.
1366 */
1367 multiVerCommit.commitId.resize(20); // commit id size
1368 RAND_bytes(multiVerCommit.commitId.data(), 20); // commit id size
1369 multiVerCommit.deviceInfo = DBCommon::TransferHashString("deviceB") + "deviceB1";
1370 multiVerCommit.timestamp = 1000UL; // the first data timestamp.
1371 /**
1372 * @tc.steps: step2. Put the multiver commit of other device.
1373 */
1374 int errCode = g_naturalStore->PutCommitData(multiVerCommit, entries, "deviceB");
1375 if (errCode != E_OK) {
1376 return false;
1377 }
1378 return true;
1379 }
1380
PutSecondSyncCommitData(const MultiVerCommitNode & multiVerCommit,MultiVerCommitNode & newCommit)1381 static bool PutSecondSyncCommitData(const MultiVerCommitNode &multiVerCommit, MultiVerCommitNode &newCommit)
1382 {
1383 GenericMultiVerKvEntry entry;
1384 entry.SetOperFlag(1); // add flag
1385 entry.SetKey(KEY_3);
1386
1387 MultiVerValueObject valueObject;
1388 valueObject.SetValue(VALUE_3);
1389 Value objectSerial;
1390 valueObject.GetSerialData(objectSerial);
1391 entry.SetValue(objectSerial);
1392 entry.SetTimestamp(2000UL); // bigger than the first one.
1393
1394 std::vector<MultiVerKvEntry *> entries;
1395 entries.push_back(&entry);
1396
1397 newCommit.commitId.resize(20); // commit id size
1398 RAND_bytes(newCommit.commitId.data(), 20); // commit id size.
1399 newCommit.leftParent = multiVerCommit.commitId;
1400 newCommit.deviceInfo = DBCommon::TransferHashString("deviceB") + "deviceB1";
1401 newCommit.timestamp = 2000UL; // bigger than the first one.
1402
1403 int errCode = g_naturalStore->PutCommitData(newCommit, entries, "deviceB");
1404 if (errCode != E_OK) {
1405 return false;
1406 }
1407 std::vector<MultiVerCommitNode> multiVerCommits;
1408 multiVerCommits.push_back(multiVerCommit);
1409 multiVerCommits.push_back(newCommit);
1410
1411 errCode = g_naturalStore->MergeSyncCommit(newCommit, multiVerCommits);
1412 if (errCode != E_OK) {
1413 return false;
1414 }
1415 return true;
1416 }
1417
1418 /**
1419 * @tc.name: CommitTimestamp002
1420 * @tc.desc: Test the timestamp of the native commits.
1421 * @tc.type: FUNC
1422 * @tc.require: AR000CQE11
1423 * @tc.author: wangbingquan
1424 */
1425 HWTEST_F(DistributedDBStorageTransactionDataTest, CommitTimestamp002, TestSize.Level1)
1426 {
1427 /**
1428 * @tc.steps: step1. Put in some data(non-empty key, non-empty value) within one transaction.
1429 */
1430 EXPECT_EQ(g_naturalStoreConnection->StartTransaction(), E_OK);
1431 IOption option;
1432 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_1, VALUE_1), E_OK);
1433 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_2, VALUE_2), E_OK);
1434 EXPECT_EQ(g_naturalStoreConnection->Commit(), E_OK);
1435
1436 CommitID commitId;
1437 Timestamp stampFirst = GetCommitTimestamp(commitId);
1438 ASSERT_NE(stampFirst, 0UL); // non-zero
1439
1440 /**
1441 * @tc.steps: step2. Add another data within one transaction.
1442 */
1443 std::srand(std::time(0)); // set the current time to the seed.
1444 std::this_thread::sleep_for(std::chrono::milliseconds(std::rand() % 1000));
1445 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_4, VALUE_4), E_OK);
1446 /**
1447 * @tc.steps: step3. Check the timestamp of the two commits.
1448 * @tc.expected: step3. the timestamp of the second commit is greater than the timestamp of the first commit.
1449 */
1450 Timestamp stampSecond = GetCommitTimestamp(commitId);
1451 ASSERT_NE(stampSecond, 0UL); // non-zero
1452 LOGD("TimeFirst:%" PRIu64 ", TimeSecond:%" PRIu64, stampFirst, stampSecond);
1453 ASSERT_GT(stampSecond, stampFirst);
1454 }
ReleaseKvEntries(std::vector<MultiVerKvEntry * > & entries)1455 static void ReleaseKvEntries(std::vector<MultiVerKvEntry *> &entries)
1456 {
1457 for (auto &item : entries) {
1458 if (item == nullptr) {
1459 continue;
1460 }
1461 g_naturalStore->ReleaseKvEntry(item);
1462 item = nullptr;
1463 }
1464 }
1465
1466 /**
1467 * @tc.name: CommitTimestamp003
1468 * @tc.desc: Test the timestamp of the foreign commits.
1469 * @tc.type: FUNC
1470 * @tc.require: AR000CQE11
1471 * @tc.author: wangbingquan
1472 */
1473 HWTEST_F(DistributedDBStorageTransactionDataTest, CommitTimestamp003, TestSize.Level1)
1474 {
1475 /**
1476 * @tc.steps: step1. Put in some data(non-empty key, non-empty value) within one transaction.
1477 */
1478 EXPECT_EQ(g_naturalStoreConnection->StartTransaction(), E_OK);
1479 IOption option;
1480 EXPECT_EQ(g_naturalStoreConnection->Put(option, KEY_1, VALUE_1), E_OK);
1481 EXPECT_EQ(g_naturalStoreConnection->Commit(), E_OK);
1482
1483 /**
1484 * @tc.steps: step2. Add different operations(add,update,delete,clear) within one transaction.
1485 */
1486 std::srand(std::time(0)); // set the current time to the seed.
1487 std::this_thread::sleep_for(std::chrono::milliseconds(std::rand() % 1000));
1488 MultiVerCommitNode commit;
1489 ASSERT_EQ(PutFirstSyncCommitData(commit), true); // add
1490
1491 GetReadTransaction();
1492 std::vector<MultiVerKvEntry *> entries;
1493 g_transaction->GetEntriesByVersion(g_version, entries);
1494 ASSERT_EQ(entries.size(), 1UL); // sync commit have only one entry.
1495 ASSERT_NE(entries[0], nullptr);
1496 uint64_t timestamp = 0;
1497 entries[0]->GetTimestamp(timestamp);
1498 ReleaseKvEntries(entries);
1499
1500 /**
1501 * @tc.steps: step3. Check the timestamp of the commit and the data.
1502 * @tc.steps: expected. the timestamp of the sync commit is equal to the timestamp of the data record.
1503 */
1504 Timestamp commitTimestamp = GetCommitTimestamp(commit.commitId);
1505 LOGD("TimeRecord:%" PRIu64 ", TimeCommit:%" PRIu64, timestamp, commitTimestamp);
1506 ASSERT_EQ(timestamp, commitTimestamp);
1507 ASSERT_NE(commitTimestamp, 0UL);
1508 }
1509
1510 /**
1511 * @tc.name: CommitTimestamp004
1512 * @tc.desc: Test the timestamp of the merge commits.
1513 * @tc.type: FUNC
1514 * @tc.require: AR000CQE11
1515 * @tc.author: wangbingquan
1516 */
1517 HWTEST_F(DistributedDBStorageTransactionDataTest, CommitTimestamp004, TestSize.Level1)
1518 {
1519 /**
1520 * @tc.steps: step1. Add the first sync commit.
1521 */
1522 MultiVerCommitNode commit;
1523 ASSERT_EQ(PutFirstSyncCommitData(commit), true); // add the first sync commit.
1524
1525 std::srand(std::time(0)); // set the current time to the seed.
1526 std::this_thread::sleep_for(std::chrono::milliseconds(std::rand() % 1000)); // sleep for random interval.
1527
1528 /**
1529 * @tc.steps: step2. Add the second sync commit and merge the commit.
1530 */
1531 MultiVerCommitNode newCommit;
1532 ASSERT_EQ(PutSecondSyncCommitData(commit, newCommit), true);
1533
1534 /**
1535 * @tc.steps: step3. Get the newest entries.
1536 */
1537 GetReadTransaction();
1538 std::vector<MultiVerKvEntry *> entries;
1539 g_transaction->GetEntriesByVersion(g_version, entries);
1540 ASSERT_EQ(entries.size(), 2UL); // merge node has 2 entries.
1541
1542 std::set<uint64_t> timeSet;
1543 for (auto &item : entries) {
1544 ASSERT_NE(item, nullptr);
1545 uint64_t timestamp = 0;
1546 item->GetTimestamp(timestamp);
1547 g_naturalStore->ReleaseKvEntry(item);
1548 item = nullptr;
1549 timeSet.insert(timestamp);
1550 }
1551 /**
1552 * @tc.steps: step4. Get the timestamp of newest entries.
1553 * @tc.expected: step4. The merged commit have different timestamp.
1554 */
1555 ASSERT_EQ(timeSet.size(), 2UL); // entries have different timestamp.
1556 for (auto item : timeSet) {
1557 ASSERT_NE(item, 0UL);
1558 }
1559 }
1560
1561 /**
1562 * @tc.name: GetBranchTag
1563 * @tc.desc: Test the branch tag of the commits.
1564 * @tc.type: FUNC
1565 * @tc.require: AR000CQE11
1566 * @tc.author: wangbingquan
1567 */
1568 HWTEST_F(DistributedDBStorageTransactionDataTest, GetBranchTag001, TestSize.Level1)
1569 {
1570 KvStoreDelegateManager::SetProcessLabel("123", "456");
1571 KvStoreDelegateManager::SetProcessCommunicator(std::make_shared<ProcessCommunicatorTestStub>());
1572 ASSERT_NE(g_naturalStore, nullptr);
1573 std::vector<uint8_t> vectTag;
1574 g_naturalStore->GetCurrentTag(vectTag);
1575 DBCommon::PrintHexVector(vectTag);
1576 for (int i = 0; i < 10; i++) {
1577 if (g_naturalStore != nullptr) {
1578 if (g_naturalStoreConnection != nullptr) {
1579 g_naturalStoreConnection->Close();
1580 g_naturalStoreConnection = nullptr;
1581 }
1582 g_naturalStore->DecObjRef(g_naturalStore);
1583 g_naturalStore = new (std::nothrow) MultiVerNaturalStore;
1584 ASSERT_NE(g_naturalStore, nullptr);
1585 EXPECT_EQ(g_naturalStore->Open(g_prop), E_OK);
1586 std::vector<uint8_t> readTag;
1587 g_naturalStore->GetCurrentTag(readTag);
1588 DBCommon::PrintHexVector(readTag);
1589 EXPECT_EQ(vectTag, readTag);
1590 }
1591 }
1592 }
1593 #endif // OMIT_MULTI_VER