Update unit test and Fix bug.
authorKIM JungYong <jyong2.kim@samsung.com>
Thu, 8 Sep 2016 09:02:41 +0000 (18:02 +0900)
committerUze Choi <uzchoi@samsung.com>
Fri, 9 Sep 2016 01:37:43 +0000 (01:37 +0000)
Unit test is updated for apply latest consumer logic.
And unit test of basic topic operation is added.

Invalid memory access is fixed.

Change-Id: I0fd30c6e0eb3e97196e591b5754aaf38c814ffa2
Signed-off-by: KIM JungYong <jyong2.kim@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/11569
Reviewed-by: Uze Choi <uzchoi@samsung.com>
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
service/notification/src/consumer/NSConsumerInternalTaskController.c
service/notification/unittest/NSConsumerTest.cpp
service/notification/unittest/NSProviderSimulator.h

index 0c156d0..1cd5772 100644 (file)
@@ -174,6 +174,8 @@ void NSCancelAllSubscription()
 
         NSConsumerPushEvent(task);
     }
+
+    NSDestroyMessageStateList();
 }
 
 void NSConsumerHandleProviderDiscovered(NSProvider_internal * provider)
@@ -544,6 +546,12 @@ NSMessageStateLL * NSFindMessageState(uint64_t msgId)
     NSMessageStateLL * iter = NULL;
 
     NSLockMessageListMutex();
+    if (NSGetMessageStateList()->head == NULL)
+    {
+        NSUnlockMessageListMutex();
+        return false;
+    }
+
     for (iter = NSGetMessageStateList()->head; iter; iter = iter->next)
     {
         if (iter->messageId == msgId)
@@ -659,5 +667,8 @@ void NSDestroyMessageStateList()
         NSOICFree(del);
     }
 
+    NSGetMessageStateList()->head = NULL;
+    NSGetMessageStateList()->tail = NULL;
+
     NSUnlockMessageListMutex();
 }
index 4360a2b..d841b51 100644 (file)
@@ -52,6 +52,8 @@ namespace
     };
 
     NSConsumerConfig cfg;
+
+    NSProviderSimulator::NS_TopicStateList g_topicStateList;
 }
 
 class TestWithMock: public testing::Test
@@ -302,10 +304,14 @@ TEST_F(NotificationConsumerTest, ExpectReceiveNotification)
     std::string title = "title";
     std::string msg = "msg";
 
