1 /*
2  * Copyright (c) 2021-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 
16 #include "gtest/gtest.h"
17 
18 #include <thread>
19 
20 #include "utils.h"
21 
22 #include "device_profile_errors.h"
23 #include "distributed_device_profile_client.h"
24 #include "nlohmann/json.hpp"
25 
26 namespace OHOS {
27 namespace DeviceProfile {
28 using namespace std::chrono_literals;
29 using namespace testing;
30 using namespace testing::ext;
31 
32 namespace {
33 const int32_t UT_ERROR = -1;
34 }
35 class EventSubscribeTest : public testing::Test {
36 public:
37     static void SetUpTestCase();
38     static void TearDownTestCase();
39     void SetUp();
40     void TearDown();
41 };
42 
SetUpTestCase()43 void EventSubscribeTest::SetUpTestCase()
44 {
45     DistributedDeviceProfileClient::GetInstance().DeleteDeviceProfile("111111");
46 }
47 
TearDownTestCase()48 void EventSubscribeTest::TearDownTestCase()
49 {
50 }
51 
SetUp()52 void EventSubscribeTest::SetUp()
53 {
54 }
55 
TearDown()56 void EventSubscribeTest::TearDown()
57 {
58 }
59 
60 class ProfileEventCallback : public IProfileEventCallback {
61 public:
62     ProfileEventCallback() = default;
63     ~ProfileEventCallback() = default;
64 
OnSyncCompleted(const SyncResult & syncResults)65     void OnSyncCompleted(const SyncResult& syncResults) override
66     {
67     }
68 
OnProfileChanged(const ProfileChangeNotification & changeNotification)69     void OnProfileChanged(const ProfileChangeNotification& changeNotification) override
70     {
71         if (!subServiceIds_.empty()) {
72             const auto& profileEntries = changeNotification.GetProfileEntries();
73             for (const auto& ProfileEntry : profileEntries) {
74                 auto key = ProfileEntry.key;
75                 DTEST_LOG << "key: " << key << std::endl;
76                 auto iter = std::find(subServiceIds_.begin(), subServiceIds_.end(), key);
77                 EXPECT_TRUE(iter != subServiceIds_.end());
78                 numNotifications_++;
79             }
80         }
81     }
82 
SetSubServiceIds(const std::list<std::string> & subServiceIds)83     void SetSubServiceIds(const std::list<std::string>& subServiceIds)
84     {
85         subServiceIds_ = subServiceIds;
86     }
87 
GetNotificationNum() const88     int32_t GetNotificationNum() const
89     {
90         return numNotifications_;
91     }
92 
93 private:
94     std::list<std::string> subServiceIds_;
95     int32_t numNotifications_ {0};
96 };
97 
PutFakeStorage()98 int32_t PutFakeStorage()
99 {
100     ServiceCharacteristicProfile profile;
101     profile.SetServiceId("fakeStorage");
102     profile.SetServiceType("fakeStorage");
103     nlohmann::json j;
104     j["capacity"] = 0;
105     profile.SetCharacteristicProfileJson(j.dump());
106     return DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile);
107 }
108 
PutFakeSystem()109 int32_t PutFakeSystem()
110 {
111     ServiceCharacteristicProfile profile;
112     profile.SetServiceId("fakeSystem");
113     profile.SetServiceType("fakeSystem");
114     nlohmann::json j;
115     j["harmonyVersion"] = "2.2.0";
116     profile.SetCharacteristicProfileJson(j.dump());
117     return DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile);
118 }
119 
MockSubscribeEvents(const std::shared_ptr<ProfileEventCallback> & eventCb,const std::list<std::string> & serviceIds,const std::string & deviceId)120 int32_t MockSubscribeEvents(const std::shared_ptr<ProfileEventCallback>& eventCb,
121     const std::list<std::string>& serviceIds, const std::string& deviceId)
122 {
123     if (eventCb == nullptr) {
124         return UT_ERROR;
125     }
126     eventCb->SetSubServiceIds(serviceIds);
127     ExtraInfo extraInfo;
128     extraInfo["deviceId"] = deviceId;
129     extraInfo["serviceIds"] = serviceIds;
130 
131     std::list<SubscribeInfo> subscribeInfos;
132     SubscribeInfo eventChange;
133     eventChange.profileEvent = ProfileEvent::EVENT_PROFILE_CHANGED;
134     eventChange.extraInfo = std::move(extraInfo);
135     subscribeInfos.emplace_back(eventChange);
136 
137     SubscribeInfo eventSync;
138     eventSync.profileEvent = ProfileEvent::EVENT_SYNC_COMPLETED;
139     subscribeInfos.emplace_back(eventSync);
140 
141     std::list<ProfileEvent> failedEvents;
142     return DistributedDeviceProfileClient::GetInstance().SubscribeProfileEvents(
143         subscribeInfos, eventCb, failedEvents);
144 }
145 
MockUnsubscribeEvents(const std::shared_ptr<ProfileEventCallback> & eventCb)146 int32_t MockUnsubscribeEvents(const std::shared_ptr<ProfileEventCallback>& eventCb)
147 {
148     if (eventCb == nullptr) {
149         return UT_ERROR;
150     }
151     std::list<ProfileEvent> profileEvents;
152     profileEvents.emplace_back(ProfileEvent::EVENT_PROFILE_CHANGED);
153     profileEvents.emplace_back(ProfileEvent::EVENT_SYNC_COMPLETED);
154     std::list<ProfileEvent> failedEvents;
155     return DistributedDeviceProfileClient::GetInstance().UnsubscribeProfileEvents(
156         profileEvents, eventCb, failedEvents);
157 }
158 
MockSubscribeEvent(const std::shared_ptr<ProfileEventCallback> & eventCb,const std::list<std::string> & serviceIds,const std::string & deviceId)159 int32_t MockSubscribeEvent(const std::shared_ptr<ProfileEventCallback>& eventCb,
160     const std::list<std::string>& serviceIds, const std::string& deviceId)
161 {
162     if (eventCb == nullptr) {
163         return UT_ERROR;
164     }
165     eventCb->SetSubServiceIds(serviceIds);
166     ExtraInfo extraInfo;
167     extraInfo["deviceId"] = deviceId;
168     extraInfo["serviceIds"] = serviceIds;
169 
170     SubscribeInfo subscribeInfo;
171     subscribeInfo.profileEvent = ProfileEvent::EVENT_PROFILE_CHANGED;
172     subscribeInfo.extraInfo = std::move(extraInfo);
173     return DistributedDeviceProfileClient::GetInstance().SubscribeProfileEvent(subscribeInfo, eventCb);
174 }
175 
176 /**
177  * @tc.name: Subscribe001
178  * @tc.desc: subscribe a service and put a service profile
179  * @tc.type: FUNC
180  */
181 HWTEST_F(EventSubscribeTest, Subscribe001, TestSize.Level2)
182 {
183     auto callback = std::make_shared<ProfileEventCallback>();
184     if (MockSubscribeEvent(callback, {"fakeStorage"}, "")) {
185         EXPECT_TRUE(MockSubscribeEvent(callback, {"fakeStorage"}, ""));
186         DTEST_LOG << "subscribe failed" << std::endl;
187         return;
188     }
189 
190     int32_t errCode = PutFakeStorage();
191     EXPECT_EQ(errCode, ERR_OK);
192     if (errCode == ERR_OK) {
193         DTEST_LOG << "put succeeded" << std::endl;
194         std::this_thread::sleep_for(1s);
195         EXPECT_TRUE(callback->GetNotificationNum() == 1);
196     }
197 }
198 
199 /**
200  * @tc.name: Subscribe002
201  * @tc.desc: subscribe a service and put a unsubscribed service
202  * @tc.type: FUNC
203  */
204 HWTEST_F(EventSubscribeTest, Subscribe002, TestSize.Level2)
205 {
206     auto callback = std::make_shared<ProfileEventCallback>();
207     if (MockSubscribeEvent(callback, {"fakeSystem"}, "")) {
208         EXPECT_TRUE(MockSubscribeEvent(callback, {"fakeSystem"}, ""));
209         DTEST_LOG << "subscribe failed" << std::endl;
210         return;
211     }
212     int32_t errCode = PutFakeStorage();
213     EXPECT_EQ(errCode, ERR_OK);
214     if (errCode == ERR_OK) {
215         DTEST_LOG << "put succeeded" << std::endl;
216         std::this_thread::sleep_for(1s);
217         EXPECT_TRUE(callback->GetNotificationNum() == 0);
218     }
219 }
220 
221 /**
222  * @tc.name: Subscribe003
223  * @tc.desc: subscribe services and put service
224  * @tc.type: FUNC
225  */
226 HWTEST_F(EventSubscribeTest, Subscribe003, TestSize.Level2)
227 {
228     auto callback = std::make_shared<ProfileEventCallback>();
229     std::list<std::string> serviceIds = {"fakeStorage", "fakeSystem"};
230     if (MockSubscribeEvents(callback, serviceIds, "") != ERR_OK) {
231         EXPECT_NE(MockSubscribeEvents(callback, serviceIds, ""), ERR_OK);
232         DTEST_LOG << "subscribe failed" << std::endl;
233         return;
234     }
235     int32_t errCode = PutFakeSystem();
236     EXPECT_EQ(errCode, ERR_OK);
237     if (errCode == ERR_OK) {
238         DTEST_LOG << "put succeeded" << std::endl;
239         std::this_thread::sleep_for(1s);
240         EXPECT_TRUE(callback->GetNotificationNum() == 1);
241     }
242 }
243 
244 /**
245  * @tc.name: Subscribe004
246  * @tc.desc: subscribe with invalid deviceId
247  * @tc.type: FUNC
248  */
249 HWTEST_F(EventSubscribeTest, Subscribe004, TestSize.Level2)
250 {
251     auto callback = std::make_shared<ProfileEventCallback>();
252     std::list<std::string> serviceIds = {"fakeStorage", "fakeSystem"};
253     if (MockSubscribeEvent(callback, serviceIds, "fake_device_id") != ERR_OK) {
254         EXPECT_NE(MockSubscribeEvent(callback, serviceIds, "fake_device_id"), ERR_OK);
255         DTEST_LOG << "subscribe failed" << std::endl;
256         return;
257     }
258     int32_t errCode = PutFakeStorage();
259     EXPECT_EQ(errCode, ERR_OK);
260     if (errCode == ERR_OK) {
261         DTEST_LOG << "put succeeded" << std::endl;
262         std::this_thread::sleep_for(1s);
263         EXPECT_TRUE(callback->GetNotificationNum() == 0);
264     }
265 }
266 
267 /**
268  * @tc.name: Subscribe005
269  * @tc.desc: subscribe services and put services
270  * @tc.type: FUNC
271  */
272 HWTEST_F(EventSubscribeTest, Subscribe005, TestSize.Level2)
273 {
274     auto callback = std::make_shared<ProfileEventCallback>();
275     /**
276      * @tc.steps: step1. subscribe change event with two services
277      */
278     std::list<std::string> serviceIds = {"fakeStorage", "fakeSystem"};
279     if (MockSubscribeEvent(callback, serviceIds, "") != ERR_OK) {
280         EXPECT_NE(MockSubscribeEvent(callback, serviceIds, ""), ERR_OK);
281         DTEST_LOG << "subscribe failed" << std::endl;
282         return;
283     }
284 
285     /**
286      * @tc.steps: step2. put service profile which is subscribed
287      * @tc.expected: step2. got one notification.
288      */
289     int32_t errCode = PutFakeStorage();
290     EXPECT_EQ(errCode, ERR_OK);
291     if (errCode == ERR_OK) {
292         DTEST_LOG << "put succeeded" << std::endl;
293         std::this_thread::sleep_for(1s);
294         EXPECT_TRUE(callback->GetNotificationNum() == 1);
295     }
296     /**
297      * @tc.steps: step3. put the other subscribed service profile
298      * @tc.expected: step3. got notification again.
299      */
300     errCode = PutFakeSystem();
301     EXPECT_EQ(errCode, ERR_OK);
302     if (errCode == ERR_OK) {
303         DTEST_LOG << "put succeeded" << std::endl;
304         std::this_thread::sleep_for(1s);
305         EXPECT_TRUE(callback->GetNotificationNum() == 2);
306     }
307 }
308 
309 /**
310  * @tc.name: Subscribe006
311  * @tc.desc: subscribe with duplicated events
312  * @tc.type: FUNC
313  */
314 HWTEST_F(EventSubscribeTest, Subscribe006, TestSize.Level0)
315 {
316     auto callback = std::make_shared<ProfileEventCallback>();
317     std::list<SubscribeInfo> subscribeInfos;
318     ExtraInfo extraInfo;
319     extraInfo["deviceId"] = "";
320     extraInfo["serviceIds"] = {"fakeSystem"};
321 
322     SubscribeInfo eventChange;
323     eventChange.profileEvent = ProfileEvent::EVENT_PROFILE_CHANGED;
324     eventChange.extraInfo = std::move(extraInfo);
325     subscribeInfos.emplace_back(eventChange);
326     subscribeInfos.emplace_back(eventChange);
327 
328     std::list<ProfileEvent> failedEvents;
329     int32_t errCode = DistributedDeviceProfileClient::GetInstance().SubscribeProfileEvents(
330         subscribeInfos, callback, failedEvents);
331     EXPECT_TRUE(errCode == ERR_DP_INVALID_PARAMS);
332 }
333 
334 /**
335  * @tc.name: Unsubscribe001
336  * @tc.desc: unsubscribe event which is not subscribed yet
337  * @tc.type: FUNC
338  */
339 HWTEST_F(EventSubscribeTest, Unsubscribe001, TestSize.Level0)
340 {
341     auto callback = std::make_shared<ProfileEventCallback>();
342     int32_t errCode = DistributedDeviceProfileClient::GetInstance().UnsubscribeProfileEvent(
343         ProfileEvent::EVENT_PROFILE_CHANGED, callback);
344     EXPECT_TRUE(errCode == ERR_DP_NOT_SUBSCRIBED);
345 }
346 
347 /**
348  * @tc.name: Unsubscribe002
349  * @tc.desc: unsubscribe events which are not subscribed yet
350  * @tc.type: FUNC
351  */
352 HWTEST_F(EventSubscribeTest, Unsubscribe002, TestSize.Level0)
353 {
354     auto callback = std::make_shared<ProfileEventCallback>();
355     int32_t errCode = MockUnsubscribeEvents(callback);
356     EXPECT_TRUE(errCode == ERR_DP_NOT_SUBSCRIBED);
357 }
358 
359 /**
360  * @tc.name: SubscribeWithUnsusbscribe001
361  * @tc.desc: subscribe events and then unsubscribe one
362  * @tc.type: FUNC
363  */
364 HWTEST_F(EventSubscribeTest, SubscribeWithUnsusbscribe001, TestSize.Level2)
365 {
366     auto callback = std::make_shared<ProfileEventCallback>();
367 
368     /**
369      * @tc.steps: step1. subscribe sync and change event
370      */
371     std::list<std::string> serviceIds = {"fakeStorage", "fakeSystem"};
372     if (MockSubscribeEvents(callback, serviceIds, "") != ERR_OK) {
373         EXPECT_NE(MockSubscribeEvents(callback, serviceIds, ""), ERR_OK);
374         DTEST_LOG << "subscribe failed" << std::endl;
375         return;
376     }
377 
378     /**
379      * @tc.steps: step2. put service profile which is subscribed
380      * @tc.expected: step2. got one notification.
381      */
382     int32_t errCode = PutFakeSystem();
383     EXPECT_EQ(errCode, ERR_OK);
384     if (errCode == ERR_OK) {
385         DTEST_LOG << "put succeeded" << std::endl;
386         std::this_thread::sleep_for(1s);
387         EXPECT_TRUE(callback->GetNotificationNum() == 1);
388     }
389 
390     /**
391      * @tc.steps: step3. unsubscribe sync event
392      */
393     errCode = DistributedDeviceProfileClient::GetInstance().UnsubscribeProfileEvent(
394         ProfileEvent::EVENT_SYNC_COMPLETED, callback);
395     if (errCode != ERR_OK) {
396         EXPECT_NE(errCode, ERR_OK);
397         DTEST_LOG << "unsubscribe failed" << std::endl;
398         return;
399     }
400     EXPECT_EQ(errCode, ERR_OK);
401 
402     /**
403      * @tc.steps: step4. put the other subscribed service profile
404      * @tc.expected: step4. got notification again.
405      */
406     errCode = PutFakeStorage();
407     EXPECT_EQ(errCode, ERR_OK);
408     if (errCode == ERR_OK) {
409         DTEST_LOG << "put succeeded" << std::endl;
410         std::this_thread::sleep_for(1s);
411         EXPECT_TRUE(callback->GetNotificationNum() == 2);
412     }
413 }
414 
415 /**
416  * @tc.name: SubscribeWithUnsusbscribe002
417  * @tc.desc: subscribe events and then unsubscribe all
418  * @tc.type: FUNC
419  */
420 HWTEST_F(EventSubscribeTest, SubscribeWithUnsusbscribe002, TestSize.Level2)
421 {
422     auto callback = std::make_shared<ProfileEventCallback>();
423 
424     /**
425      * @tc.steps: step1. subscribe sync and change event
426      */
427     std::list<std::string> serviceIds = {"fakeStorage", "fakeSystem"};
428     if (MockSubscribeEvents(callback, serviceIds, "") != ERR_OK) {
429         EXPECT_NE(MockSubscribeEvents(callback, serviceIds, ""), ERR_OK);
430         DTEST_LOG << "subscribe failed" << std::endl;
431         return;
432     }
433 
434     /**
435      * @tc.steps: step2. put service profile which is subscribed
436      * @tc.expected: step2. got one notification.
437      */
438     int32_t errCode = PutFakeSystem();
439     EXPECT_EQ(errCode, ERR_OK);
440     if (errCode == ERR_OK) {
441         DTEST_LOG << "put succeeded" << std::endl;
442         std::this_thread::sleep_for(1s);
443         EXPECT_TRUE(callback->GetNotificationNum() == 1);
444     }
445 
446     /**
447      * @tc.steps: step3. unsubscribe all events
448      */
449     if (MockUnsubscribeEvents(callback) != ERR_OK) {
450         EXPECT_NE(MockUnsubscribeEvents(callback), ERR_OK);
451         DTEST_LOG << "unsubscribe failed" << std::endl;
452         return;
453     }
454 
455     /**
456      * @tc.steps: step4. put a subscribed service profile
457      * @tc.expected: step4. can't receive notification.
458      */
459     errCode = PutFakeStorage();
460     EXPECT_EQ(errCode, ERR_OK);
461     if (errCode == ERR_OK) {
462         DTEST_LOG << "put succeeded" << std::endl;
463         std::this_thread::sleep_for(1s);
464         EXPECT_TRUE(callback->GetNotificationNum() == 1);
465     }
466 }
467 
468 /**
469  * @tc.name: SubDeviceProfile_001
470  * @tc.desc: sub device profile
471  * @tc.type: FUNC
472  * @tc.require: I51HKG
473  */
474 HWTEST_F(EventSubscribeTest, UnsubDeviceProfile_001, TestSize.Level3)
475 {
476     auto callback = std::make_shared<ProfileEventCallback>();
477     std::list<ProfileEvent> profileEvents;
478     profileEvents.emplace_back(ProfileEvent::EVENT_PROFILE_CHANGED);
479     std::list<ProfileEvent> failedEvents;
480     auto result = DistributedDeviceProfileClient::GetInstance().UnsubscribeProfileEvents(
481         profileEvents, callback, failedEvents);
482     DTEST_LOG << "result: " << result << std::endl;
483     EXPECT_NE(result, ERR_INVALID_DATA);
484 }
485 }
486 }