Added Unit Test of Notification service.
authorjyong2.kim <jyong2.kim@samsung.com>
Wed, 18 May 2016 06:46:06 +0000 (15:46 +0900)
committerUze Choi <uzchoi@samsung.com>
Fri, 20 May 2016 05:48:29 +0000 (05:48 +0000)
Unit test of Notification serivces is added for public APIs on positive case.

Change-Id: Ie658a444b2b7cc6052cb64933f54bfd58ceceb5c
Signed-off-by: jyong2.kim <jyong2.kim@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/8209
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Uze Choi <uzchoi@samsung.com>
service/notification/SConscript
service/notification/unittest/NSConsumerSimulator.h [new file with mode: 0644]
service/notification/unittest/NSConsumerTest.cpp [new file with mode: 0644]
service/notification/unittest/NSProviderSimulator.h [new file with mode: 0644]
service/notification/unittest/NSProviderTest.cpp [new file with mode: 0644]
service/notification/unittest/SConscript [new file with mode: 0644]

index b1e51df..9319104 100644 (file)
@@ -118,8 +118,8 @@ notification_env.UserInstallTargetLib(consumersdk, 'libnotification_consumer')
 #      'service/notification', 'NSConsumerIngerface.h')
 
 # Go to build Unit test
-#if target_os == 'linux':
-#      SConscript('unittest/SConscript')
+if target_os == 'linux':
+       SConscript('unittest/SConscript')
 
 # Go to build sample apps
 SConscript('examples/SConscript')
