Modify Notification Manager for updating resource encapsulation
authorYounghyun Joo <yh_.joo@samsung.com>
Sat, 19 Sep 2015 06:26:32 +0000 (15:26 +0900)
committerMadan Lanka <lanka.madan@samsung.com>
Sat, 19 Sep 2015 07:24:47 +0000 (07:24 +0000)
- Modify Notification Manager files
- Add UnitTest codes

Change-Id: I7b3ac0931a77935fc26a9c060a96200f13de27ca
Signed-off-by: Younghyun Joo <yh_.joo@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/2775
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Madan Lanka <lanka.madan@samsung.com>
12 files changed:
service/notification-manager/NotificationManager/include/hosting.h
service/notification-manager/NotificationManager/src/HostingObject.cpp
service/notification-manager/NotificationManager/src/HostingObject.h
service/notification-manager/NotificationManager/src/RequestObject.cpp
service/notification-manager/NotificationManager/src/RequestObject.h
service/notification-manager/NotificationManager/src/ResourceHosting.cpp
service/notification-manager/NotificationManager/src/ResourceHosting.h
service/notification-manager/NotificationManager/src/unittest/RequestObjectUnitTest.cpp [new file with mode: 0644]
service/notification-manager/NotificationManager/src/unittest/ResourceEncapsulationTestSimulator.h [new file with mode: 0644]
service/notification-manager/NotificationManager/src/unittest/ResourceHostingTest.cpp [new file with mode: 0644]
service/notification-manager/NotificationManager/src/unittest/SConscript [new file with mode: 0644]
service/notification-manager/SConscript

