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