Reenable IPCA unit tests.
authorSoemin Tjong <stjong@microsoft.com>
Sun, 26 Mar 2017 22:28:44 +0000 (15:28 -0700)
committerDan Mihai <Daniel.Mihai@microsoft.com>
Thu, 30 Mar 2017 22:25:54 +0000 (22:25 +0000)
Fix: https://jira.iotivity.org/browse/IOT-1960

Address a couple of items:
Make a snapshot of vector variables for calling back to apps to address
issue with vector update in the middle of callbacks.

Also, properly delete observe handles in the mock library when app
cancels resource observation.  Otherwise the unit tests slow down as
number of test iteration increases.

Change-Id: I0116deb534ddfaa8e29b84a942ba3d95c1986816
Signed-off-by: Soemin Tjong <stjong@microsoft.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/18181
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Alex Kelley <alexke@microsoft.com>
Reviewed-by: Dan Mihai <Daniel.Mihai@microsoft.com>
resource/IPCA/src/callback.cpp
resource/IPCA/src/inc/callback.h
resource/IPCA/src/inc/ocfframework.h
resource/IPCA/src/ocfframework.cpp
resource/IPCA/unittests/ipcaunittests.cpp
resource/IPCA/unittests/mockOC.cpp

index d602a34..9414123 100644 (file)
@@ -508,8 +508,8 @@ void Callback::GetCallbackInfoList(CallbackType type, std::vector<CallbackInfo::
 }
 
 bool Callback::MatchAllRequiredResourceTypes(
-                    std::vector<std::string>& requiredResourceTypes,
-                    std::vector<std::string>& deviceResourceTypes)
+                    const std::vector<std::string>& requiredResourceTypes,
+                    const std::vector<std::string>& deviceResourceTypes)
 {
     for (auto const& targetResourceType : requiredResourceTypes)
     {
@@ -538,8 +538,8 @@ bool Callback::MatchAllRequiredResourceTypes(
 void Callback::DeviceDiscoveryCallback(
                     bool deviceResponding,
                     bool newInfoLearntAboutDevice,
-                    InternalDeviceInfo deviceInfo,
-                    std::vector<std::string> deviceResourceTypeList)
+                    const InternalDeviceInfo& deviceInfo,
+                    const std::vector<std::string>& deviceResourceTypeList)
 {
     // Create IPCADiscoveredDeviceInfo object for callback.
     IPCADiscoveredDeviceInfo  deviceInfoUsedForCallback = {0};
index 2f11231..69d1b08 100644 (file)
@@ -147,8 +147,8 @@ class Callback
         // Device discovery related.
         void DeviceDiscoveryCallback(bool deviceResponding,
                 bool newInfoLearntAboutDevice,
-                InternalDeviceInfo deviceInfo,
-                std::vector<std::string> resourceTypes);
+                const InternalDeviceInfo& deviceInfo,
+                const std::vector<std::string>& resourceTypes);
 
         // resource->get() callback.
         void GetCallback(IPCAStatus status,
@@ -185,8 +185,8 @@ class Callback
         void RequestAccessCompletionCallback(IPCAStatus status, CallbackInfo::Ptr cbInfo);
 
     private:
-        bool MatchAllRequiredResourceTypes(std::vector<std::string>& requiredResourceTypes,
-                                           std::vector<std::string>& deviceResourceTypes);
+        bool MatchAllRequiredResourceTypes(const std::vector<std::string>& requiredResourceTypes,
+                                           const std::vector<std::string>& deviceResourceTypes);
 
     private:
         // Mutex for synchronization use.
index dbc1a1f..5c8965c 100644 (file)
@@ -233,7 +233,7 @@ class OCFFramework
         // Entry point for the thread that will request access to a device.
         static void RequestAccessWorkerThread(RequestAccessContext* requestContext);
 
-        // Get DeviceDetails for devieId.
+        // Get DeviceDetails for deviceId.
         IPCAStatus FindDeviceDetails(const std::string& deviceId,
                     DeviceDetails::Ptr& deviceDetails);
 
@@ -249,6 +249,10 @@ class OCFFramework
         void DebugOutputOCFDevices();
         void DebugOutputOCRep(const OCRepresentation& rep);
 
+        // Thread safe copy.
+        template <typename _T>
+        void ThreadSafeCopy(const _T& source, _T& dest);
+
     private:
         // Lock for sync access to protected members in OCFFramework.
         std::recursive_mutex m_OCFFrameworkMutex;
index 0fc0a27..f44fc51 100644 (file)
@@ -268,23 +268,28 @@ void OCFFramework::WorkerThread(OCFFramework* ocfFramework)
             ocfFramework->GetCommonResources(device);
         }
 
-        // Make a snapshot of all callbacks.
+        // Take a snapshot of callbacks for thread safe iteration.
         std::vector<Callback::Ptr> callbackSnapshot;
-        {
-            std::lock_guard<std::recursive_mutex> lock(ocfFramework->m_OCFFrameworkMutex);
-            callbackSnapshot = ocfFramework->m_callbacks;
-        }
+        ocfFramework->ThreadSafeCopy(ocfFramework->m_callbacks, callbackSnapshot);
 
         // Callback to apps.
         for (const auto& device : devicesThatAreNotResponding)
         {
+            // Take a snapshot of device->discoveredResourceTypes and deviceInfo
+            // for thread safe use by the callee.
+            std::vector<std::string> resourceTypesSnapshot;
+            ocfFramework->ThreadSafeCopy(device->discoveredResourceTypes, resourceTypesSnapshot);
+
+            InternalDeviceInfo deviceInfoSnapshot;
+            ocfFramework->ThreadSafeCopy(device->deviceInfo, deviceInfoSnapshot);
+
             for (const auto& callback : callbackSnapshot)
             {
                 callback->DeviceDiscoveryCallback(
                                         false, /* device is no longer responding to discovery */
                                         false,
-                                        device->deviceInfo,
-                                        device->discoveredResourceTypes);
+                                        deviceInfoSnapshot,
+                                        resourceTypesSnapshot);
             }
         }
 
@@ -298,6 +303,8 @@ void OCFFramework::WorkerThread(OCFFramework* ocfFramework)
 
 IPCAStatus OCFFramework::IPCADeviceOpenCalled(std::string& deviceId)
 {
+    std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
+
     // Has the app discovered the device?
     DeviceDetails::Ptr deviceDetails;
     IPCAStatus status = FindDeviceDetails(deviceId, deviceDetails);
@@ -455,12 +462,17 @@ void OCFFramework::OnResourceFound(std::shared_ptr<OCResource> resource)
     }
 
     // Inform apps. If new device, the device info may come in subsequent discovery callbacks with
-    // IPCA_DEVICE_UPDATED_INFO status. Make a snapshot of all callbacks.
+    // IPCA_DEVICE_UPDATED_INFO status.
+
+    // Take a snapshot of variables that may be updated by the stack during the callback.
     std::vector<Callback::Ptr> callbackSnapshot;
-    {
-        std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
-        callbackSnapshot = m_callbacks;
-    }
+    ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+    std::vector<std::string> resourceTypesSnapshot;
+    ThreadSafeCopy(deviceDetails->discoveredResourceTypes, resourceTypesSnapshot);
+
+    InternalDeviceInfo deviceInfoSnapshot;
+    ThreadSafeCopy(deviceDetails->deviceInfo, deviceInfoSnapshot);
 
     // Indicate discovery to apps.
     for (const auto& callback : callbackSnapshot)
@@ -468,8 +480,8 @@ void OCFFramework::OnResourceFound(std::shared_ptr<OCResource> resource)
         callback->DeviceDiscoveryCallback(
                     true,
                     updatedDeviceInformation,
-                    deviceDetails->deviceInfo,
-                    deviceDetails->discoveredResourceTypes);
+                    deviceInfoSnapshot,
+                    resourceTypesSnapshot);
     }
 
 