diff --git a/service/notification/unittest/NSConsumerSimulator.h b/service/notification/unittest/NSConsumerSimulator.h
new file mode 100644 (file)
index 0000000..f1177ba
--- /dev/null
@@ -0,0 +1,147 @@
+//******************************************************************
+//
+// Copyright 2016 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef _NS_CONSUMER_SIMULATOR_H_
+#define _NS_CONSUMER_SIMULATOR_H_
+
+#include <iostream>
+
+#include "OCPlatform.h"
+#include "OCApi.h"
+
+class NSConsumerSimulator
+{
+private:
+    std::function<void(const std::string&, const std::string&, const std::string&)> m_messageFunc;
+    std::function<void(int, const std::string&)> m_syncFunc;
+
+    std::shared_ptr<OC::OCResource> m_syncResource;
+
+
+public:
+    NSConsumerSimulator()
+    : m_messageFunc(), m_syncFunc(),
+      m_syncResource() { };
+    ~NSConsumerSimulator() = default;
+
+    NSConsumerSimulator(const NSConsumerSimulator &) = delete;
+    NSConsumerSimulator & operator = (const NSConsumerSimulator &) = delete;
+
+    NSConsumerSimulator(NSConsumerSimulator &&) = delete;
+    NSConsumerSimulator & operator = (NSConsumerSimulator &&) = delete;
+
+    void findProvider()
+    {
+        OC::OCPlatform::findResource("", std::string("/oic/res?rt=oic.r.notification"),
+                OCConnectivityType::CT_DEFAULT,
+                std::bind(&NSConsumerSimulator::findResultCallback, this, std::placeholders::_1),
+                OC::QualityOfService::LowQos);
+    }
+
+    void syncToProvider(int & type, const std::string & id)
+    {
+        if (m_syncResource == nullptr)
+        {
+            std::cout << "m_syncResource is null" << std::endl;
+            return;
+        }
+
+        OC::OCRepresentation rep;
+        rep.setValue("ID", id);
+        rep.setValue("STATE", type);
+
+        m_syncResource->post(rep, OC::QueryParamsMap(), &onPost, OC::QualityOfService::LowQos);
+    }
+
+    void setCallback(const std::function<void(const std::string&, const std::string&, const std::string&)> & messageFunc,
+            const std::function<void(int, const std::string&)> & syncFunc)
+    {
+        m_messageFunc = messageFunc;
+        m_syncFunc = syncFunc;
+    }
+
+private:
+    static void onPost(const OC::HeaderOptions &/*headerOption*/,
+                const OC::OCRepresentation & /*rep*/ , const int eCode)
+    {
+        std::cout << __func__ << " result : " << eCode << std::endl;
+    }
+    void findResultCallback(std::shared_ptr<OC::OCResource> resource)
+    {
+        std::cout << __func__ << " " << resource->host() << std::endl;
+        resource->get(OC::QueryParamsMap(),
+                std::bind(&NSConsumerSimulator::onGet, this,
+                        std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, resource),
+                OC::QualityOfService::LowQos);
+    }
+    void onGet(const OC::HeaderOptions &/*headerOption*/,
+            const OC::OCRepresentation & rep , const int eCode,
+            std::shared_ptr<OC::OCResource> resource)
+    {
+        std::cout << __func__ << " " << rep.getHost() << " result : " << eCode << std::endl;
+
+        std::shared_ptr<OC::OCResource> msgResource
+            = OC::OCPlatform::constructResourceObject(resource->host(), resource->uri() + "/message",
+                    resource->connectivityType(), false, resource->getResourceTypes(),
+                    resource->getResourceInterfaces());
+        m_syncResource
+            = OC::OCPlatform::constructResourceObject(resource->host(), resource->uri() + "/sync",
+                    resource->connectivityType(), false, resource->getResourceTypes(),
+                    resource->getResourceInterfaces());
+
+        msgResource->observe(OC::ObserveType::Observe, OC::QueryParamsMap(),
+                std::bind(&NSConsumerSimulator::onObserve, this,
+                        std::placeholders::_1, std::placeholders::_2,
+                        std::placeholders::_3, std::placeholders::_4, resource),
+                OC::QualityOfService::LowQos);
+        m_syncResource->observe(OC::ObserveType::Observe, OC::QueryParamsMap(),
+                std::bind(&NSConsumerSimulator::onObserve, this,
+                        std::placeholders::_1, std::placeholders::_2,
+                        std::placeholders::_3, std::placeholders::_4, resource),
+                OC::QualityOfService::LowQos);
+
+    }
+    void onObserve(const OC::HeaderOptions &/*headerOption*/,
+            const OC::OCRepresentation &rep , const int &eCode, const int &,
+            std::shared_ptr<OC::OCResource> )
+    {
+        std::cout << __func__ << " " << rep.getHost() << " result : " << eCode;
+        std::cout << " uri : " << rep.getUri() << std::endl;
+
+        if (rep.getUri() == "/notification/message" && rep.hasAttribute("ID")
+                && rep.getValueToString("ID") != "0000-0000-0000-0000")
+        {
+            std::cout << "ID : " << rep.getValueToString("ID") << std::endl;
+            std::cout << "TITLE : " << rep.getValueToString("TITLE") << std::endl;
+            std::cout << "CONTENT : " << rep.getValueToString("CONTENT") << std::endl;
+            m_messageFunc(std::string(rep.getValueToString("ID")),
+                          std::string(rep.getValueToString("TITLE")),
+                          std::string(rep.getValueToString("CONTENT")));
+        }
+        else if (rep.getUri() == "/notification/sync")
+        {
+            m_syncFunc(int(rep.getValue<int>("STATE")),
+                       std::string(rep.getValueToString("ID")));
+        }
+    }
+};
+
+
+#endif //_NS_CONSUMER_SIMULATOR_H_
diff --git a/service/notification/unittest/NSConsumerTest.cpp b/service/notification/unittest/NSConsumerTest.cpp
new file mode 100644 (file)
index 0000000..8f38d43
--- /dev/null
@@ -0,0 +1,436 @@
+//******************************************************************
+//
+// Copyright 2016 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 <gtest/gtest.h>
+#include <HippoMocks/hippomocks.h>
+#include <atomic>
+#include <functional>
+#include <condition_variable>
+#include <mutex>
+#include <chrono>
+
+#include "ocstack.h"
+
+#include "NSCommon.h"
+#include "NSConsumerInterface.h"
+
+#include "NSProviderSimulator.h"
+
+namespace
+{
+    NSProviderSimulator g_providerSimul;
+    NSProvider * g_provider;
+
+    std::atomic_bool g_isStartedStack(false);
+
+    std::chrono::milliseconds g_waitForResponse(500);
+
+    std::condition_variable responseCon;
+    std::mutex mutexForCondition;
+
+}
+
+class TestWithMock: public testing::Test
+{
+public:
+    MockRepository mocks;
+
+protected:
+    virtual ~TestWithMock() noexcept(noexcept(std::declval<Test>().~Test())) {}
+
+    virtual void TearDown() {
+        try
+        {
+            mocks.VerifyAll();
+        }
+        catch (...)
+        {
+            mocks.reset();
+            throw;
+        }
+    }
+};
+
+class NotificationConsumerTest : public TestWithMock
+{
+public:
+    NotificationConsumerTest() = default;
+    ~NotificationConsumerTest() = default;
+
+    static void NSProviderDiscoveredCallbackEmpty(NSProvider *)
+    {
+        std::cout << __func__ << std::endl;
+    }
+
+    static void NSNotificationReceivedCallbackEmpty(NSProvider *, NSMessage *) { }
+
+    static void NSSyncCallbackEmpty(NSProvider *, NSSync *) { }
+
+    static void foundResourceEmpty(std::shared_ptr< OC::OCResource >) { }
+
+protected:
+
+    void SetUp()
+    {
+        TestWithMock::SetUp();
+
+        if (g_isStartedStack == false)
+        {
+            OC::PlatformConfig cfg
+            {
+                OC::ServiceType::InProc,
+                OC::ModeType::Both,
+                "0.0.0.0",
+                0,
+                OC::QualityOfService::LowQos
+            };
+            OC::OCPlatform::Configure(cfg);
+
+            try
+            {
+                OC::OCPlatform::stopPresence();
+            }
+            catch (...)
+            {
+
+            }
+
+            g_isStartedStack = true;
+        }
+
+    }
+
+    void TearDown()
+    {
+        TestWithMock::TearDown();
+    }
+
+};
+
+TEST_F(NotificationConsumerTest, StartConsumerPositive)
+{
+    EXPECT_EQ(NS_OK,
+              NSStartConsumer(
+                    NSProviderDiscoveredCallbackEmpty,
+                    NSNotificationReceivedCallbackEmpty,
+                    NSSyncCallbackEmpty));
+}
+
+TEST_F(NotificationConsumerTest, StopConsumerPositive)
+{
+    EXPECT_EQ(NSStopConsumer(), NS_OK);
+}
+
+TEST_F(NotificationConsumerTest, DiscoverProviderWithNonAccepterWhenStartedConsumerFirst)
+{
+    mocks.ExpectCallFunc(NSProviderDiscoveredCallbackEmpty).Do(
+            [this, & responseCon](NSProvider *)
+            {
+                std::cout << "Call Discovered" << std::endl;
+                responseCon.notify_all();
+            });
+
+    NSStartConsumer(
+            NSProviderDiscoveredCallbackEmpty,
+            NSNotificationReceivedCallbackEmpty,
+            NSSyncCallbackEmpty);
+
+    g_providerSimul.setAccepter(1);
+    g_providerSimul.createNotificationResource();
+
+    std::unique_lock< std::mutex > lock{ mutexForCondition };
+    responseCon.wait_for(lock, g_waitForResponse);
+
+    NSStopConsumer();
+    g_providerSimul.deleteNotificationResource();
+}
+
+TEST_F(NotificationConsumerTest, DiscoverProviderWithNonAccepterWhenStartedConsumerAfter)
+{
+    g_providerSimul.setAccepter(1);
+    g_providerSimul.createNotificationResource();
+    {
+        std::unique_lock< std::mutex > lock{ mutexForCondition };
+        responseCon.wait_for(lock, g_waitForResponse);
+    }
+
+    mocks.ExpectCallFunc(NSProviderDiscoveredCallbackEmpty).Do(
+            [this, & responseCon](NSProvider *)
+            {
+                std::cout << "Call Discovered" << std::endl;
+                responseCon.notify_all();
+            });
+
+    NSStartConsumer(
+            NSProviderDiscoveredCallbackEmpty,
+            NSNotificationReceivedCallbackEmpty,
+            NSSyncCallbackEmpty);
+
+    std::unique_lock< std::mutex > lock{ mutexForCondition };
+    responseCon.wait_for(lock, g_waitForResponse);
+
+}
+
+TEST_F(NotificationConsumerTest, DiscoverProviderWithNonAccepterWhenRescan)
+{
+    mocks.ExpectCallFunc(NSProviderDiscoveredCallbackEmpty)
+            .Do(
+            [this, & responseCon](NSProvider * provider)
+            {
+                std::cout << "Call Discovered" << std::endl;
+                g_provider = provider;
+                responseCon.notify_all();
+            });
+
+    NSRescanProvider();
+
+    std::unique_lock< std::mutex > lock{ mutexForCondition };
+    responseCon.wait_for(lock, g_waitForResponse);
+
+//    NSStopConsumer();
+}
+
+TEST_F(NotificationConsumerTest, ExpectSubscribeSuccess)
+{
+    NSResult ret = NSSubscribe(g_provider);
+    std::unique_lock< std::mutex > lock{ mutexForCondition };
+    responseCon.wait_for(lock, g_waitForResponse);
+
+    EXPECT_EQ(NS_OK, ret);
+}
+
+TEST_F(NotificationConsumerTest, ExpectReceiveNotification)
+{
+    std::string id = "id";
+    std::string title = "title";
+    std::string msg = "msg";
+
+    mocks.ExpectCallFunc(NSNotificationReceivedCallbackEmpty).Do(
+            [](NSProvider *, NSMessage * message)
+            {
+                std::cout << "Income Notification : " << message->mId << std::endl;
+                NSDropNSObject(message);
+            });
+
+    g_providerSimul.notifyMessage(id, title, msg);
+
+    std::unique_lock< std::mutex > lock{ mutexForCondition };
+    responseCon.wait_for(lock, g_waitForResponse);
+
+}
+
+TEST_F(NotificationConsumerTest, ExpectUnsubscribeSuccess)
+{
+    NSResult ret = NSUnsubscribe(g_provider);
+    std::unique_lock< std::mutex > lock{ mutexForCondition };
+    responseCon.wait_for(lock, g_waitForResponse);
+
+    EXPECT_EQ(NS_OK, ret);
+}
+
+TEST_F(NotificationConsumerTest, ExpectReceiveNotificationWithAccepterisProvider)
+{
+    std::string id = "ExpectReceiveNotificationWithAccepterisProvider";
+    std::string title = "title";
+    std::string msg = "msg";
+
+    g_providerSimul.setAccepter(0);
+
+    NSRescanProvider();
+    {
+        std::unique_lock< std::mutex > lock{ mutexForCondition };
+        responseCon.wait_for(lock, g_waitForResponse);
+    }
+
+    mocks.ExpectCallFunc(NSNotificationReceivedCallbackEmpty).Do(
+            [](NSProvider *, NSMessage * message)
+            {
+                std::cout << "Income Notification : " << message->mId << std::endl;
+                NSDropNSObject(message);
+            });
+
+    g_providerSimul.notifyMessage(id, title, msg);
+
+    std::unique_lock< std::mutex > lock{ mutexForCondition };
+    responseCon.wait_for(lock, g_waitForResponse);
+
+//    g_providerSimul.deleteNotificationResource();
+//    NSStopConsumer();
+}
+
+TEST_F(NotificationConsumerTest, ExpectCallbackReadCheckWhenProviderNotifySync)
+{
+    std::string id = "ExpectCallbackReadCheckWhenProviderNotifySync";
+    std::string title = "title";
+    std::string msg = "msg";
+
+    NSSyncTypes type = Notification_Dismiss;
+
+    mocks.OnCallFunc(NSNotificationReceivedCallbackEmpty).Do(
+            [](NSProvider *, NSMessage * message)
+            {
+                std::cout << "Income Notification : " << message->mId << std::endl;
+                NSDropNSObject(message);
+            });
+
+    mocks.ExpectCallFunc(NSSyncCallbackEmpty).Do(
+            [& type](NSProvider *, NSSync * sync)
+            {
+                std::cout << "Income Notification : " << sync->mMessageId
+                        << ", State : " << sync->mState << std::endl;
+                type = sync->mState;
+
+            });
+
+    g_providerSimul.notifyMessage(id, title, msg);
+    {
+        std::unique_lock< std::mutex > lock{ mutexForCondition };
+        responseCon.wait_for(lock, g_waitForResponse);
+    }
+
+    g_providerSimul.sendRead(id);
+    {
+        std::unique_lock< std::mutex > lock{ mutexForCondition };
+        responseCon.wait_for(lock, g_waitForResponse);
+    }
+
+//    g_providerSimul.deleteNotificationResource();
+//    NSStopConsumer();
+
+    EXPECT_EQ(Notification_Read, type);
+}
+
+TEST_F(NotificationConsumerTest, ExpectCallbackDismissCheckWhenProviderNotifySync)
+{
+    std::string id = "ExpectCallbackDismissCheckWhenProviderNotifySync";
+    std::string title = "title";
+    std::string msg = "msg";
+
+    NSSyncTypes type = Notification_Read;
+
+    mocks.OnCallFunc(NSNotificationReceivedCallbackEmpty).Do(
+            [](NSProvider *, NSMessage * message)
+            {
+                std::cout << "Income Notification : " << message->mId << std::endl;
+                NSDropNSObject(message);
+            });
+
+    mocks.ExpectCallFunc(NSSyncCallbackEmpty).Do(
+            [& type](NSProvider *, NSSync * sync)
+            {
+                std::cout << "Income Notification : " << sync->mMessageId
+                        << ", State : " << sync->mState << std::endl;
+                type = sync->mState;
+
+            });
+
+    g_providerSimul.notifyMessage(id, title, msg);
+    {
+        std::unique_lock< std::mutex > lock{ mutexForCondition };
+        responseCon.wait_for(lock, g_waitForResponse);
+    }
+
+    g_providerSimul.sendDismiss(id);
+    {
+        std::unique_lock< std::mutex > lock{ mutexForCondition };
+        responseCon.wait_for(lock, g_waitForResponse);
+    }
+
+//    g_providerSimul.deleteNotificationResource();
+//    NSStopConsumer();
+
+    EXPECT_EQ(Notification_Dismiss, type);
+}
+
+TEST_F(NotificationConsumerTest, ExpectCallbackReadCheckWhenConsumerPostSync)
+{
+    std::string id = "ExpectCallbackReadCheckWhenConsumerPostSync";
+    std::string title = "title";
+    std::string msg = "msg";
+
+    NSSyncTypes type = Notification_Dismiss;
+
+    mocks.OnCallFunc(NSNotificationReceivedCallbackEmpty).Do(
+            [](NSProvider *, NSMessage * message)
+            {
+                std::cout << "Income Notification : " << message->mId << std::endl;
+                NSConsumerReadCheck(message);
+                std::unique_lock< std::mutex > lock{ mutexForCondition };
+                responseCon.wait_for(lock, g_waitForResponse);
+            });
+
+    mocks.ExpectCallFunc(NSSyncCallbackEmpty).Do(
+            [& type](NSProvider *, NSSync * sync)
+            {
+                std::cout << "Income Notification : " << sync->mMessageId
+                        << ", State : " << sync->mState << std::endl;
+                type = sync->mState;
+
+            });
+
+    g_providerSimul.notifyMessage(id, title, msg);
+    {
+        std::unique_lock< std::mutex > lock{ mutexForCondition };
+        responseCon.wait_for(lock, g_waitForResponse);
+    }
+
+//    g_providerSimul.deleteNotificationResource();
+//    NSStopConsumer();
+
+    EXPECT_EQ(Notification_Read, type);
+}
+
+TEST_F(NotificationConsumerTest, ExpectCallbackDismissCheckWhenConsumerPostSync)
+{
+    std::string id = "ExpectCallbackDismissCheckWhenConsumerPostSync";
+    std::string title = "title";
+    std::string msg = "msg";
+
+    NSSyncTypes type = Notification_Read;
+
+    mocks.OnCallFunc(NSNotificationReceivedCallbackEmpty).Do(
+            [](NSProvider *, NSMessage * message)
+            {
+                std::cout << "Income Notification : " << message->mId << std::endl;
+                NSConsumerDismissCheck(message);
+                std::unique_lock< std::mutex > lock{ mutexForCondition };
+                responseCon.wait_for(lock, g_waitForResponse);
+            });
+
+    mocks.ExpectCallFunc(NSSyncCallbackEmpty).Do(
+            [& type](NSProvider *, NSSync * sync)
+            {
+                std::cout << "Income Notification : " << sync->mMessageId
+                        << ", State : " << sync->mState << std::endl;
+                type = sync->mState;
+
+            });
+
+    g_providerSimul.notifyMessage(id, title, msg);
+    {
+        std::unique_lock< std::mutex > lock{ mutexForCondition };
+        responseCon.wait_for(lock, g_waitForResponse);
+    }
+
+    g_providerSimul.deleteNotificationResource();
+    NSStopConsumer();
+
+    EXPECT_EQ(Notification_Dismiss, type);
+}
diff --git a/service/notification/unittest/NSProviderSimulator.h b/service/notification/unittest/NSProviderSimulator.h
new file mode 100644 (file)
index 0000000..36a8f54
--- /dev/null
@@ -0,0 +1,300 @@
+//******************************************************************
+//
+// Copyright 2016 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef _NS_PROVIDER_SIMULATOR_H_
+#define _NS_PROVIDER_SIMULATOR_H_
+
+#include <iostream>
+
+#include "OCPlatform.h"
+#include "OCApi.h"
+#include "OCResourceResponse.h"
+
+namespace
+{
+    enum class requestType
+    {
+        NS_NOTIFICATION,
+        NS_MESSAGE,
+        NS_SYNC,
+    };
+}
+
+class NSProviderSimulator
+{
+private:
+    OCResourceHandle m_notificationHandle;
+    OCResourceHandle m_messageHandle;
+    OCResourceHandle m_syncHandle;
+    OC::OCRepresentation m_syncRep;
+    OC::OCRepresentation m_messageRep;
+    int m_accepter;
+
+    std::string m_notificationUri;
+    std::string m_messageUri;
+    std::string m_syncUri;
+
+    OC::ObservationIds m_syncObservers;
+
+public:
+    NSProviderSimulator()
+    : m_notificationHandle(), m_messageHandle(), m_syncHandle(),
+      m_syncRep(), m_messageRep(), m_accepter(0),
+      m_notificationUri(std::string("/notification")),
+      m_messageUri(std::string("/message")),
+      m_syncUri(std::string("/sync")),
+      m_syncObservers() { };
+
+    ~NSProviderSimulator() = default;
+
+    NSProviderSimulator(const NSProviderSimulator &) = delete;
+    NSProviderSimulator & operator = (const NSProviderSimulator &) = delete;
+
+    NSProviderSimulator(NSProviderSimulator &&) = delete;
+    NSProviderSimulator & operator = (NSProviderSimulator &&) = delete;
+
+private:
+    std::shared_ptr<OC::OCResourceResponse> getResponse(
+            std::shared_ptr< OC::OCResourceRequest > requests, requestType type)
+    {
+        auto response = std::make_shared<OC::OCResourceResponse>();
+        response->setRequestHandle(requests->getRequestHandle());
+        response->setResourceHandle(requests->getResourceHandle());
+
+        int requestFlag = requests->getRequestHandlerFlag();
+        if (requestFlag == OC::RequestHandlerFlag::RequestFlag)
+        {
+            std::string request = requests->getRequestType();
+
+            response->setErrorCode(200);
+            response->setResponseResult(OC_EH_OK);
+
+            if (request == "GET")
+            {
+                OC::OCRepresentation rep;
+
+                if (type == requestType::NS_NOTIFICATION)
+                {
+                    std::string msgUri = m_notificationUri + m_messageUri;
+                    std::string syncUri = m_notificationUri + m_syncUri;
+                    rep.setValue("ACCEPTER", m_accepter);
+                    rep.setValue("MESSAGE_URI", msgUri);
+                    rep.setValue("SYNC_URI", syncUri);
+                }
+                else if (type == requestType::NS_SYNC)
+                {
+                    rep = m_syncRep;
+                }
+                else if (type == requestType::NS_MESSAGE)
+                {
+                    rep = m_messageRep;
+                }
+                else
+                {
+                    return NULL;
+                }
+
+                response->setResourceRepresentation(rep);
+                return response;
+            }
+
+            else if (request == "POST" && type == requestType::NS_SYNC)
+            {
+                m_syncRep = requests->getResourceRepresentation();
+
+                std::cout << "Receive POST at Sync" << std::endl;
+                std::cout << "Sync Id : " << m_syncRep.getValueToString("ID") << std::endl;
+                std::cout << "Sync State : " << m_syncRep.getValueToString("STATE") << std::endl;
+
+                response->setResourceRepresentation(m_syncRep);
+
+                OC::OCPlatform::notifyListOfObservers(m_syncHandle, m_syncObservers, response);
+
+                return response;
+            }
+        }
+
+        return NULL;
+    }
+
+    void setObserver(std::shared_ptr< OC::OCResourceRequest > requests, requestType type)
+    {
+        if (type == requestType::NS_SYNC)
+        {
+            OC::ObservationInfo observationInfo = requests->getObservationInfo();
+            if (OC::ObserveAction::ObserveRegister == observationInfo.action)
+            {
+                m_syncObservers.push_back(observationInfo.obsId);
+            }
+            else if (OC::ObserveAction::ObserveUnregister == observationInfo.action)
+            {
+                m_syncObservers.erase(std::remove(
+                        m_syncObservers.begin(), m_syncObservers.end(),
+                        observationInfo.obsId), m_syncObservers.end());
+            }
+        }
+    }
+
+    OCEntityHandlerResult entityHandler(
+            std::shared_ptr< OC::OCResourceRequest > request, requestType type)
+    {
+        if (!request)
+        {
+            return OC_EH_ERROR;
+        }
+
+        std::cout << "Provider : Income request : " << request->getRequestHandlerFlag() << std::endl;
+        if ((request->getRequestHandlerFlag() & OC::RequestHandlerFlag::ObserverFlag))
+        {
+            std::cout << "Provider : Income Observe : " << std::endl;
+            setObserver(request, type);
+            return OC_EH_OK;
+        }
+
+        auto pResponse = getResponse(request, type);
+        if (pResponse == nullptr)
+        {
+            return OC_EH_ERROR;
+        }
+
+        try
+        {
+            OC::OCPlatform::sendResponse(pResponse);
+        }
+        catch (std::exception & e)
+        {
+            return OC_EH_ERROR;
+        }
+
+        return OC_EH_OK;
+    }
+
+public:
+
+    void setAccepter(int accepter)
+    {
+        m_accepter = accepter;
+    }
+
+    void notifyMessage()
+    {
+        std::cout << "Provider : notify~" << std::endl;
+        OC::OCPlatform::notifyAllObservers(m_messageHandle);
+    }
+
+    void notifyMessage(const std::string & id, const std::string & title, const std::string & content)
+    {
+        setMessage(id, title, content);
+        notifyMessage();
+    }
+
+    void sendRead(const std::string & id)
+    {
+        m_syncRep.setValue("ID", id);
+        m_syncRep.setValue("STATE", (int)0);
+        OC::OCPlatform::notifyAllObservers(m_syncHandle);
+    }
+    void sendDismiss(const std::string & id)
+    {
+        m_syncRep.setValue("ID", id);
+        m_syncRep.setValue("STATE", (int)1);
+        OC::OCPlatform::notifyAllObservers(m_syncHandle);
+    }
+
+    void setMessage(const std::string & id, const std::string & title, const std::string & content)
+    {
+        m_messageRep.setValue("ID", id);
+        m_messageRep.setValue("TITLE", title);
+        m_messageRep.setValue("CONTENTTEXT", content);
+    }
+
+    void deleteNotificationResource()
+    {
+        OC::OCPlatform::unregisterResource(m_notificationHandle);
+        OC::OCPlatform::unregisterResource(m_messageHandle);
+        OC::OCPlatform::unregisterResource(m_syncHandle);
+    }
+
+    void createNotificationResource()
+    {
+        createNotificationResource(m_notificationUri);
+    }
+
+    void createNotificationResource(const std::string & uri)
+    {
+        if (m_notificationUri != uri)
+        {
+            m_notificationUri = uri;
+        }
+
+        OC::OCPlatform::startPresence(30);
+
+        std::string notificationUri = m_notificationUri;
+        std::string resourceTypeName = "oic.r.message.notification";
+        std::string resourceInterface = OC::DEFAULT_INTERFACE;
+
+        uint8_t resourceProperty = OC_OBSERVABLE;
+        std::string childUri = uri + m_messageUri;
+        try
+        {
+            OC::OCPlatform::registerResource(
+                    m_messageHandle, childUri,
+                    resourceTypeName, resourceInterface,
+                    std::bind(& NSProviderSimulator::entityHandler, this,
+                            std::placeholders::_1, requestType::NS_MESSAGE),
+                            resourceProperty);
+        } catch (std::exception & e)
+        {
+            std::cout << e.what() << std::endl;
+        }
+
+        resourceTypeName = "oic.r.sync.notification";
+        childUri = uri + m_syncUri;
+        try
+        {
+            OC::OCPlatform::registerResource(
+                    m_syncHandle, childUri,
+                    resourceTypeName, resourceInterface,
+                    std::bind(& NSProviderSimulator::entityHandler, this,
+                            std::placeholders::_1, requestType::NS_SYNC),
+                            resourceProperty);
+        } catch (std::exception & e)
+        {
+            std::cout << e.what() << std::endl;
+        }
+
+        resourceProperty = OC_DISCOVERABLE;
+        resourceTypeName = "oic.r.notification";
+        try
+        {
+            OC::OCPlatform::registerResource(
+                    m_notificationHandle, notificationUri,
+                    resourceTypeName, resourceInterface,
+                    std::bind(& NSProviderSimulator::entityHandler, this,
+                            std::placeholders::_1, requestType::NS_NOTIFICATION),
+                            resourceProperty);
+        } catch (std::exception & e)
+        {
+            std::cout << e.what() << std::endl;
+        }
+    }
+};
+
+#endif /* _NS_PROVIDER_SIMULATOR_H_ */
diff --git a/service/notification/unittest/NSProviderTest.cpp b/service/notification/unittest/NSProviderTest.cpp
new file mode 100644 (file)
index 0000000..22f8421
--- /dev/null
@@ -0,0 +1,286 @@
+//******************************************************************
+//
+// Copyright 2016 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 <gtest/gtest.h>
+#include <HippoMocks/hippomocks.h>
+#include <atomic>
+#include <functional>
+#include <condition_variable>
+#include <mutex>
+#include <chrono>
+
+#include "NSConsumerSimulator.h"
+
+#include "NSCommon.h"
+#include "NSProviderInterface.h"
+
+namespace
+{
+    std::atomic_bool g_isStartedStack(false);
+
+    std::chrono::milliseconds g_waitForResponse(500);
+
+    std::condition_variable responseCon;
+    std::mutex mutexForCondition;
+
+    NSConsumerSimulator g_consumerSimul;
+    NSConsumer * g_consumer;
+
+}
+
+class TestWithMock: public testing::Test
+{
+public:
+    MockRepository mocks;
+
+protected:
+    virtual ~TestWithMock() noexcept(noexcept(std::declval<Test>().~Test())) {}
+
+    virtual void TearDown() {
+        try
+        {
+            mocks.VerifyAll();
+        }
+        catch (...)
+        {
+            mocks.reset();
+            throw;
+        }
+    }
+};
+
+class NotificationProviderTest : public TestWithMock
+{
+public:
+    NotificationProviderTest() = default;
+    ~NotificationProviderTest() = default;
+
+    static void NSRequestedSubscribeCallbackEmpty(NSConsumer *)
+    {
+        std::cout << __func__ << std::endl;
+    }
+
+    static void NSSyncCallbackEmpty(NSSync *)
+    {
+        std::cout << __func__ << std::endl;
+    }
+
+    static void NSMessageCallbackFromConsumerEmpty(
+            const std::string &, const std::string &, const std::string &)
+    {
+        std::cout << __func__ << std::endl;
+    }
+
+    static void NSSyncCallbackFromConsumerEmpty(int, const std::string &)
+    {
+        std::cout << __func__ << std::endl;
+    }
+
+protected:
+
+    void SetUp()
+    {
+        TestWithMock::SetUp();
+
+        if (g_isStartedStack == false)
+        {
+            OC::PlatformConfig cfg
+            {
+                OC::ServiceType::InProc,
+                OC::ModeType::Both,
+                "0.0.0.0",
+                0,
+                OC::QualityOfService::LowQos
+            };
+            OC::OCPlatform::Configure(cfg);
+
+            try
+            {
+                OC::OCPlatform::stopPresence();
+            }
+            catch (...)
+            {
+
+            }
+
+            g_isStartedStack = true;
+        }
+
+    }
+
+    void TearDown()
+    {
+        TestWithMock::TearDown();
+    }
+
+};
+
+TEST_F(NotificationProviderTest, StartProviderPositive)
+{
+    NSResult ret = NSStartProvider(NS_ACCEPTER_PROVIDER,
+            NSRequestedSubscribeCallbackEmpty,
+            NSSyncCallbackEmpty);
+
+    std::unique_lock< std::mutex > lock{ mutexForCondition };
+    responseCon.wait_for(lock, g_waitForResponse);
+
+    EXPECT_EQ(ret, NS_OK);
+}
+
+TEST_F(NotificationProviderTest, StopProviderPositive)
+{
+    NSResult ret = NSStopProvider();
+
+    std::unique_lock< std::mutex > lock{ mutexForCondition };
+    responseCon.wait_for(lock, g_waitForResponse);
+
+    EXPECT_EQ(ret, NS_OK);
+}
+
+TEST_F(NotificationProviderTest, ExpectCallbackWhenReceiveSubscribeRequestWithAccepterProvider)
+{
+    mocks.ExpectCallFunc(NSRequestedSubscribeCallbackEmpty).Do(
+            [](NSConsumer * consumer)
+            {
+                std::cout << "NSRequestedSubscribeCallback" << std::endl;
+                g_consumer = consumer;
+                responseCon.notify_all();
+            });
+
+    NSStartProvider(NS_ACCEPTER_PROVIDER,
+            NSRequestedSubscribeCallbackEmpty, NSSyncCallbackEmpty);
+
+    {
+        std::unique_lock< std::mutex > lock{ mutexForCondition };
+        responseCon.wait_for(lock, g_waitForResponse);
+    }
+
+    g_consumerSimul.setCallback(NSMessageCallbackFromConsumerEmpty,
+            NSSyncCallbackFromConsumerEmpty);
+    g_consumerSimul.findProvider();
+
+    std::unique_lock< std::mutex > lock{ mutexForCondition };
+    responseCon.wait_for(lock, std::chrono::milliseconds(1000));
+}
+
+TEST_F(NotificationProviderTest, NeverCallNotifyOnConsumerByAcceptIsFalse)
+{
+    bool expectTrue = true;
+
+    mocks.OnCallFunc(NSMessageCallbackFromConsumerEmpty).Do(
+            [& expectTrue](const std::string &id, const std::string&, const std::string&)
+            {
+                if (id == "NeverCallNotifyOnConsumerByAcceptIsFalse")
+                {
+                    std::cout << "This function never call" << std::endl;
+                    expectTrue = false;
+                }
+            });
+
+    NSAccept(g_consumer, false);
+
+    NSMessage * msg = new NSMessage();
+    msg->mId = strdup(std::string("NeverCallNotifyOnConsumerByAcceptIsFalse").c_str());
+    msg->mTitle = strdup(std::string("Title").c_str());
+    msg->mContentText = strdup(std::string("ContentText").c_str());
+    NSSendNotification(msg);
+    {
+        std::unique_lock< std::mutex > lock{ mutexForCondition };
+        responseCon.wait_for(lock, g_waitForResponse);
+    }
+
+    std::unique_lock< std::mutex > lock{ mutexForCondition };
+    responseCon.wait_for(lock, std::chrono::milliseconds(1000));
+
+    EXPECT_EQ(expectTrue, true);
+}
+
+TEST_F(NotificationProviderTest, ExpectCallNotifyOnConsumerByAcceptIsTrue)
+{
+    mocks.ExpectCallFunc(NSMessageCallbackFromConsumerEmpty).Do(
+            [](const std::string &id, const std::string&, const std::string&)
+            {
+                if (id == "ExpectCallNotifyOnConsumerByAcceptIsTrue")
+                {
+                    std::cout << "ExpectCallNotifyOnConsumerByAcceptIsTrue" << std::endl;
+                    responseCon.notify_all();
+                }
+            });
+
+    NSAccept(g_consumer, true);
+
+    NSMessage * msg = new NSMessage();
+    msg->mId = strdup(std::string("ExpectCallNotifyOnConsumerByAcceptIsTrue").c_str());
+    msg->mTitle = strdup(std::string("Title").c_str());
+    msg->mContentText = strdup(std::string("ContentText").c_str());
+    NSSendNotification(msg);
+    {
+        std::unique_lock< std::mutex > lock{ mutexForCondition };
+        responseCon.wait_for(lock, g_waitForResponse);
+    }
+
+    std::unique_lock< std::mutex > lock{ mutexForCondition };
+    responseCon.wait_for(lock, g_waitForResponse);
+}
+
+//TEST_F(NotificationProviderTest, ExpectCallbackSyncOnReadToConsumer)
+//{
+//    int type = 0;
+//    std::string id = "ExpectCallNotifyOnConsumerByAcceptIsTrue";
+//    mocks.ExpectCallFunc(NSSyncCallbackFromConsumerEmpty).Do(
+//            [& id](int type, const std::string & syncId)
+//            {
+//        std::cout << "NSSyncCallbackEmpty" << std::endl;
+//                if (syncId == id &&
+//                        type == Notification_Read)
+//                {
+//                    std::cout << "ExpectCallbackSyncOnReadFromConsumer" << std::endl;
+//                    responseCon.notify_all();
+//                }
+//            });
+//
+//    NSMessage * msg = new NSMessage();
+//    msg->mId = strdup(std::string("ExpectCallNotifyOnConsumerByAcceptIsTrue").c_str());
+//    msg->mTitle = strdup(std::string("Title").c_str());
+//    msg->mContentText = strdup(std::string("ContentText").c_str());
+//    NSProviderReadCheck(msg);
+//    std::unique_lock< std::mutex > lock{ mutexForCondition };
+//    responseCon.wait_for(lock, std::chrono::milliseconds(5000));
+//}
+
+//TEST_F(NotificationProviderTest, ExpectCallbackSyncOnReadFromConsumer)
+//{
+//    int type = 0;
+//    std::string id("ExpectCallNotifyOnConsumerByAcceptIsTrue");
+//    mocks.ExpectCallFunc(NSSyncCallbackEmpty).Do(
+//            [& id](NSSync * sync)
+//            {
+//                std::cout << "NSSyncCallbackEmpty" << std::endl;
+//                if (sync->mMessageId == id && sync->mState == Notification_Read)
+//                {
+//                    std::cout << "ExpectCallbackSyncOnReadFromConsumer" << std::endl;
+//                    responseCon.notify_all();
+//                }
+//            });
+//
+//    g_consumerSimul.syncToProvider(type, std::string(id));
+//    std::unique_lock< std::mutex > lock{ mutexForCondition };
+//    responseCon.wait_for(lock, std::chrono::milliseconds(5000));
+//}
diff --git a/service/notification/unittest/SConscript b/service/notification/unittest/SConscript
new file mode 100644 (file)
index 0000000..2d8b990
--- /dev/null
@@ -0,0 +1,96 @@
+#******************************************************************
+#
+# Copyright 2016 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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+##
+# Notification 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'
+
+notification_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')
+
+notification_test_env.AppendUnique(LIBPATH = [lib_env.get('BUILD_DIR')])
+notification_test_env.AppendUnique(LIBS = [
+    'connectivity_abstraction', 'oc', 'octbstack', 'oc_logger', 'coap',
+    GTest_Main, GTest])
+
+if target_os not in ['windows', 'winrt']:
+    notification_test_env.AppendUnique(CXXFLAGS = ['-O2', '-g', '-Wall', '-fmessage-length=0', '-std=c++0x'])
+
+notification_test_env.AppendUnique(CXXFLAGS = ['-pthread'])
+notification_test_env.AppendUnique(LIBS = ['pthread'])
+
+notification_test_env.PrependUnique(CPPPATH = [ src_dir + '/extlibs/hippomocks-master', gtest_dir + '/include'])
+notification_test_env.AppendUnique(CPPPATH = ['../include'])
+
+#if not env.get('RELEASE'):
+#    notification_test_env.PrependUnique(LIBS = ['gcov'])
+#    notification_test_env.AppendUnique(CXXFLAGS = ['--coverage'])
+
+######################################################################
+# Build Test
+######################################################################
+
+notification_consumer_test_env = notification_test_env.Clone()
+notification_consumer_test_env.AppendUnique(LIBS = ['notification_consumer'])
+
+notification_provider_test_env = notification_test_env.Clone()
+notification_provider_test_env.AppendUnique(LIBS = ['notification_provider'])
+
+notification_consumer_test_src = env.Glob('./NSConsumerTest.cpp')
+notification_consumer_test = notification_consumer_test_env.Program('notification_consumer_test', notification_consumer_test_src)
+Alias("notification_consumer_test", notification_consumer_test)
+env.AppendTarget('notification_consumer_test')
+
+notification_provider_test_src = env.Glob('./NSProviderTest.cpp')
+notification_provider_test = notification_provider_test_env.Program('notification_provider_test', notification_provider_test_src)
+Alias("notification_provider_test", notification_provider_test)
+env.AppendTarget('notification_provider_test')
+
+if env.get('TEST') == '1':
+    if target_os == 'linux':
+            from tools.scons.RunTest import *
+            run_test(notification_consumer_test_env, '', 'service/notification/unittest/notification_consumer_test')
+            #run_test(notification_provider_test_env, '', 'service/notification/unittest/notification_provider_test')
\ No newline at end of file