-    mocks.ExpectCallFunc(NSNotificationReceivedCallbackEmpty).Do(
-            [this](NSMessage * message)
+    uint64_t revId = 0;
+
+    mocks.OnCallFunc(NSNotificationReceivedCallbackEmpty).Do(
+            [this, & revId](NSMessage * message)
             {
                 std::cout << "Income Notification : " << message->messageId << std::endl;
+                revId = message->messageId;
+                responseCon.notify_all();
             });
 
     g_providerSimul.notifyMessage(id, title, msg);
@@ -313,16 +319,31 @@ TEST_F(NotificationConsumerTest, ExpectReceiveNotification)
     std::unique_lock< std::mutex > lock{ mutexForCondition };
     responseCon.wait_for(lock, g_waitForResponse);
 
+    EXPECT_EQ(id, revId);
     NSStopConsumer();
+    g_providerSimul.deleteNotificationResource();
 }
 
 TEST_F(NotificationConsumerTest, ExpectReceiveSubAllowWithAccepterisProvider)
 {
     g_providerSimul.setAccepter((int)NSSelector::NS_SELECTION_PROVIDER);
     NSProviderState revState = NS_DENY;
+    g_providerSimul.createNotificationResource();
+    {
+        std::unique_lock< std::mutex > lock{ mutexForCondition };
+        responseCon.wait_for(lock, g_waitForResponse);
+    }
 
     mocks.OnCallFunc(NSProviderChangedCallback).Do(
-            [this, & revState](NSProvider * , NSProviderState state)
+            [this, & revState](NSProvider * provider, NSProviderState state)
+            {
+                std::cout << "Income Changed Callback : " << state << std::endl;
+                revState = state;
+                g_provider = provider;
+                responseCon.notify_all();
+            });
+    mocks.OnCallFunc(NSProviderChangedCallback).Do(
+            [this, & revState](NSProvider *, NSProviderState state)
             {
                 std::cout << "Income Changed Callback : " << state << std::endl;
                 revState = state;
@@ -348,6 +369,7 @@ TEST_F(NotificationConsumerTest, ExpectReceiveNotificationWithAccepterisProvider
             {
                 std::cout << "Income Notification : " << message->messageId << std::endl;
                 revId = message->messageId;
+                responseCon.notify_all();
             });
 
     g_providerSimul.notifyMessage(id, title, msg);
@@ -369,6 +391,7 @@ TEST_F(NotificationConsumerTest, ExpectCallbackReadCheckWhenProviderNotifySync)
             [this](NSMessage * message)
             {
                 std::cout << "Income Notification : " << message->messageId << std::endl;
+                responseCon.notify_all();
             });
 
     mocks.OnCallFunc(NSSyncCallbackEmpty).Do(
@@ -377,6 +400,7 @@ TEST_F(NotificationConsumerTest, ExpectCallbackReadCheckWhenProviderNotifySync)
                 std::cout << "Income SyncInfo : " << sync->messageId
                         << ", State : " << sync->state << std::endl;
                 type = sync->state;
+                responseCon.notify_all();
             });
 
     g_providerSimul.notifyMessage(id, title, msg);
@@ -405,6 +429,7 @@ TEST_F(NotificationConsumerTest, ExpectCallbackDismissCheckWhenProviderNotifySyn
             [this](NSMessage * message)
             {
                 std::cout << "Income Notification : " << message->messageId << std::endl;
+                responseCon.notify_all();
             });
 
     mocks.OnCallFunc(NSSyncCallbackEmpty).Do(
@@ -413,6 +438,7 @@ TEST_F(NotificationConsumerTest, ExpectCallbackDismissCheckWhenProviderNotifySyn
                 std::cout << "Income Notification : " << sync->messageId
                         << ", State : " << sync->state << std::endl;
                 type = sync->state;
+                responseCon.notify_all();
             });
 
     g_providerSimul.notifyMessage(id, title, msg);
@@ -452,6 +478,7 @@ TEST_F(NotificationConsumerTest, ExpectCallbackReadCheckWhenConsumerPostSync)
                 std::cout << "Income Notification : " << sync->messageId
                         << ", State : " << sync->state << std::endl;
                 type = sync->state;
+                responseCon.notify_all();
             });
 
     g_providerSimul.notifyMessage(id, title, msg);
@@ -485,6 +512,7 @@ TEST_F(NotificationConsumerTest, ExpectCallbackDismissCheckWhenConsumerPostSync)
                 std::cout << "Income Notification : " << sync->messageId
                         << ", State : " << sync->state << std::endl;
                 state = sync->state;
+                responseCon.notify_all();
             });
 
     g_providerSimul.notifyMessage(id, title, msg);
@@ -494,8 +522,68 @@ TEST_F(NotificationConsumerTest, ExpectCallbackDismissCheckWhenConsumerPostSync)
     }
 
     EXPECT_EQ(NS_SYNC_DELETED, state);