@@ -595,12 +607,15 @@ void OCFFramework::OnDeviceInfoCallback(const OCRepresentation& rep)
     }
 
     // Inform apps.
-    // Make a snapshot of all callbacks.
+    // Take snapshots of variables that may be updated during the callback.
     std::vector<Callback::Ptr> callbackSnapshot;
-    {
-        std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
-        callbackSnapshot = m_callbacks;
-    }
+    ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+    std::vector<std::string> resourceTypesSnapshot;
+    ThreadSafeCopy(deviceDetails->discoveredResourceTypes, resourceTypesSnapshot);
+
+    InternalDeviceInfo deviceInfoSnapshot;
+    ThreadSafeCopy(deviceDetails->deviceInfo, deviceInfoSnapshot);
 
     // Indicate discovery to apps.
     for (const auto& callback : callbackSnapshot)
@@ -608,8 +623,8 @@ void OCFFramework::OnDeviceInfoCallback(const OCRepresentation& rep)
         callback->DeviceDiscoveryCallback(
                     true,   /* device is responding */
                     true,   /* this is an updated device info */
-                    deviceDetails->deviceInfo,
-                    deviceDetails->discoveredResourceTypes);
+                    deviceInfoSnapshot,
+                    resourceTypesSnapshot);
     }
 
     DebugOutputOCFDevices();
