Update unit test and Fix bug.
[platform/upstream/iotivity.git] / service / notification / unittest / NSConsumerTest.cpp
1 //******************************************************************
2 //
3 // Copyright 2016 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include <gtest/gtest.h>
22 #include <HippoMocks/hippomocks.h>
23 #include <atomic>
24 #include <functional>
25 #include <condition_variable>
26 #include <mutex>
27 #include <chrono>
28
29 #include "ocstack.h"
30
31 #include "NSCommon.h"
32 #include "NSConsumerInterface.h"
33
34 #include "NSProviderSimulator.h"
35
36 namespace
37 {
38     NSProviderSimulator g_providerSimul;
39     NSProvider * g_provider;
40
41     std::atomic_bool g_isStartedStack(false);
42
43     std::chrono::milliseconds g_waitForResponse(500);
44
45     std::condition_variable responseCon;
46     std::mutex mutexForCondition;
47
48     enum class NSSelector
49     {
50         NS_SELECTION_CONSUMER = 0,
51         NS_SELECTION_PROVIDER = 1
52     };
53
54     NSConsumerConfig cfg;
55
56     NSProviderSimulator::NS_TopicStateList g_topicStateList;
57 }
58
59 class TestWithMock: public testing::Test
60 {
61 public:
62     MockRepository mocks;
63
64 protected:
65     virtual ~TestWithMock() noexcept(noexcept(std::declval<Test>().~Test()))
66     {
67
68     }
69
70     virtual void TearDown()
71     {
72         try
73         {
74             mocks.VerifyAll();
75         }
76         catch (...)
77         {
78             mocks.reset();
79             throw;
80         }
81     }
82 };
83
84 class NotificationConsumerTest : public TestWithMock
85 {
86 public:
87     NotificationConsumerTest() = default;
88     ~NotificationConsumerTest() = default;
89
90     static void NSNotificationReceivedCallbackEmpty(NSMessage *)
91     {
92         std::cout << __func__ << std::endl;
93     }
94
95     static void NSSyncCallbackEmpty(NSSyncInfo *)
96     {
97         std::cout << __func__ << std::endl;
98     }
99
100     static void NSFoundResourceEmpty(std::shared_ptr< OC::OCResource >)
101     {
102         std::cout << __func__ << std::endl;
103     }
104
105     static void NSProviderChangedCallback(NSProvider *,  NSProviderState)
106     {
107         std::cout << __func__ << std::endl;
108     }
109
110 protected:
111
112     void SetUp()
113     {
114         TestWithMock::SetUp();
115
116         if (g_isStartedStack == false)
117         {
118             OC::PlatformConfig occfg
119             {
120                 OC::ServiceType::InProc,
121                 OC::ModeType::Both,
122                 "0.0.0.0",
123                 0,
124                 OC::QualityOfService::LowQos
125             };
126             OC::OCPlatform::Configure(occfg);
127
128             try
129             {
130                 OC::OCPlatform::stopPresence();
131             }
132             catch (...)
133             {
134
135             }
136
137             g_isStartedStack = true;
138
139             cfg.changedCb = NSProviderChangedCallback;
140             cfg.messageCb = NSNotificationReceivedCallbackEmpty;
141             cfg.syncInfoCb = NSSyncCallbackEmpty;
142         }
143
144     }
145
146     void TearDown()
147     {
148         TestWithMock::TearDown();
149     }
150
151 };
152
153 TEST_F(NotificationConsumerTest, StartConsumerNegativeNonSetChangedCB)
154 {
155     cfg.changedCb = NULL;
156     cfg.messageCb = NSNotificationReceivedCallbackEmpty;
157     cfg.syncInfoCb = NSSyncCallbackEmpty;
158
159     EXPECT_EQ(NS_ERROR, NSStartConsumer(cfg));
160     std::unique_lock< std::mutex > lock{ mutexForCondition };
161     responseCon.wait_for(lock, g_waitForResponse);
162 }
163
164 TEST_F(NotificationConsumerTest, StartConsumerNegativeNonSetNotiReceiveCB)
165 {
166     cfg.changedCb = NSProviderChangedCallback;
167     cfg.messageCb = NULL;
168     cfg.syncInfoCb = NSSyncCallbackEmpty;
169
170     EXPECT_EQ(NS_ERROR, NSStartConsumer(cfg));
171     std::unique_lock< std::mutex > lock{ mutexForCondition };
172     responseCon.wait_for(lock, g_waitForResponse);
173 }
174
175 TEST_F(NotificationConsumerTest, StartConsumerNegativeNonSetSyncCB)
176 {
177     cfg.changedCb = NSProviderChangedCallback;
178     cfg.messageCb = NSNotificationReceivedCallbackEmpty;
179     cfg.syncInfoCb = NULL;
180
181     EXPECT_EQ(NS_ERROR, NSStartConsumer(cfg));
182     std::unique_lock< std::mutex > lock{ mutexForCondition };
183     responseCon.wait_for(lock, g_waitForResponse);
184 }
185
186 TEST_F(NotificationConsumerTest, StartConsumerPositive)
187 {
188     cfg.changedCb = NSProviderChangedCallback;
189     cfg.messageCb = NSNotificationReceivedCallbackEmpty;
190     cfg.syncInfoCb = NSSyncCallbackEmpty;
191
192     EXPECT_EQ(NS_OK, NSStartConsumer(cfg));
193     std::unique_lock< std::mutex > lock{ mutexForCondition };
194     responseCon.wait_for(lock, g_waitForResponse);
195 }
196
197 TEST_F(NotificationConsumerTest, StopConsumerPositive)
198 {
199     EXPECT_EQ(NSStopConsumer(), NS_OK);
200 }
201
202 TEST_F(NotificationConsumerTest, StopConsumerNegative)
203 {
204     EXPECT_EQ(NSStopConsumer(), NS_ERROR);
205 }
206
207 TEST_F(NotificationConsumerTest, DiscoverProviderWithNonAccepterWhenStartedConsumerFirst)
208 {
209     NSProviderState revState = NS_STOPPED;
210     mocks.OnCallFunc(NSProviderChangedCallback).Do(
211             [this, & revState](NSProvider *, NSProviderState state)
212             {
213                 std::cout << "Call Discovered" << std::endl;
214                 revState = state;
215                 responseCon.notify_all();
216             });
217
218     NSStartConsumer(cfg);
219
220     g_providerSimul.setAccepter((int)NSSelector::NS_SELECTION_CONSUMER);
221     g_providerSimul.createNotificationResource();
222
223     std::unique_lock< std::mutex > lock{ mutexForCondition };
224     responseCon.wait_for(lock, g_waitForResponse);
225
226     NSStopConsumer();
227     g_providerSimul.deleteNotificationResource();
228
229     EXPECT_EQ(NS_DISCOVERED, revState);
230 }
231
232 TEST_F(NotificationConsumerTest, DiscoverProviderWithNonAccepterWhenStartedConsumerAfter)
233 {
234     g_providerSimul.setAccepter((int)NSSelector::NS_SELECTION_CONSUMER);
235     g_providerSimul.createNotificationResource();
236     {
237         std::unique_lock< std::mutex > lock{ mutexForCondition };
238         responseCon.wait_for(lock, g_waitForResponse);
239     }
240
241     NSProviderState revState = NS_STOPPED;
242     mocks.OnCallFunc(NSProviderChangedCallback).Do(
243             [this, & revState](NSProvider * provider, NSProviderState state)
244             {
245                 std::cout << "Call Discovered" << std::endl;
246
247                 g_provider = provider;
248                 revState = state;
249                 responseCon.notify_all();
250             });
251
252     NSStartConsumer(cfg);
253
254     std::unique_lock< std::mutex > lock{ mutexForCondition };
255     responseCon.wait_for(lock, g_waitForResponse);
256
257     EXPECT_EQ(NS_DISCOVERED, revState);
258 }
259
260 TEST_F(NotificationConsumerTest, DiscoverProviderWithNonAccepterWhenRescan)
261 {
262     g_providerSimul.setAccepter((int)NSSelector::NS_SELECTION_CONSUMER);
263     NSProviderState revState = NS_STOPPED;
264     mocks.OnCallFunc(NSProviderChangedCallback).Do(
265             [this, &revState](NSProvider * provider, NSProviderState state)
266             {
267                 std::cout << "Call Discovered" << std::endl;
268                 revState = state;
269                 g_provider = provider;
270                 std::cout << g_provider->providerId << std::endl;
271                 responseCon.notify_all();
272             });
273
274     NSRescanProvider();
275
276     std::unique_lock< std::mutex > lock{ mutexForCondition };
277     responseCon.wait_for(lock, g_waitForResponse);
278
279     EXPECT_EQ(NS_DISCOVERED, revState);
280 }
281
282 TEST_F(NotificationConsumerTest, ExpectSubscribeSuccess)
283 {
284     NSProviderState revState = NS_DENY;
285     mocks.OnCallFunc(NSProviderChangedCallback).Do(
286             [this, & revState](NSProvider * , NSProviderState state)
287             {
288                 std::cout << "Income Changed Callback : " << state << std::endl;
289                 revState = state;
290                 responseCon.notify_all();
291             });
292
293     NSResult ret = NSSubscribe(g_provider->providerId);
294     std::unique_lock< std::mutex > lock{ mutexForCondition };
295     responseCon.wait_for(lock, g_waitForResponse);
296
297     EXPECT_EQ(NS_ALLOW, revState);
298     EXPECT_EQ(NS_OK, ret);
299 }
300
301 TEST_F(NotificationConsumerTest, ExpectReceiveNotification)
302 {
303     uint64_t id = 10;
304     std::string title = "title";
305     std::string msg = "msg";
306
307     uint64_t revId = 0;
308
309     mocks.OnCallFunc(NSNotificationReceivedCallbackEmpty).Do(
310             [this, & revId](NSMessage * message)
311             {
312                 std::cout << "Income Notification : " << message->messageId << std::endl;
313                 revId = message->messageId;
314                 responseCon.notify_all();
315             });
316
317     g_providerSimul.notifyMessage(id, title, msg);
318
319     std::unique_lock< std::mutex > lock{ mutexForCondition };
320     responseCon.wait_for(lock, g_waitForResponse);
321
322     EXPECT_EQ(id, revId);
323     NSStopConsumer();
324     g_providerSimul.deleteNotificationResource();
325 }
326
327 TEST_F(NotificationConsumerTest, ExpectReceiveSubAllowWithAccepterisProvider)
328 {
329     g_providerSimul.setAccepter((int)NSSelector::NS_SELECTION_PROVIDER);
330     NSProviderState revState = NS_DENY;
331     g_providerSimul.createNotificationResource();
332     {
333         std::unique_lock< std::mutex > lock{ mutexForCondition };
334         responseCon.wait_for(lock, g_waitForResponse);
335     }
336
337     mocks.OnCallFunc(NSProviderChangedCallback).Do(
338             [this, & revState](NSProvider * provider, NSProviderState state)
339             {
340                 std::cout << "Income Changed Callback : " << state << std::endl;
341                 revState = state;
342                 g_provider = provider;
343                 responseCon.notify_all();
344             });
345     mocks.OnCallFunc(NSProviderChangedCallback).Do(
346             [this, & revState](NSProvider *, NSProviderState state)
347             {
348                 std::cout << "Income Changed Callback : " << state << std::endl;
349                 revState = state;
350                 responseCon.notify_all();
351             });
352
353     NSStartConsumer(cfg);
354     std::unique_lock< std::mutex > lock{ mutexForCondition };
355     responseCon.wait_for(lock, g_waitForResponse);
356
357     EXPECT_EQ(NS_ALLOW, revState);
358 }
359
360 TEST_F(NotificationConsumerTest, ExpectReceiveNotificationWithAccepterisProvider)
361 {
362     uint64_t id = 11;
363     std::string title = "title";
364     std::string msg = "msg";
365     uint64_t revId = 1;
366
367     mocks.OnCallFunc(NSNotificationReceivedCallbackEmpty).Do(
368             [this, & id, & revId](NSMessage * message)
369             {
370                 std::cout << "Income Notification : " << message->messageId << std::endl;
371                 revId = message->messageId;
372                 responseCon.notify_all();
373             });
374
375     g_providerSimul.notifyMessage(id, title, msg);
376
377     std::unique_lock< std::mutex > lock{ mutexForCondition };
378     responseCon.wait_for(lock, g_waitForResponse);
379
380     EXPECT_EQ(id, revId);
381 }
382
383 TEST_F(NotificationConsumerTest, ExpectCallbackReadCheckWhenProviderNotifySync)
384 {
385     uint64_t id = 12;
386     std::string title = "title";
387     std::string msg = "msg";
388     NSSyncType type = NS_SYNC_DELETED;
389
390     mocks.OnCallFunc(NSNotificationReceivedCallbackEmpty).Do(
391             [this](NSMessage * message)
392             {
393                 std::cout << "Income Notification : " << message->messageId << std::endl;
394                 responseCon.notify_all();
395             });
396
397     mocks.OnCallFunc(NSSyncCallbackEmpty).Do(
398             [& type, this](NSSyncInfo * sync)
399             {
400                 std::cout << "Income SyncInfo : " << sync->messageId
401                         << ", State : " << sync->state << std::endl;
402                 type = sync->state;
403                 responseCon.notify_all();
404             });
405
406     g_providerSimul.notifyMessage(id, title, msg);
407     {
408         std::unique_lock< std::mutex > lock{ mutexForCondition };
409         responseCon.wait_for(lock, g_waitForResponse);
410     }
411
412     g_providerSimul.sendRead(id);
413     {
414         std::unique_lock< std::mutex > lock{ mutexForCondition };
415         responseCon.wait_for(lock, g_waitForResponse);
416     }
417
418     EXPECT_EQ(NS_SYNC_READ, type);
419 }
420
421 TEST_F(NotificationConsumerTest, ExpectCallbackDismissCheckWhenProviderNotifySync)
422 {
423     uint64_t id = 13;
424     std::string title = "title";
425     std::string msg = "msg";
426     NSSyncType type = NS_SYNC_READ;
427
428     mocks.OnCallFunc(NSNotificationReceivedCallbackEmpty).Do(
429             [this](NSMessage * message)
430             {
431                 std::cout << "Income Notification : " << message->messageId << std::endl;
432                 responseCon.notify_all();
433             });
434
435     mocks.OnCallFunc(NSSyncCallbackEmpty).Do(
436             [& type, this](NSSyncInfo * sync)
437             {
438                 std::cout << "Income Notification : " << sync->messageId
439                         << ", State : " << sync->state << std::endl;
440                 type = sync->state;
441                 responseCon.notify_all();
442             });
443
444     g_providerSimul.notifyMessage(id, title, msg);
445     {
446         std::unique_lock< std::mutex > lock{ mutexForCondition };
447         responseCon.wait_for(lock, g_waitForResponse);
448     }
449
450     g_providerSimul.sendDismiss(id);
451     {
452         std::unique_lock< std::mutex > lock{ mutexForCondition };
453         responseCon.wait_for(lock, g_waitForResponse);
454     }
455
456     EXPECT_EQ(NS_SYNC_DELETED, type);
457 }
458
459 TEST_F(NotificationConsumerTest, ExpectCallbackReadCheckWhenConsumerPostSync)
460 {
461     uint64_t id = 14;
462     std::string title = "title";
463     std::string msg = "msg";
464     NSSyncType type = NS_SYNC_DELETED;
465
466     mocks.OnCallFunc(NSNotificationReceivedCallbackEmpty).Do(
467             [this](NSMessage * message)
468             {
469                 std::cout << "Income Notification : " << message->messageId << std::endl;
470                 NSConsumerSendSyncInfo(message->providerId, message->messageId, NS_SYNC_READ);
471                 std::unique_lock< std::mutex > lock{ mutexForCondition };
472                 responseCon.wait_for(lock, g_waitForResponse);
473             });
474
475     mocks.OnCallFunc(NSSyncCallbackEmpty).Do(
476             [& type, this](NSSyncInfo * sync)
477             {
478                 std::cout << "Income Notification : " << sync->messageId
479                         << ", State : " << sync->state << std::endl;
480                 type = sync->state;
481                 responseCon.notify_all();
482             });
483
484     g_providerSimul.notifyMessage(id, title, msg);
485     {
486         std::unique_lock< std::mutex > lock{ mutexForCondition };
487         responseCon.wait_for(lock, g_waitForResponse);
488     }
489
490     EXPECT_EQ(NS_SYNC_READ, type);
491 }
492
493 TEST_F(NotificationConsumerTest, ExpectCallbackDismissCheckWhenConsumerPostSync)
494 {
495     uint64_t id = 15;
496     std::string title = "title";
497     std::string msg = "msg";
498     NSSyncType state = NS_SYNC_READ;
499
500     mocks.OnCallFunc(NSNotificationReceivedCallbackEmpty).Do(
501             [this](NSMessage * message)
502             {
503                 std::cout << "Income Notification : " << message->messageId << std::endl;
504                 NSConsumerSendSyncInfo(message->providerId, message->messageId, NS_SYNC_DELETED);
505                 std::unique_lock< std::mutex > lock{ mutexForCondition };
506                 responseCon.wait_for(lock, g_waitForResponse);
507             });
508
509     mocks.OnCallFunc(NSSyncCallbackEmpty).Do(
510             [& state, this](NSSyncInfo * sync)
511             {
512                 std::cout << "Income Notification : " << sync->messageId
513                         << ", State : " << sync->state << std::endl;
514                 state = sync->state;
515                 responseCon.notify_all();
516             });
517
518     g_providerSimul.notifyMessage(id, title, msg);
519     {
520         std::unique_lock< std::mutex > lock{ mutexForCondition };
521         responseCon.wait_for(lock, g_waitForResponse);
522     }
523
524     EXPECT_EQ(NS_SYNC_DELETED, state);
525 }
526
527 TEST_F(NotificationConsumerTest, ExpectGetTopicListIsNULL)
528 {
529     NSTopicLL * currentTopics = NSConsumerGetTopicList(g_provider->providerId);
530     EXPECT_EQ(NULL, currentTopics);
531 }
532
533 TEST_F(NotificationConsumerTest, ExpectCallbackTopicUpdated)
534 {
535     NSProviderState revState = NS_STOPPED;
536     mocks.OnCallFunc(NSProviderChangedCallback).Do(
537         [this, & revState](NSProvider * , NSProviderState state)
538         {
539             std::cout << "Income Changed Callback : " << state << std::endl;
540             revState = state;
541             responseCon.notify_all();
542         });
543
544     NSProviderSimulator::NS_TopicList topics;
545     topics.push_back("1");
546     topics.push_back("2");
547     topics.push_back("3");
548
549     g_providerSimul.setTopics(topics);
550
551     std::unique_lock< std::mutex > lock{ mutexForCondition };
552     responseCon.wait_for(lock, g_waitForResponse);
553
554     EXPECT_EQ(NS_TOPIC, revState);
555 }
556
557 TEST_F(NotificationConsumerTest, ExpectEQTopicList)
558 {
559     bool isSame = false;
560
561     NSProviderSimulator::NS_TopicList topics;
562     topics.push_back("1");
563     topics.push_back("2");
564     topics.push_back("3");
565
566     NSTopicLL * retTopic = NSConsumerGetTopicList(g_provider->providerId);
567     std::for_each (topics.begin(), topics.end(),
568             [this, & retTopic, & isSame](const std::string & str)
569             {
570                 isSame = (str == std::string(retTopic->topicName));
571                 retTopic = retTopic->next;
572             });
573
574     EXPECT_EQ(true, isSame);
575 }
576
577 TEST_F(NotificationConsumerTest, ExpectFailUpdateTopicOnConsumer)
578 {
579     NSTopicLL * retTopic = NSConsumerGetTopicList(g_provider->providerId);
580     for (; retTopic; retTopic = retTopic->next)
581     {
582         retTopic->state = NS_TOPIC_SUBSCRIBED;
583     }
584     NSResult ret = NSConsumerUpdateTopicList(g_provider->providerId, retTopic);
585
586     EXPECT_EQ(NS_ERROR, ret);
587 }
588
589 TEST_F(NotificationConsumerTest, ExpectCallbackDeletedProvider)
590 {
591     NSProviderState type = NS_ALLOW;
592     mocks.OnCallFunc(NSProviderChangedCallback).Do(
593             [& type, this](NSProvider * , NSProviderState state)
594             {
595                 std::cout << "Income Changed Callback : " << state << std::endl;
596                 type = state;
597                 responseCon.notify_all();
598             });
599
600     g_providerSimul.deleteNotificationResource();
601
602     std::unique_lock< std::mutex > lock{ mutexForCondition };
603     responseCon.wait_for(lock, std::chrono::milliseconds(2000));
604
605     EXPECT_EQ(type, NS_STOPPED);
606     NSStopConsumer();
607 }