Imported Upstream version 0.9.2
[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(), PlatformException);
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
147 class AutoNotifyTest: public ResourceObjectTest
148 {
149 protected:
150     void initMocks()
151     {
152         mocks.OnCallFuncOverload(static_cast< NotifyAllObservers >(
153                 OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
154     }
155
156     virtual void initResourceObject() {
157         // intended blank
158     }
159 };
160
161 TEST_F(AutoNotifyTest, DefalutAutoNotifyPolicyIsUpdated)
162 {
163     ASSERT_EQ(RCSResourceObject::AutoNotifyPolicy::UPDATED, server->getAutoNotifyPolicy());
164 }
165
166 TEST_F(AutoNotifyTest, AutoNotifyPolicyCanBeSet)
167 {
168     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::NEVER);
169
170     ASSERT_EQ(RCSResourceObject::AutoNotifyPolicy::NEVER, server->getAutoNotifyPolicy());
171 }
172
173 TEST_F(AutoNotifyTest, WithUpdatedPolicy_NeverBeNotifiedIfAttributeIsNotChanged)
174 {
175     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
176     server->setAttribute(KEY, value);
177
178     mocks.NeverCallFuncOverload(static_cast< NotifyAllObservers >(
179             OC::OCPlatform::notifyAllObservers));
180
181     server->setAttribute(KEY, value);
182 }
183
184 TEST_F(AutoNotifyTest, WithUpdatedPolicy_WillBeNotifiedIfAttributeIsChanged)
185 {
186     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
187     server->setAttribute(KEY, value);
188
189     mocks.ExpectCallFuncOverload(static_cast< NotifyAllObservers >(
190             OC::OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
191
192     server->setAttribute(KEY, value + 1);
193 }
194
195 TEST_F(AutoNotifyTest, WithUpdatedPolicy_WillBeNotifiedIfValueIsAdded)
196 {
197     constexpr char newKey[]{ "newKey" };
198     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
199
200     mocks.ExpectCallFuncOverload(static_cast< NotifyAllObservers >(
201             OC::OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
202
203     server->setAttribute(newKey, value);
204 }
205
206 TEST_F(AutoNotifyTest, WithNeverPolicy_NeverBeNotifiedEvenIfAttributeIsChanged)
207 {
208     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::NEVER);
209
210     mocks.NeverCallFuncOverload(static_cast< NotifyAllObservers >(
211             OC::OCPlatform::notifyAllObservers));
212
213     RCSResourceObject::LockGuard lock{ server };
214     server->setAttribute(KEY, value);
215 }
216
217 TEST_F(AutoNotifyTest, WithUpdatePolicy_WillBeNotifiedIfAttributeIsDeleted)
218 {
219     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
220     server->setAttribute(KEY, value);
221
222     mocks.ExpectCallFuncOverload(static_cast< NotifyAllObservers >(
223             OC::OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
224
225     server->removeAttribute(KEY);
226 }
227
228 class AutoNotifyWithGuardTest: public AutoNotifyTest
229 {
230 };
231
232 TEST_F(AutoNotifyWithGuardTest, GuardFollowsServerPolicyByDefault)
233 {
234     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
235
236     mocks.ExpectCallFuncOverload(static_cast< NotifyAllObservers >(
237             OC::OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
238
239     RCSResourceObject::LockGuard guard{ server };
240     server->setAttribute(KEY, value);
241 }
242
243 TEST_F(AutoNotifyWithGuardTest, GuardCanOverridePolicy)
244 {
245     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::ALWAYS);
246
247     mocks.NeverCallFuncOverload(static_cast< NotifyAllObservers >(
248             OC::OCPlatform::notifyAllObservers));
249
250     RCSResourceObject::LockGuard guard{ server, RCSResourceObject::AutoNotifyPolicy::NEVER };
251     server->getAttributes()[KEY] = value;
252 }
253
254 TEST_F(AutoNotifyWithGuardTest, GuardInvokesNotifyWhenDestroyed)
255 {
256     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::NEVER);
257
258     mocks.ExpectCallFuncOverload(static_cast< NotifyAllObservers >(
259             OC::OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
260
261     {
262         RCSResourceObject::LockGuard guard{ server, RCSResourceObject::AutoNotifyPolicy::ALWAYS };
263         server->setAttribute(KEY, value);
264     }
265
266     mocks.NeverCallFuncOverload(static_cast< NotifyAllObservers >(
267                OC::OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
268
269     server->setAttribute(KEY, value);
270 }
271
272
273
274 class ResourceObjectHandlingRequestTest: public ResourceObjectTest
275 {
276 public:
277     EntityHandler handler;
278
279     static constexpr OCRequestHandle fakeRequestHandle =
280             reinterpret_cast<OCRequestHandle>(0x1234);
281     static constexpr OCResourceHandle fakeResourceHandle =
282             reinterpret_cast<OCResourceHandle>(0x4321);
283
284 public:
285     OCResourceRequest::Ptr createRequest(OCMethod method = OC_REST_GET, OCRepresentation ocRep =
286             OCRepresentation{})
287     {
288         auto request = make_shared<OCResourceRequest>();
289
290         OCEntityHandlerRequest ocEntityHandlerRequest { 0 };
291         OC::MessageContainer mc;
292
293         mc.addRepresentation(ocRep);
294
295         ocEntityHandlerRequest.requestHandle = fakeRequestHandle;
296         ocEntityHandlerRequest.resource = fakeResourceHandle;
297         ocEntityHandlerRequest.method = method;
298         ocEntityHandlerRequest.payload = reinterpret_cast<OCPayload*>(mc.getPayload());
299
300         formResourceRequest(OC_REQUEST_FLAG, &ocEntityHandlerRequest, request);
301
302         return request;
303     }
304
305 protected:
306     OCStackResult registerResourceFake(OCResourceHandle&, string&, const string&,
307             const string&, EntityHandler handler, uint8_t)
308     {
309         this->handler = handler;
310         return OC_STACK_OK;
311     }
312
313     void initMocks()
314     {
315         mocks.OnCallFuncOverload(
316             static_cast<registerResource>(OCPlatform::registerResource)).Do(
317                     bind(&ResourceObjectHandlingRequestTest::registerResourceFake,
318                             this, _1, _2, _3, _4, _5, _6));
319         mocks.OnCallFunc(OCPlatform::unregisterResource).Return(OC_STACK_OK);
320     }
321 };
322
323 TEST_F(ResourceObjectHandlingRequestTest, CallSendResponseWhenReceiveRequest)
324 {
325     mocks.ExpectCallFunc(OCPlatform::sendResponse).Return(OC_STACK_OK);
326
327     ASSERT_EQ(OC_EH_OK, handler(createRequest()));
328 }
329
330 TEST_F(ResourceObjectHandlingRequestTest, ReturnErrorCodeWhenSendResponseFailed)
331 {
332     mocks.ExpectCallFunc(OCPlatform::sendResponse).Return(OC_STACK_ERROR);
333
334     ASSERT_EQ(OC_EH_ERROR, handler(createRequest()));
335 }
336
337 TEST_F(ResourceObjectHandlingRequestTest, SendResponseWithSameHandlesPassedByRequest)
338 {
339     mocks.ExpectCallFunc(OCPlatform::sendResponse).Match(
340             [](const shared_ptr<OCResourceResponse> response)
341             {
342                 return response->getRequestHandle() == fakeRequestHandle &&
343                         response->getResourceHandle() == fakeResourceHandle;
344             }
345     ).Return(OC_STACK_OK);
346
347     ASSERT_EQ(OC_EH_OK, handler(createRequest()));
348 }
349
350 TEST_F(ResourceObjectHandlingRequestTest, SendResponseWithRCSResponseResults)
351 {
352     constexpr int errorCode{ 1999 };
353     constexpr OCEntityHandlerResult result{ OC_EH_SLOW };
354
355     server->setGetRequestHandler(
356             [](const RCSRequest&, RCSResourceAttributes&) -> RCSGetResponse
357             {
358                 return RCSGetResponse::create(result, errorCode);
359             }
360     );
361
362     mocks.ExpectCallFunc(OCPlatform::sendResponse).Match(
363             [](const shared_ptr<OCResourceResponse> response)
364             {
365                 return response->getErrorCode() == errorCode &&
366                         response->getResponseResult() == result;
367             }
368     ).Return(OC_STACK_OK);
369
370     ASSERT_EQ(OC_EH_OK, handler(createRequest()));
371 }
372
373 TEST_F(ResourceObjectHandlingRequestTest, SendSetResponseWithCustomAttrsAndResults)
374 {
375     constexpr int errorCode{ 1999 };
376     constexpr OCEntityHandlerResult result{ OC_EH_SLOW };
377     constexpr char value[]{ "value" };
378
379     server->setSetRequestHandler(
380             [](const RCSRequest&, RCSResourceAttributes&) -> RCSSetResponse
381             {
382                 RCSResourceAttributes attrs;
383                 attrs[KEY] = value;
384                 return RCSSetResponse::create(attrs, result, errorCode);
385             }
386     );
387
388     mocks.ExpectCallFunc(OCPlatform::sendResponse).Match(
389             [](const shared_ptr<OCResourceResponse> response)
390             {
391                 return value == response->getResourceRepresentation()[KEY].getValue<std::string>()
392                         && response->getErrorCode() == errorCode
393                         && response->getResponseResult() == result;
394             }
395     ).Return(OC_STACK_OK);
396
397     ASSERT_EQ(OC_EH_OK, handler(createRequest(OC_REST_PUT)));
398 }
399
400
401 class SetRequestHandlerPolicyTest: public ResourceObjectHandlingRequestTest
402 {
403 public:
404     typedef OCStackResult (*SendResponse)(std::shared_ptr<OCResourceResponse>);
405
406 public:
407     OCRepresentation createOCRepresentation()
408     {
409         OCRepresentation ocRep;
410
411         vector<string> interface{"oic.if.baseline"};
412         vector<string> type{"core.light"};
413
414         ocRep.setUri(RESOURCE_URI);
415         ocRep.setResourceInterfaces(interface);
416         ocRep.setResourceTypes(type);
417
418         return ocRep;
419     }
420
421     void initMocks()
422     {
423         ResourceObjectHandlingRequestTest::initMocks();
424         mocks.OnCallFunc(OCPlatform::sendResponse).Return(OC_STACK_OK);
425     }
426 };
427
428 TEST_F(SetRequestHandlerPolicyTest, DefalutSetRequestHandlerPolicyIsNever)
429 {
430     ASSERT_EQ(RCSResourceObject::SetRequestHandlerPolicy::NEVER,
431                 server->getSetRequestHandlerPolicy());
432 }
433
434 TEST_F(SetRequestHandlerPolicyTest, SetRequestHandlerPolicyCanBeSet)
435 {
436     server->setSetRequestHandlerPolicy(RCSResourceObject::SetRequestHandlerPolicy::ACCEPTANCE);
437
438     ASSERT_EQ(RCSResourceObject::SetRequestHandlerPolicy::ACCEPTANCE,
439                 server->getSetRequestHandlerPolicy());
440 }
441
442 TEST_F(SetRequestHandlerPolicyTest, WithNeverPolicy_NotAddedIfReceivedNewKeyValuePair)
443 {
444     OCRepresentation ocRep = createOCRepresentation();
445     ocRep.setValue("NewKey", value);
446     server->setSetRequestHandlerPolicy(RCSResourceObject::SetRequestHandlerPolicy::NEVER);
447
448     handler(createRequest(OC_REST_PUT, ocRep));
449
450     RCSResourceObject::LockGuard guard{ server };
451     ASSERT_FALSE((server->getAttributes()).contains("NewKey"));
452 }
453
454 TEST_F(SetRequestHandlerPolicyTest, WithAcceptancePolicy_WillBeAddedIfReceivedNewKeyValuePair)
455 {
456     OCRepresentation ocRep = createOCRepresentation();
457     ocRep.setValue("NewKey", value);
458     server->setSetRequestHandlerPolicy(RCSResourceObject::SetRequestHandlerPolicy::ACCEPTANCE);
459
460     handler(createRequest(OC_REST_PUT, ocRep));
461
462     RCSResourceObject::LockGuard guard{ server };
463     ASSERT_TRUE((server->getAttributes()).contains("NewKey"));
464 }
465
466
467 class ResourceObjectSynchronizationTest: public ResourceObjectHandlingRequestTest
468 {
469 public:
470
471     static void withLock(RCSResourceObject::Ptr serverResource, int count)
472     {
473         for (int i=0; i<count; ++i)
474         {
475             RCSResourceObject::LockGuard lock{ serverResource };
476
477             auto& attrs = serverResource->getAttributes();
478
479             attrs[KEY] = attrs[KEY].get<int>() + 1;
480         }
481     }
482
483     static void withSetter(RCSResourceObject::Ptr serverResource, int count)
484     {
485         for (int i=0; i<count; ++i)
486         {
487             RCSResourceObject::LockGuard lock{ serverResource };
488
489             serverResource->setAttribute(KEY, serverResource->getAttribute<int>(KEY) + 1);
490         }
491     }
492 };
493
494 TEST_F(ResourceObjectSynchronizationTest, MultipleAccessToServerResource)
495 {
496     int expected { 0 };
497     vector<thread> threads;
498
499     server->setAttribute(KEY, 0);
500
501     for (int i = 20; i >= 0; --i) {
502         int count = 5000 + i * 100;
503         threads.push_back(thread { withLock, server, count });
504         expected += count;
505     }
506
507     for (int i = 20; i >= 0; --i) {
508         int count = 5000 + i * 100;
509         threads.push_back(thread { withSetter, server, count });
510         expected +=count;
511     }
512
513     for (auto& t : threads)
514     {
515         t.join();
516     }
517
518     ASSERT_EQ(expected, server->getAttribute<int>(KEY));
519 }
520
521 TEST_F(ResourceObjectSynchronizationTest, MultipleAccessToServerResourceWithRequests)
522 {
523     int expected { 0 };
524     vector<thread> threads;
525
526     mocks.OnCallFunc(OCPlatform::sendResponse).Return(OC_STACK_OK);
527
528     server->setAttribute(KEY, 0);
529
530     for (int i = 20; i >= 0; --i) {
531         int count = 5000 + i * 100;
532         threads.push_back(thread{ withLock, server, count });
533         expected += count;
534     }
535
536     for (int i = 20; i >= 0; --i) {
537         int count = 5000 + i * 100;
538         threads.push_back(thread{ withSetter, server, count });
539         expected +=count;
540     }
541
542     threads.push_back(thread{
543         [this]()
544         {
545             for (int i=0; i<10000; ++i)
546             {
547                 if (i % 5 == 0) handler(createRequest(OC_REST_OBSERVE));
548                 handler(createRequest((i & 1) ? OC_REST_GET : OC_REST_PUT));
549             }
550         }
551     });
552
553     for (auto& t : threads)
554     {
555         t.join();
556     }
557
558     ASSERT_EQ(expected, server->getAttribute<int>(KEY));
559 }
560
561
562 class AttributeUpdatedListenerTest: public ResourceObjectHandlingRequestTest
563 {
564 public:
565     typedef OCStackResult (*SendResponse)(std::shared_ptr<OCResourceResponse>);
566
567 public:
568     OCRepresentation createOCRepresentation(void)
569     {
570         OCRepresentation ocRep;
571
572         vector<string> interface{"oic.if.baseline"};
573         vector<string> type{"core.light"};
574
575         ocRep.setUri(RESOURCE_URI);
576         ocRep.setResourceInterfaces(interface);
577         ocRep.setResourceTypes(type);
578         ocRep[KEY] = value;
579
580         return ocRep;
581     }
582
583     void initMocks()
584     {
585         ResourceObjectHandlingRequestTest::initMocks();
586         mocks.OnCallFunc(OCPlatform::sendResponse).Return(OC_STACK_OK);
587     }
588 };
589
590 class FunctionsForAttributeUpdatedListener
591 {
592 public:
593     virtual void fCalled(const OIC::Service::RCSResourceAttributes::Value&,
594         const OIC::Service::RCSResourceAttributes::Value&)=0;
595     virtual void fNotCalled(const OIC::Service::RCSResourceAttributes::Value&,
596         const OIC::Service::RCSResourceAttributes::Value&)=0;
597 };
598
599 TEST_F(AttributeUpdatedListenerTest, AddListenerRunsAddedFunction)
600 {
601     FunctionsForAttributeUpdatedListener *ptrMock =
602         mocks.Mock<FunctionsForAttributeUpdatedListener>();
603
604     server->setAttribute(KEY, 0);
605
606     mocks.ExpectCall(ptrMock, FunctionsForAttributeUpdatedListener::fCalled);
607
608     server->addAttributeUpdatedListener(KEY,
609         (std::bind(&FunctionsForAttributeUpdatedListener::fCalled, ptrMock, _1, _2)));
610
611     handler(createRequest(OC_REST_PUT, createOCRepresentation()));
612 }
613
614 TEST_F(AttributeUpdatedListenerTest, AddListenerRunsAccordingToLastAddedFunction)
615 {
616     FunctionsForAttributeUpdatedListener *ptrMock =
617         mocks.Mock<FunctionsForAttributeUpdatedListener>();
618
619     string duplicateKEY(KEY);
620     server->setAttribute(KEY, 0);
621
622     mocks.ExpectCall(ptrMock, FunctionsForAttributeUpdatedListener::fCalled);
623     mocks.NeverCall(ptrMock, FunctionsForAttributeUpdatedListener::fNotCalled);
624
625     server->addAttributeUpdatedListener(duplicateKEY,
626         (std::bind(&FunctionsForAttributeUpdatedListener::fNotCalled, ptrMock, _1, _2)));
627     server->addAttributeUpdatedListener(KEY,
628         (std::bind(&FunctionsForAttributeUpdatedListener::fCalled, ptrMock, _1, _2)));
629
630     handler(createRequest(OC_REST_PUT, createOCRepresentation()));
631 }
632
633 TEST_F(AttributeUpdatedListenerTest, RemoveListenerReturnsTrueIfListenerIsNotAdded)
634 {
635     ASSERT_FALSE(server->removeAttributeUpdatedListener(KEY));
636 }
637
638 TEST_F(AttributeUpdatedListenerTest, RemoveListenerReturnsTrueIfListenerIsAdded)
639 {
640     FunctionsForAttributeUpdatedListener *ptrMock =
641         mocks.Mock<FunctionsForAttributeUpdatedListener>();
642
643     server->addAttributeUpdatedListener(KEY,
644         (std::bind(&FunctionsForAttributeUpdatedListener::fNotCalled, ptrMock, _1, _2)));
645
646     ASSERT_TRUE(server->removeAttributeUpdatedListener(KEY));
647 }
648
649 TEST_F(AttributeUpdatedListenerTest, RemoveListenerNeverRunsRemovedFunc)
650 {
651     FunctionsForAttributeUpdatedListener *ptrMock =
652         mocks.Mock<FunctionsForAttributeUpdatedListener>();
653
654     mocks.NeverCall(ptrMock, FunctionsForAttributeUpdatedListener::fNotCalled);
655
656     server->setAttribute(KEY, 0);
657     server->addAttributeUpdatedListener(KEY,
658         (std::bind(&FunctionsForAttributeUpdatedListener::fNotCalled, ptrMock, _1, _2)));
659     server->removeAttributeUpdatedListener(KEY);
660
661     handler(createRequest(OC_REST_PUT, createOCRepresentation()));
662 }
663
664
665