-//    g_providerSimul.deleteNotificationResource();
-//    NSStopConsumer();
+}
+
+TEST_F(NotificationConsumerTest, ExpectGetTopicListIsNULL)
+{
+    NSTopicLL * currentTopics = NSConsumerGetTopicList(g_provider->providerId);
+    EXPECT_EQ(NULL, currentTopics);
+}
+
+TEST_F(NotificationConsumerTest, ExpectCallbackTopicUpdated)
+{
+    NSProviderState revState = NS_STOPPED;
+    mocks.OnCallFunc(NSProviderChangedCallback).Do(
+        [this, & revState](NSProvider * , NSProviderState state)
+        {
+            std::cout << "Income Changed Callback : " << state << std::endl;
+            revState = state;
+            responseCon.notify_all();
+        });
+
+    NSProviderSimulator::NS_TopicList topics;
+    topics.push_back("1");
+    topics.push_back("2");
+    topics.push_back("3");
+
+    g_providerSimul.setTopics(topics);
+
+    std::unique_lock< std::mutex > lock{ mutexForCondition };
+    responseCon.wait_for(lock, g_waitForResponse);
+
+    EXPECT_EQ(NS_TOPIC, revState);
+}
+
+TEST_F(NotificationConsumerTest, ExpectEQTopicList)
+{
+    bool isSame = false;
+
+    NSProviderSimulator::NS_TopicList topics;
+    topics.push_back("1");
+    topics.push_back("2");
+    topics.push_back("3");
+
+    NSTopicLL * retTopic = NSConsumerGetTopicList(g_provider->providerId);
+    std::for_each (topics.begin(), topics.end(),
+            [this, & retTopic, & isSame](const std::string & str)
+            {
+                isSame = (str == std::string(retTopic->topicName));
+                retTopic = retTopic->next;
+            });
+
+    EXPECT_EQ(true, isSame);
+}
+
+TEST_F(NotificationConsumerTest, ExpectFailUpdateTopicOnConsumer)
+{
+    NSTopicLL * retTopic = NSConsumerGetTopicList(g_provider->providerId);
+    for (; retTopic; retTopic = retTopic->next)
+    {
+        retTopic->state = NS_TOPIC_SUBSCRIBED;
+    }
+    NSResult ret = NSConsumerUpdateTopicList(g_provider->providerId, retTopic);
+
+    EXPECT_EQ(NS_ERROR, ret);
 }
 
 TEST_F(NotificationConsumerTest, ExpectCallbackDeletedProvider)
@@ -505,7 +593,6 @@ TEST_F(NotificationConsumerTest, ExpectCallbackDeletedProvider)
             [& type, this](NSProvider * , NSProviderState state)
             {
                 std::cout << "Income Changed Callback : " << state << std::endl;
-                //EXPECT_EQ(state, NS_STOPPED);
                 type = state;
                 responseCon.notify_all();
             });
@@ -513,20 +600,8 @@ TEST_F(NotificationConsumerTest, ExpectCallbackDeletedProvider)
     g_providerSimul.deleteNotificationResource();
 
     std::unique_lock< std::mutex > lock{ mutexForCondition };
-    responseCon.wait_for(lock, g_waitForResponse);
+    responseCon.wait_for(lock, std::chrono::milliseconds(2000));
 
     EXPECT_EQ(type, NS_STOPPED);
     NSStopConsumer();
 }
-
-//TEST_F(NotificationConsumerTest, ExpectUnsubscribeSuccess)
-//{
-//    NSResult ret = NSUnsubscribe(g_provider->providerId);
-//    std::unique_lock< std::mutex > lock{ mutexForCondition };
-//    responseCon.wait_for(lock, g_waitForResponse);
-//
-//    g_providerSimul.deleteNotificationResource();
-//    NSStopConsumer();
-//
-//    EXPECT_EQ(NS_OK, ret);
-//}
index bae719b..49d1c33 100644 (file)
@@ -22,6 +22,7 @@
 #define _NS_PROVIDER_SIMULATOR_H_
 
 #include <iostream>
+#include <memory>
 
 #include "OCPlatform.h"
 #include "OCApi.h"
@@ -34,15 +35,33 @@ namespace
         NS_NOTIFICATION,
         NS_MESSAGE,
         NS_SYNC,
