Imported Upstream version 1.1.0
[platform/upstream/iotivity.git] / service / resource-encapsulation / src / serverBuilder / unittests / RCSResourceObjectTest.cpp
index ba441fd..d942636 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-#include <UnitTestHelper.h>
+#include "UnitTestHelper.h"
 
-#include <RCSResourceObject.h>
+#include "RCSResourceObject.h"
+#include "RCSRequest.h"
+#include "RCSSeparateResponse.h"
+#include "InterfaceHandler.h"
+#include "ResourceAttributesConverter.h"
 
-#include <OCPlatform.h>
+#include "OCPlatform.h"
 
 using namespace std;
 using namespace std::placeholders;
@@ -38,7 +42,8 @@ typedef OCStackResult (*NotifyAllObservers)(OCResourceHandle);
 constexpr char RESOURCE_URI[]{ "a/test" };
 constexpr char RESOURCE_TYPE[]{ "resourcetype" };
 constexpr char KEY[]{ "key" };
-constexpr int value{ 100 };
+constexpr char CUSTOM_INTERFACE[]{ "oic.if.custom" };
+constexpr int VALUE{ 100 };
 
 TEST(ResourceObjectBuilderCreateTest, ThrowIfUriIsInvalid)
 {
@@ -86,6 +91,39 @@ TEST_F(ResourceObjectBuilderTest, ResourceServerHasAttrsSetByBuilder)
     EXPECT_EQ(attrs, serverResource->getAttributes());
 }
 
+TEST_F(ResourceObjectBuilderTest, TypesAddedInBuilderWillBeBound)
+{
+    int count = 0;
+    mocks.OnCallFunc(OCPlatform::bindTypeToResource).Do(
+            [&count](const OCResourceHandle&, const std::string&)
+            {
+                ++count;
+                return OC_STACK_OK;
+            }
+    );
+
+    auto serverResource = RCSResourceObject::Builder(RESOURCE_URI, RESOURCE_TYPE, "").
+            addType("1").addType("2").build();
+
+    EXPECT_EQ(2, count);
+}
+
+TEST_F(ResourceObjectBuilderTest, InterfaceAddedInBuilderWillBeBound)
+{
+    int count = 0;
+    mocks.OnCallFunc(OCPlatform::bindInterfaceToResource).Do(
+            [&count](const OCResourceHandle&, const std::string&)
+            {
+                ++count;
+                return OC_STACK_OK;
+            }
+    );
+
+    auto serverResource = RCSResourceObject::Builder(RESOURCE_URI, RESOURCE_TYPE, "").
+            addInterface("1").addInterface("2").build();
+
+    EXPECT_EQ(2, count);
+}
 
 class ResourceObjectTest: public TestWithMock
 {
@@ -122,10 +160,10 @@ TEST_F(ResourceObjectTest, AccessAttributesWithLock)
     {
         RCSResourceObject::LockGuard lock{ server };
         auto& attr = server->getAttributes();
-        attr[KEY] = value;
+        attr[KEY] = VALUE;
     }
 
-    ASSERT_EQ(value, server->getAttribute<int>(KEY));
+    ASSERT_EQ(VALUE, server->getAttribute<int>(KEY));
 }
 
 TEST_F(ResourceObjectTest, ThrowIfTryToAccessAttributesWithoutGuard)
@@ -137,10 +175,10 @@ TEST_F(ResourceObjectTest, SettingAttributesWithinGuardDoesntCauseDeadLock)
 {
     {
         RCSResourceObject::LockGuard guard{ server };
-        server->setAttribute(KEY, value);
+        server->setAttribute(KEY, VALUE);
     }
 
-    ASSERT_EQ(value, server->getAttribute<int>(KEY));
+    ASSERT_EQ(VALUE, server->getAttribute<int>(KEY));
 }
 
 TEST_F(ResourceObjectTest, SettingNestedAttributesIsSameToGettingNestedAttributes)
