ba441fdbe7d6471d75724e4342cc22e20697d796
[platform/upstream/iotivity.git] / service / resource-encapsulation / src / serverBuilder / unittests / RCSResourceObjectTest.cpp
1 //******************************************************************
2 //
3 // Copyright 2015 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 <UnitTestHelper.h>
22
23 #include <RCSResourceObject.h>
24
25 #include <OCPlatform.h>
26
27 using namespace std;
28 using namespace std::placeholders;
29
30 using namespace OIC::Service;
31 using namespace OC;
32
33 typedef OCStackResult (*registerResource)(OCResourceHandle&, string&, const string&, const string&,
34                            EntityHandler, uint8_t );
35
36 typedef OCStackResult (*NotifyAllObservers)(OCResourceHandle);
37
38 constexpr char RESOURCE_URI[]{ "a/test" };
39 constexpr char RESOURCE_TYPE[]{ "resourcetype" };
40 constexpr char KEY[]{ "key" };
41 constexpr int value{ 100 };
42
43 TEST(ResourceObjectBuilderCreateTest, ThrowIfUriIsInvalid)
44 {
45     ASSERT_THROW(RCSResourceObject::Builder("", "", "").build(), RCSPlatformException);
46 }
47
48 class ResourceObjectBuilderTest: public TestWithMock
49 {
50 protected:
51     void SetUp()
52     {
53         TestWithMock::SetUp();
54
55         mocks.OnCallFuncOverload(static_cast< registerResource >(OCPlatform::registerResource))
56                 .Return(OC_STACK_OK);
57     }
58 };
59
60 TEST_F(ResourceObjectBuilderTest, RegisterResourceWhenCallCreate)
61 {
62     mocks.ExpectCallFuncOverload(static_cast< registerResource >(OCPlatform::registerResource))
63             .Return(OC_STACK_OK);
64
65     RCSResourceObject::Builder(RESOURCE_URI, RESOURCE_TYPE, "").build();
66 }
67
68 TEST_F(ResourceObjectBuilderTest, ResourceServerHasPropertiesSetByBuilder)
69 {
70     auto serverResource = RCSResourceObject::Builder(RESOURCE_URI, RESOURCE_TYPE, "").
71             setDiscoverable(false).setObservable(true).build();
72
73     EXPECT_FALSE(serverResource->isDiscoverable());
74     EXPECT_TRUE(serverResource->isObservable());
75 }
76
77 TEST_F(ResourceObjectBuilderTest, ResourceServerHasAttrsSetByBuilder)
78 {
79     RCSResourceAttributes attrs;
80     attrs[KEY] = 100;
81
82     auto serverResource = RCSResourceObject::Builder(RESOURCE_URI, RESOURCE_TYPE, "").
83             setAttributes(attrs).build();
84
85     RCSResourceObject::LockGuard lock{ serverResource, RCSResourceObject::AutoNotifyPolicy::NEVER };
86     EXPECT_EQ(attrs, serverResource->getAttributes());
87 }
88
89
90 class ResourceObjectTest: public TestWithMock
91 {
92 public:
93     RCSResourceObject::Ptr server;
94
95 protected:
96     void SetUp()
97     {
98         TestWithMock::SetUp();
99
100         initMocks();
101
102         server = RCSResourceObject::Builder(RESOURCE_URI, RESOURCE_TYPE, "").build();
103
104         initResourceObject();
105     }
106
107     virtual void initMocks()
108     {
109         mocks.OnCallFuncOverload(static_cast< registerResource >(OCPlatform::registerResource)).
110                 Return(OC_STACK_OK);
111
112         mocks.OnCallFunc(OCPlatform::unregisterResource).Return(OC_STACK_OK);
113     }
114
115     virtual void initResourceObject() {
116         server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::NEVER);
117     }
118 };
119
120 TEST_F(ResourceObjectTest, AccessAttributesWithLock)
121 {
122     {
123         RCSResourceObject::LockGuard lock{ server };
124         auto& attr = server->getAttributes();
125         attr[KEY] = value;
126     }
127
128     ASSERT_EQ(value, server->getAttribute<int>(KEY));
129 }
130
131 TEST_F(ResourceObjectTest, ThrowIfTryToAccessAttributesWithoutGuard)
132 {
133     ASSERT_THROW(server->getAttributes(), NoLockException);
134 }
135
136 TEST_F(ResourceObjectTest, SettingAttributesWithinGuardDoesntCauseDeadLock)
137 {
138     {
139         RCSResourceObject::LockGuard guard{ server };
140         server->setAttribute(KEY, value);
141     }
142
143     ASSERT_EQ(value, server->getAttribute<int>(KEY));
144 }
145
146 TEST_F(ResourceObjectTest, SettingNestedAttributesIsSameToGettingNestedAttributes)
147 {
148     RCSResourceAttributes lightAttributes;
149
150     lightAttributes["red"]=50;
151     lightAttributes["blue"]=100;
152     lightAttributes["green"]=150;
153
154     server->setAttribute(KEY, lightAttributes);
155
156     ASSERT_EQ(lightAttributes, server->getAttribute<RCSResourceAttributes>(KEY));
157 }
158
159 TEST_F(ResourceObjectTest, SettingNestedVectorAttributesIsSameToGettingNestedVectorAttributes)
160 {
161     vector<int> arr11 = {0,1}, arr12 = {4,5}, arr13 ={7,8};
162     vector<vector<int>> arr21 = { arr11, arr12 }, arr22 = { arr12, arr13 };
163     vector<vector<vector<int>>> arr31={ arr21, arr22 };
164
165     server->setAttribute(KEY, arr31);
166
167     ASSERT_EQ(arr31, server->getAttribute<vector<vector<vector<int>>>>(KEY));
168 }
169
170
171 class AutoNotifyTest: public ResourceObjectTest
172 {
173 protected:
174     void initMocks()
175     {
176         mocks.OnCallFuncOverload(static_cast< NotifyAllObservers >(
177                 OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
178     }
179
180     virtual void initResourceObject() {
181         // intended blank
182     }
183 };
184
185 TEST_F(AutoNotifyTest, DefalutAutoNotifyPolicyIsUpdated)
186 {
187     ASSERT_EQ(RCSResourceObject::AutoNotifyPolicy::UPDATED, server->getAutoNotifyPolicy());
188 }
189
190 TEST_F(AutoNotifyTest, AutoNotifyPolicyCanBeSet)
191 {
192     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::NEVER);
193
194     ASSERT_EQ(RCSResourceObject::AutoNotifyPolicy::NEVER, server->getAutoNotifyPolicy());
195 }
196
197 TEST_F(AutoNotifyTest, WithUpdatedPolicy_NeverBeNotifiedIfAttributeIsNotChanged)
198 {
199     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
200     server->setAttribute(KEY, value);
201
202     mocks.NeverCallFuncOverload(static_cast< NotifyAllObservers >(
203             OC::OCPlatform::notifyAllObservers));
204
205     server->setAttribute(KEY, value);
206 }
207
208 TEST_F(AutoNotifyTest, WithUpdatedPolicy_WillBeNotifiedIfAttributeIsChanged)
209 {
210     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
211     server->setAttribute(KEY, value);
212
213     mocks.ExpectCallFuncOverload(static_cast< NotifyAllObservers >(
214             OC::OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
215
216     server->setAttribute(KEY, value + 1);
217 }
218
219 TEST_F(AutoNotifyTest, WithUpdatedPolicy_WillBeNotifiedIfValueIsAdded)
220 {
221     constexpr char newKey[]{ "newKey" };
222     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
223
224     mocks.ExpectCallFuncOverload(static_cast< NotifyAllObservers >(
225             OC::OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
226
227     server->setAttribute(newKey, value);
228 }
229
230 TEST_F(AutoNotifyTest, WithNeverPolicy_NeverBeNotifiedEvenIfAttributeIsChanged)
231 {
232     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::NEVER);
233
234     mocks.NeverCallFuncOverload(static_cast< NotifyAllObservers >(
235             OC::OCPlatform::notifyAllObservers));
236
237     RCSResourceObject::LockGuard lock{ server };
238     server->setAttribute(KEY, value);
239 }
240
241 TEST_F(AutoNotifyTest, WithUpdatePolicy_WillBeNotifiedIfAttributeIsDeleted)
242 {
243     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
244     server->setAttribute(KEY, value);
245
246     mocks.ExpectCallFuncOverload(static_cast< NotifyAllObservers >(
247             OC::OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
248
249     server->removeAttribute(KEY);
250 }
251
252 class AutoNotifyWithGuardTest: public AutoNotifyTest
253 {
254 };
255
256 TEST_F(AutoNotifyWithGuardTest, GuardFollowsServerPolicyByDefault)
257 {
258     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
259
260     mocks.ExpectCallFuncOverload(static_cast< NotifyAllObservers >(
261             OC::OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
262
263     RCSResourceObject::LockGuard guard{ server };
264     server->setAttribute(KEY, value);
265 }
266
267 TEST_F(AutoNotifyWithGuardTest, GuardCanOverridePolicy)
268 {
269     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::ALWAYS);
270
271     mocks.NeverCallFuncOverload(static_cast< NotifyAllObservers >(
272             OC::OCPlatform::notifyAllObservers));
273
274     RCSResourceObject::LockGuard guard{ server, RCSResourceObject::AutoNotifyPolicy::NEVER };
275     server->getAttributes()[KEY] = value;
276 }
277
278 TEST_F(AutoNotifyWithGuardTest, GuardInvokesNotifyWhenDestroyed)
279 {
280     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::NEVER);
281
282     mocks.ExpectCallFuncOverload(static_cast< NotifyAllObservers >(
283             OC::OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
284
285     {
286         RCSResourceObject::LockGuard guard{ server, RCSResourceObject::AutoNotifyPolicy::ALWAYS };
287         server->setAttribute(KEY, value);
288     }
289
290     mocks.NeverCallFuncOverload(static_cast< NotifyAllObservers >(
291                OC::OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
292
293     server->setAttribute(KEY, value);
294 }
295
296
297
298 class ResourceObjectHandlingRequestTest: public ResourceObjectTest
299 {
300 public:
301     EntityHandler handler;
302
303     static constexpr OCRequestHandle fakeRequestHandle =
304             reinterpret_cast<OCRequestHandle>(0x1234);
305     static constexpr OCResourceHandle fakeResourceHandle =
306             reinterpret_cast<OCResourceHandle>(0x4321);
307
308 public:
309     OCResourceRequest::Ptr createRequest(OCMethod method = OC_REST_GET, OCRepresentation ocRep =
310             OCRepresentation{})
311     {
312         auto request = make_shared<OCResourceRequest>();
313
314         OCEntityHandlerRequest ocEntityHandlerRequest;
315         memset(&ocEntityHandlerRequest, 0, sizeof(OCEntityHandlerRequest));
316         OC::MessageContainer mc;
317
318         mc.addRepresentation(ocRep);
319
320         ocEntityHandlerRequest.requestHandle = fakeRequestHandle;
321         ocEntityHandlerRequest.resource = fakeResourceHandle;
322         ocEntityHandlerRequest.method = method;
323         ocEntityHandlerRequest.payload = reinterpret_cast<OCPayload*>(mc.getPayload());
324
325         formResourceRequest(OC_REQUEST_FLAG, &ocEntityHandlerRequest, request);
326
327         return request;
328     }
329
330 protected:
331     OCStackResult registerResourceFake(OCResourceHandle&, string&, const string&,
332             const string&, EntityHandler handler, uint8_t)
333     {
334         this->handler = handler;
335         return OC_STACK_OK;
336     }
337
338     void initMocks()
339     {
340         mocks.OnCallFuncOverload(
341             static_cast<registerResource>(OCPlatform::registerResource)).Do(
342                     bind(&ResourceObjectHandlingRequestTest::registerResourceFake,
343                             this, _1, _2, _3, _4, _5, _6));
344         mocks.OnCallFunc(OCPlatform::unregisterResource).Return(OC_STACK_OK);
345     }
346 };
347
348 TEST_F(ResourceObjectHandlingRequestTest, CallSendResponseWhenReceiveRequest)
349 {
350     mocks.ExpectCallFunc(OCPlatform::sendResponse).Return(OC_STACK_OK);
351
352     ASSERT_EQ(OC_EH_OK, handler(createRequest()));
353 }
354
355 TEST_F(ResourceObjectHandlingRequestTest, ReturnErrorCodeWhenSendResponseFailed)
356 {
357     mocks.ExpectCallFunc(OCPlatform::sendResponse).Return(OC_STACK_ERROR);
358
359     ASSERT_EQ(OC_EH_ERROR, handler(createRequest()));
360 }
361
362 TEST_F(ResourceObjectHandlingRequestTest, SendResponseWithSameHandlesPassedByRequest)
363 {
364     mocks.ExpectCallFunc(OCPlatform::sendResponse).Match(
365             [](const shared_ptr<OCResourceResponse> response)
366             {
367                 return response->getRequestHandle() == fakeRequestHandle &&
368                         response->getResourceHandle() == fakeResourceHandle;
369             }
370     ).Return(OC_STACK_OK);
371
372     ASSERT_EQ(OC_EH_OK, handler(createRequest()));
373 }
374
375 TEST_F(ResourceObjectHandlingRequestTest, SendResponseWithRCSResponseResults)
376 {
377     constexpr int errorCode{ 1999 };
378
379     server->setGetRequestHandler(
380             [](const RCSRequest&, RCSResourceAttributes&) -> RCSGetResponse
381             {
382                 return RCSGetResponse::create(errorCode);
383             }
384     );
385
386     mocks.ExpectCallFunc(OCPlatform::sendResponse).Match(
387             [](const shared_ptr<OCResourceResponse> response)
388             {
389                 return response->getErrorCode() == errorCode;
390             }
391     ).Return(OC_STACK_OK);
392
393     ASSERT_EQ(OC_EH_OK, handler(createRequest()));
394 }
395
396 TEST_F(ResourceObjectHandlingRequestTest, SendSetResponseWithCustomAttrs)
397 {
398     constexpr int errorCode{ 1999 };
399     constexpr char value[]{ "value" };
400
401     server->setSetRequestHandler(
402             [](const RCSRequest&, RCSResourceAttributes&) -> RCSSetResponse
403             {
404                 RCSResourceAttributes attrs;
405                 attrs[KEY] = value;
406                 return RCSSetResponse::create(attrs, errorCode);
407             }
408     );
409
410     mocks.ExpectCallFunc(OCPlatform::sendResponse).Match(
411             [](const shared_ptr<OCResourceResponse> response)
412             {
413                 return value == response->getResourceRepresentation()[KEY].getValue<std::string>()
414                         && response->getErrorCode() == errorCode;
415             }
416     ).Return(OC_STACK_OK);
417
418     ASSERT_EQ(OC_EH_OK, handler(createRequest(OC_REST_PUT)));
419 }
420
421
422 class SetRequestHandlerPolicyTest: public ResourceObjectHandlingRequestTest
423 {
424 public:
425     typedef OCStackResult (*SendResponse)(std::shared_ptr<OCResourceResponse>);
426
427 public:
428     OCRepresentation createOCRepresentation()
429     {
430         OCRepresentation ocRep;
431
432         vector<string> interface{"oic.if.baseline"};
433         vector<string> type{"core.light"};
434
435         ocRep.setUri(RESOURCE_URI);
436         ocRep.setResourceInterfaces(interface);
437         ocRep.setResourceTypes(type);
438
439         return ocRep;
440     }
441
442     void initMocks()
443     {
444         ResourceObjectHandlingRequestTest::initMocks();
445         mocks.OnCallFunc(OCPlatform::sendResponse).Return(OC_STACK_OK);
446     }
447 };
448
449 TEST_F(SetRequestHandlerPolicyTest, DefalutSetRequestHandlerPolicyIsNever)
450 {
451     ASSERT_EQ(RCSResourceObject::SetRequestHandlerPolicy::NEVER,
452                 server->getSetRequestHandlerPolicy());
453 }
454
455 TEST_F(SetRequestHandlerPolicyTest, SetRequestHandlerPolicyCanBeSet)
456 {
457     server->setSetRequestHandlerPolicy(RCSResourceObject::SetRequestHandlerPolicy::ACCEPTANCE);
458
459     ASSERT_EQ(RCSResourceObject::SetRequestHandlerPolicy::ACCEPTANCE,
460                 server->getSetRequestHandlerPolicy());
461 }
462
463 TEST_F(SetRequestHandlerPolicyTest, WithNeverPolicy_NotAddedIfReceivedNewKeyValuePair)
464 {
465     OCRepresentation ocRep = createOCRepresentation();
466     ocRep.setValue("NewKey", value);
467     server->setSetRequestHandlerPolicy(RCSResourceObject::SetRequestHandlerPolicy::NEVER);
468
469     handler(createRequest(OC_REST_PUT, ocRep));
470
471     RCSResourceObject::LockGuard guard{ server };
472     ASSERT_FALSE((server->getAttributes()).contains("NewKey"));
473 }
474
475 TEST_F(SetRequestHandlerPolicyTest, WithAcceptancePolicy_WillBeAddedIfReceivedNewKeyValuePair)
476 {
477     OCRepresentation ocRep = createOCRepresentation();
478     ocRep.setValue("NewKey", value);
479     server->setSetRequestHandlerPolicy(RCSResourceObject::SetRequestHandlerPolicy::ACCEPTANCE);
480
481     handler(createRequest(OC_REST_PUT, ocRep));
482
483     RCSResourceObject::LockGuard guard{ server };
484     ASSERT_TRUE((server->getAttributes()).contains("NewKey"));
485 }
486
487
488 class ResourceObjectSynchronizationTest: public ResourceObjectHandlingRequestTest
489 {
490 public:
491
492     static void withLock(RCSResourceObject::Ptr serverResource, int count)
493     {
494         for (int i=0; i<count; ++i)
495         {
496             RCSResourceObject::LockGuard lock{ serverResource };
497
498             auto& attrs = serverResource->getAttributes();
499
500             attrs[KEY] = attrs[KEY].get<int>() + 1;
501         }
502     }
503
504     static void withSetter(RCSResourceObject::Ptr serverResource, int count)
505     {
506         for (int i=0; i<count; ++i)
507         {
508             RCSResourceObject::LockGuard lock{ serverResource };
509
510             serverResource->setAttribute(KEY, serverResource->getAttribute<int>(KEY) + 1);
511         }
512     }
513 };
514
515 TEST_F(ResourceObjectSynchronizationTest, MultipleAccessToServerResource)
516 {
517     int expected { 0 };
518     vector<thread> threads;
519
520     server->setAttribute(KEY, 0);
521
522     for (int i = 20; i >= 0; --i) {
523         int count = 5000 + i * 100;
524         threads.push_back(thread { withLock, server, count });
525         expected += count;
526     }
527
528     for (int i = 20; i >= 0; --i) {
529         int count = 5000 + i * 100;
530         threads.push_back(thread { withSetter, server, count });
531         expected +=count;
532     }
533
534     for (auto& t : threads)
535     {
536         t.join();
537     }
538
539     ASSERT_EQ(expected, server->getAttribute<int>(KEY));
540 }
541
542 TEST_F(ResourceObjectSynchronizationTest, MultipleAccessToServerResourceWithRequests)
543 {
544     int expected { 0 };
545     vector<thread> threads;
546
547     mocks.OnCallFunc(OCPlatform::sendResponse).Return(OC_STACK_OK);
548
549     server->setAttribute(KEY, 0);
550
551     for (int i = 20; i >= 0; --i) {
552         int count = 5000 + i * 100;
553         threads.push_back(thread{ withLock, server, count });
554         expected += count;
555     }
556
557     for (int i = 20; i >= 0; --i) {
558         int count = 5000 + i * 100;
559         threads.push_back(thread{ withSetter, server, count });
560         expected +=count;
561     }
562
563     threads.push_back(thread{
564         [this]()
565         {
566             for (int i=0; i<10000; ++i)
567             {
568                 if (i % 5 == 0) handler(createRequest(OC_REST_OBSERVE));
569                 handler(createRequest((i & 1) ? OC_REST_GET : OC_REST_PUT));
570             }
571         }
572     });
573
574     for (auto& t : threads)
575     {
576         t.join();
577     }
578
579     ASSERT_EQ(expected, server->getAttribute<int>(KEY));
580 }
581
582
583 class AttributeUpdatedListenerTest: public ResourceObjectHandlingRequestTest
584 {
585 public:
586     typedef OCStackResult (*SendResponse)(std::shared_ptr<OCResourceResponse>);
587
588 public:
589     OCRepresentation createOCRepresentation(void)
590     {
591         OCRepresentation ocRep;
592
593         vector<string> interface{"oic.if.baseline"};
594         vector<string> type{"core.light"};
595
596         ocRep.setUri(RESOURCE_URI);
597         ocRep.setResourceInterfaces(interface);
598         ocRep.setResourceTypes(type);
599         ocRep[KEY] = value;
600
601         return ocRep;
602     }
603
604     void initMocks()
605     {
606         ResourceObjectHandlingRequestTest::initMocks();
607         mocks.OnCallFunc(OCPlatform::sendResponse).Return(OC_STACK_OK);
608     }
609 };
610
611 class FunctionsForAttributeUpdatedListener
612 {
613 public:
614     virtual void fCalled(const OIC::Service::RCSResourceAttributes::Value&,
615         const OIC::Service::RCSResourceAttributes::Value&)=0;
616     virtual void fNotCalled(const OIC::Service::RCSResourceAttributes::Value&,
617         const OIC::Service::RCSResourceAttributes::Value&)=0;
618 };
619
620 TEST_F(AttributeUpdatedListenerTest, AddListenerRunsAddedFunction)
621 {
622     FunctionsForAttributeUpdatedListener *ptrMock =
623         mocks.Mock<FunctionsForAttributeUpdatedListener>();
624
625     server->setAttribute(KEY, 0);
626
627     mocks.ExpectCall(ptrMock, FunctionsForAttributeUpdatedListener::fCalled);
628
629     server->addAttributeUpdatedListener(KEY,
630         (std::bind(&FunctionsForAttributeUpdatedListener::fCalled, ptrMock, _1, _2)));
631
632     handler(createRequest(OC_REST_PUT, createOCRepresentation()));
633 }
634
635 TEST_F(AttributeUpdatedListenerTest, AddListenerRunsAccordingToLastAddedFunction)
636 {
637     FunctionsForAttributeUpdatedListener *ptrMock =
638         mocks.Mock<FunctionsForAttributeUpdatedListener>();
639
640     string duplicateKEY(KEY);
641     server->setAttribute(KEY, 0);
642
643     mocks.ExpectCall(ptrMock, FunctionsForAttributeUpdatedListener::fCalled);
644     mocks.NeverCall(ptrMock, FunctionsForAttributeUpdatedListener::fNotCalled);
645
646     server->addAttributeUpdatedListener(duplicateKEY,
647         (std::bind(&FunctionsForAttributeUpdatedListener::fNotCalled, ptrMock, _1, _2)));
648     server->addAttributeUpdatedListener(KEY,
649         (std::bind(&FunctionsForAttributeUpdatedListener::fCalled, ptrMock, _1, _2)));
650
651     handler(createRequest(OC_REST_PUT, createOCRepresentation()));
652 }
653
654 TEST_F(AttributeUpdatedListenerTest, RemoveListenerReturnsTrueIfListenerIsNotAdded)
655 {
656     ASSERT_FALSE(server->removeAttributeUpdatedListener(KEY));
657 }
658
659 TEST_F(AttributeUpdatedListenerTest, RemoveListenerReturnsTrueIfListenerIsAdded)
660 {
661     FunctionsForAttributeUpdatedListener *ptrMock =
662         mocks.Mock<FunctionsForAttributeUpdatedListener>();
663
664     server->addAttributeUpdatedListener(KEY,
665         (std::bind(&FunctionsForAttributeUpdatedListener::fNotCalled, ptrMock, _1, _2)));
666
667     ASSERT_TRUE(server->removeAttributeUpdatedListener(KEY));
668 }
669
670 TEST_F(AttributeUpdatedListenerTest, RemoveListenerNeverRunsRemovedFunc)
671 {
672     FunctionsForAttributeUpdatedListener *ptrMock =
673         mocks.Mock<FunctionsForAttributeUpdatedListener>();
674
675     mocks.NeverCall(ptrMock, FunctionsForAttributeUpdatedListener::fNotCalled);
676
677     server->setAttribute(KEY, 0);
678     server->addAttributeUpdatedListener(KEY,
679         (std::bind(&FunctionsForAttributeUpdatedListener::fNotCalled, ptrMock, _1, _2)));
680     server->removeAttributeUpdatedListener(KEY);
681
682     handler(createRequest(OC_REST_PUT, createOCRepresentation()));
683 }
684
685
686