+        NS_TOPIC,
+    };
+    enum class messageType
+    {
+        NS_ALLOW = 1,
+        NS_DENY,
+        NS_TOPIC,
     };
 }
 
 class NSProviderSimulator
 {
+public:
+    enum class TopicAllowState
+    {
+        DENY,
+        ALLOW
+    };
+    typedef std::pair<std::string, TopicAllowState> NS_TopicState;
+    typedef std::map<std::string, TopicAllowState> NS_TopicStateList;
+
+    typedef std::list<std::string> NS_TopicList;
 private:
     OCResourceHandle m_notificationHandle;
     OCResourceHandle m_messageHandle;
     OCResourceHandle m_syncHandle;
+    OCResourceHandle m_topicHandle;
     OC::OCRepresentation m_syncRep;
     OC::OCRepresentation m_messageRep;
     int m_accepter;
@@ -50,16 +69,22 @@ private:
     std::string m_notificationUri;
     std::string m_messageUri;
     std::string m_syncUri;
+    std::string m_topicUri;
+    NS_TopicList m_topicList;
+    NS_TopicStateList m_allowedTopicList;
 
     OC::ObservationIds m_syncObservers;
 
 public:
     NSProviderSimulator()
-    : m_notificationHandle(), m_messageHandle(), m_syncHandle(),
+    : m_notificationHandle(), m_messageHandle(), m_syncHandle(), m_topicHandle(),
       m_syncRep(), m_messageRep(), m_accepter(0),
       m_notificationUri(std::string("/notification")),
       m_messageUri(std::string("/message")),
       m_syncUri(std::string("/sync")),
+      m_topicUri(std::string("/topic")),
+      m_topicList(),
+      m_allowedTopicList(),
       m_syncObservers()
     {
 
@@ -97,10 +122,12 @@ private:
                 {
                     std::string msgUri = m_notificationUri + m_messageUri;
                     std::string syncUri = m_notificationUri + m_syncUri;
+                    std::string topicUri = m_notificationUri + m_topicUri;
                     std::string providerId = "123456789012345678901234567890123456";
-                    rep.setValue("ACCEPTER", (bool) m_accepter);
+                    rep.setValue("ACCEPTER", m_accepter);
                     rep.setValue("MESSAGE_URI", msgUri);
                     rep.setValue("SYNC_URI", syncUri);
+                    rep.setValue("TOPIC_URI", topicUri);
                     rep.setValue("PROVIDER_ID", providerId);
                 }
                 else if (type == requestType::NS_SYNC)
@@ -111,6 +138,35 @@ private:
                 {
                     rep = m_messageRep;
                 }
+                else if (type == requestType::NS_TOPIC)
+                {
+                    if (m_allowedTopicList.empty())
+                    {
+                        std::for_each (m_topicList.begin(), m_topicList.end(),
+                            [this](const std::string & topic)
+                            {
+                                m_allowedTopicList.insert(
+                                        std::make_pair<std::string, TopicAllowState>(
+                                                std::string(topic), TopicAllowState::DENY));
+                            }
+                        );
+                    }
+
+                    std::vector<OC::OCRepresentation> topicArr;
+
+                    std::for_each (m_allowedTopicList.begin(), m_allowedTopicList.end(),
+                        [& topicArr](const NS_TopicState & topicState)
+                        {
+                            OC::OCRepresentation topic;
+                            topic.setValue("TOPIC_NAME", topicState.first);
+                            topic.setValue("TOPIC_STATE", (int) topicState.second);
+                            topicArr.push_back(topic);
+                        }
+                    );
+
+                    rep.setValue<std::vector<OC::OCRepresentation>>
+                        ("TOPIC_LIST", topicArr);
+                }
                 else
                 {
                     return NULL;
@@ -122,17 +178,37 @@ private:
 
             else if (request == "POST" && type == requestType::NS_SYNC)
             {
-                m_syncRep = requests->getResourceRepresentation();
+                if (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;
+                    std::cout << "Receive POST for 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);
+                    response->setResourceRepresentation(m_syncRep);
 
-                OC::OCPlatform::notifyListOfObservers(m_syncHandle, m_syncObservers, response);
+                    OC::OCPlatform::notifyAllObservers(m_syncHandle);
 
-                return response;
+                    return response;
+                }
+                else if (type == requestType::NS_TOPIC)
+                {
+                    auto receivePayload =
+                            requests->getResourceRepresentation()
+                            .getValue<std::vector<OC::OCRepresentation>>("TOPIC_LIST");
+
+                    std::for_each (receivePayload.begin(), receivePayload.end(),
+                          [this](const OC::OCRepresentation & rep)
+                          {
+                              auto tmp = m_allowedTopicList.find(rep.getValueToString("TOPIC_NAME"));
+                              if (tmp != m_allowedTopicList.end())
+                              {
+                                  tmp->second = (TopicAllowState) rep.getValue<int>("TOPIC_STATE");
+                              }
+                          }
+                    );
+                }
             }
         }
 
@@ -159,7 +235,7 @@ private:
         {
             OC::OCRepresentation rep;
             std::string providerId = "123456789012345678901234567890123456";
-            rep.setValue<int>("MESSAGE_ID", (int)1);
+            rep.setValue<int>("MESSAGE_ID", (int)messageType::NS_ALLOW);
             rep.setValue("PROVIDER_ID", providerId);
 
             auto response = std::make_shared<OC::OCResourceResponse>();
@@ -255,11 +331,56 @@ public:
         m_messageRep.setValue("PROVIDER_ID", providerId);
     }
 
+    void setTopics(const NS_TopicList & topics)
+    {
+        bool isChanged = false;
+        std::for_each (topics.begin(), topics.end(),
+            [this, & isChanged](const std::string & topic)
+            {
+                auto found = std::find(
+                        this->m_topicList.begin(), this->m_topicList.end(), topic);
+                if (found == this->m_topicList.end())
+                {
+                    this->m_topicList.push_back(topic);
+                    isChanged = true;
+                }
+            });
+
+        if (isChanged)
+        {
+            this->notifyMessage((uint64_t)messageType::NS_TOPIC, "", "");
+        }
+    }
+
+    NS_TopicList getTopics() const
+    {
+        return m_topicList;
+    }
+
+    void updateTopicState(const NS_TopicStateList & allowedTopics)
+    {
+        std::for_each (allowedTopics.begin(), allowedTopics.end(),
+            [this](const NS_TopicState & allowedTopic)
+            {
+                auto found = this->m_allowedTopicList.find(allowedTopic.first);
+                if (found != this->m_allowedTopicList.end())
+                {
+                    found->second = allowedTopic.second;
+                }
+            });
+    }
+
+    NS_TopicStateList getTopicAllowState() const
+    {
+        return m_allowedTopicList;
+    }
+
     void deleteNotificationResource()
     {
         OC::OCPlatform::unregisterResource(m_notificationHandle);
         OC::OCPlatform::unregisterResource(m_messageHandle);
         OC::OCPlatform::unregisterResource(m_syncHandle);
+        OC::OCPlatform::unregisterResource(m_topicHandle);
     }
 
     void createNotificationResource()
@@ -277,11 +398,28 @@ public:
         OC::OCPlatform::startPresence(30);
 
         std::string notificationUri = m_notificationUri;
-        std::string resourceTypeName = "oic.r.message.notification";
+        std::string resourceTypeName = "oic.r.topic.notification";
         std::string resourceInterface = OC::DEFAULT_INTERFACE;
 
         uint8_t resourceProperty = OC_OBSERVABLE;
-        std::string childUri = uri + m_messageUri;
+        std::string childUri = uri + m_topicUri;
+        try
+        {
+            OC::OCPlatform::registerResource(
+                    m_topicHandle, childUri,
+                    resourceTypeName, resourceInterface,
+                    std::bind(& NSProviderSimulator::entityHandler, this,
+                            std::placeholders::_1, requestType::NS_TOPIC),
+                            resourceProperty);
+        }
+        catch(std::exception & e)
+        {
+            std::cout << e.what() << std::endl;
+        }
+
+        //resourceProperty |= OC_OBSERVABLE;
+        resourceTypeName = "oic.r.message.notification";
+        childUri = uri + m_messageUri;
         try
         {
             OC::OCPlatform::registerResource(
@@ -312,7 +450,7 @@ public:
             std::cout << e.what() << std::endl;
         }
 
-        resourceProperty = OC_DISCOVERABLE;
+        resourceProperty |= OC_DISCOVERABLE;
         resourceTypeName = "oic.r.notification";
         try
         {