@@ -795,7 +810,11 @@ void OCFFramework::OnPostPut(const HeaderOptions& headerOptions,
 
     IPCAStatus status = MapOCStackResultToIPCAStatus((OCStackResult)eCode);
 
-    for (const auto& callback : m_callbacks)
+    // Take a snapshot of callbacks for thread safe iteration.
+    std::vector<Callback::Ptr> callbackSnapshot;
+    ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+    for (const auto& callback : callbackSnapshot)
     {
         callback->SetCallback(status, rep, callbackInfo);
     }
@@ -816,7 +835,11 @@ void OCFFramework::OnGet(const HeaderOptions& headerOptions,
         status = IPCA_FAIL;
     }
 
-    for (const auto& callback : m_callbacks)
+    // Take a snapshot of callbacks for thread safe iteration.
+    std::vector<Callback::Ptr> callbackSnapshot;
+    ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+    for (const auto& callback : callbackSnapshot)
     {
         callback->GetCallback(status, rep, callbackInfo);
     }
@@ -837,7 +860,11 @@ void OCFFramework::OnObserve(
         status = IPCA_FAIL;
     }
 
-    for (const auto& callback : m_callbacks)
+    // Take a snapshot of callbacks for thread safe iteration.
+    std::vector<Callback::Ptr> callbackSnapshot;
+    ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+    for (const auto& callback : callbackSnapshot)
     {
         callback->ObserveCallback(status, rep, callbackInfo);
     }
@@ -851,7 +878,11 @@ void OCFFramework::OnDelete(const HeaderOptions& headerOptions,
 
     IPCAStatus status = MapOCStackResultToIPCAStatus((OCStackResult)eCode);
 
-    for (const auto& callback : m_callbacks)
+    // Take a snapshot of callbacks for thread safe iteration.
+    std::vector<Callback::Ptr> callbackSnapshot;
+    ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+    for (const auto& callback : callbackSnapshot)
     {
         callback->DeleteResourceCallback(status, callbackInfo);
     }
@@ -1038,6 +1069,8 @@ std::shared_ptr<OCResource> OCFFramework::FindOCResource(
                                                 const std::string& targetResourcePath,
                                                 const std::string& targetRT)
 {
+    std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
+
     // Return resource matching resource path.
     if (deviceDetails->resourceMap.find(targetResourcePath) != deviceDetails->resourceMap.end())
     {
@@ -1061,6 +1094,8 @@ std::shared_ptr<OCResource> OCFFramework::FindOCResource(
 
 IPCAStatus OCFFramework::CopyDeviceInfo(std::string& deviceId, IPCADeviceInfo** callerDeviceInfo)
 {
+    std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
+
     *callerDeviceInfo = nullptr;
 
     DeviceDetails::Ptr deviceDetails;
@@ -1143,6 +1178,8 @@ void OCFFramework::FreeDeviceInfo(IPCADeviceInfo* deviceInfo)
 IPCAStatus OCFFramework::CopyPlatformInfo(std::string& deviceId,
                                           IPCAPlatformInfo** callerPlatformInfo)
 {
+    std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
+
     *callerPlatformInfo = nullptr;
 
     DeviceDetails::Ptr deviceDetails;
@@ -1240,6 +1277,8 @@ IPCAStatus OCFFramework::CopyResourcePaths(const std::string& resourceInterface,
                                 std::string& deviceId,
                                 std::vector<std::string>& resourcePathList)
 {
+    std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
+
     DeviceDetails::Ptr deviceDetails;
     IPCAStatus status = FindDeviceDetails(deviceId, deviceDetails);
     if (status != IPCA_OK)
@@ -1272,6 +1311,8 @@ IPCAStatus OCFFramework::CopyResourceInfo(const std::string& deviceId,
                             ResourceInfoType resourceInfoType,
                             std::vector<std::string>& resourceInfo)
 {
+    std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
+
     DeviceDetails::Ptr deviceDetails;
     IPCAStatus status = FindDeviceDetails(deviceId, deviceDetails);
     if (status != IPCA_OK)
@@ -1518,9 +1559,13 @@ void OCFFramework::RequestAccessWorkerThread(RequestAccessContext* requestContex
                         size_t passwordBufferSize = OXM_PRECONFIG_PIN_MAX_SIZE + 1;
                         memset(passwordBuffer, 0, passwordBufferSize);
 
+                        // Take a snapshot of callbacks for thread safe iteration.
+                        std::vector<Callback::Ptr> callbackSnapshot;
+                        ocfFramework->ThreadSafeCopy(ocfFramework->m_callbacks, callbackSnapshot);
+
                         // We need to set the preconfigured pin before attempting to do MOT.
                         // Callback to the app asking for the password.
-                        for (const auto& callback : ocfFramework->m_callbacks)
+                        for (const auto& callback : callbackSnapshot)
                         {
                             callback->PasswordInputCallback(deviceId,
                                         IPCA_OWNERSHIP_TRANSFER_PRECONFIGURED_PIN,
@@ -1590,8 +1635,12 @@ void OCFFramework::RequestAccessWorkerThread(RequestAccessContext* requestContex
             }
             else
             {
+                // Take a snapshot of callbacks for thread safe iteration.
+                std::vector<Callback::Ptr> callbackSnapshot;
+                ocfFramework->ThreadSafeCopy(ocfFramework->m_callbacks, callbackSnapshot);
+
                 // This app is already a subowner of the device
-                for (const auto& callback : ocfFramework->m_callbacks)
+                for (const auto& callback : callbackSnapshot)
                 {
                     callback->RequestAccessCompletionCallback(
                                     IPCA_SECURITY_UPDATE_REQUEST_FINISHED,
@@ -1611,14 +1660,19 @@ void OCFFramework::RequestAccessWorkerThread(RequestAccessContext* requestContex
     // success or failure of doMultipleOwnershipTransfer.
     if (IPCA_OK != status)
     {
-        for (const auto& callback : ocfFramework->m_callbacks)
+        // Take a snapshot of callbacks for thread safe iteration.
+        std::vector<Callback::Ptr> callbackSnapshot;
+        ocfFramework->ThreadSafeCopy(ocfFramework->m_callbacks, callbackSnapshot);
+
+        for (const auto& callback : callbackSnapshot)
         {
             callback->RequestAccessCompletionCallback(callbackStatus, callbackInfo);
         }
     }
 }
 
-void OCFFramework::OnMultipleOwnershipTransferCompleteCallback(PMResultList_t* result,
+void OCFFramework::OnMultipleOwnershipTransferCompleteCallback(
+                                    PMResultList_t* result,
                                     bool error,
                                     std::string deviceId,
                                     CallbackInfo::Ptr callbackInfo)
@@ -1635,7 +1689,11 @@ void OCFFramework::OnMultipleOwnershipTransferCompleteCallback(PMResultList_t* r
         status = IPCA_SECURITY_UPDATE_REQUEST_FAILED;
     }
 
-    for (const auto& callback : m_callbacks)
+    // Take a snapshot of callbacks for thread safe iteration.
+    std::vector<Callback::Ptr> callbackSnapshot;
+    ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+    for (const auto& callback : callbackSnapshot)
     {
         callback->RequestAccessCompletionCallback(status, callbackInfo);
     }
@@ -1675,7 +1733,11 @@ void OCFFramework::OnPasswordInputCallback(OicUuid_t deviceId,
     OCConvertUuidToString(deviceId.id, uuidString);
     strDeviceId = uuidString;
 
-    for (const auto& callback : m_callbacks)
+    // Take a snapshot of callbacks for thread safe iteration.
+    std::vector<Callback::Ptr> callbackSnapshot;
+    ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+    for (const auto& callback : callbackSnapshot)
     {
         callback->PasswordInputCallback(
                     strDeviceId,
@@ -1706,7 +1768,11 @@ void OCFFramework::OnPasswordDisplayCallback(char* passwordBuffer,
 {
     OC_UNUSED(passwordBufferSize);
 
-    for (const auto& callback : m_callbacks)
+    // Take a snapshot of callbacks for thread safe iteration.
+    std::vector<Callback::Ptr> callbackSnapshot;
+    ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+    for (const auto& callback : callbackSnapshot)
     {
         callback->PasswordDisplayCallback("",
                     IPCA_OWNERSHIP_TRANSFER_RANDOM_PIN,
@@ -1758,3 +1824,10 @@ void OCFFramework::CleanupRequestAccessDevices()
         }
     }
 }
+
+template <typename _T>
+void OCFFramework::ThreadSafeCopy(const _T& source, _T& dest)
+{
+    std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
+    dest = source;
+}
index 153c216..13216e9 100644 (file)
@@ -80,14 +80,14 @@ void StopElevator1()
 }
 
 // Start the test elevator once and use it through out the rest of the tests.
-TEST(ElevatorServerStart, DISABLED_start)
+TEST(ElevatorServerStart, start)
 {
     IPCASetUnitTestMode();
     ASSERT_TRUE(StartElevator1());
 }
 
 // Test IoTivity api directly before subsequent tests which use IPCA apis.
-TEST(IoTivityDirect, DISABLED_IsIoTivityWorking)
+TEST(IoTivityDirect, IsIoTivityWorking)
 {
     ElevatorClient elevatorClient;
     int loopCount;
@@ -164,20 +164,20 @@ class IPCAPropertyBagTest : public testing::Test
         }
 };
 
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagNonExistenceAttribute)
+TEST_F(IPCAPropertyBagTest, PropertyBagNonExistenceAttribute)
 {
     EXPECT_EQ(IPCA_FAIL, IPCAPropertyBagGetValueInt(m_propertyBagHandle,
                                 "NonexistenceAttribute", &m_intValue));
 }
 
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagInt)
+TEST_F(IPCAPropertyBagTest, PropertyBagInt)
 {
     ASSERT_EQ(IPCA_OK, IPCAPropertyBagSetValueInt(m_propertyBagHandle, "IntValue", 3));
     ASSERT_EQ(IPCA_OK, IPCAPropertyBagGetValueInt(m_propertyBagHandle, "IntValue", &m_intValue));
     EXPECT_EQ(3, m_intValue);
 }
 
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagDouble)
+TEST_F(IPCAPropertyBagTest, PropertyBagDouble)
 {
     ASSERT_EQ(IPCA_OK, IPCAPropertyBagSetValueDouble(m_propertyBagHandle,
                                 "DoubleValue", 12345678));
@@ -195,7 +195,7 @@ TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagDouble)
                                 "doubleValue", &m_doubleValue)); // incorrect capital case
 }
 
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagBool)
+TEST_F(IPCAPropertyBagTest, PropertyBagBool)
 {
     bool trueBool, falseBool;
 
@@ -212,7 +212,7 @@ TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagBool)
     EXPECT_FALSE(falseBool);
 }
 
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagString)
+TEST_F(IPCAPropertyBagTest, PropertyBagString)
 {
     ASSERT_EQ(IPCA_OK, IPCAPropertyBagSetValueString(m_propertyBagHandle,
                                 "MyString", "Hello World"));
@@ -222,7 +222,7 @@ TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagString)
     IPCAPropertyBagFreeString(m_charPointerValue);
 }
 
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagPropertyBagType)
+TEST_F(IPCAPropertyBagTest, PropertyBagPropertyBagType)
 {
     IPCAPropertyBagHandle propertyBagHandle1, propertyBagHandle2, propertyBagHandle3;
     CreateIntPropertyBag(propertyBagHandle1, "IntValue1", 1);
@@ -269,7 +269,7 @@ TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagPropertyBagType)
     IPCAPropertyBagDestroy(propertyBag3);
 }
 
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagIntArrayType)
+TEST_F(IPCAPropertyBagTest, PropertyBagIntArrayType)
 {
     // array of int
     int intArray[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
@@ -286,7 +286,7 @@ TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagIntArrayType)
     IPCAPropertyBagFreeIntArray(readBackIntArray);
 }
 
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagDoubleArrayType)
+TEST_F(IPCAPropertyBagTest, PropertyBagDoubleArrayType)
 {
     // array of double
     double doubleArray[] = {1.01, 2.02, 3.03, 4.04, 5.05, 6.06, 7.07, 8.08, 9.09, 10.010};
@@ -303,7 +303,7 @@ TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagDoubleArrayType)
     IPCAPropertyBagFreeDoubleArray(readBackDoubleArray);
 }
 
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagBoolArrayType)
+TEST_F(IPCAPropertyBagTest, PropertyBagBoolArrayType)
 {
     // array of bool
     bool boolArray[] = {true, true, false, false, true, false, true, false, false, false};
@@ -320,7 +320,7 @@ TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagBoolArrayType)
     IPCAPropertyBagFreeBoolArray(readBackBoolArray);
 }
 
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagStringArrayType)
+TEST_F(IPCAPropertyBagTest, PropertyBagStringArrayType)
 {
     // array of string
     char* stringArray[] = {"hello world 1", "hello world 2", "hello world 3"};
@@ -338,7 +338,7 @@ TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagStringArrayType)
     IPCAPropertyBagFreeStringArray(readBackString, readbackStringSize);
 }
 
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagPropertyBagArrayType)
+TEST_F(IPCAPropertyBagTest, PropertyBagPropertyBagArrayType)
 {
     IPCAPropertyBagHandle propertyBagHandle1, propertyBagHandle1A;
     EXPECT_EQ(IPCA_OK, IPCAPropertyBagCreate(&propertyBagHandle1));
@@ -452,12 +452,12 @@ class IPCAMiscTest : public testing::Test
         }
 };
 
