[Enrollee] Unit Test case implementation for linux enrollee
authorSandipan Patra <sandipan.p@samsung.com>
Wed, 24 Feb 2016 04:20:32 +0000 (09:50 +0530)
committerMadan Lanka <lanka.madan@samsung.com>
Sat, 27 Feb 2016 11:14:31 +0000 (11:14 +0000)
Change-Id: I5f5a2c7424d643f755af32d5485a2a1858c1f1a8
Signed-off-by: Sandipan Patra <sandipan.p@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/5153
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Madan Lanka <lanka.madan@samsung.com>
service/easy-setup/SConscript
service/easy-setup/enrollee/SConscript
service/easy-setup/enrollee/unittests/SConscript [new file with mode: 0644]
service/easy-setup/enrollee/unittests/enrolleetests.cpp [new file with mode: 0644]
service/easy-setup/enrollee/unittests/gtesthelper.h [new file with mode: 0644]

index b2d3760..3028c08 100755 (executable)
@@ -28,7 +28,7 @@ es_role = env.get('ES_ROLE')
 es_target_enrollee = env.get('ES_TARGET_ENROLLEE')
 
 print "************************************************************************************"
-print " Easysetup device role --> %s " % es_role
+print "Easysetup device role --> %s " % es_role
 print "Target Platform --> %s " % es_target
 print "Target Enrollee platform --> %s " % es_target_enrollee
 print "************************************************************************************"
index 47b895e..8b19cb1 100644 (file)
@@ -149,5 +149,6 @@ if target_os == 'arduino':
 
 if target_os == 'linux':
        SConscript('../sampleapp/enrollee/linux/SConscript')
-
+       #Build UnitTestcases for Enrollee
+       SConscript('../enrollee/unittests/SConscript')
 