@@ -164,7 +202,35 @@ TEST_F(ResourceObjectTest, SettingNestedVectorAttributesIsSameToGettingNestedVec
 
     server->setAttribute(KEY, arr31);
 
-    ASSERT_EQ(arr31, server->getAttribute<vector<vector<vector<int>>>>(KEY));
+    ASSERT_EQ(arr31, server->getAttributeValue(KEY));
+}
+
+TEST_F(ResourceObjectTest, ThrowIfResourceToBindIsInvalid)
+{
+    ASSERT_THROW(server->bindResource(server), RCSInvalidParameterException);
+}
+
+TEST_F(ResourceObjectTest, ThrowIfBindResourceFailed)
+{
+    mocks.OnCallFunc(OCBindResource).Return(OC_STACK_ERROR);
+
+    ASSERT_THROW(server->bindResource(
+            RCSResourceObject::Builder("a/temp", RESOURCE_TYPE, "").build()), RCSPlatformException);
+}
+
+TEST_F(ResourceObjectTest, ThrowIfResourceToUnbindIsInvalid)
+{
+    ASSERT_THROW(server->unbindResource(server), RCSInvalidParameterException);
+}
+
+TEST_F(ResourceObjectTest, BoundResourceCanBeRetrieved)
+{
+    mocks.OnCallFunc(OCBindResource).Return(OC_STACK_OK);
+
+    auto boundResource = RCSResourceObject::Builder("a/temp", RESOURCE_TYPE, "").build();
+    server->bindResource(boundResource);
+
+    ASSERT_EQ(boundResource, server->getBoundResources()[0]);
 }
 
 
@@ -197,23 +263,23 @@ TEST_F(AutoNotifyTest, AutoNotifyPolicyCanBeSet)
 TEST_F(AutoNotifyTest, WithUpdatedPolicy_NeverBeNotifiedIfAttributeIsNotChanged)
 {
     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
-    server->setAttribute(KEY, value);
+    server->setAttribute(KEY, VALUE);
 
     mocks.NeverCallFuncOverload(static_cast< NotifyAllObservers >(
             OC::OCPlatform::notifyAllObservers));
 
-    server->setAttribute(KEY, value);
+    server->setAttribute(KEY, VALUE);
 }
 
 TEST_F(AutoNotifyTest, WithUpdatedPolicy_WillBeNotifiedIfAttributeIsChanged)
 {
     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
-    server->setAttribute(KEY, value);
+    server->setAttribute(KEY, VALUE);
 
     mocks.ExpectCallFuncOverload(static_cast< NotifyAllObservers >(
             OC::OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
 
-    server->setAttribute(KEY, value + 1);
+    server->setAttribute(KEY, VALUE + 1);
 }
 
 TEST_F(AutoNotifyTest, WithUpdatedPolicy_WillBeNotifiedIfValueIsAdded)
@@ -224,7 +290,7 @@ TEST_F(AutoNotifyTest, WithUpdatedPolicy_WillBeNotifiedIfValueIsAdded)
     mocks.ExpectCallFuncOverload(static_cast< NotifyAllObservers >(
             OC::OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
 
-    server->setAttribute(newKey, value);
+    server->setAttribute(newKey, VALUE);
 }
 
 TEST_F(AutoNotifyTest, WithNeverPolicy_NeverBeNotifiedEvenIfAttributeIsChanged)
@@ -235,13 +301,13 @@ TEST_F(AutoNotifyTest, WithNeverPolicy_NeverBeNotifiedEvenIfAttributeIsChanged)
             OC::OCPlatform::notifyAllObservers));
 
     RCSResourceObject::LockGuard lock{ server };
-    server->setAttribute(KEY, value);
+    server->setAttribute(KEY, VALUE);
 }
 
 TEST_F(AutoNotifyTest, WithUpdatePolicy_WillBeNotifiedIfAttributeIsDeleted)
 {
     server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
-    server->setAttribute(KEY, value);
+    server->setAttribute(KEY, VALUE);
 
     mocks.ExpectCallFuncOverload(static_cast< NotifyAllObservers >(
             OC::OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
@@ -261,7 +327,7 @@ TEST_F(AutoNotifyWithGuardTest, GuardFollowsServerPolicyByDefault)
             OC::OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
 
     RCSResourceObject::LockGuard guard{ server };
-    server->setAttribute(KEY, value);
+    server->setAttribute(KEY, VALUE);
 }
 
 TEST_F(AutoNotifyWithGuardTest, GuardCanOverridePolicy)
@@ -272,7 +338,7 @@ TEST_F(AutoNotifyWithGuardTest, GuardCanOverridePolicy)
             OC::OCPlatform::notifyAllObservers));
 
     RCSResourceObject::LockGuard guard{ server, RCSResourceObject::AutoNotifyPolicy::NEVER };
