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 }