-TEST_F(IPCAMiscTest, DISABLED_ShouldNotAllowMultipleCallsToIPCOpen)
+TEST_F(IPCAMiscTest, ShouldNotAllowMultipleCallsToIPCOpen)
 {
     EXPECT_EQ(IPCA_ALREADY_OPENED, DoAnotherIPCAOpen());
 }
 
-TEST_F(IPCAMiscTest, DISABLED_IPCAOpenShouldBeAllowedAfterIPCAClose)
+TEST_F(IPCAMiscTest, IPCAOpenShouldBeAllowedAfterIPCAClose)
 {
     IPCAClose(m_ipcaAppHandle);
     m_ipcaAppHandle = NULL;
@@ -468,7 +468,7 @@ TEST_F(IPCAMiscTest, DISABLED_IPCAOpenShouldBeAllowedAfterIPCAClose)
 /*
  * IPCADiscoverDevices() must be called before IPCAOpenDevice().
  */
-TEST_F(IPCAMiscTest, DISABLED_ShouldFailOpenDeviceWithoutDiscoveryFirst)
+TEST_F(IPCAMiscTest, ShouldFailOpenDeviceWithoutDiscoveryFirst)
 {
     IPCADeviceHandle deviceHandle;
 
@@ -478,32 +478,32 @@ TEST_F(IPCAMiscTest, DISABLED_ShouldFailOpenDeviceWithoutDiscoveryFirst)
                                                 &deviceHandle));
 }
 
