1 /*
2 * Copyright (C) 2023 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 <unistd.h>
17
18 #include "accesstoken_kit.h"
19 #include "datashare_helper.h"
20 #include "datashare_log.h"
21 #include "datashare_template.h"
22 #include "hap_token_info.h"
23 #include "iservice_registry.h"
24 #include "system_ability_definition.h"
25 #include "token_setproc.h"
26 #include "datashare_errno.h"
27
28 namespace OHOS {
29 namespace DataShare {
30 using namespace testing::ext;
31 using namespace OHOS::Security::AccessToken;
32 std::string DATA_SHARE_PROXY_URI = "datashareproxy://com.acts.ohos.data.datasharetest/test";
33 std::shared_ptr<DataShare::DataShareHelper> dataShareHelper;
34 std::shared_ptr<DataShare::DataShareHelper> dataShareHelper2; // for another subscriber
35 std::string TBL_NAME0 = "name0";
36 std::string TBL_NAME1 = "name1";
37 constexpr int SUBSCRIBER_ID = 100;
38 std::atomic_int g_callbackTimes = 0;
39
40 class ProxyDatasTest : public testing::Test {
41 public:
42 static void SetUpTestCase(void);
43 static void TearDownTestCase(void);
44 void SetUp();
45 void TearDown();
46 };
47
SetUpTestCase(void)48 void ProxyDatasTest::SetUpTestCase(void)
49 {
50 LOG_INFO("SetUpTestCase invoked");
51 int sleepTime = 1;
52 sleep(sleepTime);
53
54 HapInfoParams info = { .userID = 100,
55 .bundleName = "ohos.datashareproxyclienttest.demo",
56 .instIndex = 0,
57 .appIDDesc = "ohos.datashareproxyclienttest.demo",
58 .isSystemApp = true };
59 HapPolicyParams policy = { .apl = APL_SYSTEM_BASIC,
60 .domain = "test.domain",
61 .permList = { { .permissionName = "ohos.permission.GET_BUNDLE_INFO",
62 .bundleName = "ohos.datashareproxyclienttest.demo",
63 .grantMode = 1,
64 .availableLevel = APL_SYSTEM_BASIC,
65 .label = "label",
66 .labelId = 1,
67 .description = "ohos.datashareproxyclienttest.demo",
68 .descriptionId = 1 } },
69 .permStateList = { { .permissionName = "ohos.permission.GET_BUNDLE_INFO",
70 .isGeneral = true,
71 .resDeviceID = { "local" },
72 .grantStatus = { PermissionState::PERMISSION_GRANTED },
73 .grantFlags = { 1 } } } };
74 AccessTokenKit::AllocHapToken(info, policy);
75 auto testTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenIDEx(
76 info.userID, info.bundleName, info.instIndex);
77 SetSelfTokenID(testTokenId.tokenIDEx);
78
79 CreateOptions options;
80 options.enabled_ = true;
81 dataShareHelper = DataShare::DataShareHelper::Creator(DATA_SHARE_PROXY_URI, options);
82 ASSERT_TRUE(dataShareHelper != nullptr);
83 dataShareHelper2 = DataShare::DataShareHelper::Creator(DATA_SHARE_PROXY_URI, options);
84 ASSERT_TRUE(dataShareHelper2 != nullptr);
85 LOG_INFO("SetUpTestCase end");
86 }
87
TearDownTestCase(void)88 void ProxyDatasTest::TearDownTestCase(void)
89 {
90 auto tokenId = AccessTokenKit::GetHapTokenID(100, "ohos.datashareclienttest.demo", 0);
91 AccessTokenKit::DeleteToken(tokenId);
92 dataShareHelper = nullptr;
93 dataShareHelper2 = nullptr;
94 }
95
SetUp(void)96 void ProxyDatasTest::SetUp(void)
97 {
98 }
TearDown(void)99 void ProxyDatasTest::TearDown(void)
100 {
101 }
102
103 /**
104 * @tc.name: ProxyDatasTest_Insert_Test_001
105 * @tc.desc: Verify the functionality of DataShareHelper successfully inserting data into the data share proxy
106 * @tc.type: FUNC
107 * @tc.require: None
108 * @tc.precon: None
109 * @tc.step:
110 1. Obtain the DataShareHelper instance
111 2. Create a Uri object using the data share proxy URI
112 3. Prepare a DataShareValuesBucket and add string data to it
113 4. Call the Insert method of DataShareHelper with the Uri and ValuesBucket
114 * @tc.expect:
115 1. The return value of the Insert method is greater than 0, indicating successful data insertion
116 */
117 HWTEST_F(ProxyDatasTest, ProxyDatasTest_Insert_Test_001, TestSize.Level1)
118 {
119 LOG_INFO("ProxyDatasTest_Insert_Test_001::Start");
120 auto helper = dataShareHelper;
121 Uri uri(DATA_SHARE_PROXY_URI);
122 DataShare::DataShareValuesBucket valuesBucket;
123 std::string name0 = "wang";
124 valuesBucket.Put(TBL_NAME0, name0);
125 std::string name1 = "wu";
126 valuesBucket.Put(TBL_NAME1, name1);
127
128 int retVal = helper->Insert(uri, valuesBucket);
129 EXPECT_EQ((retVal > 0), true);
130 LOG_INFO("ProxyDatasTest_Insert_Test_001::End");
131 }
132
133 /**
134 * @tc.name: ProxyDatasTest_QUERY_Test_001
135 * @tc.desc: Verify basic query functionality with specific equality condition
136 * @tc.type: FUNC
137 * @tc.require: issueIC8OCN
138 * @tc.precon: Test data containing record with TBL_NAME0 value "wang" exists
139 * @tc.step:
140 1. Obtain the DataShareHelper instance
141 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI
142 3. Create DataSharePredicates with condition: TBL_NAME0 equals "wang"
143 4. Execute query with empty columns list
144 5. Check the returned result set and its row count
145 * @tc.expect:
146 1. Query returns a non-null result set
147 2. Result set contains exactly 1 record (row count = 1)
148 */
149 HWTEST_F(ProxyDatasTest, ProxyDatasTest_QUERY_Test_001, TestSize.Level1)
150 {
151 LOG_INFO("ProxyDatasTest_QUERY_Test_001::Start");
152 auto helper = dataShareHelper;
153 Uri uri(DATA_SHARE_PROXY_URI);
154 DataShare::DataSharePredicates predicates;
155 predicates.EqualTo(TBL_NAME0, "wang");
156 std::vector<string> columns;
157 auto resultSet = helper->Query(uri, predicates, columns);
158 EXPECT_NE(resultSet, nullptr);
159 int result = 0;
160 resultSet->GetRowCount(result);
161 EXPECT_EQ(result, 1);
162 LOG_INFO("ProxyDatasTest_QUERY_Test_001::End");
163 }
164
165 /**
166 * @tc.name: ProxyDatasTest_QueryTimout_Test_001
167 * @tc.desc: Verify query timeout functionality with zero timeout configuration
168 * @tc.type: FUNC
169 * @tc.require: issueIC8OCN
170 * @tc.precon: Test data containing record with TBL_NAME0 value "wang" exists
171 * @tc.step:
172 1. Obtain the DataShareHelper instance
173 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI
174 3. Create DataSharePredicates with condition: TBL_NAME0 equals "wang"
175 4. Configure DataShareOption with timeout set to 0
176 5. Execute QueryTimeout with specified parameters and business error pointer
177 6. Verify result set and error code
178 * @tc.expect:
179 1. Query returns a non-null result set
180 2. Business error code is E_OK (success status)
181 */
182 HWTEST_F(ProxyDatasTest, ProxyDatasTest_QueryTimeout_Test_001, TestSize.Level1)
183 {
184 LOG_INFO("ProxyDatasTest_QueryTimeout_Test_001::Start");
185 auto helper = dataShareHelper;
186 Uri uri(DATA_SHARE_PROXY_URI);
187 DataShare::DataSharePredicates predicates;
188 predicates.EqualTo(TBL_NAME0, "wang");
189 std::vector<string> columns;
190 DataShareOption option;
191 option.timeout = 0;
192 DatashareBusinessError businessError;
193 auto resultSet = helper->Query(uri, predicates, columns, option, &businessError);
194 EXPECT_NE(resultSet, nullptr);
195 EXPECT_EQ(businessError.GetCode(), E_OK);
196 LOG_INFO("ProxyDatasTest_QueryTimeout_Test_001::End");
197 }
198
199 /**
200 * @tc.name: ProxyDatasTest_QueryTimeout_Test_002
201 * @tc.desc: Verify query timeout stability and performance with multiple executions
202 * @tc.type: FUNC
203 * @tc.require: issueIC8OCN
204 * @tc.precon: Test data containing record with TBL_NAME0 value "wang" exists
205 * @tc.step:
206 1. Obtain the DataShareHelper instance
207 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI
208 3. Create DataSharePredicates with condition: TBL_NAME0 equals "wang"
209 4. Configure DataShareOption with 4000ms timeout
210 5. Execute QueryTimeout 100 times in sequence
211 6. Measure execution time for each query
212 7. Verify result set, error code and row count for each execution
213 * @tc.expect:
214 1. Each query returns a non-null result set
215 2. Each query completes within 1000ms
216 3. Each query returns business error code E_OK
217 4. Each result set contains exactly 1 record
218 */
219 HWTEST_F(ProxyDatasTest, ProxyDatasTest_QueryTimeout_Test_002, TestSize.Level1)
220 {
221 LOG_INFO("ProxyDatasTest_QueryTimeout_Test_002::Start");
222 auto helper = dataShareHelper;
223 Uri uri(DATA_SHARE_PROXY_URI);
224 DataShare::DataSharePredicates predicates;
225 predicates.EqualTo(TBL_NAME0, "wang");
226 std::vector<string> columns;
227 DataShareOption option;
228 option.timeout = 4000; // 4000 is the query timeout time.
229 auto limitTime = 1000; // 1000 is used to detect whether the query timeout waiting logic is abnormal.
230 int repeatTimes = 100; // 100 is the number of times the query is executed.
231 DatashareBusinessError businessError;
232 for (int i = 0; i < repeatTimes; i++) {
233 auto start = std::chrono::steady_clock::now();
234 auto resultSet = helper->Query(uri, predicates, columns, option, &businessError);
235 auto finish = std::chrono::steady_clock::now();
236 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(finish - start);
237 EXPECT_TRUE(duration < std::chrono::milliseconds(limitTime));
238 EXPECT_NE(resultSet, nullptr);
239 EXPECT_EQ(businessError.GetCode(), E_OK);
240 int result = 0;
241 resultSet->GetRowCount(result);
242 EXPECT_EQ(result, 1);
243 }
244 LOG_INFO("ProxyDatasTest_QueryTimeout_Test_002::End");
245 }
246
247 /**
248 * @tc.name: ProxyDatasTest_QueryTimeout_Test_003
249 * @tc.desc: Verify query timeout stability under multi-threaded concurrent access
250 * @tc.type: FUNC
251 * @tc.require: issueIC8OCN
252 * @tc.precon: Test data containing record with TBL_NAME0 value "wang" exists
253 * @tc.step:
254 1. Obtain the DataShareHelper instance
255 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI
256 3. Create DataSharePredicates with condition: TBL_NAME0 equals "wang"
257 4. Configure DataShareOption with 4000ms timeout
258 5. Define query function that executes QueryTimeout 100 times
259 6. Create 10 threads to run the query function concurrently
260 7. Wait for all threads to complete execution
261 8. Verify each query's execution time, result set and error code
262 * @tc.expect:
263 1. All threads complete without execution errors
264 2. Each query returns a non-null result set
265 3. Each query completes within 1000ms
266 4. Each query returns business error code E_OK
267 5. Each result set contains exactly 1 record
268 */
269 HWTEST_F(ProxyDatasTest, ProxyDatasTest_QueryTimeout_Test_003, TestSize.Level1)
270 {
271 LOG_INFO("ProxyDatasTest_QueryTimeout_Test_003::Start");
272 auto helper = dataShareHelper;
273 Uri uri(DATA_SHARE_PROXY_URI);
274 DataShare::DataSharePredicates predicates;
275 predicates.EqualTo(TBL_NAME0, "wang");
276 std::vector<string> columns;
277 DataShareOption option;
278 option.timeout = 4000; // 4000 is the query timeout time.
279 auto limitTime = 1000; // 1000 is used to detect whether the query timeout waiting logic is abnormal.
280 int repeatTimes = 100; // 100 is the number of times the query is executed.
281 DatashareBusinessError businessError;
282
283 std::function<void()> func = [&option, &helper, &uri, &predicates, &columns, &businessError,
__anon7d17ed310102() 284 &limitTime, &repeatTimes]() {
285 for (int i = 0; i < repeatTimes; i++) {
286 auto start = std::chrono::steady_clock::now();
287 auto resultSet = helper->Query(uri, predicates, columns, option, &businessError);
288 auto finish = std::chrono::steady_clock::now();
289 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(finish - start);
290 EXPECT_TRUE(duration < std::chrono::milliseconds(limitTime));
291 EXPECT_NE(resultSet, nullptr);
292 EXPECT_EQ(businessError.GetCode(), E_OK);
293 int result = 0;
294 resultSet->GetRowCount(result);
295 EXPECT_EQ(result, 1);
296 }
297 };
298 int threadNum = 10; // 10 is the number of threads.
299 std::thread threads[threadNum];
300 for (int i = 0; i < threadNum; ++i) {
301 threads[i] = std::thread(func);
302 }
303
304 for (int i = 0; i < threadNum; ++i) {
305 threads[i].join();
306 }
307 LOG_INFO("ProxyDatasTest_QueryTimeout_Test_003::End");
308 }
309
310 /**
311 * @tc.name: ProxyDatasTest_QueryTimeout_Test_004
312 * @tc.require: issueIC8OCN
313 * @tc.desc: Verify query timeout behavior when threshold is intentionally exceeded
314 * @tc.type: FUNC
315 * @tc.precon: Data store has sufficient capacity for test data insertion
316 * @tc.step:
317 1. Obtain the DataShareHelper instance
318 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI
319 3. Insert 500 test records with TBL_NAME0 values "query0" to "query499"
320 4. Create DataSharePredicates with LIKE condition for TBL_NAME0 containing "query"
321 5. Configure DataShareOption with 1ms timeout (intentionally short)
322 6. Execute QueryTimeout 10 times and count timeout errors
323 7. Delete all inserted test records using cleanup predicate
324 8. Verify insertion success, timeout occurrences and cleanup success
325 * @tc.expect:
326 1. All 500 test records are inserted successfully
327 2. At least one query execution results in E_TIMEOUT_ERROR
328 3. Cleanup delete operation removes all inserted records successfully
329 */
330 HWTEST_F(ProxyDatasTest, ProxyDatasTest_QueryTimeout_Test_004, TestSize.Level1)
331 {
332 LOG_INFO("ProxyDatasTest_QueryTimeout_Test_004::Start");
333 auto helper = dataShareHelper;
334 Uri uri(DATA_SHARE_PROXY_URI);
335 std::string name = "timeout";
336 int retVal = 0;
337 int insertTimes = 500; // 500 is the number of times the insert is executed.
338 for (int i = 0; i < insertTimes; i++) {
339 DataShare::DataShareValuesBucket valuesBucket;
340 std::string name0 = "query" + std::to_string(i);
341 valuesBucket.Put(TBL_NAME0, name0);
342 valuesBucket.Put(TBL_NAME1, name);
343 retVal = helper->Insert(uri, valuesBucket);
344 EXPECT_EQ((retVal > 0), true);
345 }
346
347 DataShare::DataSharePredicates predicates;
348 predicates.Like(TBL_NAME0, "query");
349 std::vector<string> columns;
350 DataShareOption option;
351 option.timeout = 1; // 1 is the query timeout time.
352 int count = 0;
353 int queryTimes = 10; // 10 is the number of times the query is executed.
354 for (int i = 0; i < queryTimes; i++) {
355 DatashareBusinessError businessError;
356 auto resultSet = helper->Query(uri, predicates, columns, option, &businessError);
357 if (businessError.GetCode() == E_TIMEOUT_ERROR) {
358 count++;
359 }
360 }
361 LOG_INFO("ProxyDatasTest_QueryTimeout_Test_004 Query Timeout %{public}d times", count);
362 EXPECT_TRUE(count > 0);
363 DataShare::DataSharePredicates delPredicates;
364 delPredicates.EqualTo(TBL_NAME1, name);
365 retVal = helper->Delete(uri, delPredicates);
366 EXPECT_EQ((retVal > 0), true);
367 LOG_INFO("ProxyDatasTest_QueryTimeout_Test_004::End");
368 }
369
370 /**
371 * @tc.name: ProxyDatasTest_QueryTimeout_Test_005
372 * @tc.desc: test QueryTimeout function
373 * @tc.type: FUNC
374 * @tc.require: issueICS05H
375 * @tc.precon: None
376 * @tc.step:
377 1.Creat a DataShareHelper class
378 2.call QueryTimeout function
379 * @tc.experct: QueryTimeout return nullptr when The function of the parent class was called
380 */
381 HWTEST_F(ProxyDatasTest, ProxyDatasTest_QueryTimeout_Test_005, TestSize.Level1)
382 {
383 LOG_INFO("ProxyDatasTest_QueryTimeout_Test_005::Start");
384 auto helper = dataShareHelper;
385 Uri uri(DATA_SHARE_PROXY_URI);
386 DataShare::DataSharePredicates predicates;
387 predicates.EqualTo(TBL_NAME0, "wang");
388 std::vector<string> columns;
389 DataShareOption option;
390 option.timeout = 0; // The function has no specific implementation, timeoutis meaningless
391 DatashareBusinessError businessError;
392 auto resultSet = helper->DataShareHelper::Query(uri, predicates, columns, option, &businessError);
393 EXPECT_EQ(resultSet, nullptr);
394 LOG_INFO("ProxyDatasTest_QueryTimeout_Test_005::End");
395 }
396
397 /**
398 * @tc.name: ProxyDatasTest_ResultSet_Test_001
399 * @tc.desc: Verify result set functionality and error handling for invalid operations
400 * @tc.type: FUNC
401 * @tc.require: issueIC8OCN
402 * @tc.precon: Test data containing record with TBL_NAME0 value "wang" exists
403 * @tc.step:
404 1. Obtain the DataShareHelper instance
405 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI
406 3. Execute query to get result set for TBL_NAME0 equals "wang"
407 4. Verify basic result set properties and row count
408 5. Check block management functionality (HasBlock, GetBlock)
409 6. Test error handling with invalid column index for GetBlob
410 7. Nullify block and verify subsequent value retrieval errors
411 * @tc.expect:
412 1. Query returns non-null result set with row count = 1
413 2. Result set reports HasBlock = true and non-null block
414 3. GetBlob with invalid column index returns E_INVALID_COLUMN_INDEX
415 4. After SetBlock(nullptr), GetBlock returns null
416 5. GetString and GetInt operations after nullifying block return E_ERROR
417 */
418 HWTEST_F(ProxyDatasTest, ProxyDatasTest_ResultSet_Test_001, TestSize.Level1)
419 {
420 LOG_INFO("ProxyDatasTest_ResultSet_Test_001::Start");
421 auto helper = dataShareHelper;
422 Uri uri(DATA_SHARE_PROXY_URI);
423 DataShare::DataSharePredicates predicates;
424 predicates.EqualTo(TBL_NAME0, "wang");
425 std::vector<string> columns;
426 auto resultSet = helper->Query(uri, predicates, columns);
427 EXPECT_NE(resultSet, nullptr);
428 int result = 0;
429 resultSet->GetRowCount(result);
430 EXPECT_EQ(result, 1);
431
432 bool hasBlock = resultSet->HasBlock();
433 EXPECT_EQ(hasBlock, true);
434 EXPECT_NE(resultSet->GetBlock(), nullptr);
435
436 std::vector<uint8_t> blob;
437 int err = resultSet->GetBlob(-1, blob);
438 EXPECT_EQ(err, E_INVALID_COLUMN_INDEX);
439 resultSet->SetBlock(nullptr);
440 EXPECT_EQ(nullptr, resultSet->GetBlock());
441 std::string stringValue;
442 result = resultSet->GetString(0, stringValue);
443 EXPECT_EQ(result, E_ERROR);
444 int intValue;
445 result = resultSet->GetInt(0, intValue);
446 EXPECT_EQ(result, E_ERROR);
447 LOG_INFO("ProxyDatasTest_ResultSet_Test_001::End");
448 }
449
450 /**
451 * @tc.name: ProxyDatasTest_Template_Test_001
452 * @tc.desc: Verify the functionality of adding and deleting query templates in the data share proxy
453 * @tc.type: FUNC
454 * @tc.require: None
455 * @tc.precon: None
456 * @tc.step:
457 1. Obtain the DataShareHelper instance
458 2. Create PredicateTemplateNode objects with SQL queries
459 3. Assemble the nodes into a Template object
460 4. Call AddQueryTemplate to register the template with the proxy URI and subscriber ID
461 5. Call DelQueryTemplate to remove the registered template
462 * @tc.expect:
463 1. AddQueryTemplate returns 0, indicating successful template registration
464 2. DelQueryTemplate returns 0, indicating successful template deletion
465 */
466 HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_001, TestSize.Level1)
467 {
468 LOG_INFO("ProxyDatasTest_Template_Test_001::Start");
469 auto helper = dataShareHelper;
470 PredicateTemplateNode node1("p1", "select name0 as name from TBL00");
471 PredicateTemplateNode node2("p2", "select name1 as name from TBL00");
472 std::vector<PredicateTemplateNode> nodes;
473 nodes.emplace_back(node1);
474 nodes.emplace_back(node2);
475 Template tpl(nodes, "select name1 as name from TBL00");
476
477 auto result = helper->AddQueryTemplate(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID, tpl);
478 EXPECT_EQ(result, 0);
479 result = helper->DelQueryTemplate(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID);
480 EXPECT_EQ(result, 0);
481 LOG_INFO("ProxyDatasTest_Template_Test_001::End");
482 }
483
484 /**
485 * @tc.name: ProxyDatasTest_Template_Test_002
486 * @tc.desc: Verify that adding and deleting query templates with an invalid URI fails as expected
487 * @tc.type: FUNC
488 * @tc.require: None
489 * @tc.precon: None
490 * @tc.step:
491 1. Obtain the DataShareHelper instance
492 2. Create PredicateTemplateNode objects and assemble them into a Template
493 3. Call AddQueryTemplate with an invalid URI and subscriber ID
494 4. Call DelQueryTemplate with the same invalid URI and subscriber ID
495 * @tc.expect:
496 1. AddQueryTemplate returns E_URI_NOT_EXIST, indicating failure due to invalid URI
497 2. DelQueryTemplate returns E_URI_NOT_EXIST, indicating failure due to invalid URI
498 */
499 HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_002, TestSize.Level1)
500 {
501 LOG_INFO("ProxyDatasTest_Template_Test_002::Start");
502 auto helper = dataShareHelper;
503 PredicateTemplateNode node1("p1", "select name0 as name from TBL00");
504 PredicateTemplateNode node2("p2", "select name1 as name from TBL00");
505 std::vector<PredicateTemplateNode> nodes;
506 nodes.emplace_back(node1);
507 nodes.emplace_back(node2);
508 Template tpl(nodes, "select name1 as name from TBL00");
509
510 std::string errorUri = "datashareproxy://com.acts.ohos.data.datasharetest";
511 auto result = helper->AddQueryTemplate(errorUri, SUBSCRIBER_ID, tpl);
512 EXPECT_EQ(result, E_URI_NOT_EXIST);
513 result = helper->DelQueryTemplate(errorUri, SUBSCRIBER_ID);
514 EXPECT_EQ(result, E_URI_NOT_EXIST);
515 LOG_INFO("ProxyDatasTest_Template_Test_002::End");
516 }
517
518 /**
519 * @tc.name: ProxyDatasTest_Template_Test_003
520 * @tc.desc: Verify the update functionality of query templates in the data share proxy
521 * @tc.type: FUNC
522 * @tc.require: None
523 * @tc.precon: None
524 * @tc.step:
525 1. Create a Template with an update SQL statement and register it via AddQueryTemplate
526 2. Subscribe to RDB data changes using the template ID
527 3. Insert new data that triggers the template's update condition
528 4. Query the data to verify the update was applied
529 5. Unsubscribe from RDB data changes
530 * @tc.expect:
531 1. Template registration returns 0 (success)
532 2. Subscription and unsubscription operations return 0 (success)
533 3. Insert operation succeeds (return value > 0)
534 4. Query returns a result set with 1 row, confirming the update was applied
535 */
536 HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_003, TestSize.Level1)
537 {
538 LOG_INFO("ProxyDatasTest_Template_Test_003::Start");
539 auto helper = dataShareHelper;
540 PredicateTemplateNode node1("p1", "select name0 as name from TBL00");
541 std::vector<PredicateTemplateNode> nodes;
542 nodes.emplace_back(node1);
543 Template tpl(nodes, "select name0 as name from TBL00");
544 tpl.update_ = "update TBL00 set name0 = 'updatetest' where name0 = 'name00'";
545 auto result = helper->AddQueryTemplate(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID, tpl);
546 EXPECT_EQ(result, 0);
547
548 std::vector<std::string> uris;
549 uris.emplace_back(DATA_SHARE_PROXY_URI);
550 TemplateId tplId;
551 tplId.subscriberId_ = SUBSCRIBER_ID;
552 tplId.bundleName_ = "ohos.datashareproxyclienttest.demo";
553 std::string data1;
554 std::vector<OperationResult> results1 =
__anon7d17ed310202(const RdbChangeNode &changeNode) 555 helper->SubscribeRdbData(uris, tplId, [&data1](const RdbChangeNode &changeNode) {
556 data1 = changeNode.data_[0];
557 });
558 for (auto const &operationResult : results1) {
559 EXPECT_EQ(operationResult.errCode_, 0);
560 }
561
562 Uri uri(DATA_SHARE_PROXY_URI);
563 DataShare::DataShareValuesBucket valuesBucket;
564 std::string name0 = "name00";
565 valuesBucket.Put(TBL_NAME0, name0);
566 int retVal = helper->Insert(uri, valuesBucket);
567 EXPECT_GT(retVal, 0);
568
569 DataShare::DataSharePredicates predicates;
570 predicates.EqualTo(TBL_NAME0, "updatetest");
571 std::vector<string> columns;
572 auto resultSet = helper->Query(uri, predicates, columns);
573 EXPECT_NE(resultSet, nullptr);
574 int queryResult = 0;
575 resultSet->GetRowCount(queryResult);
576 EXPECT_EQ(queryResult, 1);
577
578 std::vector<OperationResult> results2 = helper->UnsubscribeRdbData(uris, tplId);
579 EXPECT_EQ(results2.size(), uris.size());
580 for (auto const &operationResult : results2) {
581 EXPECT_EQ(operationResult.errCode_, 0);
582 }
583 LOG_INFO("ProxyDatasTest_Template_Test_003::End");
584 }
585
586 /**
587 * @tc.name: ProxyDatasTest_Template_Test_004
588 * @tc.desc: Verify adding and deleting query templates with parameterized update functions
589 * @tc.type: FUNC
590 * @tc.require: None
591 * @tc.precon: None
592 * @tc.step:
593 1. Create a Template with predicate nodes and register it via AddQueryTemplate
594 2. Delete the registered template via DelQueryTemplate
595 3. Create another Template with an explicit update SQL statement and register it
596 4. Delete the second template
597 * @tc.expect:
598 1. All AddQueryTemplate calls return 0 (success)
599 2. All DelQueryTemplate calls return 0 (success)
600 */
601 HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_004, TestSize.Level1)
602 {
603 LOG_INFO("ProxyDatasTest_Template_Test_004::Start");
604 auto helper = dataShareHelper;
605 PredicateTemplateNode node1("p1", "select name0 as name from TBL00");
606 PredicateTemplateNode node2("p2", "select name1 as name from TBL00");
607 std::vector<PredicateTemplateNode> nodes;
608 nodes.emplace_back(node1);
609 nodes.emplace_back(node2);
610 Template tpl(nodes, "select name1 as name from TBL00");
611
612 auto result = helper->AddQueryTemplate(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID, tpl);
613 EXPECT_EQ(result, 0);
614 result = helper->DelQueryTemplate(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID);
615 EXPECT_EQ(result, 0);
616
617 Template tpl2("update TBL00 set name0 = 'update'", nodes, "select name1 as name from TBL00");
618 result = helper->AddQueryTemplate(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID, tpl2);
619 EXPECT_EQ(result, 0);
620 result = helper->DelQueryTemplate(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID);
621 EXPECT_EQ(result, 0);
622 LOG_INFO("ProxyDatasTest_Template_Test_004::End");
623 }
624
625 /**
626 * @tc.name: ProxyDatasTest_Template_Test_005
627 * @tc.desc: Verify that adding a template with an invalid parameterized update function (non-update SQL) fails
628 * @tc.type: FUNC
629 * @tc.require: None
630 * @tc.precon: None
631 * @tc.step:
632 1. Create a Template with an insert SQL statement as the update function
633 2. Attempt to register the template via AddQueryTemplate
634 3. Attempt to delete the (unregistered) template via DelQueryTemplate
635 * @tc.expect:
636 1. AddQueryTemplate returns -1 (failure) due to invalid update SQL
637 2. DelQueryTemplate returns 0 (success) (no error if template does not exist)
638 */
639 HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_005, TestSize.Level1)
640 {
641 LOG_INFO("ProxyDatasTest_Template_Test_005::Start");
642 auto helper = dataShareHelper;
643 PredicateTemplateNode node1("p1", "select name0 as name from TBL00");
644 PredicateTemplateNode node2("p2", "select name1 as name from TBL00");
645 std::vector<PredicateTemplateNode> nodes;
646 nodes.emplace_back(node1);
647 nodes.emplace_back(node2);
648 Template tpl2("insert into TBL00 (name0) values ('test')", nodes, "select name1 as name from TBL00");
649
650 auto result = helper->AddQueryTemplate(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID, tpl2);
651 EXPECT_EQ(result, -1);
652 result = helper->DelQueryTemplate(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID);
653 EXPECT_EQ(result, 0);
654 LOG_INFO("ProxyDatasTest_Template_Test_005::End");
655 }
656
657 /**
658 * @tc.name: ProxyDatasTest_Template_Test_006
659 * @tc.desc: Verify adding and deleting query templates using a URI with a user ID parameter
660 * @tc.type: FUNC
661 * @tc.require: None
662 * @tc.precon: None
663 * @tc.step:
664 1. Create a URI by appending "?user=100" to the base data share proxy URI
665 2. Create a Template with predicate nodes and register it using the new URI
666 3. Delete the registered template using the same URI
667 * @tc.expect:
668 1. AddQueryTemplate returns E_OK (success)
669 2. DelQueryTemplate returns E_OK (success)
670 */
671 HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_006, TestSize.Level1)
672 {
673 LOG_INFO("ProxyDatasTest_Template_Test_006::Start");
674 auto helper = dataShareHelper;
675 PredicateTemplateNode node1("p1", "select name0 as name from TBL00");
676 PredicateTemplateNode node2("p2", "select name1 as name from TBL00");
677 std::vector<PredicateTemplateNode> nodes;
678 nodes.emplace_back(node1);
679 nodes.emplace_back(node2);
680 Template tpl(nodes, "select name1 as name from TBL00");
681
682 std::string uri = DATA_SHARE_PROXY_URI + "?user=100";
683 auto result = helper->AddQueryTemplate(uri, SUBSCRIBER_ID, tpl);
684 EXPECT_EQ(result, E_OK);
685 result = helper->DelQueryTemplate(uri, SUBSCRIBER_ID);
686 EXPECT_EQ(result, E_OK);
687 LOG_INFO("ProxyDatasTest_Template_Test_006::End");
688 }
689
690 /**
691 * @tc.name: ProxyDatasTest_Publish_Test_001
692 * @tc.desc: Verify the functionality of publishing string data via the data share proxy and retrieving it
693 * @tc.type: FUNC
694 * @tc.require: None
695 * @tc.precon: None
696 * @tc.step:
697 1. Create a Data object containing a URI, subscriber ID, and string value
698 2. Publish the data using Publish method with the target bundle name
699 3. Retrieve the published data using GetPublishedData
700 4. Verify the retrieved data matches the published data
701 * @tc.expect:
702 1. Publish returns OperationResult with errCode_ 0 (success)
703 2. GetPublishedData returns errCode_ 0 (success)
704 3. Retrieved data has the same size, subscriber ID, key, and value as published data
705 */
706 HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_001, TestSize.Level1)
707 {
708 LOG_INFO("ProxyDatasTest_Publish_Test_001::Start");
709 auto helper = dataShareHelper;
710 std::string bundleName = "com.acts.ohos.data.datasharetest";
711 Data data;
712 data.datas_.emplace_back("datashareproxy://com.acts.ohos.data.datasharetest/test", SUBSCRIBER_ID, "value1");
713 std::vector<OperationResult> results = helper->Publish(data, bundleName);
714 EXPECT_EQ(results.size(), data.datas_.size());
715 for (auto const &result : results) {
716 EXPECT_EQ(result.errCode_, 0);
717 }
718
719 int errCode = 0;
720 auto getData = helper->GetPublishedData(bundleName, errCode);
721 EXPECT_EQ(errCode, 0);
722 EXPECT_EQ(getData.datas_.size(), data.datas_.size());
723 for (auto &publishedDataItem : getData.datas_) {
724 EXPECT_EQ(publishedDataItem.subscriberId_, SUBSCRIBER_ID);
725 bool isString = publishedDataItem.IsString();
726 EXPECT_EQ(isString, true);
727 EXPECT_EQ(publishedDataItem.key_, "datashareproxy://com.acts.ohos.data.datasharetest/test");
728 auto value = publishedDataItem.GetData();
729 EXPECT_EQ(std::get<std::string>(value), "value1");
730 }
731 LOG_INFO("ProxyDatasTest_Publish_Test_001::End");
732 }
733
734 /**
735 * @tc.name: ProxyDatasTest_Publish_Test_002
736 * @tc.desc: Verify that publishing data with a non-existent bundle name fails as expected
737 * @tc.type: FUNC
738 * @tc.require: None
739 * @tc.precon: None
740 * @tc.step:
741 1. Create a Data object with a URI, subscriber ID, and string value
742 2. Attempt to publish the data using a non-existent bundle name
743 3. Attempt to retrieve published data using the same invalid bundle name
744 * @tc.expect:
745 1. Publish returns OperationResult with errCode_ E_BUNDLE_NAME_NOT_EXIST (failure)
746 2. GetPublishedData returns errCode_ E_BUNDLE_NAME_NOT_EXIST (failure)
747 */
748 HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_002, TestSize.Level1)
749 {
750 LOG_INFO("ProxyDatasTest_Publish_Test_002::Start");
751 auto helper = dataShareHelper;
752 std::string bundleName = "com.acts.ohos.error";
753 Data data;
754 data.datas_.emplace_back("datashareproxy://com.acts.ohos.error", SUBSCRIBER_ID, "value1");
755 std::vector<OperationResult> results = helper->Publish(data, bundleName);
756 EXPECT_EQ(results.size(), data.datas_.size());
757 for (auto const &result : results) {
758 EXPECT_EQ(result.errCode_, E_BUNDLE_NAME_NOT_EXIST);
759 }
760
761 int errCode = 0;
762 auto getData = helper->GetPublishedData(bundleName, errCode);
763 EXPECT_EQ(errCode, E_BUNDLE_NAME_NOT_EXIST);
764 LOG_INFO("ProxyDatasTest_Publish_Test_002::End");
765 }
766
767 /**
768 * @tc.name: ProxyDatasTest_Publish_Test_003
769 * @tc.desc: Verify the functionality of publishing binary data (ashmem) via the data share proxy and retrieving it
770 * @tc.type: FUNC
771 * @tc.require: None
772 * @tc.precon: None
773 * @tc.step:
774 1. Create a Data object containing a URI, subscriber ID, and binary buffer
775 2. Publish the data using Publish method with the target bundle name
776 3. Retrieve the published data using GetPublishedData
777 4. Verify the retrieved binary data matches the published data
778 * @tc.expect:
779 1. Publish returns OperationResult with errCode_ 0 (success)
780 2. GetPublishedData returns errCode_ 0 (success)
781 3. Retrieved data has the same size, subscriber ID, and binary content as published data
782 */
783 HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_003, TestSize.Level1)
784 {
785 LOG_INFO("ProxyDatasTest_Publish_Test_003::Start");
786 auto helper = dataShareHelper;
787 Data data;
788 std::vector<uint8_t> buffer= {10, 20, 30};
789 data.datas_.emplace_back("datashareproxy://com.acts.ohos.data.datasharetest/test", SUBSCRIBER_ID, buffer);
790 std::string bundleName = "com.acts.ohos.data.datasharetest";
791 std::vector<OperationResult> results = helper->Publish(data, bundleName);
792 EXPECT_EQ(results.size(), data.datas_.size());
793 for (auto const &result : results) {
794 EXPECT_EQ(result.errCode_, 0);
795 }
796
797 int errCode = 0;
798 auto getData = helper->GetPublishedData(bundleName, errCode);
799 EXPECT_EQ(errCode, 0);
800 EXPECT_EQ(getData.datas_.size(), data.datas_.size());
801 for (auto &publishedDataItem : getData.datas_) {
802 EXPECT_EQ(publishedDataItem.subscriberId_, SUBSCRIBER_ID);
803 bool isAshmem = publishedDataItem.IsAshmem();
804 EXPECT_TRUE(isAshmem);
805 auto value = publishedDataItem.GetData();
806 EXPECT_EQ(std::get<std::vector<uint8_t>>(value)[0], buffer[0]);
807 }
808 LOG_INFO("ProxyDatasTest_Publish_Test_003::End");
809 }
810
811 /**
812 * @tc.name: ProxyDatasTest_CombinationRdbData_Test_001
813 * @tc.desc: Verify combination functionality of RDB data subscription, enabling/disabling, and unsubscription
814 * @tc.type: FUNC
815 * @tc.require: None
816 * @tc.precon: None
817 * @tc.step:
818 1. Register a query template and subscribe to RDB data changes with a callback
819 2. Enable RDB subscriptions
820 3. Insert data to trigger the subscription callback
821 4. Verify the callback is invoked the expected number of times
822 5. Unsubscribe from RDB data changes and insert more data
823 * @tc.expect:
824 1. Template registration, subscription, and enabling return 0 (success)
825 2. Insert operations return values > 0 (success)
826 3. Callback is invoked 2 times before unsubscription
827 4. No additional callback invocations after unsubscription
828 */
829 HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationRdbData_Test_001, TestSize.Level1)
830 {
831 LOG_INFO("ProxyDatasTest_CombinationRdbData_Test_001::Start");
832 auto helper = dataShareHelper;
833 PredicateTemplateNode node("p1", "select name0 as name from TBL00");
834 std::vector<PredicateTemplateNode> nodes;
835 nodes.emplace_back(node);
836 Template tpl(nodes, "select name1 as name from TBL00");
837 auto result = helper->AddQueryTemplate(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID, tpl);
838 EXPECT_EQ(result, 0);
839 std::vector<std::string> uris;
840 uris.emplace_back(DATA_SHARE_PROXY_URI);
841 TemplateId tplId;
842 tplId.subscriberId_ = SUBSCRIBER_ID;
843 tplId.bundleName_ = "ohos.datashareproxyclienttest.demo";
844 std::vector<OperationResult> results1 =
__anon7d17ed310302(const RdbChangeNode &changeNode) 845 helper->SubscribeRdbData(uris, tplId, [&tplId](const RdbChangeNode &changeNode) {
846 EXPECT_EQ(changeNode.uri_, DATA_SHARE_PROXY_URI);
847 EXPECT_EQ(changeNode.templateId_.bundleName_, tplId.bundleName_);
848 EXPECT_EQ(changeNode.templateId_.subscriberId_, tplId.subscriberId_);
849 g_callbackTimes++;
850 });
851 EXPECT_EQ(results1.size(), uris.size());
852 for (auto const &operationResult : results1) {
853 EXPECT_EQ(operationResult.errCode_, 0);
854 }
855
856 std::vector<OperationResult> results3 = helper->EnableRdbSubs(uris, tplId);
857 for (auto const &operationResult : results3) {
858 EXPECT_EQ(operationResult.errCode_, 0);
859 }
860 Uri uri(DATA_SHARE_PROXY_URI);
861 DataShare::DataShareValuesBucket valuesBucket1, valuesBucket2;
862 std::string name1 = "wu";
863 std::string name2 = "liu";
864 valuesBucket1.Put(TBL_NAME1, name1);
865 int retVal1 = helper->Insert(uri, valuesBucket1);
866 EXPECT_EQ((retVal1 > 0), true);
867 EXPECT_EQ(g_callbackTimes, 2);
868 std::vector<OperationResult> results4 = helper->UnsubscribeRdbData(uris, tplId);
869 EXPECT_EQ(results4.size(), uris.size());
870 for (auto const &operationResult : results4) {
871 EXPECT_EQ(operationResult.errCode_, 0);
872 }
873 valuesBucket2.Put(TBL_NAME1, name2);
874 int retVal2 = helper->Insert(uri, valuesBucket2);
875 EXPECT_EQ((retVal2 > 0), true);
876 EXPECT_EQ(g_callbackTimes, 2);
877 LOG_INFO("ProxyDatasTest_CombinationRdbData_Test_001::End");
878 }
879
880 /**
881 * @tc.name: ProxyDatasTest_CombinationRdbData_Test_002
882 * @tc.desc: Verify combination functionality of RDB data subscription, multiple disable operations, and re-enable
883 * @tc.type: FUNC
884 * @tc.require: None
885 * @tc.precon: None
886 * @tc.step:
887 1. Register a template and subscribe to RDB data changes with two helpers
888 2. Disable subscriptions, insert data, and disable again
889 3. Re-enable subscriptions and verify callback behavior
890 4. Unsubscribe from both helpers
891 * @tc.expect:
892 1. Template registration, subscriptions, disable/enable return 0 (success)
893 2. Insert operation returns value > 0 (success)
894 3. Callback is invoked 2 times total (1 before disable, 1 after re-enable)
895 */
896 HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationRdbData_Test_002, TestSize.Level1)
897 {
898 auto helper = dataShareHelper;
899 auto helper2 = dataShareHelper2;
900 std::vector<PredicateTemplateNode> nodes;
901 Template tpl(nodes, "select name1 as name from TBL00");
902 auto result = helper->AddQueryTemplate(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID, tpl);
903 EXPECT_EQ(result, 0);
904
905 std::vector<std::string> uris = {DATA_SHARE_PROXY_URI};
906 TemplateId tplId;
907 tplId.subscriberId_ = SUBSCRIBER_ID;
908 tplId.bundleName_ = "ohos.datashareproxyclienttest.demo";
909 std::atomic_int callbackTimes = 0;
910 std::mutex mutex;
911 std::condition_variable cv;
912 auto timeout = std::chrono::seconds(2);
913 std::vector<OperationResult> results =
__anon7d17ed310402(const RdbChangeNode &changeNode) 914 helper->SubscribeRdbData(uris, tplId, [&callbackTimes, &mutex, &cv](const RdbChangeNode &changeNode) {
915 std::lock_guard<std::mutex> lock(mutex);
916 callbackTimes++;
917 cv.notify_all();
918 });
919 EXPECT_EQ(results.size(), uris.size());
920 for (auto const &result : results) EXPECT_EQ(result.errCode_, 0);
921 // if there is only one subscriber in a key, the subscriber can't be disabled twice
__anon7d17ed310502(const RdbChangeNode &changeNode) 922 results = helper2->SubscribeRdbData(uris, tplId, [](const RdbChangeNode &changeNode) {
923 });
924
925 std::unique_lock<std::mutex> lock(mutex);
926 cv.wait_for(lock, timeout);
927 EXPECT_EQ(callbackTimes, 1);
928 lock.unlock();
929 results = helper->DisableRdbSubs(uris, tplId);
930 EXPECT_EQ(results.size(), uris.size());
931 for (auto const &result : results) EXPECT_EQ(result.errCode_, 0);
932
933 Uri uri(DATA_SHARE_PROXY_URI);
934 DataShare::DataShareValuesBucket valuesBucket;
935 valuesBucket.Put(TBL_NAME1, 1);
936 int retVal = helper->Insert(uri, valuesBucket);
937 EXPECT_GT(retVal, 0);
938
939 results = helper->DisableRdbSubs(uris, tplId);
940 EXPECT_EQ(results.size(), uris.size());
941 for (auto const &result : results) EXPECT_EQ(result.errCode_, 0);
942 results = helper->EnableRdbSubs(uris, tplId);
943 for (auto const &result : results) EXPECT_EQ(result.errCode_, 0);
944 EXPECT_EQ(callbackTimes, 2);
945 helper->UnsubscribeRdbData(uris, tplId);
946 helper2->UnsubscribeRdbData(uris, tplId);
947 }
948
949 /**
950 * @tc.name: ProxyDatasTest_CombinationRdbData_Test_003
951 * @tc.desc: Verify combination functionality of RDB data subscription, disable, re-enable, and unsubscription
952 * @tc.type: FUNC
953 * @tc.require: None
954 * @tc.precon: None
955 * @tc.step:
956 1. Register a template and subscribe to RDB data changes with a callback
957 2. Disable subscriptions, then re-enable them
958 3. Unsubscribe from RDB data changes
959 * @tc.expect:
960 1. Template registration, subscription, disable/enable, and unsubscription return 0 (success)
961 2. Callback is invoked 1 time (initial subscription)
962 3. No additional callback invocations after disable/re-enable
963 */
964 HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationRdbData_Test_003, TestSize.Level1)
965 {
966 LOG_INFO("ProxyDatasTest_CombinationRdbData_Test_003::Start");
967 auto helper = dataShareHelper;
968 std::vector<PredicateTemplateNode> nodes;
969 Template tpl(nodes, "select name1 as name from TBL00");
970 auto result = helper->AddQueryTemplate(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID, tpl);
971 EXPECT_EQ(result, E_OK);
972
973 std::vector<std::string> uris = {DATA_SHARE_PROXY_URI};
974 TemplateId tplId;
975 tplId.subscriberId_ = SUBSCRIBER_ID;
976 tplId.bundleName_ = "ohos.datashareproxyclienttest.demo";
977 std::atomic_int callbackTimes = 0;
978 std::mutex mutex;
979 std::condition_variable cv;
980 auto timeout = std::chrono::seconds(2);
981 std::vector<OperationResult> results =
__anon7d17ed310602(const RdbChangeNode &changeNode) 982 helper->SubscribeRdbData(uris, tplId, [&callbackTimes, &mutex, &cv](const RdbChangeNode &changeNode) {
983 std::lock_guard<std::mutex> lock(mutex);
984 callbackTimes++;
985 cv.notify_all();
986 });
987 EXPECT_EQ(results.size(), uris.size());
988 for (auto const &result : results) {
989 EXPECT_EQ(result.errCode_, E_OK);
990 }
991
992 std::unique_lock<std::mutex> lock(mutex);
993 cv.wait_for(lock, timeout);
994 EXPECT_EQ(callbackTimes, 1);
995 lock.unlock();
996 results = helper->DisableRdbSubs(uris, tplId);
997 EXPECT_EQ(results.size(), uris.size());
998 for (auto const &result : results) {
999 EXPECT_EQ(result.errCode_, 0);
1000 }
1001 results = helper->EnableRdbSubs(uris, tplId);
1002 for (auto const &result : results) {
1003 EXPECT_EQ(result.errCode_, 0);
1004 }
1005 EXPECT_EQ(callbackTimes, 1);
1006 results = helper->UnsubscribeRdbData(uris, tplId);
1007 EXPECT_EQ(results.size(), uris.size());
1008 for (auto const &result : results) {
1009 EXPECT_EQ(result.errCode_, E_OK);
1010 }
1011 LOG_INFO("ProxyDatasTest_CombinationRdbData_Test_003::End");
1012 }
1013
1014 /**
1015 * @tc.name: ProxyDatasTest_CombinationPublishedData_Test_001
1016 * @tc.desc: Verify combination functionality of published data subscription, disable, re-enable, and unsubscription
1017 * @tc.type: FUNC
1018 * @tc.require: None
1019 * @tc.precon: None
1020 * @tc.step:
1021 1. Publish data and subscribe to published data changes with two helpers
1022 2. Disable subscriptions, republish data, then disable again
1023 3. Re-enable subscriptions and verify callback behavior
1024 4. Unsubscribe from both helpers
1025 * @tc.expect:
1026 1. Publish, subscription, disable/enable return 0 (success)
1027 2. Callback is invoked 2 times total (1 before disable, 1 after re-enable)
1028 */
1029 HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationPublishedData_Test_001, TestSize.Level1)
1030 {
1031 LOG_INFO("ProxyDatasTest_CombinationPublishedData_Test_001::Start");
1032 auto helper = dataShareHelper;
1033 auto helper2 = dataShareHelper2;
1034 std::string bundleName = "com.acts.ohos.data.datasharetest";
1035 Data data;
1036 data.datas_.emplace_back(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID, "value1");
1037 std::vector<OperationResult> results = helper->Publish(data, bundleName);
1038 EXPECT_EQ(results.size(), data.datas_.size());
1039 for (auto const &result : results) EXPECT_EQ(result.errCode_, 0);
1040 std::vector<std::string> uris = {DATA_SHARE_PROXY_URI};
1041 std::atomic_int callbackTimes = 0;
1042 std::mutex mutex;
1043 std::condition_variable cv;
1044 auto timeout = std::chrono::seconds(2);
1045 results = helper->SubscribePublishedData(uris, SUBSCRIBER_ID,
__anon7d17ed310702(const PublishedDataChangeNode &changeNode) 1046 [&callbackTimes, &mutex, &cv](const PublishedDataChangeNode &changeNode) {
1047 std::lock_guard<std::mutex> lock(mutex);
1048 callbackTimes++;
1049 cv.notify_all();
1050 });
1051 EXPECT_EQ(results.size(), uris.size());
1052 for (auto const &operationResult : results) EXPECT_EQ(operationResult.errCode_, 0);
1053 // if there is only one subscriber in a key, the subscriber can't be disabled twice
__anon7d17ed310802(const PublishedDataChangeNode &changeNode) 1054 results = helper2->SubscribePublishedData(uris, SUBSCRIBER_ID, [](const PublishedDataChangeNode &changeNode) {});
1055 EXPECT_EQ(results.size(), uris.size());
1056 for (auto const &operationResult : results) {
1057 EXPECT_EQ(operationResult.errCode_, 0);
1058 }
1059 std::unique_lock<std::mutex> lock(mutex);
1060 cv.wait_for(lock, timeout);
1061 EXPECT_EQ(callbackTimes, 1);
1062 lock.unlock();
1063 results = helper->DisablePubSubs(uris, SUBSCRIBER_ID);
1064 EXPECT_EQ(results.size(), uris.size());
1065 for (auto const &operationResult : results) EXPECT_EQ(operationResult.errCode_, 0);
1066
1067 results = helper->Publish(data, bundleName);
1068 EXPECT_EQ(results.size(), data.datas_.size());
1069 for (auto const &result : results) EXPECT_EQ(result.errCode_, 0);
1070 results = helper->DisablePubSubs(uris, SUBSCRIBER_ID);
1071 for (auto const &operationResult : results) EXPECT_EQ(operationResult.errCode_, 0);
1072 results = helper->EnablePubSubs(uris, SUBSCRIBER_ID);
1073 for (auto const &operationResult : results) EXPECT_EQ(operationResult.errCode_, 0);
1074 EXPECT_EQ(callbackTimes, 2);
1075 helper->UnsubscribePublishedData(uris, SUBSCRIBER_ID);
1076 helper2->UnsubscribePublishedData(uris, SUBSCRIBER_ID);
1077 LOG_INFO("ProxyDatasTest_CombinationPublishedData_Test_001::End");
1078 }
1079
1080 /**
1081 * @tc.name: ProxyDatasTest_SubscribePublishedData_Test_001
1082 * @tc.desc: Verify the functionality of subscribing to published data changes
1083 * @tc.type: FUNC
1084 * @tc.require: None
1085 * @tc.precon: None
1086 * @tc.step:
1087 1. Create a list of URIs to subscribe to
1088 2. Call SubscribePublishedData with the URIs, subscriber ID, and a verification callback
1089 * @tc.expect:
1090 1. Subscription returns OperationResult with errCode_ 0 (success)
1091 2. Callback verifies the owner bundle name when triggered
1092 */
1093 HWTEST_F(ProxyDatasTest, ProxyDatasTest_SubscribePublishedData_Test_001, TestSize.Level1)
1094 {
1095 LOG_INFO("ProxyDatasTest_SubscribePublishedData_Test_001::Start");
1096 auto helper = dataShareHelper;
1097 std::vector<std::string> uris;
1098 uris.emplace_back(DATA_SHARE_PROXY_URI);
1099 std::vector<OperationResult> results =
__anon7d17ed310902(const PublishedDataChangeNode &changeNode) 1100 helper->SubscribePublishedData(uris, SUBSCRIBER_ID, [](const PublishedDataChangeNode &changeNode) {
1101 EXPECT_EQ(changeNode.ownerBundleName_, "ohos.datashareproxyclienttest.demo");
1102 });
1103 EXPECT_EQ(results.size(), uris.size());
1104 for (auto const &operationResult : results) {
1105 EXPECT_EQ(operationResult.errCode_, 0);
1106 }
1107 LOG_INFO("ProxyDatasTest_SubscribePublishedData_Test_001::End");
1108 }
1109
1110 /**
1111 * @tc.name: ProxyDatasTest_DisablePubSubs_Test_001
1112 * @tc.desc: Verify the functionality of disabling published data subscriptions
1113 * @tc.type: FUNC
1114 * @tc.require: None
1115 * @tc.precon: None
1116 * @tc.step:
1117 1. Create a list of URIs with active subscriptions
1118 2. Call DisablePubSubs with the URIs and subscriber ID
1119 * @tc.expect:
1120 1. DisablePubSubs returns OperationResult with errCode_ 0 (success)
1121 */
1122 HWTEST_F(ProxyDatasTest, ProxyDatasTest_DisablePubSubs_Test_001, TestSize.Level1)
1123 {
1124 LOG_INFO("ProxyDatasTest_DisablePubSubs_Test_001::Start");
1125 auto helper = dataShareHelper;
1126 std::vector<std::string> uris;
1127 uris.emplace_back(DATA_SHARE_PROXY_URI);
1128 std::vector<OperationResult> results = helper->DisablePubSubs(uris, SUBSCRIBER_ID);
1129 for (auto const &operationResult : results) {
1130 EXPECT_EQ(operationResult.errCode_, 0);
1131 }
1132 LOG_INFO("ProxyDatasTest_DisablePubSubs_Test_001::End");
1133 }
1134
1135 /**
1136 * @tc.name: ProxyDatasTest_EnablePubSubs_Test_001
1137 * @tc.desc: Verify the functionality of enabling published data subscriptions
1138 * @tc.type: FUNC
1139 * @tc.require: None
1140 * @tc.precon: None
1141 * @tc.step:
1142 1. Create a list of URIs with disabled subscriptions
1143 2. Call EnablePubSubs with the URIs and subscriber ID
1144 * @tc.expect:
1145 1. EnablePubSubs returns OperationResult with errCode_ 0 (success)
1146 */
1147 HWTEST_F(ProxyDatasTest, ProxyDatasTest_EnablePubSubs_Test_001, TestSize.Level1)
1148 {
1149 LOG_INFO("ProxyDatasTest_EnablePubSubs_Test_001::Start");
1150 auto helper = dataShareHelper;
1151 std::vector<std::string> uris;
1152 uris.emplace_back(DATA_SHARE_PROXY_URI);
1153 std::vector<OperationResult> results = helper->EnablePubSubs(uris, SUBSCRIBER_ID);
1154 for (auto const &operationResult : results) {
1155 EXPECT_EQ(operationResult.errCode_, 0);
1156 }
1157 LOG_INFO("ProxyDatasTest_EnablePubSubs_Test_001::End");
1158 }
1159
1160 /**
1161 * @tc.name: ProxyDatasTest_UnsubscribePublishedData_Test_001
1162 * @tc.desc: Verify the functionality of unsubscribing from published data changes
1163 * @tc.type: FUNC
1164 * @tc.require: None
1165 * @tc.precon: None
1166 * @tc.step:
1167 1. Create a list of URIs with active subscriptions
1168 2. Call UnsubscribePublishedData with the URIs and subscriber ID
1169 * @tc.expect:
1170 1. UnsubscribePublishedData returns OperationResult with errCode_ 0 (success)
1171 */
1172 HWTEST_F(ProxyDatasTest, ProxyDatasTest_UnsubscribePublishedData_Test_001, TestSize.Level1)
1173 {
1174 LOG_INFO("ProxyDatasTest_UnsubscribePublishedData_Test_001::Start");
1175 auto helper = dataShareHelper;
1176 std::vector<std::string> uris;
1177 uris.emplace_back(DATA_SHARE_PROXY_URI);
1178 std::vector<OperationResult> results = helper->UnsubscribePublishedData(uris, SUBSCRIBER_ID);
1179 EXPECT_EQ(results.size(), uris.size());
1180 for (auto const &operationResult : results) {
1181 EXPECT_EQ(operationResult.errCode_, 0);
1182 }
1183 LOG_INFO("ProxyDatasTest_UnsubscribePublishedData_Test_001::End");
1184 }
1185
1186 /**
1187 * @tc.name: ProxyDatasTest_extSpCtl_Null_Test_001
1188 * @tc.desc: Verify extended special control operations after releasing the helper
1189 * @tc.type: FUNC
1190 * @tc.require: None
1191 * @tc.precon: None
1192 * @tc.step:
1193 1. Release the DataShareHelper instance
1194 2. Call GetFileTypes with an empty URI and string
1195 3. Call OpenFile and OpenRawFile with an empty URI and string
1196 * @tc.expect:
1197 1. Release returns true (success)
1198 2. GetFileTypes returns an empty list
1199 3. OpenFile and OpenRawFile return -1 (failure)
1200 */
1201 HWTEST_F(ProxyDatasTest, ProxyDatasTest_extSpCtl_Null_Test_001, TestSize.Level1)
1202 {
1203 LOG_INFO("ProxyDatasTest_extSpCtl_Null_Test_001::Start");
1204 auto helper = dataShareHelper;
1205 bool ret = helper->Release();
1206 EXPECT_EQ(ret, true);
1207 Uri uri("");
1208 std::string str;
1209 std::vector<std::string> result = helper->GetFileTypes(uri, str);
1210 EXPECT_EQ(result.size(), 0);
1211 int err = helper->OpenFile(uri, str);
1212 EXPECT_EQ(err, -1);
1213 err = helper->OpenRawFile(uri, str);
1214 EXPECT_EQ(err, -1);
1215 LOG_INFO("ProxyDatasTest_extSpCtl_Null_Test_001::End");
1216 }
1217
1218 /**
1219 * @tc.name: ProxyDatasTest_extSpCtl_Null_Test_002
1220 * @tc.desc: Verify NormalizeUri and DenormalizeUri operations after releasing the helper
1221 * @tc.type: FUNC
1222 * @tc.require: None
1223 * @tc.precon: None
1224 * @tc.step:
1225 1. Release the DataShareHelper instance
1226 2. Call NormalizeUri and DenormalizeUri with an empty URI
1227 * @tc.expect:
1228 1. Release returns true (success)
1229 2. NormalizeUri and DenormalizeUri return the input empty URI unchanged
1230 */
1231 HWTEST_F(ProxyDatasTest, ProxyDatasTest_extSpCtl_Null_Test_002, TestSize.Level1)
1232 {
1233 LOG_INFO("ProxyDatasTest_extSpCtl_Null_Test_002::Start");
1234 auto helper = dataShareHelper;
1235 bool ret = helper->Release();
1236 EXPECT_EQ(ret, true);
1237 Uri uri("");
1238 Uri uriResult = helper->NormalizeUri(uri);
1239 EXPECT_EQ(uriResult, uri);
1240 uriResult = helper->DenormalizeUri(uri);
1241 EXPECT_EQ(uriResult, uri);
1242 LOG_INFO("ProxyDatasTest_extSpCtl_Null_Test_002::End");
1243 }
1244 } // namespace DataShare
1245 } // namespace OHOS