-    server->getAttributes()[KEY] = value;
+    server->getAttributes()[KEY] = VALUE;
 }
 
 TEST_F(AutoNotifyWithGuardTest, GuardInvokesNotifyWhenDestroyed)
@@ -284,17 +350,15 @@ TEST_F(AutoNotifyWithGuardTest, GuardInvokesNotifyWhenDestroyed)
 
     {
         RCSResourceObject::LockGuard guard{ server, RCSResourceObject::AutoNotifyPolicy::ALWAYS };
-        server->setAttribute(KEY, value);
+        server->setAttribute(KEY, VALUE);
     }
 
     mocks.NeverCallFuncOverload(static_cast< NotifyAllObservers >(
                OC::OCPlatform::notifyAllObservers)).Return(OC_STACK_OK);
 
-    server->setAttribute(KEY, value);
+    server->setAttribute(KEY, VALUE);
 }
 
-
-
 class ResourceObjectHandlingRequestTest: public ResourceObjectTest
 {
 public:
@@ -307,7 +371,7 @@ public:
 
 public:
     OCResourceRequest::Ptr createRequest(OCMethod method = OC_REST_GET, OCRepresentation ocRep =
-            OCRepresentation{})
+            OCRepresentation{}, const string& interface="")
     {
         auto request = make_shared<OCResourceRequest>();
 
@@ -322,6 +386,12 @@ public:
         ocEntityHandlerRequest.method = method;
         ocEntityHandlerRequest.payload = reinterpret_cast<OCPayload*>(mc.getPayload());
 
+        if(!interface.empty())
+        {
+            const string query = string("if=" + interface);
+            ocEntityHandlerRequest.query = const_cast<char *> (query.c_str());
+        }
+
         formResourceRequest(OC_REQUEST_FLAG, &ocEntityHandlerRequest, request);
 
         return request;
@@ -396,7 +466,7 @@ TEST_F(ResourceObjectHandlingRequestTest, SendResponseWithRCSResponseResults)
 TEST_F(ResourceObjectHandlingRequestTest, SendSetResponseWithCustomAttrs)
 {
     constexpr int errorCode{ 1999 };
-    constexpr char value[]{ "value" };
+    constexpr char value[]{ "VALUE" };
 
     server->setSetRequestHandler(
             [](const RCSRequest&, RCSResourceAttributes&) -> RCSSetResponse
@@ -415,9 +485,225 @@ TEST_F(ResourceObjectHandlingRequestTest, SendSetResponseWithCustomAttrs)
             }
     ).Return(OC_STACK_OK);
 
-    ASSERT_EQ(OC_EH_OK, handler(createRequest(OC_REST_PUT)));
+    ASSERT_EQ(OC_EH_OK, handler(createRequest(OC_REST_POST)));
 }
 