-TEST_F(IPCAElevatorClient, DISABLED_DiscoveryShouldFindElevatorServer)
+TEST_F(IPCAElevatorClient, DiscoveryShouldFindElevatorServer)
 {
     EXPECT_TRUE(IsElevator1Discovered());
 }
 
-TEST_F(IPCAElevatorClient, DISABLED_DiscoveryShouldFindDeviceAndPlatformInfo)
+TEST_F(IPCAElevatorClient, DiscoveryShouldFindDeviceAndPlatformInfo)
 {
     EXPECT_EQ(IPCA_OK, ConfirmDeviceAndPlatformInfo());
 }
 
-TEST_F(IPCAElevatorClient, DISABLED_DiscoveryShouldFindElevatorResources)
+TEST_F(IPCAElevatorClient, DiscoveryShouldFindElevatorResources)
 {
     EXPECT_EQ(IPCA_OK, ConfirmResources());
 }
 
-TEST_F(IPCAElevatorClient, DISABLED_DiscoveryShouldFindTargetedResourceTypes)
+TEST_F(IPCAElevatorClient, DiscoveryShouldFindTargetedResourceTypes)
 {
     EXPECT_EQ(IPCA_OK, ConfirmResourceTypes());
 }
 
-TEST_F(IPCAElevatorClient, DISABLED_ShouldBeAbleToFilterOnResourceInterface)
+TEST_F(IPCAElevatorClient, ShouldBeAbleToFilterOnResourceInterface)
 {
     EXPECT_EQ(IPCA_OK, ConfirmResourceInterfaces());
 }
 
