• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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