+TEST_F(ResourceObjectHandlingRequestTest, SeparateResponseIsSlowResponse)
+{
+    server->setGetRequestHandler(
+            [](const RCSRequest&, RCSResourceAttributes&) -> RCSGetResponse
+            {
+                return RCSGetResponse::separate();
+            }
+    );
+
+    ASSERT_EQ(OC_EH_SLOW, handler(createRequest()));
+}
+
+TEST_F(ResourceObjectHandlingRequestTest, SetMethodOfSeparateResponseInvokesSendResponse)
+{
+    RCSRequest aRequest;
+    server->setGetRequestHandler(
+            [&aRequest](const RCSRequest& request, RCSResourceAttributes&) -> RCSGetResponse
+            {
+                aRequest = request;
+                return RCSGetResponse::separate();
+            }
+    );
+    handler(createRequest(OC_REST_GET));
+
+    mocks.ExpectCallFunc(OCPlatform::sendResponse).Return(OC_STACK_OK);
+
+    RCSSeparateResponse(aRequest).set();
+}
+
+TEST_F(ResourceObjectHandlingRequestTest, SetMethodOfSeparateResponseThrowsIfTheResourceIsDestroyed)
+{
+    RCSRequest aRequest;
+    server->setGetRequestHandler(
+            [&aRequest](const RCSRequest& request, RCSResourceAttributes&) -> RCSGetResponse
+            {
+                aRequest = request;
+                return RCSGetResponse::separate();
+            }
+    );
+    handler(createRequest(OC_REST_GET));
+
+    RCSSeparateResponse resp(aRequest);
+
+    server.reset();
+
+    EXPECT_THROW(resp.set(), RCSBadRequestException);
+}
+
+static bool checkResponse(const OCRepresentation& ocRep, const RCSResourceAttributes& rcsAttr,
+            const std::vector<std::string>& interfaces,
+            const std::vector<std::string>& resourceTypes, const std::string& resourceUri)
+{
+    return resourceUri == ocRep.getUri() &&
+           interfaces == ocRep.getResourceInterfaces() &&
+           resourceTypes == ocRep.getResourceTypes() &&
+           rcsAttr == ResourceAttributesConverter::fromOCRepresentation(ocRep);
+}
+
+static bool compareResponse(const OCRepresentation& ocRep1, const OCRepresentation& ocRep2)
+{
+    return ocRep1.getUri() == ocRep2.getUri() &&
+           ocRep1.getResourceInterfaces() == ocRep2.getResourceInterfaces() &&
+           ocRep1.getResourceTypes() == ocRep2.getResourceTypes() &&
+           ResourceAttributesConverter::fromOCRepresentation(ocRep1) ==
+                   ResourceAttributesConverter::fromOCRepresentation(ocRep2);
+}
+
+class ResourceObjectInterfaceHandlerTest: public ResourceObjectHandlingRequestTest
+{
+public:
+    void initServer(vector<string> interfaces,
+                const std::string& defaultInterface = BASELINE_INTERFACE)
+    {
+        auto initBuilder = RCSResourceObject::Builder(RESOURCE_URI, RESOURCE_TYPE,
+                BASELINE_INTERFACE);
+
+        for(const auto& itf : interfaces)
+        {
+            initBuilder.addInterface(itf);
+        }
+
+        RCSResourceAttributes rcsAttr;
+        rcsAttr[KEY] = 2;
+        initBuilder.setAttributes(rcsAttr);
+        initBuilder.setDefaultInterface(defaultInterface);
+
+        server = initBuilder.build();
+        server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::NEVER);
+        server->setSetRequestHandlerPolicy(RCSResourceObject::SetRequestHandlerPolicy::ACCEPTANCE);
+    }
+
+protected:
+
+    void SetUp()
+    {
+        TestWithMock::SetUp();
+
+        initMocks();
+    }
+
+    void initMocks()
+    {
+        ResourceObjectHandlingRequestTest::initMocks();
+
+        mocks.OnCallFunc(OCPlatform::bindInterfaceToResource).Return(OC_STACK_OK);
+    }
+};
+
+TEST_F(ResourceObjectInterfaceHandlerTest, GetResponseForBaselineContainsAllPropertiesOfServer)
+{
+    initServer({BASELINE_INTERFACE});
+
+    OCRepresentation ocRep;
+
+    mocks.ExpectCallFunc(OCPlatform::sendResponse).Match(
+            [=](const shared_ptr<OCResourceResponse> response)
+            {
+                RCSResourceObject::LockGuard guard{ server };
+
+                return checkResponse(response->getResourceRepresentation(),
+                        server->getAttributes(), server->getInterfaces(), server->getTypes(),
+                        server->getUri());
+
+            }
+    ).Return(OC_STACK_OK);
+
+    handler(createRequest(OC_REST_GET, ocRep, BASELINE_INTERFACE));
+}
+
+TEST_F(ResourceObjectInterfaceHandlerTest, SetResponseForActuatorContainsOnlyRequestedAttributes)
+{
+    initServer({ACTUATOR_INTERFACE});
+
+    OCRepresentation ocRep;
+    ocRep[KEY] = VALUE;
+
+    mocks.ExpectCallFunc(OCPlatform::sendResponse).Match(
+            [&ocRep](const shared_ptr<OCResourceResponse> response)
+            {
+                return checkResponse(response->getResourceRepresentation(),
+                        ResourceAttributesConverter::fromOCRepresentation(ocRep), {}, {}, "");
+            }
+    ).Return(OC_STACK_OK);
+
+    handler(createRequest(OC_REST_POST, ocRep, ACTUATOR_INTERFACE));
+}
+
+TEST_F(ResourceObjectInterfaceHandlerTest, SetResponseForBaselineContainsAppliedAttributes)
+{
+    initServer({BASELINE_INTERFACE});
+
+    OCRepresentation ocRep;
+    ocRep["NEWKEY"] = std::string("NEWVALUE");
+
+    mocks.ExpectCallFunc(OCPlatform::sendResponse).Match(
+            [=](const shared_ptr<OCResourceResponse> response)
+            {
+                RCSResourceObject::LockGuard guard{ server };
+
+                return checkResponse(response->getResourceRepresentation(),
+                        server->getAttributes(), server->getInterfaces(), server->getTypes(),
+                        server->getUri());
+            }
+    ).Return(OC_STACK_OK);
+
+    handler(createRequest(OC_REST_POST, ocRep, BASELINE_INTERFACE));
+}
+
+TEST_F(ResourceObjectInterfaceHandlerTest, GetResponseForCustomEqualsResponseForDefault)
+{
+    initServer({CUSTOM_INTERFACE});
+
+    OCRepresentation ocRep;
+    OCRepresentation repArray[2];
+    int cnt = 0;
+
+    mocks.OnCallFunc(OCPlatform::sendResponse).Do(
+            [&repArray, &cnt](const shared_ptr<OCResourceResponse> response)
+            {
+                repArray[cnt++] = response->getResourceRepresentation();
+                return OC_STACK_OK;
+            }
+    );
+
+    handler(createRequest(OC_REST_GET, ocRep, CUSTOM_INTERFACE));
+    handler(createRequest(OC_REST_GET, ocRep, server->getDefaultInterface()));
+
+    EXPECT_EQ(cnt, 2);
+    EXPECT_TRUE(compareResponse(repArray[0], repArray[1]));
+}
+
+TEST_F(ResourceObjectInterfaceHandlerTest, SetRequestForSensorGotNoHandler)
+{
+    initServer({SENSOR_INTERFACE});
+
+    OCRepresentation ocRep;
+    ocRep[KEY] = VALUE;
+
+    EXPECT_EQ(OC_EH_ERROR, handler(createRequest(OC_REST_POST, ocRep, SENSOR_INTERFACE)));
+}
+
+TEST_F(ResourceObjectInterfaceHandlerTest, ThrowIfDefaultInterfaceIsInvalid)
+{
+    auto builder = RCSResourceObject::Builder(RESOURCE_URI, RESOURCE_TYPE, BASELINE_INTERFACE);
+
+    ASSERT_THROW(builder.setDefaultInterface(ACTUATOR_INTERFACE), RCSBadRequestException);
+}
+
+TEST_F(ResourceObjectInterfaceHandlerTest, SettingDefaultInterfaceEqualsGetDefaultInterface)
+{
+    initServer({SENSOR_INTERFACE}, BASELINE_INTERFACE);
+
+    EXPECT_EQ(BASELINE_INTERFACE, server->getDefaultInterface());
+}
+
+
 
 class SetRequestHandlerPolicyTest: public ResourceObjectHandlingRequestTest
 {
@@ -428,14 +714,7 @@ public:
     OCRepresentation createOCRepresentation()
     {
         OCRepresentation ocRep;
-
-        vector<string> interface{"oic.if.baseline"};
-        vector<string> type{"core.light"};
-
-        ocRep.setUri(RESOURCE_URI);
-        ocRep.setResourceInterfaces(interface);
-        ocRep.setResourceTypes(type);
-
+        ocRep[KEY] = VALUE;
         return ocRep;
     }
 
@@ -460,31 +739,28 @@ TEST_F(SetRequestHandlerPolicyTest, SetRequestHandlerPolicyCanBeSet)
                 server->getSetRequestHandlerPolicy());
 }
 