diff --git a/service/easy-setup/enrollee/unittests/SConscript b/service/easy-setup/enrollee/unittests/SConscript
new file mode 100644 (file)
index 0000000..6dc60e1
--- /dev/null
@@ -0,0 +1,94 @@
+#######################################################################
+# 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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+Import('env')
+import os
+import os.path
+enrollee_test_env = env.Clone()
+
+src_dir = enrollee_test_env.get('SRC_DIR')
+
+######################################################################
+# Build flags
+######################################################################
+
+enrollee_test_env.PrependUnique(CPPPATH = [
+               enrollee_test_env.get('SRC_DIR') + '/extlibs/gtest/gtest-1.7.0/include',
+               enrollee_test_env.get('SRC_DIR') + '/resource/c_common/ocrandom/include',
+               enrollee_test_env.get('SRC_DIR') + '/resource/csdk/stack/include/internal',
+               enrollee_test_env.get('SRC_DIR') + '/resource/csdk/connectivity/api',
+               enrollee_test_env.get('SRC_DIR') + '/resource/c_common/oic_malloc/include',
+               enrollee_test_env.get('SRC_DIR') + '/resource/include',
+               enrollee_test_env.get('SRC_DIR') + '/resource/csdk/logger/include',
+               enrollee_test_env.get('SRC_DIR') + '/resource/oc_logger/include',
+       enrollee_test_env.get('SRC_DIR') + '/resource/csdk/stack/include',
+               enrollee_test_env.get('SRC_DIR') + '/resource/csdk/stack/include/internal',
+        enrollee_test_env.get('SRC_DIR') + '/resource/csdk/logger/include',
+               enrollee_test_env.get('SRC_DIR') + '/resource/csdk/security/include',
+               enrollee_test_env.get('SRC_DIR') + '/extlibs/cjson',
+               enrollee_test_env.get('SRC_DIR') + '/extlibs/sqlite3',
+               enrollee_test_env.get('SRC_DIR') + '/service/easy-setup/inc',
+               enrollee_test_env.get('SRC_DIR') + '/service/easy-setup/enrollee/linux/wifi',
+               enrollee_test_env.get('SRC_DIR') + '/service/easy-setup/enrollee/inc',
+               enrollee_test_env.get('SRC_DIR') + '/service/easy-setup/enrollee/src'])
+
+enrollee_test_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+enrollee_test_env.AppendUnique(LIBS = ['-lpthread'])
+enrollee_test_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+enrollee_test_env.AppendUnique(LIBPATH = [src_dir + '/extlibs/gtest/gtest-1.7.0/lib/.libs'])
+enrollee_test_env.PrependUnique(LIBS = ['m',
+                                    'octbstack',
+                                    'ocsrm',
+                                    'connectivity_abstraction',
+                                    'coap',
+                                    'gtest',
+                                    'gtest_main'])
+
+target_os = env.get('TARGET_OS')
+if target_os != 'darwin':
+    enrollee_test_env.PrependUnique(LIBS = ['oc_logger'])
+
+if env.get('SECURED') == '1':
+    enrollee_test_env.AppendUnique(LIBS = ['tinydtls'])
+
+if env.get('LOGGING'):
+       enrollee_test_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+
+if env.get('ES_SOFTAP_MODE') == 'ENROLLEE_SOFTAP':
+       print "ES_SOFTAP_MODE == ENROLLEE_SOFTAP"
+       enrollee_test_env.AppendUnique(CPPDEFINES = ['ENROLLEE_SOFTAP'])
+
+enrollee_test_env.PrependUnique(LIBS = ['ESEnrolleeSDK'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+enrolleetests = enrollee_test_env.Program('enrolleetests', ['enrolleetests.cpp'])
+
+Alias("test", [enrolleetests])
+
+env.AppendTarget('test')
+if env.get('TEST') == '1':
+       target_os = env.get('TARGET_OS')
+       if target_os == 'linux':
+                from tools.scons.RunTest import *
+                run_test(enrollee_test_env,
+                         '',
+                         'service/easy-setup/enrollee/unittests/enrolleetests')
+
diff --git a/service/easy-setup/enrollee/unittests/enrolleetests.cpp b/service/easy-setup/enrollee/unittests/enrolleetests.cpp
new file mode 100644 (file)
index 0000000..6f55811
--- /dev/null
@@ -0,0 +1,304 @@
+//******************************************************************
+//
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/**
+ * @file
+ *
+ * This file contains the implementation for EasySetup Enrollee testcases
+ */
+
+#include "gtest/gtest.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+//-----------------------------------------------------------------------------
+// Includes
+//-----------------------------------------------------------------------------
+#include <stdio.h>
+#include <string.h>
+
+#include <iostream>
+#include <stdint.h>
+
+#include "ocstack.h"
+#include "logger.h"
+#include "oic_malloc.h"
+#include "escommon.h"
+#include "easysetup.h"
+#include "onboarding.h"
+#include "resourcehandler.h"
+#include "softap.h"
+
+#include "gtesthelper.h"
+
+using namespace std;
+
+namespace itst = iotivity::test;
+
+#define DEFAULT_CONTEXT_VALUE 0x99
+
+//-----------------------------------------------------------------------------
+// Private variables
+//-----------------------------------------------------------------------------
+static const char TAG[] = "TestHarness";
+
+char ssid[] = "EasySetup123";
+char passwd[] = "EasySetup123";
+
+void OnboardingCallback(ESResult esResult);
+
+//-----------------------------------------------------------------------------
+// Callback functions
+//-----------------------------------------------------------------------------
+extern "C"  void EventCallbackInApplication(ESResult esResult,
+                                                                    EnrolleeState enrolleeState)
+{
+    OIC_LOG(INFO, TAG, "Entering EventCallbackInApplication");
+
+    if(esResult != ES_OK)
+    {
+        cout<<"Easy stup is failed at Enrollee state = "<<enrolleeState<<endl;
+    }
+    else
+    {
+        if(enrolleeState == ES_ON_BOARDED_STATE)
+        {
+            cout<<"Device is successfully OnBoared on Adhoc network"<<endl;
+        }
+        else if (enrolleeState == ES_PROVISIONED_STATE)
+        {
+            cout<<"Device is provisioned with target network's credentials"<<endl;
+        }
+        else if (enrolleeState == ES_ON_BOARDED_TARGET_NETWORK_STATE)
+        {
+            cout<<"Device is onboarded/connected with target network"<<endl;
+        }
+        else
+        {
+            cout<<"Wrong state !! Easy setup is failed at Enrollee state = "<<enrolleeState<<endl;
+        }
+    }
+}
+
+//-----------------------------------------------------------------------------
+//  Local functions
+//-----------------------------------------------------------------------------
+
+void InitESEnrollee()
+{
+    OIC_LOG(INFO, TAG, "Entering InitESEnrollee");
+
+    EXPECT_EQ(ES_OK, InitEasySetup(CT_ADAPTER_IP,
+                                    "EasySetup123",
+                                    "EasySetup123",
+                                    0,
+                                    EventCallbackInApplication));
+    OIC_LOG(INFO, TAG, "Leaving InitESEnrollee");
+}
+
+//-----------------------------------------------------------------------------
+// Tests
+//-----------------------------------------------------------------------------
+
+TEST(ESEnrolleeInit, ESEnrolleeInitNullSSID)
+{
+    EXPECT_EQ(ES_ERROR, InitEasySetup(CT_ADAPTER_IP, 0, passwd, 0, EventCallbackInApplication));
+}
+
+TEST(ESEnrolleeInit, ESEnrolleeInitNullPassword)
+{
+    EXPECT_EQ(ES_ERROR, InitEasySetup(CT_ADAPTER_IP, ssid, 0, 0, EventCallbackInApplication));
+}
+
+TEST(ESEnrolleeInit, ESEnrolleeInitNullCb)
+{
+    EXPECT_EQ(ES_ERROR, InitEasySetup(CT_ADAPTER_IP, ssid, passwd, 0, 0));
+}
+
+TEST(ESEnrolleeInit, ESEnrolleeInitEasySetupSuccess)
+{
+    EXPECT_EQ(ES_OK, InitEasySetup(CT_ADAPTER_IP,
+                                    ssid,
+                                    passwd,
+                                    0,
+                                    EventCallbackInApplication));
+}
+
+TEST(ESEnrolleeInit, ESEnrolleeBleOnboarding)
+{
+    EXPECT_EQ(0, ESBleOnboarding());
+}
+
+TEST(ESEnrolleeInit, ESEnrolleeSoftapOnboarding)
+{
+    EXPECT_EQ(true, ESSoftapOnboarding());
+}
+
+TEST(ESOCInit, ESOCInitNullIPAddr)
+{
+    EXPECT_EQ(OC_STACK_OK, OCInit(0, 5683, OC_SERVER));
+    EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
+TEST(ESOCInit, ESOCInitNullPort)
+{
+    EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 0, OC_SERVER));
+    EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
+TEST(ESOCInit, ESOCInitNullAddrAndPort)
+{
+    EXPECT_EQ(OC_STACK_OK, OCInit(0, 0, OC_SERVER));
+    EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
+TEST(ESOCInit, ESOCInitInvalidMode)
+{
+    EXPECT_EQ(OC_STACK_ERROR, OCInit(0, 0, (OCMode)10));
+    EXPECT_EQ(OC_STACK_ERROR, OCStop());
+}
+
+TEST(ESProvisioning, ESInitProvisioning)
+{
+    EXPECT_EQ(ES_RESOURCECREATED, InitProvisioning());
+}
+
+TEST(ESProvisioning, ESInitProvisioningWithOCStackClientMode)
+{
+    EXPECT_EQ(OC_STACK_OK, OCInit(NULL, 0, OC_CLIENT));
+    EXPECT_EQ(ES_ERROR, InitProvisioning());
+    EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
+TEST(ESProvisioningResource, ESCreateProvisioningResourceSecurityDisabled)
+{
+    EXPECT_EQ(OC_STACK_OK, OCInit(0, 0, OC_SERVER));
+    EXPECT_EQ(OC_STACK_OK, CreateProvisioningResource(0));
+    EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
+TEST(ESProvisioningResource, ESCreateProvisioningResourceSecurityEnabled)
+{
+    EXPECT_EQ(OC_STACK_OK, OCInit(0, 0, OC_SERVER));
+    EXPECT_EQ(OC_STACK_OK, CreateProvisioningResource(1));
+    EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
+TEST(ESProvisioningResource, ESDeleteProvisioningResource)
+{
+    EXPECT_EQ(OC_STACK_OK, OCInit(0, 0, OC_SERVER));
+    EXPECT_EQ(OC_STACK_OK, CreateProvisioningResource(0));
+    EXPECT_EQ(OC_STACK_OK, DeleteProvisioningResource());
+    EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
+TEST(ESProvisioningResource, ESDeleteProvisioningResourceWithoutCreating)
+{
+    EXPECT_EQ(OC_STACK_OK, OCInit(0, 0, OC_SERVER));
+    EXPECT_EQ(OC_STACK_NO_RESOURCE, DeleteProvisioningResource());
+    EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
+TEST(ESOnboarding, ESOnboardingSoftAp)
+{
+    EXPECT_EQ(1, ESOnboard(ssid, passwd, OnboardingCallback));
+}
+
+TEST(ESOnboarding, ESOnboardingSoftApEnrollee)
+{
+#ifdef ENROLLEE_SOFTAP
+    EXPECT_EQ(1, ESSoftapAtEnrollee());
+    EXPECT_EQ(0, ESSoftapAtMediator());
+#endif
+}
+
+TEST(ESOnboarding, ESOnboardingSoftApMediator)
+{
+#ifndef ENROLLEE_SOFTAP
+    EXPECT_EQ(0, ESSoftapAtEnrollee());
+    EXPECT_EQ(1, ESSoftapAtMediator());
+#endif
+}
+
+TEST(ESOnboarding, ESOnboardingSoftApHost)
+{
+#ifdef ENROLLEE_SOFTAP
+    EXPECT_EQ(ENROLLEE, ESSoftapHost());
+#else
+    EXPECT_EQ(MEDIATOR, ESSoftapHost());
+#endif
+}
+
+TEST(ESStop, ESTerminateEasysetupWithoutESInit)
+{
+    EXPECT_EQ(ES_ERROR, TerminateEasySetup());
+}
+
+TEST(ESStop, ESTerminateEasysetupWithoutOCStack)
+{
+    EXPECT_EQ(ES_OK, InitEasySetup(CT_ADAPTER_IP,
+                                    ssid,
+                                    passwd,
+                                    0,
+                                    EventCallbackInApplication));
+    EXPECT_EQ(ES_ERROR, TerminateEasySetup());
+}
+
+TEST(ESStop, ESTerminateEasysetupWithOutCreateProvisioningResource)
+{
+    EXPECT_EQ(ES_OK, InitEasySetup(CT_ADAPTER_IP,
+                                    ssid,
+                                    passwd,
+                                    0,
+                                    EventCallbackInApplication));
+    EXPECT_EQ(OC_STACK_OK, OCInit(0, 0, OC_SERVER));
+    EXPECT_EQ(ES_ERROR, TerminateEasySetup());
+    EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
+TEST(ESStop, ESTerminateEasysetupWithoutProviosioningResource)
+{
+    EXPECT_EQ(ES_OK, InitEasySetup(CT_ADAPTER_IP,
+                                    ssid,
+                                    passwd,
+                                    0,
+                                    EventCallbackInApplication));
+    EXPECT_EQ(OC_STACK_OK, OCInit(NULL, 0, OC_SERVER));
+    EXPECT_EQ(ES_ERROR, TerminateEasySetup());
+    EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
+TEST(ESStop, ESTerminateEasysetupSuccess)
+{
+    EXPECT_EQ(ES_OK, InitEasySetup(CT_ADAPTER_IP,
+                                    ssid,
+                                    passwd,
+                                    0,
+                                    EventCallbackInApplication));
+    EXPECT_EQ(OC_STACK_OK, OCInit(NULL, 0, OC_SERVER));
+    EXPECT_EQ(ES_RESOURCECREATED, InitProvisioning());
+    EXPECT_EQ(ES_OK, TerminateEasySetup());
+    EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
diff --git a/service/easy-setup/enrollee/unittests/gtesthelper.h b/service/easy-setup/enrollee/unittests/gtesthelper.h
new file mode 100644 (file)
index 0000000..4de59eb
--- /dev/null
@@ -0,0 +1,151 @@
+//******************************************************************
+//
+// 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 IOTY_GTEST_HELPER_H
+#define IOTY_GTEST_HELPER_H
+
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <future>
+#include <mutex>
+#include <thread>
+
+namespace iotivity
+{
+    namespace test
+    {
+        /**
+         * Simple implementation of a deadman's timer that can be used to
+         * terminate a test that hangs.
+         *
+         * Since there is no standard way to terminate an individual thread,
+         * the entire process will be killed once time has been exceeded.
+         *
+         * @note provisions for watchdog thread cleanup are not currently added.
+         * Testing has not yet shown any need for such complexity.
+         */
+        class DeadmanTimer
+        {
+        public:
+
+            /**
+             * Creates an instance of a timer set to kill the running process
+             * after the specified timeout.
+             *
+             * If the destructor is invoked before time is up (aka this instance
+             * goes out of scope) the timeout will not cause the program to be
+             * terminated.
+             *
+             * @param time to wait before assuming the process is hung and must be
+             * killed.
+             * Examples of values that can be passed include
+             * std::chrono::milliseconds(250), std::chrono::seconds(5),
+             * std::chrono::minutes(3).
+             */
+            DeadmanTimer(std::chrono::milliseconds timeout) :
+                m_ctx(new DeadmanCtx(timeout)),
+                m_thread()
+                {
+                    m_thread = std::thread([this](){run(m_ctx);});
+                    {
+                        std::unique_lock<std::mutex> lock(m_ctx->m_mutex);
+                        while (!m_ctx->m_isArmed)
+                        {
+                            m_ctx->m_cond.wait(lock);
+                        }
+                    }
+                    // Now that the thread is live, we can stop tracking it.
+                    m_thread.detach();
+                }
+
+            /**
+             * Destructor that also will cancel the termination of the
+             * running process.
+             */
+            ~DeadmanTimer()
+            {
+                std::unique_lock<std::mutex> lock(m_ctx->m_mutex);
+                m_ctx->m_isArmed = false;
+            }
+
+        private:
+
+            /**
+             * Shared data that main and child thread might both need to
+             * access.
+             *
+             * Avoids referencing data in class instances that have been
+             * deleted.
+             */
+            class DeadmanCtx
+            {
+            public:
+
+                DeadmanCtx(std::chrono::milliseconds timeout) :
+                    m_mutex(),
+                    m_cond(),
+                    m_isArmed(false),
+                    m_timeout(timeout)
+                    {
+                    }
+
+                std::mutex m_mutex;
+                std::condition_variable m_cond;
+                bool m_isArmed;
+                std::chrono::milliseconds m_timeout;
+            };
+
+            // Explicitly block assignment and copy ctor
+            DeadmanTimer &operator=(const DeadmanTimer &rhs);
+            DeadmanTimer(const iotivity::test::DeadmanTimer &rhs);
+
+            std::shared_ptr<DeadmanCtx> m_ctx;
+            std::thread m_thread;
+
+
+            static void run(std::shared_ptr<DeadmanCtx> ctx)
+            {
+                // Let the calling thread know it can stop waiting:
+                {
+                    std::unique_lock<std::mutex> lock(ctx->m_mutex);
+                    ctx->m_isArmed = true;
+                    ctx->m_cond.notify_all();
+                }
+
+                std::this_thread::sleep_for(ctx->m_timeout);
+
+                std::unique_lock<std::mutex> lock(ctx->m_mutex);
+                if (ctx->m_isArmed)
+                {
+                    try {
+                        throw std::runtime_error("deadman timer expired");
+                    }
+                    catch (std::exception&)
+                    {
+                        std::terminate();
+                    }
+                }
+            }
+        };
+    } // namespace test
+} // namespace iotivity
+
+#endif // IOTY_GTEST_HELPER_H