index 5e733dd..e4b7ed8 100644 (file)
@@ -36,7 +36,7 @@
 extern "C" {
 #endif // __cplusplus
 
-#define HOSTING_TAG  "Hosting"
+#define HOSTING_TAG  PCF("Hosting")
 
 /**
  * Start resource hosting.
index 43cb8c2..3cb127e 100644 (file)
@@ -36,7 +36,12 @@ void OIC_HOSTING_LOG(LogLevel level, const char * format, ...)
     va_start(args, format);
     vsnprintf(buffer, sizeof buffer - 1, format, args);
     va_end(args);
-    OCLog(level, "Hosting", buffer);
+    OCLog(level, PCF("Hosting"), buffer);
+}
+
+namespace
+{
+    std::mutex mutexForCB;
 }
 
 HostingObject::HostingObject()
@@ -47,6 +52,19 @@ HostingObject::HostingObject()
 {
 }
 
+HostingObject::~HostingObject()
+{
+       // shared_ptr release
+    pStateChangedCB = {};
+    pDataUpdateCB = {};
+
+    if (remoteObject)
+    {
+        remoteObject->stopMonitoring();
+        remoteObject->stopCaching();
+    }
+}
+
 HostingObject::RemoteObjectPtr HostingObject::getRemoteResource() const
 {
     return remoteObject;
@@ -54,7 +72,6 @@ HostingObject::RemoteObjectPtr HostingObject::getRemoteResource() const
 
 void HostingObject::initializeHostingObject(RemoteObjectPtr rResource, DestroyedCallback destroyCB)
 {
-
     remoteObject = rResource;
 
     pStateChangedCB = std::bind(&HostingObject::stateChangedCB, this,
@@ -142,6 +159,7 @@ void HostingObject::stateChangedCB(ResourceState state, RemoteObjectPtr rObject)
 
 void HostingObject::dataChangedCB(const RCSResourceAttributes & attributes, RemoteObjectPtr rObject)
 {
+    std::unique_lock<std::mutex> lock(mutexForCB);
     if(attributes.empty())
     {
         return;
@@ -228,6 +246,7 @@ HostingObject::ResourceObjectPtr HostingObject::createMirroredServer(RemoteObjec
 RCSSetResponse HostingObject::setRequestHandler(const RCSRequest & primitiveRequest,
             RCSResourceAttributes & resourceAttibutes)
 {
+    (void)primitiveRequest;
     try
     {
         RequestObject newRequest = { };
index af05c30..4469bd2 100644 (file)
 #ifndef RH_HOSTINGOBJECT_H_
 #define RH_HOSTINGOBJECT_H_
 
+#include "logger.h"
+
 #include "RCSRemoteResourceObject.h"
 #include "RCSResourceObject.h"
 #include "RequestObject.h"
-#include "ResourceBroker.h"
-#include "ResourceCacheManager.h"
-#include "PrimitiveResource.h"
 
 namespace OIC
 {
@@ -43,6 +42,8 @@ private:
     typedef std::shared_ptr<RequestObject> RequestObjectPtr;
     typedef std::shared_ptr<PrimitiveResource> PrimiteveResourcePtr;
 
+public:
+    typedef std::shared_ptr<HostingObject> Ptr;
     typedef std::function<void(ResourceState)> BrokerCallback;
     typedef std::function<void(const RCSResourceAttributes &)> CacheCallback;
     typedef std::function<void()> DestroyedCallback;
@@ -52,7 +53,7 @@ private:
 
 public:
     HostingObject();
-    ~HostingObject() = default;
+    ~HostingObject();
 
     void initializeHostingObject(RemoteObjectPtr rResource, DestroyedCallback destroyCB);
 
index 867cbdf..b1a2313 100644 (file)
@@ -25,6 +25,14 @@ namespace OIC
 namespace Service
 {
 
+RequestObject::RequestObject() : pSetRequestCB(nullptr){ }
+RequestObject::RequestObject(SetRequestCallback cb) : pSetRequestCB(cb){ };
+
+RequestObject::~RequestObject()
+{
+    pSetRequestCB = {};
+}
+
 void RequestObject::invokeRequest(RemoteObjectPtr remoteObject, RequestMethod method,
         RCSResourceAttributes & resourceAttibutes)
 {
@@ -33,9 +41,20 @@ void RequestObject::invokeRequest(RemoteObjectPtr remoteObject, RequestMethod me
         switch (method)
         {
         case RequestMethod::Setter:
-            remoteObject->setRemoteAttributes(resourceAttibutes,
-                    std::bind(&RequestObject::setRequestCB, this,
-                            std::placeholders::_1, resourceAttibutes));
+        {
+            if(pSetRequestCB == nullptr)
+            {
+                remoteObject->setRemoteAttributes(resourceAttibutes,
+                        std::bind(&RequestObject::setRequestCB, this,
+                                std::placeholders::_1, resourceAttibutes));
+            }
+            else
+            {
+                remoteObject->setRemoteAttributes(resourceAttibutes,
+                        std::bind(pSetRequestCB,
+                                std::placeholders::_1, resourceAttibutes));
+            }
+        }
             break;
         case RequestMethod::Getter:
         case RequestMethod::Delete:
index a4b040d..bb18236 100644 (file)
@@ -32,7 +32,9 @@ namespace Service
 class RequestObject
 {
 public:
+    typedef std::shared_ptr<RequestObject> Ptr;
     typedef std::shared_ptr<RCSRemoteResourceObject> RemoteObjectPtr;
+    typedef void (*SetRequestCallback)(const RCSResourceAttributes &, RCSResourceAttributes &);
 
     enum class RequestMethod
     {
@@ -41,8 +43,13 @@ public:
         Delete
     };
 
-    RequestObject() = default;
-    ~RequestObject() = default;
+private:
+    SetRequestCallback pSetRequestCB;
+
+public:
+    RequestObject();
+    RequestObject(SetRequestCallback cb);
+    ~RequestObject();
 
     void invokeRequest(RemoteObjectPtr remoteObject, RequestMethod method,
             RCSResourceAttributes & resourceAttibutes);
index a85a853..c9af552 100644 (file)
@@ -94,10 +94,8 @@ void ResourceHosting::stopHosting()
     {
         presenceHandle.unsubscribe();
     }
-    for(auto it : hostingObjectList)
-    {
-        it.reset();
-    }
+
+    hostingObjectList.clear();
 }
 
 void ResourceHosting::initializeResourceHosting()
@@ -185,8 +183,8 @@ void ResourceHosting::requestDiscovery(std::string address)
 {
     std::string host = address;
     RCSAddress rcsAddress = RCSAddress::unicast(host);
-    discoveryManager->discoverResourceByType(rcsAddress, OC_RSRVD_WELL_KNOWN_URI,
-            HOSTING_RESOURSE_TYPE, pDiscoveryCB);
+    discoveryTask = discoveryManager->discoverResourceByType(
+        rcsAddress, OC_RSRVD_WELL_KNOWN_URI, HOSTING_RESOURSE_TYPE, pDiscoveryCB);
 }
 
 void ResourceHosting::discoverHandler(RemoteObjectPtr remoteResource)
@@ -203,9 +201,10 @@ void ResourceHosting::discoverHandler(RemoteObjectPtr remoteResource)
     {
         try
         {
-            foundHostingObject.reset(new HostingObject());
+            foundHostingObject = std::make_shared<HostingObject>();
             foundHostingObject->initializeHostingObject(remoteResource,
-                    std::bind(&ResourceHosting::destroyedHostingObject, this, foundHostingObject));
+                    std::bind(&ResourceHosting::destroyedHostingObject, this,
+                            HostingObjectWeakPtr(foundHostingObject)));
             hostingObjectList.push_back(foundHostingObject);
         }catch(InvalidParameterException &e)
         {
@@ -237,7 +236,6 @@ bool ResourceHosting::isSameRemoteResource(
 {
     bool ret = false;
     if(remoteResource_1->getAddress() == remoteResource_2->getAddress() &&
-//       remoteResource_1->getID() == remoteResource_2->getID() &&
        remoteResource_1->getUri() == remoteResource_2->getUri())
     {
         ret = true;
@@ -245,8 +243,12 @@ bool ResourceHosting::isSameRemoteResource(
     return ret;
 }
 
-void ResourceHosting::destroyedHostingObject(HostingObjectPtr destroyedPtr)
+void ResourceHosting::destroyedHostingObject(HostingObjectWeakPtr destroyedWeakPtr)
 {
+    auto destroyedPtr = destroyedWeakPtr.lock();
+    if (destroyedPtr) return;
+
+    std::unique_lock<std::mutex> lock(mutexForList);
     hostingObjectList.remove(destroyedPtr);
 }
 
index f4f9ff6..68944e5 100644 (file)
@@ -34,6 +34,7 @@
 #include "PresenceSubscriber.h"
 #include "HostingObject.h"
 #include "PrimitiveResource.h"
+#include "RCSDiscoveryManager.h"
 
 namespace OIC
 {
@@ -45,6 +46,8 @@ class ResourceHosting
 {
 private:
     typedef std::shared_ptr<HostingObject> HostingObjectPtr;
+    typedef std::weak_ptr<HostingObject> HostingObjectWeakPtr;
+
     typedef std::shared_ptr<RCSRemoteResourceObject> RemoteObjectPtr;
     typedef std::shared_ptr<PrimitiveResource> PrimiteveResourcePtr;
 
@@ -71,11 +74,13 @@ private:
 
     static ResourceHosting * s_instance;
     static std::mutex s_mutexForCreation;
+    std::mutex mutexForList;
 
     std::list<HostingObjectPtr> hostingObjectList;
 
     RCSDiscoveryManager * discoveryManager;
     PresenceSubscriber presenceHandle;
+    std::unique_ptr<RCSDiscoveryManager::DiscoveryTask> discoveryTask;
 
     SubscribeCallback pPresenceCB;
     DiscoveryCallback pDiscoveryCB;
@@ -92,7 +97,7 @@ private:
     HostingObjectPtr findRemoteResource(RemoteObjectPtr remoteResource);
     bool isSameRemoteResource(RemoteObjectPtr remoteResource_1, RemoteObjectPtr remoteResource_2);
 
-    void destroyedHostingObject(HostingObjectPtr destroyedPtr);
+    void destroyedHostingObject(HostingObjectWeakPtr destroyedWeakPtr);
 
 };
 
diff --git a/service/notification-manager/NotificationManager/src/unittest/RequestObjectUnitTest.cpp b/service/notification-manager/NotificationManager/src/unittest/RequestObjectUnitTest.cpp
new file mode 100644 (file)
index 0000000..acbcf69
--- /dev/null
@@ -0,0 +1,103 @@
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "UnitTestHelper.h"
+
+#include "ResourceEncapsulationTestSimulator.h"
+#include "RequestObject.h"
+
+using namespace testing;
+using namespace OIC::Service;
+
+namespace
+{
+    void setRequestCB(const RCSResourceAttributes &, RCSResourceAttributes &) { }
+}
+
+class RequestObjectTest : public TestWithMock
+{
+public:
+    ResourceEncapsulationTestSimulator::Ptr testObject;
+    RCSResourceObject::Ptr server;
+    RCSRemoteResourceObject::Ptr remoteObject;
+
+    RCSResourceAttributes attr;
+
+    std::mutex mutexForCondition;
+    std::condition_variable responseCon;
+
+protected:
+
+    void SetUp()
+    {
+        TestWithMock::SetUp();
+
+        testObject = std::make_shared<ResourceEncapsulationTestSimulator>();
+        testObject->defaultRunSimulator();
+        server = testObject->getResourceServer();
+        remoteObject = testObject->getRemoteResource();
+    }
+
+    void TearDown()
+    {
+        TestWithMock::TearDown();
+        if(remoteObject->isCaching())
+        {
+            remoteObject->stopCaching();
+        }
+        if(remoteObject->isMonitoring())
+        {
+            remoteObject->stopMonitoring();
+        }
+         testObject->destroy();
+    }
+
+public:
+    void waitForCondition(int waitingTime = 1000)
+    {
+        std::unique_lock< std::mutex > lock{ mutexForCondition };
+        responseCon.wait_for(lock, std::chrono::milliseconds{ waitingTime });
+    }
+
+    void notifyCondition()
+    {
+        responseCon.notify_all();
+    }
+};
+
+TEST_F(RequestObjectTest, invokeRequestExpectCallwithSetter)
+{
+   bool isCalled = false;
+   RequestObject::Ptr instance = std::make_shared<RequestObject>(setRequestCB);
+
+   mocks.ExpectCallFunc(setRequestCB).Do(
+           [this, &isCalled](const RCSResourceAttributes &, RCSResourceAttributes &)
+           {
+               isCalled = true;
+               notifyCondition();
+           });
+
+   RCSResourceAttributes att;
+   instance->invokeRequest(remoteObject, RequestObject::RequestMethod::Setter, att);
+
+   waitForCondition();
+
+   ASSERT_TRUE(isCalled);
+}
diff --git a/service/notification-manager/NotificationManager/src/unittest/ResourceEncapsulationTestSimulator.h b/service/notification-manager/NotificationManager/src/unittest/ResourceEncapsulationTestSimulator.h
new file mode 100644 (file)
index 0000000..969fef8
--- /dev/null
@@ -0,0 +1,215 @@
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <memory>
+#include <mutex>
+#include <atomic>
+
+#include "UnitTestHelper.h"
+
+#include "RCSDiscoveryManager.h"
+#include "RCSRemoteResourceObject.h"
+#include "RCSResourceAttributes.h"
+#include "RCSAddress.h"
+
+#include "RequestObject.h"
+
+using namespace testing;
+using namespace OIC::Service;
+
+class ResourceEncapsulationTestSimulator
+        : public std::enable_shared_from_this<ResourceEncapsulationTestSimulator>
+{
+public:
+    typedef std::shared_ptr<ResourceEncapsulationTestSimulator> Ptr;
+
+    RCSResourceObject::Ptr server;
+    RCSRemoteResourceObject::Ptr remoteResource;
+
+private:
+    std::mutex mutexForDiscovery;
+    std::unique_ptr<RCSDiscoveryManager::DiscoveryTask> discoveryTask;
+
+    std::string MULTICASTURI;
+    std::string HOSTED_RESOURCEURI;
+    std::string RESOURCEURI;
+    std::string RESOURCETYPE;
+    std::string RESOURCEINTERFACE;
+    std::string ATTR_KEY;
+    int ATTR_VALUE;
+
+public:
+    ResourceEncapsulationTestSimulator()
+    :server(nullptr), remoteResource(nullptr),
+     mutexForDiscovery(),
+     MULTICASTURI("/oic/res"),
+     HOSTED_RESOURCEURI("/a/TempHumSensor"),
+     RESOURCEURI("/a/TempHumSensor/hosting"),
+     RESOURCETYPE("Resource.Hosting"),
+     RESOURCEINTERFACE("oic.if.baseline"),
+     ATTR_KEY("Temperature"),
+     ATTR_VALUE(0)
+    { }
+    ~ResourceEncapsulationTestSimulator()
+    {
+        std::cout << "~ResourceEncapsulationTestSimulator()" << std::endl;
+       // if(remoteResource->isCaching())
+       // {
+       //     std::cout << "stop cache" << std::endl;
+       //     remoteResource->stopCaching();
+       // }
+       // if(remoteResource->isMonitoring())
+       // {
+       //     std::cout << "stop monitoring" << std::endl;
+       //     remoteResource->stopMonitoring();
+       // }
+       //std::cout << "11111: " << remoteResource.use_count() << std::endl;
+    }
+
+private:
+    void onDiscoveryResource_Impl(RCSRemoteResourceObject::Ptr resourceObject)
+    {
+        if (remoteResource != nullptr)
+        {
+            return;
+        }
+
+        if (RESOURCEURI.compare(resourceObject->getUri()) != 0)
+        {
+            return;
+        }
+
+        remoteResource = resourceObject;
+        mutexForDiscovery.unlock();
+    }
+
+    static void onDiscoveryResource(RCSRemoteResourceObject::Ptr resourceObject,
+            std::weak_ptr<ResourceEncapsulationTestSimulator> rPtr)
+    {
+        std::shared_ptr<ResourceEncapsulationTestSimulator> ptr = rPtr.lock();
+        if (ptr != nullptr)
+        {
+            ptr->onDiscoveryResource_Impl(resourceObject);
+        }
+        else
+        {
+            std::cout << "Aleady delete simulator\n";
+        }
+    }
+    void waitForDiscovery()
+    {
+        std::chrono::milliseconds interval(100);
+        while(true)
+        {
+            if(mutexForDiscovery.try_lock())
+            {
+                mutexForDiscovery.unlock();
+                return;
+            }
+            std::this_thread::sleep_for(interval);
+        }
+    }
+    void WaitForPtrBeingUnique()
+    {
+        while((remoteResource && !remoteResource.unique()) || (server && !server.unique()))
+        {
+            std::this_thread::sleep_for(std::chrono::milliseconds{ 100 });
+        }
+    }
+
+public:
+    void destroy()
+    {
+        server.reset();
+        remoteResource.reset();
+        std::cout << "waitforptrbeingunique" << std::endl;
+        WaitForPtrBeingUnique();
+    }
+    void defaultRunSimulator()
+    {
+        createResource();
+        discoveryResource();
+        waitForDiscovery();
+    }
+
+    void createResource()
+    {
+        server = RCSResourceObject::Builder(RESOURCEURI, RESOURCETYPE, RESOURCEINTERFACE)
+                .setDiscoverable(true).setObservable(true).build();
+        server->setAttribute(ATTR_KEY, ATTR_VALUE);
+    }
+
+    void discoveryResource()
+    {
+        discoveryResource(RESOURCETYPE);
+    }
+
+    void discoveryResource(std::string & resourceType)
+    {
+        try
+        {
+            discoveryTask = RCSDiscoveryManager::getInstance()->discoverResourceByType(
+                    RCSAddress::multicast(), MULTICASTURI, resourceType,
+                    std::bind(onDiscoveryResource, std::placeholders::_1,
+                        std::weak_ptr<ResourceEncapsulationTestSimulator>(shared_from_this())));
+            mutexForDiscovery.lock();
+        }
+        catch(std::exception & e)
+        {
+            std::cout << "exception : " << e.what() << std::endl;
+        }
+    }
+
+    std::string getServerUri() const
+    {
+        return RESOURCEURI;
+    }
+
+    std::string getHostedServerUri() const
+    {
+        return HOSTED_RESOURCEURI;
+    }
+
+    RCSResourceObject::Ptr getResourceServer() const
+    {
+        return server;
+    }
+    RCSRemoteResourceObject::Ptr getRemoteResource() const
+    {
+        return remoteResource;
+    }
+
+    void ChangeAttributeValue()
+    {
+        std::chrono::milliseconds interval(100);
+        if (server != nullptr)
+            server->setAttribute(ATTR_KEY, ATTR_VALUE + 10);
+        std::this_thread::sleep_for(interval);
+    }
+
+    void ChangeResourceState()
+    {
+        std::chrono::milliseconds interval(400);
+        if (server != nullptr)
+            server = nullptr;
+        std::this_thread::sleep_for(interval);
+    }
+};
diff --git a/service/notification-manager/NotificationManager/src/unittest/ResourceHostingTest.cpp b/service/notification-manager/NotificationManager/src/unittest/ResourceHostingTest.cpp
new file mode 100644 (file)
index 0000000..6673cf3
--- /dev/null
@@ -0,0 +1,140 @@
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <memory>
+
+#include "ResourceEncapsulationTestSimulator.h"
+
+#include "ResourceHosting.h"
+
+using namespace testing;
+using namespace OIC::Service;
+
+namespace
+{
+    void onDiscoveryResource(RCSRemoteResourceObject::Ptr) { }
+}
+
+class ResourceHostingTest : public TestWithMock
+{
+public:
+    std::mutex mutexForCondition;
+    std::condition_variable responseCon;
+    std::unique_ptr<RCSDiscoveryManager::DiscoveryTask> discoveryTask;
+
+protected:
+
+    void SetUp()
+    {
+        TestWithMock::SetUp();
+    }
+
+    void TearDown()
+    {
+        TestWithMock::TearDown();
+
+        if (ResourceHosting::getInstance())
+        {
+            ResourceHosting::getInstance()->stopHosting();
+        }
+
+    }
+
+public:
+    void waitForCondition(int waitingTime = 1000)
+    {
+        std::unique_lock< std::mutex > lock{ mutexForCondition };
+        responseCon.wait_for(lock, std::chrono::milliseconds{ waitingTime });
+        std::cout << "condition return back" << std::endl;
+    }
+
+    void notifyCondition()
+    {
+        std::cout << "notify condition to all" << std::endl;
+        responseCon.notify_all();
+    }
+
+};
+
+TEST(ResourceHostingSTATICMethodTest, getInstanceAllwaysSameReturnInstance)
+{
+    EXPECT_EQ(ResourceHosting::getInstance(), ResourceHosting::getInstance());
+}
+
+TEST_F(ResourceHostingTest, HostingFoundBeforeMakeOriginServer)
+{
+    ResourceEncapsulationTestSimulator::Ptr testObject
+        = std::make_shared<ResourceEncapsulationTestSimulator>();
+    testObject->createResource();
+
+    ResourceHosting::getInstance()->startHosting();
+    std::this_thread::sleep_for(std::chrono::milliseconds{1000});
+
+    std::string uri = "";
+    mocks.OnCallFunc(onDiscoveryResource).Do(
+            [this, &uri, &testObject](RCSRemoteResourceObject::Ptr ptr)
+            {
+                if(testObject.use_count() <= 0)
+                {
+                    return;
+                }
+                if(ptr->getUri() == testObject->getServerUri())
+                {
+                    uri = ptr->getUri();
+                    notifyCondition();
+                }
+            });
+
+    discoveryTask = RCSDiscoveryManager::getInstance()->discoverResourceByType(
+            RCSAddress::multicast(), "Resource.Hosting", onDiscoveryResource);
+    waitForCondition(2000);
+
+    std::string mirroredUri = { testObject->getServerUri() };
+
+    testObject->destroy();
+
+    ASSERT_EQ(uri, mirroredUri);
+}
+
+TEST_F(ResourceHostingTest, startHosting)
+{
+    ResourceEncapsulationTestSimulator::Ptr testObject
+        = std::make_shared<ResourceEncapsulationTestSimulator>();
+    testObject->createResource();
+
+    ResourceHosting::getInstance()->startHosting();
+    std::this_thread::sleep_for(std::chrono::milliseconds{1000});
+
+    testObject->destroy();
+}
+
+TEST_F(ResourceHostingTest, stopHosting)
+{
+    ResourceEncapsulationTestSimulator::Ptr testObject
+        = std::make_shared<ResourceEncapsulationTestSimulator>();
+    testObject->createResource();
+
+    ResourceHosting::getInstance()->startHosting();
+    std::this_thread::sleep_for(std::chrono::milliseconds{1000});
+    
+    testObject->destroy();
+
+    ResourceHosting::getInstance()->stopHosting();
+}
\ No newline at end of file
diff --git a/service/notification-manager/NotificationManager/src/unittest/SConscript b/service/notification-manager/NotificationManager/src/unittest/SConscript
new file mode 100644 (file)
index 0000000..27a5b8a
--- /dev/null
@@ -0,0 +1,89 @@
+#******************************************************************
+#
+# Copyright 2015 Samsung Electronics All Rights Reserved.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+##
+# ResourceHosting Unit Test build script
+##
+
+Import('env')
+
+if env.get('RELEASE'):
+       env.AppendUnique(CCFLAGS = ['-Os'])
+       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
+else:
+       env.AppendUnique(CCFLAGS = ['-g'])
+
+if env.get('LOGGING'):
+       env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+######################################################################
+#unit test setting
+######################################################################
+src_dir = lib_env.get('SRC_DIR')
+gtest_dir = src_dir + '/extlibs/gtest/gtest-1.7.0'
+
+hosting_test_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+
+######################################################################
+# Build flags
+######################################################################
+GTest = File(gtest_dir + '/lib/.libs/libgtest.a')
+GTest_Main = File(gtest_dir + '/lib/.libs/libgtest_main.a')
+
+#hosting_test_env.AppendUnique(LIBPATH = [gtest_dir + '/lib/.libs'])
+hosting_test_env.AppendUnique(LIBPATH = [lib_env.get('BUILD_DIR')])
+hosting_test_env.AppendUnique(LIBS = [
+       'NotificationManager', 'rcs_server', 'rcs_client','rcs_common',
+       'oc', 'octbstack', 'oc_logger', 'connectivity_abstraction', 'coap',
+       GTest_Main, GTest])
+
+if target_os not in ['windows', 'winrt']:
+    hosting_test_env.AppendUnique(CXXFLAGS = ['-O2', '-g', '-Wall', '-fmessage-length=0', '-std=c++0x'])
+
+if target_os == 'linux':
+       hosting_test_env.AppendUnique(CXXFLAGS = ['-pthread'])
+       hosting_test_env.AppendUnique(LIBS = ['pthread'])
+
+hosting_test_env.PrependUnique(CPPPATH = [ src_dir + '/extlibs/hippomocks-master',
+                             gtest_dir + '/include'])
+hosting_test_env.AppendUnique(CPPPATH = ['../'])
+hosting_test_env.AppendUnique(CPPPATH = ['../../../../resource-encapsulation/include'])
+hosting_test_env.AppendUnique(CPPPATH = ['../../../../resource-encapsulation/src/common/primitiveResource/include'])
+hosting_test_env.AppendUnique(CPPPATH = ['../../../../resource-encapsulation/src/common/utils/include'])
+######################################################################
+# Build Test
+######################################################################
+
+hosting_test_src = env.Glob('./*.cpp')
+hosting_test = hosting_test_env.Program('hosting_test', hosting_test_src)
+Alias("hosting_test", hosting_test)
+env.AppendTarget('hosting_test')
+hosting_test_env.InstallTarget(hosting_test, 'hosting_test')
+
+#target_os = env.get('TARGET_OS')
+#if target_os == 'linux':
+#        from tools.scons.RunTest import *
+#        run_test(hosting_test_env,
+#                 '',
+#                 'service/notification-manager/NotificationManager/src/unittest/hosting_test')
\ No newline at end of file
index e40419c..1f41995 100644 (file)
@@ -44,13 +44,7 @@ target_os = env.get('TARGET_OS')
 notimgr_env.AppendUnique(CPPPATH = ['NotificationManager/include'])
 notimgr_env.AppendUnique(CPPPATH = ['../resource-encapsulation/include'])
 notimgr_env.AppendUnique(CPPPATH = ['../resource-encapsulation/src/common/primitiveResource/include'])
-notimgr_env.AppendUnique(CPPPATH = ['../resource-encapsulation/src/serverBuilder/include'])
-notimgr_env.AppendUnique(CPPPATH = ['../resource-encapsulation/src/resourceBroker/include'])
-notimgr_env.AppendUnique(CPPPATH = ['../resource-encapsulation/src/resourceCache/include'])
-notimgr_env.AppendUnique(CPPPATH = ['../resource-encapsulation/src/common/expiryTimer/include'])
-notimgr_env.AppendUnique(CPPPATH = ['../resource-encapsulation/src/common/expiryTimer/src'])
-#notimgr_env.AppendUnique(CPPPATH = ['../../extlibs/cjson'])
-#notimgr_env.AppendUnique(CPPPATH = ['../../resource/csdk/logger/include'])
+
 notimgr_env.PrependUnique(LIBS = [
        'rcs_client',
        'rcs_server',
@@ -95,7 +89,10 @@ else :
     notificationsdk = notimgr_env.StaticLibrary('NotificationManager', notimgr_src)
 
 notimgr_env.InstallTarget(notificationsdk, 'libResouceHosting')
-notimgr_env.UserInstallTargetHeader('NotificationManager/include/hosting.h', 'service/notification-manager', 'hosting.h')
+
+# Go to build Unit test
+if target_os == 'linux':
+       SConscript('NotificationManager/src/unittest/SConscript')
 
 # Go to build sample apps
 SConscript('SampleApp/SConscript')