1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <gtest/gtest.h>
16 #include <openssl/rand.h>
17 
18 #include "db_common.h"
19 #include "db_errno.h"
20 #include "distributeddb_data_generate_unit_test.h"
21 #include "distributeddb_tools_unit_test.h"
22 #include "generic_single_ver_kv_entry.h"
23 #include "kvdb_manager.h"
24 #include "process_communicator_test_stub.h"
25 #include "process_system_api_adapter_impl.h"
26 #include "query_sync_object.h"
27 #include "sqlite_single_ver_natural_store.h"
28 #include "sqlite_single_ver_natural_store_connection.h"
29 
30 using namespace testing::ext;
31 using namespace DistributedDB;
32 using namespace DistributedDBUnitTest;
33 using namespace std;
34 
35 namespace {
36 DistributedDB::KvStoreConfig g_config;
37 std::string g_testDir;
38 string g_resourceDir;
39 
40 KvStoreDelegateManager g_mgr(APP_ID, USER_ID);
41 // define the g_kvDelegateCallback, used to get some information when open a kv store.
42 DBStatus g_kvDelegateStatus = INVALID_ARGS;
43 KvStoreNbDelegate *g_kvNbDelegatePtr = nullptr;
44 auto g_kvNbDelegateCallback = bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback,
45     placeholders::_1, placeholders::_2, std::ref(g_kvDelegateStatus), std::ref(g_kvNbDelegatePtr));
46 
47 const uint8_t PRESET_DATA_SIZE = 2;
48 const std::string SUBSCRIBE_ID = "680A20600517073AE306B11FEA8306C57DC5102CD33E322F7C513176AA707F0C";
49 
50 const std::string REMOTE_DEVICE_ID = "remote_device_id";
51 const std::string REMOTE_DEVICE_A = "remote_device_A";
52 const std::string REMOTE_DEVICE_B = "remote_device_B";
53 const Key PREFIX_KEY = { 'k' };
54 const Key KEY1 = { 'k', '1' };
55 const Key KEY2 = { 'k', '2' };
56 const Key KEY3 = { 'k', '3' };
57 const Value VALUE1 = { 'v', '1' };
58 const Value VALUE2 = { 'v', '2' };
59 const Value VALUE3 = { 'v', '3' };
60 
61 const std::string NORMAL_FBS_FILE_NAME = "normal_fbs.bfbs";
62 const string SCHEMA_STRING =
63     "{\"SCHEMA_VERSION\":\"1.0\","
64     "\"SCHEMA_MODE\":\"STRICT\","
65     "\"SCHEMA_DEFINE\":{"
66     "\"field_name1\":\"BOOL\","
67     "\"field_name2\":\"BOOL\","
68     "\"field_name3\":\"INTEGER, NOT NULL\","
69     "\"field_name4\":\"LONG, DEFAULT 100\","
70     "\"field_name5\":\"DOUBLE, DEFAULT 3.14\","
71     "\"field_name6\":\"STRING, DEFAULT '3.1415'\","
72     "\"field_name7\":\"LONG, DEFAULT 100\","
73     "\"field_name8\":\"LONG, DEFAULT 100\","
74     "\"field_name9\":\"LONG, DEFAULT 100\","
75     "\"field_name10\":\"LONG, DEFAULT 100\""
76     "},"
77     "\"SCHEMA_INDEXES\":[\"$.field_name1\", \"$.field_name2\"]}";
78 
PreSetData(uint8_t dataNum)79 void PreSetData(uint8_t dataNum)
80 {
81     EXPECT_GE(dataNum, 0); // 0 No preset data
82     EXPECT_LT(dataNum, 128); // 128 Max preset data size
83     for (uint8_t i = 0; i < dataNum; i++) {
84         Key keyA = {'K', i};
85         Value value;
86         std::string validJsonData;
87         if (i % 2 == 0) { // 2 : for data construct
88             validJsonData = R"({"field_name1":false,"field_name2":true,"field_name3":100})";
89         } else {
90             validJsonData = R"({"field_name1":false,"field_name2":false,"field_name3":100})";
91         }
92         value.assign(validJsonData.begin(), validJsonData.end());
93         EXPECT_EQ(g_kvNbDelegatePtr->Put(keyA, value), E_OK);
94     }
95 }
96 
CreateAndGetStore(const std::string & storeId,const std::string & schemaString,SQLiteSingleVerNaturalStoreConnection * & conn,SQLiteSingleVerNaturalStore * & store,uint8_t preSetDataNum=0)97 void CreateAndGetStore(const std::string &storeId, const std::string &schemaString,
98     SQLiteSingleVerNaturalStoreConnection *&conn, SQLiteSingleVerNaturalStore *&store, uint8_t preSetDataNum = 0)
99 {
100     KvStoreNbDelegate::Option option = {true, false, false};
101     option.schema = schemaString;
102     g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
103     EXPECT_TRUE(g_kvNbDelegatePtr != nullptr);
104     EXPECT_TRUE(g_kvDelegateStatus == OK);
105     PreSetData(preSetDataNum);
106     EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
107 
108     std::string oriIdentifier = USER_ID + "-" + APP_ID + "-" + storeId;
109     std::string identifier = DBCommon::TransferHashString(oriIdentifier);
110     KvDBProperties property;
111     property.SetStringProp(KvDBProperties::IDENTIFIER_DATA, identifier);
112     std::string identifierHex = DBCommon::TransferStringToHex(identifier);
113     property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir);
114     property.SetStringProp(KvDBProperties::STORE_ID, storeId);
115     property.SetBoolProp(KvDBProperties::MEMORY_MODE, false);
116     property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE);
117     property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, identifierHex);
118     property.SetIntProp(KvDBProperties::CONFLICT_RESOLVE_POLICY, ConflictResolvePolicy::LAST_WIN);
119 
120     if (!schemaString.empty()) {
121         SchemaObject schemaObj;
122         schemaObj.ParseFromSchemaString(schemaString);
123         EXPECT_EQ(schemaObj.IsSchemaValid(), true);
124         property.SetSchema(schemaObj);
125     }
126 
127     int errCode = E_OK;
128     conn = static_cast<SQLiteSingleVerNaturalStoreConnection *>(KvDBManager::GetDatabaseConnection(property, errCode));
129     EXPECT_EQ(errCode, E_OK);
130     ASSERT_NE(conn, nullptr);
131     store = static_cast<SQLiteSingleVerNaturalStore *>(KvDBManager::OpenDatabase(property, errCode));
132     EXPECT_EQ(errCode, E_OK);
133     ASSERT_NE(store, nullptr);
134 }
135 
136 #ifndef OMIT_FLATBUFFER
FbfFileToSchemaString(const std::string & fileName)137 std::string FbfFileToSchemaString(const std::string &fileName)
138 {
139     std::string filePath = g_resourceDir + "fbs_files_for_ut/" + fileName;
140     std::ifstream is(filePath, std::ios::binary | std::ios::ate);
141     if (!is.is_open()) {
142         LOGE("[FbfFileToSchemaString] open file failed name : %s", filePath.c_str());
143         return "";
144     }
145 
146     auto size = is.tellg();
147     LOGE("file size %u", static_cast<unsigned>(size));
148     std::string schema(size, '\0');
149     is.seekg(0);
150     if (is.read(&schema[0], size)) {
151         return schema;
152     }
153     LOGE("[FbfFileToSchemaString] read file failed path : %s", filePath.c_str());
154     return "";
155 }
156 #endif
157 
CheckDataNumByKey(const std::string & storeId,const Key & key,size_t expSize)158 void CheckDataNumByKey(const std::string &storeId, const Key& key, size_t expSize)
159 {
160     KvStoreNbDelegate::Option option = {true, false, false};
161     option.schema = SCHEMA_STRING;
162     g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
163     EXPECT_TRUE(g_kvNbDelegatePtr != nullptr);
164     EXPECT_TRUE(g_kvDelegateStatus == OK);
165     std::vector<Entry> entries;
166     EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(key, entries), E_OK);
167     EXPECT_TRUE(entries.size() == expSize);
168     EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
169 }
170 }
171 
172 class DistributedDBStorageSubscribeQueryTest : public testing::Test {
173 public:
174     static void SetUpTestCase(void);
175     static void TearDownTestCase(void);
176     void SetUp() override;
177     void TearDown() override;
178 };
179 
180 static std::shared_ptr<ProcessSystemApiAdapterImpl> g_adapter;
SetUpTestCase(void)181 void DistributedDBStorageSubscribeQueryTest::SetUpTestCase(void)
182 {
183     g_mgr.SetProcessLabel("DistributedDBStorageSubscribeQueryTest", "test");
184     g_mgr.SetProcessCommunicator(std::make_shared<ProcessCommunicatorTestStub>()); // export and import get devID
185 
186     DistributedDBToolsUnitTest::TestDirInit(g_testDir);
187     ASSERT_EQ(DistributedDBToolsUnitTest::GetResourceDir(g_resourceDir), E_OK);
188     LOGD("Test dir is %s", g_testDir.c_str());
189     DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir + "/TestQuerySync/" + DBConstant::SINGLE_SUB_DIR);
190 
191     g_config.dataDir = g_testDir;
192     g_mgr.SetKvStoreConfig(g_config);
193 
194     g_adapter = std::make_shared<ProcessSystemApiAdapterImpl>();
195     EXPECT_TRUE(g_adapter != nullptr);
196     RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter);
197 }
198 
TearDownTestCase(void)199 void DistributedDBStorageSubscribeQueryTest::TearDownTestCase(void)
200 {
201     RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr);
202 }
203 
SetUp()204 void DistributedDBStorageSubscribeQueryTest::SetUp()
205 {
206     Test::SetUp();
207     DistributedDBToolsUnitTest::PrintTestCaseInfo();
208 }
209 
TearDown()210 void DistributedDBStorageSubscribeQueryTest::TearDown()
211 {
212     Test::TearDown();
213     DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir);
214 }
215 
216 /**
217   * @tc.name: CheckAndInitQueryCondition001
218   * @tc.desc: Check the condition is legal or not with json schema
219   * @tc.type: FUNC
220   * @tc.require: AR000FN6G9
221   * @tc.author: xulianhui
222   */
223 HWTEST_F(DistributedDBStorageSubscribeQueryTest, CheckAndInitQueryCondition001, TestSize.Level1)
224 {
225     /**
226      * @tc.steps:step1. Create a json schema db, get the natural store instance.
227      * @tc.expected: step1. Get results OK and non-null store.
228      */
229     SQLiteSingleVerNaturalStoreConnection *conn = nullptr;
230     SQLiteSingleVerNaturalStore *store = nullptr;
231     CreateAndGetStore("SchemaCondition01", SCHEMA_STRING, conn, store);
232 
233     /**
234      * @tc.steps:step2. Create a query with prefixKey only, check it as condition.
235      * @tc.expected: step2. Check condition return E_OK.
236      */
237     Query query1 = Query::Select().PrefixKey({});
238     QueryObject queryObject1(query1);
239     int errCode = store->CheckAndInitQueryCondition(queryObject1);
240     EXPECT_EQ(errCode, E_OK);
241 
242     /**
243      * @tc.steps:step3. Create a query with predicate, check it as condition.
244      * @tc.expected: step3. Check condition return E_OK.
245      */
246     Query query2 = Query::Select().GreaterThan("field_name3", 10);
247     QueryObject queryObject2(query2);
248     errCode = store->CheckAndInitQueryCondition(queryObject2);
249     EXPECT_EQ(errCode, E_OK);
250 
251     /**
252      * @tc.steps:step4. Create a query with invalid field, check it as condition.
253      * @tc.expected: step4. Check condition return E_INVALID_QUERY_FIELD.
254      */
255     Query query3 = Query::Select().GreaterThan("field_name11", 10);
256     QueryObject queryObject3(query3);
257     errCode = store->CheckAndInitQueryCondition(queryObject3);
258     EXPECT_EQ(errCode, -E_INVALID_QUERY_FIELD);
259 
260     /**
261      * @tc.steps:step5. Create a query with invalid format, check it as condition.
262      * @tc.expected: step5. Check condition return E_INVALID_QUERY_FORMAT.
263      */
264     Query query4 = Query::Select().GreaterThan("field_name3", 10).And().BeginGroup().
265         LessThan("field_name3", 100).OrderBy("field_name3").EndGroup();
266     QueryObject queryObject4(query4);
267     errCode = store->CheckAndInitQueryCondition(queryObject4);
268     EXPECT_EQ(errCode, -E_INVALID_QUERY_FORMAT);
269 
270     /**
271      * @tc.steps:step6. Close natural store
272      * @tc.expected: step6. Close ok
273      */
274     RefObject::KillAndDecObjRef(store);
275     KvDBManager::ReleaseDatabaseConnection(conn);
276 }
277 
278 #ifndef OMIT_FLATBUFFER
279 /**
280   * @tc.name: CheckAndInitQueryCondition002
281   * @tc.desc: Check the condition always illegal with flatbuffer schema
282   * @tc.type: FUNC
283   * @tc.require: AR000FN6G9
284   * @tc.author: xulianhui
285   */
286 HWTEST_F(DistributedDBStorageSubscribeQueryTest, CheckAndInitQueryCondition002, TestSize.Level1)
287 {
288     /**
289      * @tc.steps:step1. Create a flatbuffer schema db, get the natural store instance.
290      * @tc.expected: step1. Get results OK and non-null store.
291      */
292     std::string fbSchema = FbfFileToSchemaString(NORMAL_FBS_FILE_NAME);
293     EXPECT_FALSE(fbSchema.empty());
294     SQLiteSingleVerNaturalStoreConnection *conn = nullptr;
295     SQLiteSingleVerNaturalStore *store = nullptr;
296     CreateAndGetStore("SchemaCondition02", fbSchema, conn, store);
297 
298     /**
299      * @tc.steps:step2. Create a query, check it as condition.
300      *                  flatbuffer schema is not support with querySync and subscribe.
301      * @tc.expected: step2. Check condition return E_NOT_SUPPORT.
302      */
303     Query query1 = Query::Select().PrefixKey({});
304     QueryObject queryObject1(query1);
305     int errCode = store->CheckAndInitQueryCondition(queryObject1);
306     EXPECT_EQ(errCode, -E_NOT_SUPPORT);
307 
308     /**
309      * @tc.steps:step3. Close natural store
310      * @tc.expected: step3. Close ok
311      */
312     RefObject::KillAndDecObjRef(store);
313     KvDBManager::ReleaseDatabaseConnection(conn);
314 }
315 #endif
316 
317 /**
318   * @tc.name: CheckAndInitQueryCondition003
319   * @tc.desc: Check the condition always illegal with flatbuffer schema
320   * @tc.type: FUNC
321   * @tc.require: AR000FN6G9
322   * @tc.author: xulianhui
323   */
324 HWTEST_F(DistributedDBStorageSubscribeQueryTest, CheckAndInitQueryCondition003, TestSize.Level1)
325 {
326     /**
327      * @tc.steps:step1. Create a kv db, get the natural store instance.
328      * @tc.expected: step1. Get results OK and non-null store.
329      */
330     SQLiteSingleVerNaturalStoreConnection *conn = nullptr;
331     SQLiteSingleVerNaturalStore *store = nullptr;
332     CreateAndGetStore("SchemaCondition03", "", conn, store);
333 
334     /**
335      * @tc.steps:step2. Create a prefixKey query, check it as condition.
336      * @tc.expected: step2. Check condition return E_OK.
337      */
338     Query query1 = Query::Select().PrefixKey({});
339     QueryObject queryObject1(query1);
340     int errCode = store->CheckAndInitQueryCondition(queryObject1);
341     EXPECT_EQ(errCode, E_OK);
342 
343     /**
344      * @tc.steps:step2. Create a predicate query, check it as condition.
345      * @tc.expected: step2. Check condition return E_NOT_SUPPORT.
346      */
347     Query query2 = Query::Select().GreaterThan("field_name3", 10);
348     QueryObject queryObject2(query2);
349     errCode = store->CheckAndInitQueryCondition(queryObject2);
350     EXPECT_EQ(errCode, -E_NOT_SUPPORT);
351 
352     /**
353      * @tc.steps:step3. Close natural store
354      * @tc.expected: step3. Close ok
355      */
356     RefObject::KillAndDecObjRef(store);
357     KvDBManager::ReleaseDatabaseConnection(conn);
358 }
359 
360 /**
361   * @tc.name: PutSyncDataTestWithQuery
362   * @tc.desc: put remote devices sync data(get by query sync or subscribe) with query.
363   * @tc.type: FUNC
364   * @tc.require: AR000FN6G9
365   * @tc.author: xulianhui
366   */
367 HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery, TestSize.Level1)
368 {
369     /**
370      * @tc.steps:step1. create and open a schema store, preset some data;
371      * @tc.expected: step1. open success
372      */
373     const std::string storeId = "PutSyncData01";
374     SQLiteSingleVerNaturalStoreConnection *conn = nullptr;
375     SQLiteSingleVerNaturalStore *store = nullptr;
376     CreateAndGetStore(storeId, SCHEMA_STRING, conn, store, PRESET_DATA_SIZE);
377 
378     /**
379      * @tc.steps:step2. Construct sync data
380      * @tc.expected: OK
381      */
382     Key key;
383     Value value;
384     Timestamp now = store->GetCurrentTimestamp();
385     LOGD("now time is : %ld", now);
386     std::vector<DataItem> data;
387     for (uint8_t i = 0; i < PRESET_DATA_SIZE; i++) {
388         DataItem item{key, value, now, DataItem::REMOTE_DEVICE_DATA_MISS_QUERY, REMOTE_DEVICE_ID, now};
389         item.key.clear();
390         DBCommon::CalcValueHash({'K', i}, item.key);
391         EXPECT_EQ(item.key.empty(), false);
392         data.push_back(item);
393     }
394 
395     /**
396      * @tc.steps:step3. put sync data with query
397      * @tc.expected: step3. data put success
398      */
399     Query query = Query::Select().EqualTo("field_name2", true);
400     QueryObject queryObj(query);
401     EXPECT_EQ(DistributedDBToolsUnitTest::PutSyncDataTest(store, data, REMOTE_DEVICE_ID, queryObj), E_OK);
402 
403     RefObject::KillAndDecObjRef(store);
404     KvDBManager::ReleaseDatabaseConnection(conn);
405 
406     /**
407      * @tc.steps:step4. Check sync data
408      * @tc.expected: step4. check data ok
409      */
410     CheckDataNumByKey(storeId, {'K'}, PRESET_DATA_SIZE / 2);
411 }
412 
413 /**
414   * @tc.name: PutSyncDataTestWithQuery002
415   * @tc.desc: put remote devices sync data(timestamp is smaller then DB data) with query.
416   * @tc.type: FUNC
417   * @tc.require: AR000FN6G9
418   * @tc.author: xulianhui
419   */
420 HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery002, TestSize.Level1)
421 {
422     /**
423      * @tc.steps:step1. create and open a schema store, preset some data;
424      * @tc.expected: step1. open success
425      */
426     const std::string storeId = "PutSyncData02";
427 
428     SQLiteSingleVerNaturalStoreConnection *conn = nullptr;
429     SQLiteSingleVerNaturalStore *store = nullptr;
430     CreateAndGetStore(storeId, SCHEMA_STRING, conn, store);
431 
432     Key key({'K', 'e', 'y'});
433     Value value;
434     Timestamp now = store->GetCurrentTimestamp();
435     /**
436      * @tc.steps:step2. put sync data
437      * @tc.expected: OK
438      */
439     std::string validJsonData(R"({"field_name1":false,"field_name2":true,"field_name3":100})");
440     value.assign(validJsonData.begin(), validJsonData.end());
441     std::vector<DataItem> data;
442     DataItem item{key, value, now, DataItem::LOCAL_FLAG, REMOTE_DEVICE_ID, now};
443     data.push_back(item);
444     EXPECT_EQ(DistributedDBToolsUnitTest::PutSyncDataTest(store, data, REMOTE_DEVICE_ID), E_OK);
445 
446     /**
447      * @tc.steps:step3. put sync miss query data with smaller timestamp
448      * @tc.expected: OK
449      */
450     data.clear();
451     value.clear();
452     DataItem itemMiss{key, value, now - 1, DataItem::REMOTE_DEVICE_DATA_MISS_QUERY, REMOTE_DEVICE_ID, now - 1};
453     itemMiss.key.clear();
454     DBCommon::CalcValueHash({'K', 'e', 'y'}, itemMiss.key);
455     EXPECT_EQ(itemMiss.key.empty(), false);
456     data.push_back(itemMiss);
457     Query query = Query::Select().EqualTo("field_name2", true);
458     QueryObject queryObj(query);
459     EXPECT_EQ(DistributedDBToolsUnitTest::PutSyncDataTest(store, data, REMOTE_DEVICE_ID, queryObj), E_OK);
460 
461     RefObject::KillAndDecObjRef(store);
462     KvDBManager::ReleaseDatabaseConnection(conn);
463 
464     /**
465      * @tc.steps:step4. Check sync data
466      * @tc.expected: check data ok, data {key} is not erased.
467      */
468     CheckDataNumByKey(storeId, {'K', 'e', 'y'}, 1);
469 }
470 
471 /**
472   * @tc.name: PutSyncDataTestWithQuery003
473   * @tc.desc: put remote devices sync data(with same timestamp in DB data but different devices) with query.
474   * @tc.type: FUNC
475   * @tc.require: AR000FN6G9
476   * @tc.author: xulianhui
477   */
478 HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery003, TestSize.Level1)
479 {
480     /**
481      * @tc.steps:step1. create and open a schema store, preset some data;
482      * @tc.expected: step1. open success
483      */
484     const std::string storeId = "PutSyncData03";
485 
486     SQLiteSingleVerNaturalStoreConnection *conn = nullptr;
487     SQLiteSingleVerNaturalStore *store = nullptr;
488     CreateAndGetStore(storeId, SCHEMA_STRING, conn, store);
489 
490     Key key({'K', 'e', 'y'});
491     Value value;
492     Timestamp now = store->GetCurrentTimestamp();
493     /**
494      * @tc.steps:step2. put sync data
495      * @tc.expected: OK
496      */
497     std::string validJsonData(R"({"field_name1":false,"field_name2":true,"field_name3":100})");
498     value.assign(validJsonData.begin(), validJsonData.end());
499     std::vector<DataItem> data;
500     DataItem item{key, value, now, DataItem::LOCAL_FLAG, REMOTE_DEVICE_ID, now};
501     data.push_back(item);
502     EXPECT_EQ(DistributedDBToolsUnitTest::PutSyncDataTest(store, data, REMOTE_DEVICE_ID), E_OK);
503 
504     /**
505      * @tc.steps:step3. put sync miss query data with same timestamp
506      * @tc.expected: OK
507      */
508     data.clear();
509     DataItem itemMiss{key, {}, now, DataItem::REMOTE_DEVICE_DATA_MISS_QUERY, REMOTE_DEVICE_ID, now};
510     itemMiss.key.clear();
511     DBCommon::CalcValueHash({'K', 'e', 'y'}, itemMiss.key);
512     EXPECT_EQ(itemMiss.key.empty(), false);
513     data.push_back(itemMiss);
514     Query query = Query::Select().EqualTo("field_name2", true);
515     QueryObject queryObj(query);
516     EXPECT_EQ(DistributedDBToolsUnitTest::PutSyncDataTest(store, data, REMOTE_DEVICE_ID, queryObj), E_OK);
517 
518     RefObject::KillAndDecObjRef(store);
519     KvDBManager::ReleaseDatabaseConnection(conn);
520 
521     /**
522      * @tc.steps:step4. Check sync data
523      * @tc.expected: check data ok, data {key} is not erased.
524      */
525     CheckDataNumByKey(storeId, {'K', 'e', 'y'}, 1);
526 }
527 
528 /**
529   * @tc.name: PutSyncDataTestWithQuery004
530   * @tc.desc: put remote devices sync data(with same timestamp in DB data but different devices) with query.
531   * @tc.type: FUNC
532   * @tc.require: AR000FN6G9
533   * @tc.author: xulianhui
534   */
535 HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery004, TestSize.Level1)
536 {
537     /**
538      * @tc.steps:step1. create and open a schema store, preset some data;
539      * @tc.expected: step1. open success
540      */
541     const std::string storeId = "PutSyncData04";
542     SQLiteSingleVerNaturalStoreConnection *conn = nullptr;
543     SQLiteSingleVerNaturalStore *store = nullptr;
544     CreateAndGetStore(storeId, SCHEMA_STRING, conn, store);
545 
546     Key key({'K', 'e', 'y'});
547     Value value;
548     Timestamp now = store->GetCurrentTimestamp();
549     /**
550      * @tc.steps:step2. put sync data
551      * @tc.expected: OK
552      */
553     std::string validJsonData(R"({"field_name1":false,"field_name2":true,"field_name3":100})");
554     value.assign(validJsonData.begin(), validJsonData.end());
555     std::vector<DataItem> data;
556     DataItem item{key, value, now, DataItem::LOCAL_FLAG, REMOTE_DEVICE_A, now};
557     data.push_back(item);
558     EXPECT_EQ(DistributedDBToolsUnitTest::PutSyncDataTest(store, data, REMOTE_DEVICE_ID), E_OK);
559 
560     /**
561      * @tc.steps:step3. put sync miss query data with same timestamp
562      * @tc.expected: OK
563      */
564     data.clear();
565     DataItem itemMiss{key, {}, now, DataItem::REMOTE_DEVICE_DATA_MISS_QUERY, REMOTE_DEVICE_B, now};
566     itemMiss.key.clear();
567     DBCommon::CalcValueHash({'K', 'e', 'y'}, itemMiss.key);
568     EXPECT_EQ(itemMiss.key.empty(), false);
569     data.push_back(itemMiss);
570     Query query = Query::Select().EqualTo("field_name2", true);
571     QueryObject queryObj(query);
572     EXPECT_EQ(DistributedDBToolsUnitTest::PutSyncDataTest(store, data, REMOTE_DEVICE_B, queryObj), E_OK);
573 
574     RefObject::KillAndDecObjRef(store);
575     KvDBManager::ReleaseDatabaseConnection(conn);
576 
577     /**
578      * @tc.steps:step4. Check sync data
579      * @tc.expected: check data ok, data {key} is not erased.
580      */
581     CheckDataNumByKey(storeId, {'K', 'e', 'y'}, 1);
582 }
583 
584 /**
585   * @tc.name: AddSubscribeTest001
586   * @tc.desc: Add subscribe with query
587   * @tc.type: FUNC
588   * @tc.require: AR000FN6G9
589   * @tc.author: xulianhui
590   */
591 HWTEST_F(DistributedDBStorageSubscribeQueryTest, AddSubscribeTest001, TestSize.Level1)
592 {
593     /**
594      * @tc.steps:step1. Create a json schema db, get the natural store instance.
595      * @tc.expected: Get results OK and non-null store.
596      */
597     SQLiteSingleVerNaturalStoreConnection *conn = nullptr;
598     SQLiteSingleVerNaturalStore *store = nullptr;
599     CreateAndGetStore("SubscribeTest01", SCHEMA_STRING, conn, store);
600 
601     std::vector<Query> queryList;
602     queryList.push_back(Query::Select().PrefixKey({10, 20}));
603     queryList.push_back(Query::Select().EqualTo("field_name3", 30));
604     queryList.push_back(Query::Select().NotEqualTo("field_name3", 30));
605     queryList.push_back(Query::Select().GreaterThan("field_name3", 10));
606     queryList.push_back(Query::Select().LessThan("field_name3", 30));
607     queryList.push_back(Query::Select().GreaterThanOrEqualTo("field_name3", 30));
608     queryList.push_back(Query::Select().LessThanOrEqualTo("field_name3", 30));
609     queryList.push_back(Query::Select().Like("field_name6", "Abc%"));
610     queryList.push_back(Query::Select().NotLike("field_name6", "Asd%"));
611     std::vector<int> set = {1, 2, 3, 4};
612     queryList.push_back(Query::Select().In("field_name3", set));
613     queryList.push_back(Query::Select().NotIn("field_name3", set));
614     queryList.push_back(Query::Select().IsNull("field_name4"));
615     queryList.push_back(Query::Select().IsNotNull("field_name5"));
616     queryList.push_back(Query::Select().EqualTo("field_name3", 30).And().EqualTo("field_name1", true));
617     queryList.push_back(Query::Select().EqualTo("field_name3", 30).Or().EqualTo("field_name1", true));
618     queryList.push_back(Query::Select().EqualTo("field_name2", false).Or().
619         BeginGroup().EqualTo("field_name3", 30).Or().EqualTo("field_name1", true).EndGroup());
620 
621     /**
622      * @tc.steps:step2. Add subscribe with query, remove subscribe.
623      * @tc.expected: success.
624      */
625     for (const auto &query : queryList) {
626         QueryObject queryObj(query);
627         EXPECT_EQ(store->AddSubscribe(SUBSCRIBE_ID, queryObj, false), E_OK);
628         EXPECT_EQ(store->RemoveSubscribe(SUBSCRIBE_ID), E_OK);
629     }
630 
631     /**
632      * @tc.steps:step6. Close natural store
633      * @tc.expected: step6. Close ok
634      */
635     RefObject::KillAndDecObjRef(store);
636     KvDBManager::ReleaseDatabaseConnection(conn);
637 }
638 
639 /**
640   * @tc.name: AddSubscribeTest002
641   * @tc.desc: Add subscribe with same query not failed
642   * @tc.type: FUNC
643   * @tc.require: AR000FN6G9
644   * @tc.author: xulianhui
645   */
646 HWTEST_F(DistributedDBStorageSubscribeQueryTest, AddSubscribeTest002, TestSize.Level1)
647 {
648     /**
649      * @tc.steps:step1. Create a json schema db, get the natural store instance.
650      * @tc.expected: Get results OK and non-null store.
651      */
652     SQLiteSingleVerNaturalStoreConnection *conn = nullptr;
653     SQLiteSingleVerNaturalStore *store = nullptr;
654     CreateAndGetStore("SubscribeTest02", SCHEMA_STRING, conn, store);
655 
656     Query query = Query::Select().EqualTo("field_name2", false).Or().
657         BeginGroup().EqualTo("field_name3", 30).Or().EqualTo("field_name1", true).EndGroup();
658     /**
659      * @tc.steps:step2. Add subscribe with same query
660      * @tc.expected: step2. add success
661      */
662     QueryObject queryObj(query);
663     int errCode = store->AddSubscribe(SUBSCRIBE_ID, queryObj, false);
664     EXPECT_EQ(errCode, E_OK);
665     errCode = store->AddSubscribe(SUBSCRIBE_ID, queryObj, false);
666     EXPECT_EQ(errCode, E_OK);
667     EXPECT_EQ(store->RemoveSubscribe(SUBSCRIBE_ID), E_OK);
668     /**
669      * @tc.steps:step3. Close natural store
670      * @tc.expected: step3. Close ok
671      */
672     RefObject::KillAndDecObjRef(store);
673     KvDBManager::ReleaseDatabaseConnection(conn);
674 }
675 
676 /**
677   * @tc.name: AddSubscribeErrTest001
678   * @tc.desc: Test invalid parameters of Subscribe
679   * @tc.type: FUNC
680   * @tc.require:
681   * @tc.author: bty
682   */
683 HWTEST_F(DistributedDBStorageSubscribeQueryTest, AddSubscribeErrTest001, TestSize.Level1)
684 {
685     DistributedDB::SQLiteSingleVerNaturalStore *store = new (std::nothrow) SQLiteSingleVerNaturalStore;
686     ASSERT_NE(store, nullptr);
687     Query query = Query::Select().EqualTo("field_name2", false);
688     QueryObject queryObj(query);
689     EXPECT_EQ(store->CheckAndInitQueryCondition(queryObj), -E_INVALID_DB);
690     EXPECT_EQ(store->AddSubscribe(SUBSCRIBE_ID, queryObj, false), -E_INVALID_DB);
691     EXPECT_EQ(store->RemoveSubscribe(SUBSCRIBE_ID), -E_INVALID_DB);
692     store->DecObjRef(store);
693 }
694 
695 namespace {
PutSyncData(SQLiteSingleVerNaturalStore * store,const Key & key,const std::string & valStr)696 void PutSyncData(SQLiteSingleVerNaturalStore *store, const Key &key, const std::string &valStr)
697 {
698     Value value(valStr.begin(), valStr.end());
699     std::vector<DataItem> data;
700     Timestamp now = store->GetCurrentTimestamp();
701     DataItem item{key, value, now, DataItem::LOCAL_FLAG, REMOTE_DEVICE_A, now};
702     data.push_back(item);
703     EXPECT_EQ(DistributedDBToolsUnitTest::PutSyncDataTest(store, data, REMOTE_DEVICE_ID), E_OK);
704 }
705 }
706 
707 /**
708   * @tc.name: GetSyncDataTransTest001
709   * @tc.desc: Get sync data with put
710   * @tc.type: FUNC
711   * @tc.require:
712   * @tc.author: xulianhui
713   */
714 HWTEST_F(DistributedDBStorageSubscribeQueryTest, GetSyncDataTransTest001, TestSize.Level3)
715 {
716     /**
717      * @tc.steps:step1. Create a json schema db, get the natural store instance.
718      * @tc.expected: Get results OK and non-null store.
719      */
720     SQLiteSingleVerNaturalStoreConnection *conn = nullptr;
721     SQLiteSingleVerNaturalStore *store = nullptr;
722     CreateAndGetStore("SubscribeTest02", SCHEMA_STRING, conn, store);
723 
724     /**
725      * @tc.steps:step2. Put data when sync
726      * @tc.expected: step2. Get sync data correct
727      */
728     std::string data1(R""({"field_name1":false,"field_name2":true,"field_name3":100})"");
729     PutSyncData(store, KEY1, data1);
730 
__anon1c80ceb30302() 731     std::thread th([store]() {
732         std::string data2(R""({"field_name1":false,"field_name2":true,"field_name3":101})"");
733         PutSyncData(store, KEY2, data2);
734     });
735 
736     std::this_thread::sleep_for(std::chrono::milliseconds(5)); // wait for 5 ms
737     Query query = Query::Select().EqualTo("field_name1", false);
738     QueryObject queryObj(query);
739     DataSizeSpecInfo  specInfo = {4 * 1024 * 1024, DBConstant::MAX_HPMODE_PACK_ITEM_SIZE};
740     std::vector<SingleVerKvEntry *> entries;
741     ContinueToken token = nullptr;
742     EXPECT_EQ(store->GetSyncData(queryObj, SyncTimeRange{}, specInfo, token, entries), E_OK);
743 
744     th.join();
745 
746     if (entries.size() == 1U) {
747         EXPECT_EQ(entries[0]->GetKey(), KEY1);
748     } else if (entries.size() == 2U) {
749         EXPECT_EQ(entries[0]->GetKey(), KEY1);
750         EXPECT_EQ(entries[0]->GetFlag(), 0U);
751         EXPECT_EQ(entries[1]->GetKey(), KEY2);
752         EXPECT_EQ(entries[1]->GetFlag(), 0U);
753     }
754 
755     /**
756      * @tc.steps:step3. Close natural store
757      * @tc.expected: step3. Close ok
758      */
759     RefObject::KillAndDecObjRef(store);
760     KvDBManager::ReleaseDatabaseConnection(conn);
761     SingleVerKvEntry::Release(entries);
762 }
763 
764 /**
765   * @tc.name: AddSubscribeTest003
766   * @tc.desc: Test put sync data with subscribe trigger
767   * @tc.type: FUNC
768   * @tc.require:
769   * @tc.author: lianhuix
770   */
771 HWTEST_F(DistributedDBStorageSubscribeQueryTest, AddSubscribeTest003, TestSize.Level1)
772 {
773     /**
774      * @tc.steps:step1. Create a json schema db, get the natural store instance.
775      * @tc.expected: Get results OK and non-null store.
776      */
777     SQLiteSingleVerNaturalStoreConnection *conn = nullptr;
778     SQLiteSingleVerNaturalStore *store = nullptr;
779     CreateAndGetStore("AddSubscribeErrTest002", SCHEMA_STRING, conn, store);
780 
781     /**
782      * @tc.steps:step2. Add subscribe with query
783      * @tc.expected: step2. add success
784      */
785     Query query = Query::Select().EqualTo("field_name2", false);
786     QueryObject queryObj(query);
787     int errCode = store->AddSubscribe(SUBSCRIBE_ID, queryObj, false);
788     EXPECT_EQ(errCode, E_OK);
789 
790     /**
791      * @tc.steps:step3. Reput same data with delete flag
792      * @tc.expected: step3. put data success
793      */
794     Key key ;
795     Value value;
796     std::string validJsonData(R"({"field_name1":false,"field_name2":false,"field_name3":100})");
797     DBCommon::StringToVector(validJsonData, value);
798     Timestamp now = store->GetCurrentTimestamp();
799     std::vector<DataItem> data;
800     data.push_back({{'K', '0'}, value, now, 0, REMOTE_DEVICE_ID, now});
801     EXPECT_EQ(DistributedDBToolsUnitTest::PutSyncDataTest(store, data, REMOTE_DEVICE_ID, queryObj), E_OK);
802 
803     data.clear();
804     Key hashKey;
805     DBCommon::CalcValueHash({'K', '0'}, hashKey);
806     data.push_back({hashKey, {}, now + 1, 1, REMOTE_DEVICE_ID, now + 1});
807     EXPECT_EQ(DistributedDBToolsUnitTest::PutSyncDataTest(store, data, REMOTE_DEVICE_ID, queryObj), E_OK);
808 
809     // repeat put with delete flag
810     EXPECT_EQ(DistributedDBToolsUnitTest::PutSyncDataTest(store, data, REMOTE_DEVICE_ID, queryObj), E_OK);
811 
812     /**
813      * @tc.steps:step4. Close natural store
814      * @tc.expected: step4. Close ok
815      */
816     RefObject::KillAndDecObjRef(store);
817     KvDBManager::ReleaseDatabaseConnection(conn);
818 }
819 
820 /**
821   * @tc.name: AddSubscribeTest004
822   * @tc.desc: Add subscribe with query by prefixKey
823   * @tc.type: FUNC
824   * @tc.require:
825   * @tc.author: xulianhui
826   */
827 HWTEST_F(DistributedDBStorageSubscribeQueryTest, AddSubscribeTest004, TestSize.Level1)
828 {
829     /**
830      * @tc.steps:step1. Create a json schema db, get the natural store instance.
831      * @tc.expected: Get results OK and non-null store.
832      */
833     SQLiteSingleVerNaturalStoreConnection *conn = nullptr;
834     SQLiteSingleVerNaturalStore *store = nullptr;
835     CreateAndGetStore("SubscribeTest02", "", conn, store);
836 
837     /**
838      * @tc.steps:step2. Add subscribe with query by prefixKey
839      * @tc.expected: step2. add success
840      */
841     Query query = Query::Select().PrefixKey(NULL_KEY_1);
842     QueryObject queryObj(query);
843     int errCode = store->AddSubscribe(SUBSCRIBE_ID, queryObj, false);
844     EXPECT_EQ(errCode, E_OK);
845 
846     IOption syncIOpt {IOption::SYNC_DATA};
847     EXPECT_EQ(conn->Put(syncIOpt, KEY_1, {}), E_OK);
848 
849     Value valGot;
850     EXPECT_EQ(conn->Get(syncIOpt, KEY_1, valGot), E_OK);
851     EXPECT_EQ(valGot, Value {});
852 
853     std::string subKey = DBConstant::SUBSCRIBE_QUERY_PREFIX + DBCommon::TransferHashString(SUBSCRIBE_ID);
854     Key metaKey(subKey.begin(), subKey.end());
855     EXPECT_EQ(store->GetMetaData(metaKey, valGot), E_OK);
856     EXPECT_NE(valGot.size(), 0u);
857 
858     /**
859      * @tc.steps:step3. Close natural store
860      * @tc.expected: step3. Close ok
861      */
862     RefObject::KillAndDecObjRef(store);
863     KvDBManager::ReleaseDatabaseConnection(conn);
864 }