From 8afbcc232fc00c4bfe8b13cf85a9c7111a74f4dc Mon Sep 17 00:00:00 2001 From: "jyong2.kim" Date: Wed, 18 May 2016 15:46:06 +0900 Subject: [PATCH] Added Unit Test of Notification service. Unit test of Notification serivces is added for public APIs on positive case. Change-Id: Ie658a444b2b7cc6052cb64933f54bfd58ceceb5c Signed-off-by: jyong2.kim Reviewed-on: https://gerrit.iotivity.org/gerrit/8209 Tested-by: jenkins-iotivity Reviewed-by: Uze Choi --- service/notification/SConscript | 4 +- .../notification/unittest/NSConsumerSimulator.h | 147 +++++++ service/notification/unittest/NSConsumerTest.cpp | 436 +++++++++++++++++++++ .../notification/unittest/NSProviderSimulator.h | 300 ++++++++++++++ service/notification/unittest/NSProviderTest.cpp | 286 ++++++++++++++ service/notification/unittest/SConscript | 96 +++++ 6 files changed, 1267 insertions(+), 2 deletions(-) create mode 100644 service/notification/unittest/NSConsumerSimulator.h create mode 100644 service/notification/unittest/NSConsumerTest.cpp create mode 100644 service/notification/unittest/NSProviderSimulator.h create mode 100644 service/notification/unittest/NSProviderTest.cpp create mode 100644 service/notification/unittest/SConscript diff --git a/service/notification/SConscript b/service/notification/SConscript index b1e51df..9319104 100644 --- a/service/notification/SConscript +++ b/service/notification/SConscript @@ -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 index 0000000..f1177ba --- /dev/null +++ b/service/notification/unittest/NSConsumerSimulator.h @@ -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 + +#include "OCPlatform.h" +#include "OCApi.h" + +class NSConsumerSimulator +{ +private: + std::function m_messageFunc; + std::function m_syncFunc; + + std::shared_ptr 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 & messageFunc, + const std::function & 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 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 resource) + { + std::cout << __func__ << " " << rep.getHost() << " result : " << eCode << std::endl; + + std::shared_ptr 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 ) + { + 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("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 index 0000000..8f38d43 --- /dev/null +++ b/service/notification/unittest/NSConsumerTest.cpp @@ -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 +#include +#include +#include +#include +#include +#include + +#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())) {} + + 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 index 0000000..36a8f54 --- /dev/null +++ b/service/notification/unittest/NSProviderSimulator.h @@ -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 + +#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 getResponse( + std::shared_ptr< OC::OCResourceRequest > requests, requestType type) + { + auto response = std::make_shared(); + 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 index 0000000..22f8421 --- /dev/null +++ b/service/notification/unittest/NSProviderTest.cpp @@ -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 +#include +#include +#include +#include +#include +#include + +#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())) {} + + 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 index 0000000..2d8b990 --- /dev/null +++ b/service/notification/unittest/SConscript @@ -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 -- 2.7.4