-TEST_F(SetRequestHandlerPolicyTest, WithNeverPolicy_NotAddedIfReceivedNewKeyValuePair)
+TEST_F(SetRequestHandlerPolicyTest, WithNeverPolicy_DeniedIfKeyIsNew)
 {
-    OCRepresentation ocRep = createOCRepresentation();
-    ocRep.setValue("NewKey", value);
     server->setSetRequestHandlerPolicy(RCSResourceObject::SetRequestHandlerPolicy::NEVER);
 
-    handler(createRequest(OC_REST_PUT, ocRep));
+    handler(createRequest(OC_REST_POST, createOCRepresentation()));
 
     RCSResourceObject::LockGuard guard{ server };
-    ASSERT_FALSE((server->getAttributes()).contains("NewKey"));
+    ASSERT_FALSE(server->getAttributes().contains(KEY));
 }
 
-TEST_F(SetRequestHandlerPolicyTest, WithAcceptancePolicy_WillBeAddedIfReceivedNewKeyValuePair)
+TEST_F(SetRequestHandlerPolicyTest, WithAcceptancePolicy_AcceptedEvenIfKeyIsNew)
 {
-    OCRepresentation ocRep = createOCRepresentation();
-    ocRep.setValue("NewKey", value);
     server->setSetRequestHandlerPolicy(RCSResourceObject::SetRequestHandlerPolicy::ACCEPTANCE);
 
-    handler(createRequest(OC_REST_PUT, ocRep));
+    handler(createRequest(OC_REST_POST, createOCRepresentation()));
 
     RCSResourceObject::LockGuard guard{ server };
-    ASSERT_TRUE((server->getAttributes()).contains("NewKey"));
+    ASSERT_TRUE(server->getAttributes().contains(KEY));
 }
 
 