-TEST_F(IPCAElevatorClient, DISABLED_SuccessfullyGetDataFromElevatorServer)
+TEST_F(IPCAElevatorClient, SuccessfullyGetDataFromElevatorServer)
 {
     // Directly set target floor of the elevator to 8.
     g_testElevator1.SetTargetFloor(8);
@@ -516,24 +516,24 @@ TEST_F(IPCAElevatorClient, DISABLED_SuccessfullyGetDataFromElevatorServer)
     EXPECT_EQ(8, elevatorTargetFloor);
 }
 
-TEST_F(IPCAElevatorClient, DISABLED_ShouldFailGetUnknownResource)
+TEST_F(IPCAElevatorClient, ShouldFailGetUnknownResource)
 {
     EXPECT_EQ(IPCA_RESOURCE_NOT_FOUND, GetUnknownResource());
 }
 
-TEST_F(IPCAElevatorClient, DISABLED_ShouldFailSetUnknownResource)
+TEST_F(IPCAElevatorClient, ShouldFailSetUnknownResource)
 {
     EXPECT_EQ(IPCA_RESOURCE_NOT_FOUND, SetUnknownResource());
 }
 
-TEST_F(IPCAElevatorClient, DISABLED_ShouldFailSetWithUnknownInterface)
+TEST_F(IPCAElevatorClient, ShouldFailSetWithUnknownInterface)
 {
     size_t incorrectInterfaceCount = g_testElevator1.GetIncorrectInterfaceCount();
     EXPECT_EQ(true, SetUnknoownInterface());
     EXPECT_EQ((incorrectInterfaceCount + 1), g_testElevator1.GetIncorrectInterfaceCount());
 }
 
-TEST_F(IPCAElevatorClient, DISABLED_SuccessfullySetElevatorServerProperties)
+TEST_F(IPCAElevatorClient, SuccessfullySetElevatorServerProperties)
 {
     g_testElevator1.SetTargetFloor(1); // Set to known target floor.
 
@@ -546,7 +546,7 @@ TEST_F(IPCAElevatorClient, DISABLED_SuccessfullySetElevatorServerProperties)
     EXPECT_EQ(8, newTargetFloor);
 }
 