+
 class ResourceObjectSynchronizationTest: public ResourceObjectHandlingRequestTest
 {
 public:
@@ -566,7 +842,7 @@ TEST_F(ResourceObjectSynchronizationTest, MultipleAccessToServerResourceWithRequ
             for (int i=0; i<10000; ++i)
             {
                 if (i % 5 == 0) handler(createRequest(OC_REST_OBSERVE));
-                handler(createRequest((i & 1) ? OC_REST_GET : OC_REST_PUT));
+                handler(createRequest((i & 1) ? OC_REST_GET : OC_REST_POST));
             }
         }
     });
@@ -580,6 +856,7 @@ TEST_F(ResourceObjectSynchronizationTest, MultipleAccessToServerResourceWithRequ
 }
 
 
+
 class AttributeUpdatedListenerTest: public ResourceObjectHandlingRequestTest
 {
 public:
@@ -589,98 +866,82 @@ public:
     OCRepresentation createOCRepresentation(void)
     {
         OCRepresentation ocRep;
-
-        vector<string> interface{"oic.if.baseline"};
-        vector<string> type{"core.light"};
-
-        ocRep.setUri(RESOURCE_URI);
-        ocRep.setResourceInterfaces(interface);
-        ocRep.setResourceTypes(type);
-        ocRep[KEY] = value;
-
+        ocRep[KEY] = VALUE;
         return ocRep;
     }
 
-    void initMocks()
+protected:
+    void SetUp()
     {
-        ResourceObjectHandlingRequestTest::initMocks();
+        ResourceObjectHandlingRequestTest::SetUp();
         mocks.OnCallFunc(OCPlatform::sendResponse).Return(OC_STACK_OK);
+
+        server->setAttribute(KEY, 0);
     }
 };
 
-class FunctionsForAttributeUpdatedListener
+class AttributeUpdatedListener
 {
 public:
-    virtual void fCalled(const OIC::Service::RCSResourceAttributes::Value&,
-        const OIC::Service::RCSResourceAttributes::Value&)=0;
-    virtual void fNotCalled(const OIC::Service::RCSResourceAttributes::Value&,
+    virtual void onUpdated(const OIC::Service::RCSResourceAttributes::Value&,
         const OIC::Service::RCSResourceAttributes::Value&)=0;
+
+    virtual ~AttributeUpdatedListener() {}
 };
 
-TEST_F(AttributeUpdatedListenerTest, AddListenerRunsAddedFunction)
-{
-    FunctionsForAttributeUpdatedListener *ptrMock =
-        mocks.Mock<FunctionsForAttributeUpdatedListener>();
 
-    server->setAttribute(KEY, 0);
+TEST_F(AttributeUpdatedListenerTest, RemoveListenerReturnsFalseIfListenerIsNotAdded)
+{
+    ASSERT_FALSE(server->removeAttributeUpdatedListener(KEY));
+}
 
-    mocks.ExpectCall(ptrMock, FunctionsForAttributeUpdatedListener::fCalled);
+TEST_F(AttributeUpdatedListenerTest, RemoveListenerReturnsTrueIfListenerIsAdded)
+{
+    auto listener = mocks.Mock< AttributeUpdatedListener >();
 
     server->addAttributeUpdatedListener(KEY,
-        (std::bind(&FunctionsForAttributeUpdatedListener::fCalled, ptrMock, _1, _2)));
+            std::bind(&AttributeUpdatedListener::onUpdated, listener, _1, _2));
 
-    handler(createRequest(OC_REST_PUT, createOCRepresentation()));
+    ASSERT_TRUE(server->removeAttributeUpdatedListener(KEY));
 }
 
-TEST_F(AttributeUpdatedListenerTest, AddListenerRunsAccordingToLastAddedFunction)
+TEST_F(AttributeUpdatedListenerTest, AddListenerRunsAddedFunction)
 {
-    FunctionsForAttributeUpdatedListener *ptrMock =
-        mocks.Mock<FunctionsForAttributeUpdatedListener>();
-
-    string duplicateKEY(KEY);
-    server->setAttribute(KEY, 0);
-
-    mocks.ExpectCall(ptrMock, FunctionsForAttributeUpdatedListener::fCalled);
-    mocks.NeverCall(ptrMock, FunctionsForAttributeUpdatedListener::fNotCalled);
+    auto listener = mocks.Mock< AttributeUpdatedListener >();
 
-    server->addAttributeUpdatedListener(duplicateKEY,
-        (std::bind(&FunctionsForAttributeUpdatedListener::fNotCalled, ptrMock, _1, _2)));
     server->addAttributeUpdatedListener(KEY,
-        (std::bind(&FunctionsForAttributeUpdatedListener::fCalled, ptrMock, _1, _2)));
+            std::bind(&AttributeUpdatedListener::onUpdated, listener, _1, _2));
 
-    handler(createRequest(OC_REST_PUT, createOCRepresentation()));
-}
+    mocks.ExpectCall(listener, AttributeUpdatedListener::onUpdated);
 