-TEST_F(IPCAElevatorClient, DISABLED_SuccessfullyCreateAndDeleteResources)
+TEST_F(IPCAElevatorClient, SuccessfullyCreateAndDeleteResources)
 {
     // Do a few rounds of create resource with relative path.
     size_t beforeCreateCount, afterCreateCount;
@@ -572,7 +572,7 @@ TEST_F(IPCAElevatorClient, DISABLED_SuccessfullyCreateAndDeleteResources)
     }
 }
 
-TEST_F(IPCAElevatorClient, DISABLED_SuccessfullyReceiveResourceChangeNotifications)
+TEST_F(IPCAElevatorClient, SuccessfullyReceiveResourceChangeNotifications)
 {
     // Set to known target floor.
     g_testElevator1.SetTargetFloor(1);
@@ -597,18 +597,18 @@ TEST_F(IPCAElevatorClient, DISABLED_SuccessfullyReceiveResourceChangeNotificatio
     StopObserve();
 }
 
-TEST_F(IPCAElevatorClient, DISABLED_SuccessfulFactoryReset)
+TEST_F(IPCAElevatorClient, SuccessfulFactoryReset)
 {
     EXPECT_EQ(IPCA_OK, FactoryResetElevator());
 }
 
-TEST_F(IPCAElevatorClient, DISABLED_SuccessfulReboot)
+TEST_F(IPCAElevatorClient, SuccessfulReboot)
 {
     EXPECT_EQ(IPCA_OK, RebootElevator());
 }
 
 
-TEST(ElevatorServerStop, DISABLED_Stop)
+TEST(ElevatorServerStop, Stop)
 {
     StopElevator1();
 }
index 818b360..b8fb122 100644 (file)
@@ -118,6 +118,7 @@ void SetMockOCDevAddr(OCDevAddr& addr)
 // Forward decl.\r
 OCEntityHandlerResult MockEntityHandler(OCEntityHandlerFlag flag,\r
                             OCMethod method,\r
+                            bool isCancelObserve,\r
                             const OCRepresentation& rep,\r
                             const QueryParamsMap& queryParametersMap,\r
                             PostCallback postCallback,\r
@@ -462,6 +463,13 @@ OCStackResult OCPlatform::sendResponse(const std::shared_ptr<OCResourceResponse>
         }\r
     }\r
 \r
+    // One time request is responded, remove the pending request.\r
+    if (pendingRequest->method & (OC_REST_POST | OC_REST_GET | OC_REST_DELETE))\r
+    {\r
+        std::lock_guard<std::recursive_mutex> lock(g_globalMutex);\r
+        g_requestList.erase(pendingRequest->requestNumber);\r
+    }\r
+\r
     return OC_STACK_OK;\r
 }\r
 \r