-TEST_F(AttributeUpdatedListenerTest, RemoveListenerReturnsTrueIfListenerIsNotAdded)
-{
-    ASSERT_FALSE(server->removeAttributeUpdatedListener(KEY));
+    handler(createRequest(OC_REST_POST, createOCRepresentation()));
 }
 
-TEST_F(AttributeUpdatedListenerTest, RemoveListenerReturnsTrueIfListenerIsAdded)
+TEST_F(AttributeUpdatedListenerTest, ListenerWithSameKeyOverridesPreviousOne)
 {
-    FunctionsForAttributeUpdatedListener *ptrMock =
-        mocks.Mock<FunctionsForAttributeUpdatedListener>();
+    auto first = mocks.Mock< AttributeUpdatedListener >();
+    auto second = mocks.Mock< AttributeUpdatedListener >();
 
+    mocks.NeverCall(first, AttributeUpdatedListener::onUpdated);
+    mocks.ExpectCall(second, AttributeUpdatedListener::onUpdated);
+
+    server->addAttributeUpdatedListener(KEY,
+            std::bind(&AttributeUpdatedListener::onUpdated, first, _1, _2));
     server->addAttributeUpdatedListener(KEY,
-        (std::bind(&FunctionsForAttributeUpdatedListener::fNotCalled, ptrMock, _1, _2)));
+            std::bind(&AttributeUpdatedListener::onUpdated, second, _1, _2));
 
-    ASSERT_TRUE(server->removeAttributeUpdatedListener(KEY));
+    handler(createRequest(OC_REST_POST, createOCRepresentation()));
 }
 
-TEST_F(AttributeUpdatedListenerTest, RemoveListenerNeverRunsRemovedFunc)
+TEST_F(AttributeUpdatedListenerTest, RemovedListenerNotBeInvoked)
 {
-    FunctionsForAttributeUpdatedListener *ptrMock =
-        mocks.Mock<FunctionsForAttributeUpdatedListener>();
+    auto listener = mocks.Mock< AttributeUpdatedListener >();
+    server->addAttributeUpdatedListener(KEY,
+            std::bind(&AttributeUpdatedListener::onUpdated, listener, _1, _2));
 
-    mocks.NeverCall(ptrMock, FunctionsForAttributeUpdatedListener::fNotCalled);
+    mocks.NeverCall(listener, AttributeUpdatedListener::onUpdated);
 
-    server->setAttribute(KEY, 0);
-    server->addAttributeUpdatedListener(KEY,
-        (std::bind(&FunctionsForAttributeUpdatedListener::fNotCalled, ptrMock, _1, _2)));
     server->removeAttributeUpdatedListener(KEY);
 
-    handler(createRequest(OC_REST_PUT, createOCRepresentation()));
+    handler(createRequest(OC_REST_POST, createOCRepresentation()));
 }
-
-
-