@@ -512,6 +520,7 @@ OCStackResult OCResource::deleteResource(DeleteCallback deleteHandler)
     OCEntityHandlerResult result = MockEntityHandler(\r
                                         OC_REQUEST_FLAG,\r
                                         OC_REST_DELETE,\r
+                                        false,\r
                                         rep,\r
                                         queryParametersMap,\r
                                         &defaultCallback,\r
@@ -533,6 +542,7 @@ OCStackResult OCResource::get(const QueryParamsMap& queryParametersMap,
     OCEntityHandlerResult result = MockEntityHandler(\r
                                         OC_REQUEST_FLAG,\r
                                         OC_REST_GET,\r
+                                        false,\r
                                         rep,\r
                                         queryParametersMap,\r
                                         &defaultCallback,\r
@@ -554,6 +564,7 @@ OCStackResult OCResource::post(const OCRepresentation& rep,
     OCEntityHandlerResult result = MockEntityHandler(\r
                                         OC_REQUEST_FLAG,\r
                                         OC_REST_POST,\r
+                                        false,\r
                                         rep,\r
                                         queryParametersMap,\r
                                         attributeHandler,\r
@@ -577,6 +588,7 @@ OCStackResult OCResource::observe(ObserveType observeType,
                                         OC_OBSERVE_FLAG,\r
                                         (observeType == ObserveType::Observe) ?\r
                                             OC_REST_OBSERVE : OC_REST_OBSERVE_ALL,\r
+                                        false,\r
                                         rep,\r
                                         queryParametersMap,\r
                                         &defaultCallback,\r
@@ -591,23 +603,22 @@ OCStackResult OCResource::observe(ObserveType observeType,
 // Client app's request to cancel observe request.\r
 OCStackResult OCResource::cancelObserve()\r
 {\r
-    std::lock_guard<std::recursive_mutex> lock(g_globalMutex);\r
+    OCRepresentation rep;\r
+    QueryParamsMap queryParametersMap;\r
 \r
-    for (auto request : g_requestList)\r
-    {\r
-        PendingRequest::Ptr pendingRequest = request.second;\r
-        if ((pendingRequest->method == OC_REST_OBSERVE) ||\r
-            (pendingRequest->method == OC_REST_OBSERVE_ALL))\r
-        {\r
-            if (pendingRequest->mockOCResource->m_uri.compare(uri()) == 0)\r
-            {\r
-                g_requestList.erase(pendingRequest->requestNumber);\r
-                break;\r
-            }\r
-        }\r
-    }\r
+    OCEntityHandlerResult result = MockEntityHandler(\r
+                                        OC_OBSERVE_FLAG,\r
+                                        OC_REST_OBSERVE,\r
+                                        true,\r
+                                        rep,\r
+                                        queryParametersMap,\r
+                                        &defaultCallback,\r
+                                        &defaultCallback,\r
+                                        &defaultObserveCallback,\r
+                                        &defaultDeleteCallback,\r
+                                        uri());\r
 \r
-    return OC_STACK_OK;\r
+    return (result == OC_EH_OK) ? OC_STACK_OK : OC_STACK_ERROR;\r
 }\r
 \r
 // Is resource observable.\r
@@ -765,6 +776,7 @@ OCResourceIdentifier OCResource::uniqueIdentifier() const
 // Every callback to server app is performed by this function.\r
 OCEntityHandlerResult MockEntityHandler(OCEntityHandlerFlag flag,\r
                             OCMethod method,\r
+                            bool isCancelObserve,\r
                             const OCRepresentation& rep,\r
                             const QueryParamsMap& queryParametersMap,\r
                             PostCallback postCallback,\r
@@ -773,6 +785,7 @@ OCEntityHandlerResult MockEntityHandler(OCEntityHandlerFlag flag,
                             DeleteCallback deleteCallback,\r
                             const std::string& uri)\r
 {\r
+    OCObservationId observationIdToCancel = 0;\r
     size_t requestNumber;\r
     MockOCResource::Ptr mockOCResource = nullptr;\r
     {\r
@@ -799,11 +812,31 @@ OCEntityHandlerResult MockEntityHandler(OCEntityHandlerFlag flag,
     pendingRequest->getCallback     = getCallback;\r
     pendingRequest->observeCallback = observeCallback;\r
     pendingRequest->deleteCallback  = deleteCallback;\r
+\r
+    if (!isCancelObserve)\r
     {\r
         // Store the request for response.\r
         std::lock_guard<std::recursive_mutex> lock(g_globalMutex);\r
         g_requestList[requestNumber] = pendingRequest;\r
     }\r
+    else\r
+    {\r
+        // Observe request is canceled. Remove the request for observe.\r
+        std::lock_guard<std::recursive_mutex> lock(g_globalMutex);\r
+        for (auto request : g_requestList)\r
+        {\r
+            PendingRequest::Ptr pendingRequest = request.second;\r
+            if (pendingRequest->method & (OC_REST_OBSERVE | OC_REST_OBSERVE_ALL))\r
+            {\r
+                if (pendingRequest->mockOCResource->m_uri.compare(uri) == 0)\r
+                {\r
+                    observationIdToCancel = pendingRequest->observationId;\r
+                    g_requestList.erase(pendingRequest->requestNumber);\r
+                    break;\r
+                }\r
+            }\r
+        }\r
+    }\r
 \r
     auto pRequest = std::make_shared<OC::OCResourceRequest>();\r
     if (pRequest == nullptr)\r
@@ -830,8 +863,10 @@ OCEntityHandlerResult MockEntityHandler(OCEntityHandlerFlag flag,
     if (flag & OC_OBSERVE_FLAG)\r
     {\r
         std::lock_guard<std::recursive_mutex> lock(g_globalMutex);\r
-        entityHandlerRequest.obsInfo.action = OC_OBSERVE_REGISTER;\r
-        entityHandlerRequest.obsInfo.obsId = ++g_observationId;\r
+        entityHandlerRequest.obsInfo.action = isCancelObserve ?\r
+                                                    OC_OBSERVE_DEREGISTER : OC_OBSERVE_REGISTER;\r
+        entityHandlerRequest.obsInfo.obsId = isCancelObserve ?\r
+                                                    observationIdToCancel : ++g_observationId;\r
         pendingRequest->observationId = entityHandlerRequest.obsInfo.obsId;\r
     }\r
 \r