From: Way Vadhanasin Date: Tue, 7 Mar 2017 00:09:50 +0000 (-0800) Subject: IOT-1868 [C++ layer] Make OCPlatform start and stop reliably X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=656e46dc35baa8b6bf89912bf23b60e9f39885ae;p=contrib%2Fiotivity.git IOT-1868 [C++ layer] Make OCPlatform start and stop reliably This change adds reference count to OCPlatform's static start and stop functions and synchronizes them. It does the following: 1. Ensures that calls to the "C" APIs OCInit and OCStop are balanced. 2. Maintains backward compatibility by introducing new PlatformConfig constructor and deprecate the old ones. 3. Updates the existing unit tests and samples. Because this change allows the framework to stop properly, it exposes some existing IoTivity leaks in Jenkins (Valgrind validation). Thus the following leaks are fixed in this change to allow successful Jenkins runs: 1. caipadapter.c: endpoint cache leak in UDP (no issue for TCP). - https://build.iotivity.org/ci/job/iotivity-verify-unit_tests/ 10907/valgrindResult/pid=24498,0x3fe 2. psinterface.c: CBOR buffer leaks in CreateResetProfile. - https://build.iotivity.org/ci/job/iotivity-verify-unit_tests/ 10922/valgrindResult/pid=2316,0x3ad 3. ocstack.c & securityResourceManager.cpp: persistent storage buffer leaks as a result of restarting and switching OCPlatform configuration after shutdown (e.g., between tests). https://build.iotivity.org/ci/job/iotivity-verify-unit_tests/ 10922/valgrindResult/pid=2316,0x3ad 4. OCRepresentationEncodingTest.cpp: representation value leaks. - https://build.iotivity.org/ci/job/iotivity-verify-unit_tests/ 10922/valgrindResult/pid=2316,0x3a9 5. runtest.py: change Valgrind callstack size from the default value of 12 to 24 so that the test name is visible in the report. Helpful for reproducibility. Change-Id: I79406f2cf4282efbb29a69c14e42aae928f54bae Signed-off-by: Way Vadhanasin Reviewed-on: https://gerrit.iotivity.org/gerrit/17685 Tested-by: jenkins-iotivity Reviewed-by: Dan Mihai --- diff --git a/resource/csdk/connectivity/src/ip_adapter/caipadapter.c b/resource/csdk/connectivity/src/ip_adapter/caipadapter.c index 91cdfd8..edf96c1 100644 --- a/resource/csdk/connectivity/src/ip_adapter/caipadapter.c +++ b/resource/csdk/connectivity/src/ip_adapter/caipadapter.c @@ -152,6 +152,11 @@ void CAIPDeinitializeQueueHandles() CAQueueingThreadDestroy(g_sendQueueHandle); OICFree(g_sendQueueHandle); g_sendQueueHandle = NULL; + + // Since the items in g_ownIpEndpointList are allocated once in a big chunk, we only need to + // free the first item. Another location this is done is in the CA_INTERFACE_DOWN handler + // in CAUpdateStoredIPAddressInfo(). + OICFree(u_arraylist_get(g_ownIpEndpointList, 0)); u_arraylist_free(&g_ownIpEndpointList); g_ownIpEndpointList = NULL; } diff --git a/resource/csdk/security/src/psinterface.c b/resource/csdk/security/src/psinterface.c index 2f90135..0bd6cca 100644 --- a/resource/csdk/security/src/psinterface.c +++ b/resource/csdk/security/src/psinterface.c @@ -632,7 +632,7 @@ OCStackResult CreateResetProfile(void) if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal)) { OIC_LOG(DEBUG, TAG, "Reset Profile already exists!!"); - return ret; + goto exit; } cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_ACL_NAME, &curVal); diff --git a/resource/csdk/security/unittest/securityresourcemanager.cpp b/resource/csdk/security/unittest/securityresourcemanager.cpp index 2fa77f4..2141dd0 100644 --- a/resource/csdk/security/unittest/securityresourcemanager.cpp +++ b/resource/csdk/security/unittest/securityresourcemanager.cpp @@ -108,7 +108,8 @@ TEST(RegisterHandlerTest, RegisterValidHandler) // PersistentStorageHandler Tests TEST(PersistentStorageHandlerTest, RegisterNullHandler) { - EXPECT_EQ(OC_STACK_INVALID_PARAM, + // Revert to the default storage handler by setting it to null. + EXPECT_EQ(OC_STACK_OK, SRMRegisterPersistentStorageHandler(NULL)); } diff --git a/resource/csdk/stack/src/ocstack.c b/resource/csdk/stack/src/ocstack.c index cc1abd0..92c311f 100644 --- a/resource/csdk/stack/src/ocstack.c +++ b/resource/csdk/stack/src/ocstack.c @@ -3467,12 +3467,7 @@ OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption OCStackResult OCRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler) { OIC_LOG(INFO, TAG, "RegisterPersistentStorageHandler !!"); - if(!persistentStorageHandler) - { - OIC_LOG(ERROR, TAG, "The persistent storage handler is invalid"); - return OC_STACK_INVALID_PARAM; - } - else + if(persistentStorageHandler) { if( !persistentStorageHandler->open || !persistentStorageHandler->close || diff --git a/resource/examples/devicediscoveryclient.cpp b/resource/examples/devicediscoveryclient.cpp index 25250d3..03e36d0 100644 --- a/resource/examples/devicediscoveryclient.cpp +++ b/resource/examples/devicediscoveryclient.cpp @@ -138,14 +138,14 @@ int main(int argc, char* argv[]) { PlatformConfig cfg { OC::ServiceType::InProc, OC::ModeType::Client, - "0.0.0.0", - 0, - OC::QualityOfService::LowQos + nullptr }; OCPlatform::Configure(cfg); try { + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); + platformDiscoveryRequest << OC_MULTICAST_PREFIX << platformDiscoveryURI; deviceDiscoveryRequest << OC_MULTICAST_PREFIX << deviceDiscoveryURI; @@ -188,6 +188,8 @@ int main(int argc, char* argv[]) { std::unique_lock lock(blocker); cv.wait(lock, []{return false;}); + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); + }catch(OCException& e) { std::cerr << "Failure in main thread: "< lock(blocker); cv.wait(lock, []{return false;}); - // No explicit call to stop the platform. - // When OCPlatform::destructor is invoked, internally we do platform cleanup - + // Perform platform clean up. + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); return 0; } diff --git a/resource/examples/directpairingclient.cpp b/resource/examples/directpairingclient.cpp index 703c378..6185e13 100644 --- a/resource/examples/directpairingclient.cpp +++ b/resource/examples/directpairingclient.cpp @@ -249,9 +249,6 @@ int main(void) PlatformConfig cfg { OC::ServiceType::InProc, OC::ModeType::Both, - "0.0.0.0", - 0, - OC::QualityOfService::LowQos, &ps }; @@ -259,6 +256,8 @@ int main(void) try { + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); + unsigned int choice; for (int out = 0; !out;) { @@ -408,6 +407,8 @@ int main(void) } } } + + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); } catch(OCException& e) { diff --git a/resource/examples/fridgeclient.cpp b/resource/examples/fridgeclient.cpp index bbbc748..e562883 100644 --- a/resource/examples/fridgeclient.cpp +++ b/resource/examples/fridgeclient.cpp @@ -316,13 +316,13 @@ int main(int argc, char* argv[]) { ServiceType::InProc, ModeType::Client, - "0.0.0.0", - 0, - QualityOfService::LowQos + nullptr }; OCPlatform::Configure(cfg); + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); ClientFridge cf(connectivityType); + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); return 0; } diff --git a/resource/examples/fridgeserver.cpp b/resource/examples/fridgeserver.cpp index 9ab20d7..2ce63ba 100644 --- a/resource/examples/fridgeserver.cpp +++ b/resource/examples/fridgeserver.cpp @@ -570,12 +570,11 @@ int main () { ServiceType::InProc, ModeType::Server, - "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces - 0, // Uses randomly available port - QualityOfService::LowQos + nullptr }; OCPlatform::Configure(cfg); + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); Refrigerator rf; std::cout << "Starting server & setting platform info\n"; @@ -603,6 +602,7 @@ int main () DeletePlatformInfo(); // we will keep the server alive for at most 30 minutes std::this_thread::sleep_for(std::chrono::minutes(30)); + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); return 0; } diff --git a/resource/examples/garageclient.cpp b/resource/examples/garageclient.cpp index 9a91da9..a8c8f93 100644 --- a/resource/examples/garageclient.cpp +++ b/resource/examples/garageclient.cpp @@ -336,14 +336,14 @@ int main(int argc, char* argv[]) { PlatformConfig cfg { OC::ServiceType::InProc, OC::ModeType::Client, - "0.0.0.0", - 0, - OC::QualityOfService::LowQos + nullptr }; OCPlatform::Configure(cfg); try { + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); + // Find all resources requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.garage"; @@ -360,6 +360,8 @@ int main(int argc, char* argv[]) { std::condition_variable cv; std::unique_lock lock(blocker); cv.wait(lock); + + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); } catch(OCException& e) { diff --git a/resource/examples/garageserver.cpp b/resource/examples/garageserver.cpp index f333d45..e8238ef 100644 --- a/resource/examples/garageserver.cpp +++ b/resource/examples/garageserver.cpp @@ -346,12 +346,11 @@ int main(int /*argc*/, char** /*argv[1]*/) PlatformConfig cfg { OC::ServiceType::InProc, OC::ModeType::Server, - "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces - 0, // Uses randomly available port - OC::QualityOfService::LowQos + nullptr }; OCPlatform::Configure(cfg); + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); std::cout << "Starting server & setting platform info\n"; OCStackResult result = SetPlatformInfo(platformId, manufacturerName, manufacturerLink, @@ -394,8 +393,7 @@ int main(int /*argc*/, char** /*argv[1]*/) oclog() << e.what(); } - // No explicit call to stop the OCPlatform - // When OCPlatform destructor is invoked, internally we do Platform cleanup + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); return 0; } diff --git a/resource/examples/groupclient.cpp b/resource/examples/groupclient.cpp index cde8eb2..ef146ab 100644 --- a/resource/examples/groupclient.cpp +++ b/resource/examples/groupclient.cpp @@ -176,13 +176,14 @@ int main(int /*argc*/, char** /*argv[]*/) requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=a.collection"; PlatformConfig config - { OC::ServiceType::InProc, ModeType::Client, "0.0.0.0", 0, OC::QualityOfService::LowQos }; + { OC::ServiceType::InProc, ModeType::Client, nullptr }; bool isRun = true; try { OCPlatform::Configure(config); + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); string resourceTypeName = "a.collection"; @@ -255,6 +256,7 @@ int main(int /*argc*/, char** /*argv[]*/) break; } } + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); } catch (OCException& e) { diff --git a/resource/examples/groupserver.cpp b/resource/examples/groupserver.cpp index f4b5e4d..13cb475 100755 --- a/resource/examples/groupserver.cpp +++ b/resource/examples/groupserver.cpp @@ -124,7 +124,7 @@ int main(int argc, char* argv[]) } PlatformConfig config - { OC::ServiceType::InProc, ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::LowQos }; + { OC::ServiceType::InProc, ModeType::Both, nullptr }; try { @@ -132,6 +132,7 @@ int main(int argc, char* argv[]) string resourceTypeName = "a.collection"; string resourceInterface = BATCH_INTERFACE; OCPlatform::Configure(config); + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); // EntityHandler cb = std::bind(, PH::_1, PH::_2); @@ -175,6 +176,8 @@ int main(int argc, char* argv[]) } } + + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); } catch (OCException& e) { diff --git a/resource/examples/lightserver.cpp b/resource/examples/lightserver.cpp index 127b858..a9b605b 100644 --- a/resource/examples/lightserver.cpp +++ b/resource/examples/lightserver.cpp @@ -408,14 +408,12 @@ int main(int /*argc*/, char** /*argv[]*/) PlatformConfig cfg { OC::ServiceType::InProc, OC::ModeType::Server, - "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces - 0, // Uses randomly available port - OC::QualityOfService::LowQos, &ps }; OCPlatform::Configure(cfg); std::cout << "Starting server & setting platform info\n"; + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); OCStackResult result = SetPlatformInfo(platformId, manufacturerName, manufacturerLink, modelNumber, dateOfManufacture, platformVersion, operatingSystemVersion, @@ -465,9 +463,8 @@ int main(int /*argc*/, char** /*argv[]*/) oclog() << "Exception in main: "<< e.what(); } - // No explicit call to stop the platform. - // When OCPlatform::destructor is invoked, internally we do platform cleanup - + // Perform platform clean up. + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); return 0; } diff --git a/resource/examples/mediaserver.cpp b/resource/examples/mediaserver.cpp index 0f07e86..d9017e7 100644 --- a/resource/examples/mediaserver.cpp +++ b/resource/examples/mediaserver.cpp @@ -669,15 +669,14 @@ int main(int argc, char* argv[]) PlatformConfig cfg { OC::ServiceType::InProc, OC::ModeType::Server, - "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces - 0, // Uses randomly available port - OC::QualityOfService::LowQos, &ps }; OCPlatform::Configure(cfg); try { + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); + // Create the instance of the resource class // (in this case instance of class 'MediaResource'). MediaResource myMedia; @@ -695,15 +694,15 @@ int main(int argc, char* argv[]) std::unique_lock lock(blocker); cout <<"Waiting" << std::endl; cv.wait(lock, []{return false;}); + + // Perform platform clean up. + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); } catch(OCException &e) { cout << "OCException in main : " << e.what() << endl; } - // No explicit call to stop the platform. - // When OCPlatform::destructor is invoked, internally we do platform cleanup - return 0; } diff --git a/resource/examples/presenceclient.cpp b/resource/examples/presenceclient.cpp index 72b672a..3603162 100644 --- a/resource/examples/presenceclient.cpp +++ b/resource/examples/presenceclient.cpp @@ -257,15 +257,15 @@ int main(int argc, char* argv[]) { PlatformConfig cfg { OC::ServiceType::InProc, OC::ModeType::Client, - "0.0.0.0", - 0, - OC::QualityOfService::LowQos + nullptr }; OCPlatform::Configure(cfg); try { + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); + std::cout << "Created Platform..."< lock(blocker); cv.wait(lock); + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); } catch(OCException& e) { diff --git a/resource/examples/presenceserver.cpp b/resource/examples/presenceserver.cpp index da1d937..a6b7311 100644 --- a/resource/examples/presenceserver.cpp +++ b/resource/examples/presenceserver.cpp @@ -304,13 +304,13 @@ int main() PlatformConfig cfg { OC::ServiceType::InProc, OC::ModeType::Server, - "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces - 0, // Uses randomly available port - OC::QualityOfService::LowQos + nullptr }; OCPlatform::Configure(cfg); + std::cout << "Starting server & setting platform info\n"; + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); OCStackResult result = SetPlatformInfo(platformId, manufacturerName, manufacturerLink, modelNumber, dateOfManufacture, platformVersion, operatingSystemVersion, @@ -321,6 +321,7 @@ int main() if (result != OC_STACK_OK) { std::cout << "Platform Registration failed\n"; + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); return -1; } @@ -329,6 +330,7 @@ int main() if (result != OC_STACK_OK) { std::cout << "Device Registration failed\n"; + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); return -1; } @@ -386,8 +388,8 @@ int main() oclog() << "Exception in main: "<< e.what(); } - // No explicit call to stop the platform. - // When OCPlatform destructor is invoked, internally we do platform cleanup + // Perform platform clean up. + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); return 0; } diff --git a/resource/examples/rdclient.cpp b/resource/examples/rdclient.cpp index 5960fa2..074e5e0 100644 --- a/resource/examples/rdclient.cpp +++ b/resource/examples/rdclient.cpp @@ -246,11 +246,12 @@ int main(int argc, char* argv[]) OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink }; PlatformConfig config - { OC::ServiceType::InProc, ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::LowQos, &ps}; + { OC::ServiceType::InProc, ModeType::Both, &ps}; try { OCPlatform::Configure(config); + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); int selectedMenu; bool isRun = true; @@ -291,6 +292,7 @@ int main(int argc, char* argv[]) } } + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); } catch (OCException& e) { diff --git a/resource/examples/roomclient.cpp b/resource/examples/roomclient.cpp index 6d04a7d..c23e846 100644 --- a/resource/examples/roomclient.cpp +++ b/resource/examples/roomclient.cpp @@ -270,12 +270,11 @@ int main(int argc, char* argv[]) { PlatformConfig cfg { OC::ServiceType::InProc, OC::ModeType::Client, - "0.0.0.0", - 0, - OC::QualityOfService::LowQos + nullptr }; OCPlatform::Configure(cfg); + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); try { @@ -294,6 +293,9 @@ int main(int argc, char* argv[]) { std::unique_lock lock(blocker); cv.wait(lock); + // Perform platform clean up. + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); + }catch(OCException& e) { oclog() << "Exception in main: "<< e.what(); diff --git a/resource/examples/roomserver.cpp b/resource/examples/roomserver.cpp index 8295401..65eefa8 100644 --- a/resource/examples/roomserver.cpp +++ b/resource/examples/roomserver.cpp @@ -656,13 +656,12 @@ int main(int argc, char* argv[]) PlatformConfig cfg { OC::ServiceType::InProc, OC::ModeType::Server, - "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces - 0, // Uses randomly available port - OC::QualityOfService::LowQos + nullptr }; OCPlatform::Configure(cfg); std::cout << "Starting server & setting platform info\n"; + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); OCStackResult result = SetPlatformInfo(platformId, manufacturerName, manufacturerLink, modelNumber, dateOfManufacture, platformVersion, operatingSystemVersion, @@ -705,8 +704,8 @@ int main(int argc, char* argv[]) std::cout << "Exception in main: " << e.what(); } - // No explicit call to stop the platform. - // When OCPlatform destructor is invoked, internally we do platform cleanup + // Perform platform clean up. + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); return 0; } diff --git a/resource/examples/simpleclient.cpp b/resource/examples/simpleclient.cpp index 6c287be..62cdc7e 100644 --- a/resource/examples/simpleclient.cpp +++ b/resource/examples/simpleclient.cpp @@ -557,16 +557,18 @@ int main(int argc, char* argv[]) { PlatformConfig cfg { OC::ServiceType::InProc, OC::ModeType::Both, - OCConnectivityType::CT_ADAPTER_IP, - OCConnectivityType::CT_ADAPTER_IP, - (OCTransportAdapter)(OCTransportAdapter::OC_ADAPTER_IP|OCTransportAdapter::OC_ADAPTER_TCP), - OC::QualityOfService::HighQos, &ps }; + cfg.transportType = static_cast(OCTransportAdapter::OC_ADAPTER_IP | + OCTransportAdapter::OC_ADAPTER_TCP); + cfg.QoS = OC::QualityOfService::HighQos; + OCPlatform::Configure(cfg); try { + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); + // makes it so that all boolean values are printed as 'true/false' in this stream std::cout.setf(std::ios::boolalpha); // Find all resources @@ -592,6 +594,9 @@ int main(int argc, char* argv[]) { std::unique_lock lock(blocker); cv.wait(lock); + // Perform platform clean up. + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); + }catch(OCException& e) { oclog() << "Exception in main: "< lock(blocker); cv.wait(lock); + // Perform platform clean up. + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); } catch(OCException& e) { diff --git a/resource/examples/simpleclientserver.cpp b/resource/examples/simpleclientserver.cpp index 596b37f..d5fcd36 100644 --- a/resource/examples/simpleclientserver.cpp +++ b/resource/examples/simpleclientserver.cpp @@ -341,9 +341,7 @@ int main(int argc, char* argv[]) PlatformConfig cfg { OC::ServiceType::InProc, OC::ModeType::Both, - "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces - 0, // Uses randomly available port - OC::QualityOfService::LowQos + nullptr }; OCPlatform::Configure(cfg); @@ -351,14 +349,18 @@ int main(int argc, char* argv[]) try { + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); if(!fooRes.createResource()) { + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); return -1; } ClientWorker cw(connectivityType); cw.start(); + + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); } catch(OCException& e) { diff --git a/resource/examples/simpleserver.cpp b/resource/examples/simpleserver.cpp index b232827..006216f 100644 --- a/resource/examples/simpleserver.cpp +++ b/resource/examples/simpleserver.cpp @@ -672,12 +672,15 @@ int main(int argc, char* argv[]) PlatformConfig cfg { OC::ServiceType::InProc, OC::ModeType::Server, - (OCTransportAdapter)(OCTransportAdapter::OC_ADAPTER_IP|OCTransportAdapter::OC_ADAPTER_TCP), - OC::QualityOfService::LowQos, &ps }; + cfg.transportType = static_cast(OCTransportAdapter::OC_ADAPTER_IP | + OCTransportAdapter::OC_ADAPTER_TCP); + cfg.QoS = OC::QualityOfService::LowQos; + OCPlatform::Configure(cfg); + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); std::cout << "Starting server & setting platform info\n"; OCStackResult result = SetPlatformInfo(platformId, manufacturerName, manufacturerLink, @@ -731,8 +734,7 @@ int main(int argc, char* argv[]) std::cout << "OCException in main : " << e.what() << endl; } - // No explicit call to stop the platform. - // When OCPlatform::destructor is invoked, internally we do platform cleanup + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); return 0; } diff --git a/resource/examples/threadingsample.cpp b/resource/examples/threadingsample.cpp index 3c61b71..78c5412 100644 --- a/resource/examples/threadingsample.cpp +++ b/resource/examples/threadingsample.cpp @@ -341,15 +341,15 @@ int main(int /*argc*/, char** /*argv[]*/) PlatformConfig cfg { OC::ServiceType::InProc, OC::ModeType::Both, - "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces - 0, // Uses randomly available port - OC::QualityOfService::LowQos + nullptr }; OCPlatform::Configure(cfg); try { + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); + // main thread running as server FooResource fooRes("/q/foo1"); if(!fooRes.createResource()) @@ -379,6 +379,9 @@ int main(int /*argc*/, char** /*argv[]*/) std::condition_variable cv; std::unique_lock lock(blocker); cv.wait(lock); + + // Perform platform clean up. + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); } catch(OCException& e) { diff --git a/resource/examples/winuiclient.cpp b/resource/examples/winuiclient.cpp index 1b892cd..ac299ea 100644 --- a/resource/examples/winuiclient.cpp +++ b/resource/examples/winuiclient.cpp @@ -29,29 +29,37 @@ void LabelPrintf (HWND hwndEdit, TCHAR * szFormat, ...); WinUIClientApp::WinUIClientApp(OCPersistentStorage ps) : persistentStorage(ps), - OBSERVE_TYPE_TO_USE(ObserveType::Observe) + OBSERVE_TYPE_TO_USE(ObserveType::Observe), + initialized(false) { } WinUIClientApp::~WinUIClientApp() { - + if (initialized) + { + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); + } } -void WinUIClientApp::Initialize() +bool WinUIClientApp::Initialize() { + assert(!initialized); + // Create PlatformConfig object PlatformConfig cfg { OC::ServiceType::InProc, OC::ModeType::Both, - "0.0.0.0", - 0, - OC::QualityOfService::LowQos, &persistentStorage }; OCPlatform::Configure(cfg); + if (OCPlatform::start() == OC_STACK_OK) + { + initialized = true; + } + return initialized; } void WinUIClientApp::Run() diff --git a/resource/examples/winuiclient.h b/resource/examples/winuiclient.h index b052e4e..53288ee 100644 --- a/resource/examples/winuiclient.h +++ b/resource/examples/winuiclient.h @@ -1,89 +1,90 @@ -/* **************************************************************** - * - * Copyright 2016 Intel Corporation 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 WINUICLIENT_H_ -#define WINUICLIENT_H_ - -#include -#include -#include -#include "OCPlatform.h" -#include "OCApi.h" -#include "OCResource.h" - -using namespace OC; -namespace WinUIClient{ - - class Media - { - public: - - bool m_state; - int m_volume; - std::string m_name; - - Media() : m_state(false), m_volume(0), m_name("") - { - } - }; - - class WinUIClientApp - { - public: - WinUIClientApp(OCPersistentStorage ps); - ~WinUIClientApp(); - - void Initialize(); - void Run(); - void FindResources(); - void GetMediaRepresentation(); - void PutMediaRepresentation(); - void PostMediaRepresentation(); - void BeginObserving(); - void CancelObserving(); - - std::shared_ptr GetResource(); - Media GetMedia(){return mymedia;} - void SetMedia(bool state, int volume){mymedia.m_state = state; mymedia.m_volume=volume;} - bool observing; - - private: - void foundResource(std::shared_ptr resource); - void onGet(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode); - void onPut(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode); - void onPost(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode); - void onPost2(const HeaderOptions& /*headerOptions*/,const OCRepresentation& rep, const int eCode); - void onObserve(const HeaderOptions /*headerOptions*/, const OCRepresentation& rep, const int& eCode, const int& sequenceNumber); - private: - int observe_count(); - - private: - typedef std::map> DiscoveredResourceMap; - - OCPersistentStorage persistentStorage; - Media mymedia; - DiscoveredResourceMap discoveredResources; - std::shared_ptr curResource; - ObserveType OBSERVE_TYPE_TO_USE; - std::mutex curResourceLock; - }; - -} - -#endif - +/* **************************************************************** + * + * Copyright 2016 Intel Corporation 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 WINUICLIENT_H_ +#define WINUICLIENT_H_ + +#include +#include +#include +#include "OCPlatform.h" +#include "OCApi.h" +#include "OCResource.h" + +using namespace OC; +namespace WinUIClient{ + + class Media + { + public: + + bool m_state; + int m_volume; + std::string m_name; + + Media() : m_state(false), m_volume(0), m_name("") + { + } + }; + + class WinUIClientApp + { + public: + WinUIClientApp(OCPersistentStorage ps); + ~WinUIClientApp(); + + bool Initialize(); + void Run(); + void FindResources(); + void GetMediaRepresentation(); + void PutMediaRepresentation(); + void PostMediaRepresentation(); + void BeginObserving(); + void CancelObserving(); + + std::shared_ptr GetResource(); + Media GetMedia(){return mymedia;} + void SetMedia(bool state, int volume){mymedia.m_state = state; mymedia.m_volume=volume;} + bool observing; + + private: + void foundResource(std::shared_ptr resource); + void onGet(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode); + void onPut(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode); + void onPost(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode); + void onPost2(const HeaderOptions& /*headerOptions*/,const OCRepresentation& rep, const int eCode); + void onObserve(const HeaderOptions /*headerOptions*/, const OCRepresentation& rep, const int& eCode, const int& sequenceNumber); + private: + int observe_count(); + + private: + typedef std::map> DiscoveredResourceMap; + + OCPersistentStorage persistentStorage; + Media mymedia; + DiscoveredResourceMap discoveredResources; + std::shared_ptr curResource; + ObserveType OBSERVE_TYPE_TO_USE; + std::mutex curResourceLock; + bool initialized; + }; + +} + +#endif + diff --git a/resource/examples/winuiclientgui.cpp b/resource/examples/winuiclientgui.cpp index c6921ce..730f899 100644 --- a/resource/examples/winuiclientgui.cpp +++ b/resource/examples/winuiclientgui.cpp @@ -186,8 +186,10 @@ WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) OCPersistentStorage ps = {client_open, fread, fwrite, fclose, unlink }; app = new WinUIClient::WinUIClientApp(ps); - app->Initialize(); - app->Run(); + if (app->Initialize()) + { + app->Run(); + } } break; case WM_DESTROY: diff --git a/resource/include/OCApi.h b/resource/include/OCApi.h index 2d200f3..c8250e5 100644 --- a/resource/include/OCApi.h +++ b/resource/include/OCApi.h @@ -31,6 +31,8 @@ #include #endif +#include "iotivity_debug.h" + #include "octypes.h" #include "OCHeaderOption.h" #include @@ -161,7 +163,34 @@ namespace OC /** persistant storage Handler structure (open/read/write/close/unlink). */ OCPersistentStorage *ps; + /** + * This flag allows legacy app to opt in the previous behavior of OCPlatform being + * cleaned up by the C++ static storage (de)initializer. + * + * The flag is set to false by default, unless a legacy constructor is used. + * + * When the flag is set to false (i.e., the new preferred behavior), users of OCPlatform + * are responsible for calling start() and stop() explicitly while ensuring that the calls + * to them are balanced as the last call to stop() shuts down the underlying stack. + */ + bool useLegacyCleanup; + public: + PlatformConfig(const ServiceType serviceType_, + const ModeType mode_, + OCPersistentStorage *ps_) + : serviceType(serviceType_), + mode(mode_), + serverConnectivity(CT_DEFAULT), + clientConnectivity(CT_DEFAULT), + transportType(OC_DEFAULT_ADAPTER), + ipAddress(""), + port(0), + QoS(QualityOfService::NaQos), + ps(ps_), + useLegacyCleanup(false) + {} + /* @deprecated: Use a non deprecated constructor. */ PlatformConfig() : serviceType(ServiceType::InProc), mode(ModeType::Both), @@ -171,8 +200,10 @@ namespace OC ipAddress("0.0.0.0"), port(0), QoS(QualityOfService::NaQos), - ps(nullptr) + ps(nullptr), + useLegacyCleanup(true) {} + /* @deprecated: Use a non deprecated constructor. */ PlatformConfig(const ServiceType serviceType_, const ModeType mode_, OCConnectivityType serverConnectivity_, @@ -187,9 +218,10 @@ namespace OC ipAddress(""), port(0), QoS(QoS_), - ps(ps_) + ps(ps_), + useLegacyCleanup(true) {} - // for backward compatibility + /* @deprecated: Use a non deprecated constructor. */ PlatformConfig(const ServiceType serviceType_, const ModeType mode_, const std::string& ipAddress_, @@ -204,8 +236,10 @@ namespace OC ipAddress(ipAddress_), port(port_), QoS(QoS_), - ps(ps_) + ps(ps_), + useLegacyCleanup(true) {} + /* @deprecated: Use a non deprecated constructor. */ PlatformConfig(const ServiceType serviceType_, const ModeType mode_, const std::string& ipAddress_, @@ -236,8 +270,10 @@ namespace OC ipAddress(""), port(0), QoS(QoS_), - ps(ps_) + ps(ps_), + useLegacyCleanup(true) {} + /* @deprecated: Use a non deprecated constructor. */ PlatformConfig(const ServiceType serviceType_, const ModeType mode_, OCConnectivityType serverConnectivity_, @@ -253,7 +289,8 @@ namespace OC ipAddress(""), port(0), QoS(QoS_), - ps(ps_) + ps(ps_), + useLegacyCleanup(true) {} }; diff --git a/resource/include/OCPlatform.h b/resource/include/OCPlatform.h index e51d5df..9891fe8 100644 --- a/resource/include/OCPlatform.h +++ b/resource/include/OCPlatform.h @@ -51,6 +51,7 @@ namespace OC /** * API for stop Base layer including resource and connectivity abstraction. + * The API is reference counted. The calls to start and stop need to be balanced. * * @return Returns ::OC_STACK_OK if success. */ @@ -59,6 +60,7 @@ namespace OC /** * API for start Base layer including resource and connectivity abstraction. * OCInit will be invoked. + * The API is reference counted. The calls to start and stop need to be balanced. * * @return Returns ::OC_STACK_OK if success. */ diff --git a/resource/include/OCPlatform_impl.h b/resource/include/OCPlatform_impl.h index 6637c16..bfbab03 100644 --- a/resource/include/OCPlatform_impl.h +++ b/resource/include/OCPlatform_impl.h @@ -348,6 +348,8 @@ namespace OC IServerWrapper::Ptr m_server; IClientWrapper::Ptr m_client; std::shared_ptr m_csdkLock; + std::mutex m_startCountLock; + uint32_t m_startCount; private: /** @@ -361,7 +363,7 @@ namespace OC /** * Private function to initialize the platform */ - void init(const PlatformConfig& config); + OCStackResult init(const PlatformConfig& config); /** * Private constructor/operators to prevent copying diff --git a/resource/include/WrapperFactory.h b/resource/include/WrapperFactory.h index 5e06e02..0a4eb7e 100644 --- a/resource/include/WrapperFactory.h +++ b/resource/include/WrapperFactory.h @@ -40,9 +40,11 @@ namespace OC typedef std::shared_ptr Ptr; virtual IClientWrapper::Ptr CreateClientWrapper( - std::weak_ptr csdkLock, PlatformConfig cfg) =0; + std::weak_ptr csdkLock, PlatformConfig cfg, + OCStackResult *result) =0; virtual IServerWrapper::Ptr CreateServerWrapper( - std::weak_ptr csdkLock, PlatformConfig cfg) =0; + std::weak_ptr csdkLock, PlatformConfig cfg, + OCStackResult *result) =0; virtual ~IWrapperFactory(){} }; @@ -53,30 +55,53 @@ namespace OC WrapperFactory(){} virtual IClientWrapper::Ptr CreateClientWrapper( - std::weak_ptr csdkLock, PlatformConfig cfg) + std::weak_ptr csdkLock, PlatformConfig cfg, OCStackResult *result) { + if (result) + { + *result = OC_STACK_NOTIMPL; + } + switch(cfg.serviceType) { case ServiceType::InProc: + if (result) + { + *result = OC_STACK_OK; + } return std::make_shared(csdkLock, cfg); case ServiceType::OutOfProc: + if (result) + { + *result = OC_STACK_OK; + } return std::make_shared(csdkLock, cfg); + default: + break; } - return nullptr; + return nullptr; } virtual IServerWrapper::Ptr CreateServerWrapper( - std::weak_ptr csdkLock, PlatformConfig cfg) + std::weak_ptr csdkLock, PlatformConfig cfg, OCStackResult *result) { + if (result) + { + *result = OC_STACK_NOTIMPL; + } + switch(cfg.serviceType) { case ServiceType::InProc: + if (result) + { + *result = OC_STACK_OK; + } return std::make_shared(csdkLock, cfg); - case ServiceType::OutOfProc: - throw OC::OCException(OC::Exception::SVCTYPE_OUTOFPROC, OC_STACK_NOTIMPL); + default: break; } - return nullptr; + return nullptr; } virtual ~WrapperFactory(){} diff --git a/resource/src/InProcClientWrapper.cpp b/resource/src/InProcClientWrapper.cpp index 194cb5c..c67e9a5 100644 --- a/resource/src/InProcClientWrapper.cpp +++ b/resource/src/InProcClientWrapper.cpp @@ -57,22 +57,10 @@ namespace OC OCStackResult InProcClientWrapper::start() { - OIC_LOG_V(INFO, TAG, "start ocplatform for client : %d", m_cfg.transportType); + OIC_LOG(INFO, TAG, "start"); if (m_cfg.mode == ModeType::Client) { - OCTransportFlags serverFlags = - static_cast(m_cfg.serverConnectivity & CT_MASK_FLAGS); - OCTransportFlags clientFlags = - static_cast(m_cfg.clientConnectivity & CT_MASK_FLAGS); - OCStackResult result = OCInit2(OC_CLIENT, serverFlags, clientFlags, - m_cfg.transportType); - - if (OC_STACK_OK != result) - { - throw InitializeException(OC::InitException::STACK_INIT_ERROR, result); - } - if (false == m_threadRun) { m_threadRun = true; @@ -84,25 +72,13 @@ namespace OC OCStackResult InProcClientWrapper::stop() { - OIC_LOG(INFO, TAG, "stop ocplatform"); + OIC_LOG(INFO, TAG, "stop"); if (m_threadRun && m_listeningThread.joinable()) { m_threadRun = false; m_listeningThread.join(); } - - // only stop if we are the ones who actually called 'start'. We are counting - // on the server to do the stop. - if (m_cfg.mode == ModeType::Client) - { - OCStackResult result = OCStop(); - - if (OC_STACK_OK != result) - { - throw InitializeException(OC::InitException::STACK_TERMINATE_ERROR, result); - } - } return OC_STACK_OK; } diff --git a/resource/src/InProcServerWrapper.cpp b/resource/src/InProcServerWrapper.cpp index 67a44ca..7d7c200 100644 --- a/resource/src/InProcServerWrapper.cpp +++ b/resource/src/InProcServerWrapper.cpp @@ -261,43 +261,11 @@ namespace OC : m_threadRun(false), m_csdkLock(csdkLock), m_cfg { cfg } { - start(); } OCStackResult InProcServerWrapper::start() { - OIC_LOG_V(INFO, TAG, "start ocplatform for server : %d", m_cfg.transportType); - - OCMode initType; - if(m_cfg.mode == ModeType::Server) - { - initType = OC_SERVER; - } - else if (m_cfg.mode == ModeType::Both) - { - initType = OC_CLIENT_SERVER; - } - else if (m_cfg.mode == ModeType::Gateway) - { - initType = OC_GATEWAY; - } - else - { - throw InitializeException(OC::InitException::NOT_CONFIGURED_AS_SERVER, - OC_STACK_INVALID_PARAM); - } - - OCTransportFlags serverFlags = - static_cast(m_cfg.serverConnectivity & CT_MASK_FLAGS); - OCTransportFlags clientFlags = - static_cast(m_cfg.clientConnectivity & CT_MASK_FLAGS); - OCStackResult result = OCInit2(initType, serverFlags, clientFlags, - m_cfg.transportType); - - if(OC_STACK_OK != result) - { - throw InitializeException(OC::InitException::STACK_INIT_ERROR, result); - } + OIC_LOG(INFO, TAG, "start"); if (false == m_threadRun) { @@ -317,13 +285,6 @@ namespace OC m_processThread.join(); } - OCStackResult res = OCStop(); - - if (OC_STACK_OK != res) - { - throw InitializeException(OC::InitException::STACK_TERMINATE_ERROR, res); - } - return OC_STACK_OK; } diff --git a/resource/src/OCPlatform_impl.cpp b/resource/src/OCPlatform_impl.cpp index b04e14e..0908d1f 100644 --- a/resource/src/OCPlatform_impl.cpp +++ b/resource/src/OCPlatform_impl.cpp @@ -43,6 +43,7 @@ #include "OCException.h" #include "OCUtilities.h" #include "ocpayload.h" +#include "iotivity_debug.h" #include "logger.h" #include "oc_logger.hpp" @@ -74,39 +75,80 @@ namespace OC { OIC_LOG(INFO, TAG, "start"); - OCStackResult res = OC_STACK_OK; - if (OC_CLIENT == m_modeType) + std::lock_guard lock(m_startCountLock); + + if (0 != m_startCount) { - if (OC_STACK_OK != checked_guard(m_client, &IClientWrapper::start)) - { - res = OC_STACK_ERROR; - } + assert(UINT_MAX != m_startCount); + m_startCount++; + return OC_STACK_OK; } - else if (OC_SERVER == m_modeType) + + // Reload from the global configuration. + m_cfg = globalConfig(); + + // First caller gets to initialize the underlying objects and start the stack. + OCStackResult res = init(m_cfg); + if (OC_STACK_OK != res) { - if (OC_STACK_OK != checked_guard(m_server, &IServerWrapper::start)) - { - res = OC_STACK_ERROR; - } + return res; } - else if (OC_CLIENT_SERVER == m_modeType || OC_GATEWAY == m_modeType) + + OCTransportFlags serverFlags = + static_cast(m_cfg.serverConnectivity & CT_MASK_FLAGS); + OCTransportFlags clientFlags = + static_cast(m_cfg.clientConnectivity & CT_MASK_FLAGS); + res = OCInit2(m_modeType, serverFlags, clientFlags, m_cfg.transportType); + if (OC_STACK_OK != res) { - if (OC_STACK_OK != checked_guard(m_client, &IClientWrapper::start)) - { - res = OC_STACK_ERROR; - } + return res; + } - if (OC_STACK_OK != checked_guard(m_server, &IServerWrapper::start)) - { + switch(m_modeType) + { + case OC_CLIENT: + if (OC_STACK_OK != checked_guard(m_client, &IClientWrapper::start)) + { + res = OC_STACK_ERROR; + } + break; + + case OC_SERVER: + if (OC_STACK_OK != checked_guard(m_server, &IServerWrapper::start)) + { + res = OC_STACK_ERROR; + } + break; + + case OC_CLIENT_SERVER: + case OC_GATEWAY: + if (OC_STACK_OK != checked_guard(m_client, &IClientWrapper::start)) + { + res = OC_STACK_ERROR; + } + if (OC_STACK_OK != checked_guard(m_server, &IServerWrapper::start)) + { + res = OC_STACK_ERROR; + } + break; + + default: + assert(!"Unknown modeType"); res = OC_STACK_ERROR; - } + break; } - else + + if (OC_STACK_OK != res) { - res = OC_STACK_ERROR; + // Stop the underlying stack. + // The counterpart of this function, OCInit2(), is called once by start(). + OC_VERIFY(OC_STACK_OK == OCStop()); + return res; } - return res; + assert(UINT_MAX != m_startCount); + m_startCount++; + return OC_STACK_OK; } OCStackResult OCPlatform_impl::stop() @@ -114,75 +156,109 @@ namespace OC OIC_LOG(INFO, TAG, "stop"); OCStackResult res = OC_STACK_OK; - if (OC_CLIENT == m_modeType) + + std::lock_guard lock(m_startCountLock); + + // Only the last call to stop() gets to do the real clean up work. + if (m_startCount == 1) { - if (OC_STACK_OK != checked_guard(m_client, &IClientWrapper::stop)) + if (OC_CLIENT == m_modeType) { - res = OC_STACK_ERROR; + if (OC_STACK_OK != checked_guard(m_client, &IClientWrapper::stop)) + { + res = OC_STACK_ERROR; + } } - } - else if (OC_SERVER == m_modeType) - { - if (OC_STACK_OK != checked_guard(m_server, &IServerWrapper::stop)) + else if (OC_SERVER == m_modeType) { - res = OC_STACK_ERROR; + if (OC_STACK_OK != checked_guard(m_server, &IServerWrapper::stop)) + { + res = OC_STACK_ERROR; + } } - } - else if (OC_CLIENT_SERVER == m_modeType) - { - if (OC_STACK_OK != checked_guard(m_client, &IClientWrapper::stop)) + else if (OC_CLIENT_SERVER == m_modeType) + { + if (OC_STACK_OK != checked_guard(m_client, &IClientWrapper::stop)) + { + res = OC_STACK_ERROR; + } + + if (OC_STACK_OK != checked_guard(m_server, &IServerWrapper::stop)) + { + res = OC_STACK_ERROR; + } + } + else { res = OC_STACK_ERROR; } - if (OC_STACK_OK != checked_guard(m_server, &IServerWrapper::stop)) + if (OC_STACK_OK == res) { - res = OC_STACK_ERROR; + res = OCStop(); } } - else + + if (OC_STACK_OK == res) { - res = OC_STACK_ERROR; + assert(0 != m_startCount); + m_startCount--; } return res; } - void OCPlatform_impl::init(const PlatformConfig& config) + OCStackResult OCPlatform_impl::init(const PlatformConfig& config) { OIC_LOG(INFO, TAG, "init"); + OCStackResult result = OC_STACK_NOTIMPL; switch(config.mode) { case ModeType::Server: - m_server = m_WrapperInstance->CreateServerWrapper(m_csdkLock, config); + m_server = m_WrapperInstance->CreateServerWrapper(m_csdkLock, config, &result); m_modeType = OC_SERVER; break; case ModeType::Client: - m_client = m_WrapperInstance->CreateClientWrapper(m_csdkLock, config); + m_client = m_WrapperInstance->CreateClientWrapper(m_csdkLock, config, &result); m_modeType = OC_CLIENT; break; case ModeType::Both: case ModeType::Gateway: - m_server = m_WrapperInstance->CreateServerWrapper(m_csdkLock, config); - m_client = m_WrapperInstance->CreateClientWrapper(m_csdkLock, config); + m_server = m_WrapperInstance->CreateServerWrapper(m_csdkLock, config, &result); + m_client = m_WrapperInstance->CreateClientWrapper(m_csdkLock, config, &result); m_modeType = OC_CLIENT_SERVER; break; - } + } + + if (OC_STACK_OK != result) + { + m_server.reset(); + m_client.reset(); + } + return result; } OCPlatform_impl::OCPlatform_impl(const PlatformConfig& config) : m_cfg { config }, m_WrapperInstance { make_unique() }, - m_csdkLock { std::make_shared() } + m_csdkLock { std::make_shared() }, + m_startCount(0) { - init(m_cfg); + if (m_cfg.useLegacyCleanup) + { + start(); + } } OCPlatform_impl::~OCPlatform_impl(void) { + if (m_cfg.useLegacyCleanup) + { + stop(); + } } OCStackResult OCPlatform_impl::setDefaultDeviceEntityHandler(EntityHandler entityHandler) diff --git a/resource/unittests/OCPlatformTest.cpp b/resource/unittests/OCPlatformTest.cpp index b71b627..ae74b11 100644 --- a/resource/unittests/OCPlatformTest.cpp +++ b/resource/unittests/OCPlatformTest.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include namespace OCPlatformTest @@ -138,13 +139,42 @@ namespace OCPlatformTest } } + class Framework + { + public: + Framework(ServiceType serviceType = OC::ServiceType::InProc, + ModeType mode = OC::ModeType::Server, + OCPersistentStorage *ps = nullptr) + : m_started(false) + { + PlatformConfig cfg(serviceType, mode, ps); + OCPlatform::Configure(cfg); + } + ~Framework() + { + if (m_started) + { + OC_VERIFY(OC_STACK_OK == OCPlatform::stop()); + m_started = false; + } + } + OCStackResult start() + { + OCStackResult result = OCPlatform::start(); + if (OC_STACK_OK == result) + { + m_started = true; + } + return result; + } + + private: + bool m_started; + }; + OCResourceHandle RegisterResource(std::string uri, std::string type, std::string iface) { - PlatformConfig cfg - { OC::ServiceType::InProc, OC::ModeType::Server, "0.0.0.0", 0, - OC::QualityOfService::LowQos, &gps }; - OCPlatform::Configure(cfg); - EXPECT_EQ(OC_STACK_OK,OCPlatform::registerResource( + EXPECT_EQ(OC_STACK_OK, OCPlatform::registerResource( resourceHandle, uri, type, iface, entityHandler, gResourceProperty)); return resourceHandle; @@ -152,10 +182,6 @@ namespace OCPlatformTest OCResourceHandle RegisterResource(std::string uri, std::string type) { - PlatformConfig cfg - { OC::ServiceType::InProc, OC::ModeType::Server, "0.0.0.0", 0, - OC::QualityOfService::LowQos, &gps }; - OCPlatform::Configure(cfg); EXPECT_EQ(OC_STACK_OK, OCPlatform::registerResource( resourceHandle, uri, type, gResourceInterface, entityHandler, gResourceProperty)); @@ -164,10 +190,6 @@ namespace OCPlatformTest OCResourceHandle RegisterResource(std::string uri) { - PlatformConfig cfg - { OC::ServiceType::InProc, OC::ModeType::Server, "0.0.0.0", 0, - OC::QualityOfService::LowQos, &gps }; - OCPlatform::Configure(cfg); EXPECT_EQ(OC_STACK_OK, OCPlatform::registerResource( resourceHandle, uri, gResourceTypeName, gResourceInterface, entityHandler, gResourceProperty)); @@ -176,10 +198,6 @@ namespace OCPlatformTest OCResourceHandle RegisterResource(std::string uri, OCTpsSchemeFlags resourceTpsTypes) { - PlatformConfig cfg - { OC::ServiceType::OutOfProc, OC::ModeType::Server, "0.0.0.0", 0, - OC::QualityOfService::LowQos, &gps }; - OCPlatform::Configure(cfg); EXPECT_EQ(OC_STACK_OK, OCPlatform::registerResource( resourceHandle, uri, gResourceTypeName, gResourceInterface, entityHandler, gResourceProperty, @@ -187,104 +205,40 @@ namespace OCPlatformTest return resourceHandle; } - //Configure - // Enable it when the stack throw an exception - // https://jira.iotivity.org/browse/IOT-428 - TEST(ConfigureTest, DISABLED_ConfigureInvalidModeType) - { - PlatformConfig cfg { - OC::ServiceType::InProc, - (OC::ModeType)99, - "0.0.0.0", - 0, - OC::QualityOfService::LowQos - }; - OCPlatform::Configure(cfg); - EXPECT_ANY_THROW(OCPlatform::setDefaultDeviceEntityHandler(nullptr)); - } + TEST(ConfigureTest, ConfigureInvalidModeType) + { + Framework framework(OC::ServiceType::InProc, (OC::ModeType)99); + EXPECT_EQ(OC_STACK_NOTIMPL, framework.start()); + } - // Enable it when the stack throw an exception - // https://jira.iotivity.org/browse/IOT-428 - TEST(ConfigureTest, DISABLED_ConfigureInvalidServiceType) - { - PlatformConfig cfg { - (OC::ServiceType)99, - OC::ModeType::Client, - "0.0.0.0", - 0, - OC::QualityOfService::LowQos - }; - OCPlatform::Configure(cfg); - EXPECT_ANY_THROW(OCPlatform::setDefaultDeviceEntityHandler(nullptr)); - } + TEST(ConfigureTest, ConfigureInvalidServiceType) + { + Framework framework((OC::ServiceType)99, OC::ModeType::Client); + EXPECT_EQ(OC_STACK_NOTIMPL, framework.start()); + } // Enable it when the stack throw an exception // https://jira.iotivity.org/browse/IOT-428 TEST(ConfigureTest, DISABLED_ConfigureClientOutProc) { - PlatformConfig cfg { - OC::ServiceType::OutOfProc, - OC::ModeType::Client, - "0.0.0.0", - 0, - OC::QualityOfService::LowQos - }; - std::string uri = "/a/light66"; - std::string type = "core.light"; - uint8_t gResourceProperty = 0; - OCPlatform::Configure(cfg); - EXPECT_ANY_THROW(OCPlatform::registerResource( - resourceHandle, uri, type, - gResourceInterface, entityHandler, gResourceProperty)); + Framework framework(OC::ServiceType::OutOfProc, OC::ModeType::Client, &gps); + EXPECT_EQ(OC_STACK_NOTIMPL, framework.start()); } TEST(ConfigureTest, ConfigureServerOutProc) { - PlatformConfig cfg - { - OC::ServiceType::OutOfProc, - OC::ModeType::Server, - "0.0.0.0", - 0, - OC::QualityOfService::LowQos, &gps - }; - std::string uri = "/a/light67"; - std::string type = "core.light"; - uint8_t gResourceProperty = 0; - OCPlatform::Configure(cfg); - - EXPECT_ANY_THROW(OCPlatform::registerResource( - resourceHandle, uri, type, - gResourceInterface, entityHandler, gResourceProperty)); - } - - TEST(ConfigureTest, ConfigureDefault) - { - std::string uri = "/a/light68"; - std::string type = "core.light"; - uint8_t gResourceProperty = 0; - PlatformConfig cfg = {}; - OCPlatform::Configure(cfg); - - EXPECT_NO_THROW(OCPlatform::registerResource( - resourceHandle, uri, type, - gResourceInterface, entityHandler, gResourceProperty)); + Framework framework(OC::ServiceType::OutOfProc, OC::ModeType::Server); + EXPECT_EQ(OC_STACK_NOTIMPL, framework.start()); } TEST(ConfigureTest, ConfigureServer) { + Framework framework(OC::ServiceType::InProc, OC::ModeType::Server, &gps); + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string uri = "/a/light69"; std::string type = "core.light"; uint8_t gResourceProperty = 0; - PlatformConfig cfg { - OC::ServiceType::InProc, - OC::ModeType::Server, - "0.0.0.0", - 0, - OC::QualityOfService::LowQos, &gps - }; - OCPlatform::Configure(cfg); - EXPECT_NO_THROW(OCPlatform::registerResource( resourceHandle, uri, type, gResourceInterface, entityHandler, gResourceProperty)); @@ -292,92 +246,43 @@ namespace OCPlatformTest TEST(ConfigureTest, ConfigureClient) { - std::string uri = "/a/light70"; - std::string type = "core.light"; - uint8_t gResourceProperty = 0; - PlatformConfig cfg - { - OC::ServiceType::InProc, - OC::ModeType::Client, - "0.0.0.0", - 0, - OC::QualityOfService::LowQos, - &gps - }; - - EXPECT_NO_THROW(OCPlatform::registerResource( - resourceHandle, uri, type, - gResourceInterface, entityHandler, gResourceProperty)); + Framework framework(OC::ServiceType::InProc, OC::ModeType::Client, &gps); + ASSERT_TRUE(OC_STACK_OK == framework.start()); } - //PersistentStorageTest - TEST(ConfigureTest, ConfigureDefaultNULLPersistentStorage) - { - PlatformConfig cfg { - OC::ServiceType::InProc, - OC::ModeType::Both, - "0.0.0.0", - 0, - OC::QualityOfService::LowQos - }; - OCPlatform::Configure(cfg); - EXPECT_NO_THROW(OCPlatform::setDefaultDeviceEntityHandler(nullptr)); - } //PersistentStorageTest TEST(ConfigureTest, ConfigureNULLPersistentStorage) { - PlatformConfig cfg { - OC::ServiceType::InProc, - OC::ModeType::Both, - "0.0.0.0", - 0, - OC::QualityOfService::LowQos, - nullptr - }; - OCPlatform::Configure(cfg); - EXPECT_NO_THROW(OCPlatform::setDefaultDeviceEntityHandler(nullptr)); - } + Framework framework(OC::ServiceType::InProc, OC::ModeType::Both); + ASSERT_TRUE(OC_STACK_OK == framework.start()); - //PersistentStorageTest - TEST(ConfigureTest, ConfigurePersistentStorage) - { - PlatformConfig cfg { - OC::ServiceType::InProc, - OC::ModeType::Both, - "0.0.0.0", - 0, - OC::QualityOfService::LowQos, - &gps - }; - OCPlatform::Configure(cfg); - EXPECT_NO_THROW(OCPlatform::setDefaultDeviceEntityHandler(nullptr)); - } + EXPECT_NO_THROW(OCPlatform::setDefaultDeviceEntityHandler(nullptr)); + } //PersistentStorageTest TEST(ConfigureTest, ConfigureNULLHandlersPersistentStorage) { - PlatformConfig cfg { - OC::ServiceType::InProc, - OC::ModeType::Both, - "0.0.0.0", - 0, - OC::QualityOfService::LowQos, - &gps - }; - OCPlatform::Configure(cfg); - EXPECT_NO_THROW(OCPlatform::setDefaultDeviceEntityHandler(nullptr)); - } + Framework framework(OC::ServiceType::InProc, OC::ModeType::Both, &gps); + ASSERT_TRUE(OC_STACK_OK == framework.start()); + EXPECT_NO_THROW(OCPlatform::setDefaultDeviceEntityHandler(nullptr)); + } //RegisterResourceTest TEST(RegisterResourceTest, RegisterSingleResource) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string uri = "/a/res2"; EXPECT_NE(HANDLE_ZERO, RegisterResource(uri)); } TEST(RegisterResourceTest, RegisterMultipleResources) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string uri = "/a/multi"; //Good enough for 5 resources. for(int i=0; i< 5; i++) @@ -389,6 +294,9 @@ namespace OCPlatformTest TEST(RegisterResourceTest, ReregisterResource) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHandle = RegisterResource(std::string("/a/light5"), std::string("core.light")); EXPECT_EQ(OC_STACK_OK, OC::OCPlatform::unregisterResource(resourceHandle)); @@ -400,6 +308,9 @@ namespace OCPlatformTest TEST(RegisterResourceTest, RegisterEmptyResource) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + // We should not allow empty URI. std::string emptyStr = ""; EXPECT_ANY_THROW(OCPlatform::registerResource(resourceHandle, emptyStr, emptyStr, @@ -408,6 +319,9 @@ namespace OCPlatformTest TEST(RegisterResourceTest, RegisterZeroResourceProperty) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string uri = "/a/light6"; std::string type = "core.light"; uint8_t gResourceProperty = 0; @@ -418,6 +332,9 @@ namespace OCPlatformTest TEST(RegisterResourceTest, RegisterWithTpsType) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string uri = "/a/light7"; std::string type = "core.light"; uint8_t gResourceProperty = 0; @@ -428,6 +345,9 @@ namespace OCPlatformTest TEST(RegisterResourceTest, RegisterWithTpsTypeAll) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string uri = "/a/light8"; std::string type = "core.light"; uint8_t gResourceProperty = 0; @@ -438,6 +358,9 @@ namespace OCPlatformTest #ifdef TCP_ADAPTER TEST(RegisterResourceTest, RegisterWithTpsTypeBitComb) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string uri = "/a/light9"; std::string type = "core.light"; uint8_t gResourceProperty = 0; @@ -450,12 +373,18 @@ namespace OCPlatformTest //UnregisterTest TEST(UnregisterTest, UnregisterZeroHandleValue) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + EXPECT_ANY_THROW(OC::OCPlatform::unregisterResource(HANDLE_ZERO)); } //UnbindResourcesTest TEST(UnbindResourcesTest, UnbindResources) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHome = RegisterResource(std::string("a/home"), std::string("core.home")); OCResourceHandle resourceKitchen = RegisterResource(std::string("a/kitchen"), @@ -472,6 +401,9 @@ namespace OCPlatformTest TEST(UnbindResourcesTest, UnbindResourcesWithZero) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHandle1 = 0; OCResourceHandle resourceHandle2 = 0; OCResourceHandle resourceHandle3 = 0; @@ -487,6 +419,9 @@ namespace OCPlatformTest //BindInterfaceToResourceTest TEST(BindInterfaceToResourceTest, BindResourceInterface) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHandle = RegisterResource(std::string("/a/light"), std::string("core.light")); OCStackResult result = OC::OCPlatform::bindInterfaceToResource(resourceHandle, @@ -500,6 +435,9 @@ namespace OCPlatformTest TEST(BindInterfaceToResourceTest, BindZeroResourceInterface) #endif { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHandle = RegisterResource(std::string("/a/light1"), std::string("core.light")); EXPECT_ANY_THROW(OC::OCPlatform::bindInterfaceToResource(resourceHandle, 0)); @@ -508,6 +446,9 @@ namespace OCPlatformTest //BindTypeToResourceTest TEST(BindTypeToResourceTest, BindResourceType) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHandle = RegisterResource(std::string("/a/light3"), std::string("core.light")); OCStackResult result = OC::OCPlatform::bindTypeToResource(resourceHandle, @@ -521,6 +462,9 @@ namespace OCPlatformTest TEST(BindTypeToResourceTest, BindZeroResourceType) #endif { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHandle = RegisterResource(std::string("/a/light4"), std::string("core.light")); EXPECT_ANY_THROW(OC::OCPlatform::bindTypeToResource(resourceHandle, 0)); @@ -529,6 +473,9 @@ namespace OCPlatformTest //UnbindResourceTest TEST(UnbindResourceTest, BindAndUnbindResource) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHandle1 = RegisterResource(std::string("a/unres"), std::string("core.unres")); OCResourceHandle resourceHandle2 = RegisterResource(std::string("a/unres2"), @@ -541,6 +488,9 @@ namespace OCPlatformTest //PresenceTest TEST(PresenceTest, DISABLED_StartAndStopPresence) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + EXPECT_EQ(OC_STACK_OK, OCPlatform::startPresence(30)); EXPECT_NE(HANDLE_ZERO, RegisterResource( std::string("/a/Presence"), std::string("core.Presence"))); @@ -549,12 +499,18 @@ namespace OCPlatformTest TEST(OCPlatformTest, UnbindZeroRsourceHandleValue) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + EXPECT_ANY_THROW(OCPlatform::unbindResource(HANDLE_ZERO, HANDLE_ZERO)); } //NotifyAllObserverTest TEST(NotifyAllObserverTest, NotifyAllObservers) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHome = RegisterResource(std::string("/a/obs1"), std::string("core.obs")); EXPECT_EQ(OC_STACK_NO_OBSERVERS, OCPlatform::notifyAllObservers(resourceHome)); @@ -562,6 +518,9 @@ namespace OCPlatformTest TEST(NotifyAllObserverTest, NotifyAllObserversWithLowQos) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHome = RegisterResource(std::string("/a/obs2"), std::string("core.obs")); EXPECT_EQ(OC_STACK_NO_OBSERVERS, OCPlatform::notifyAllObservers(resourceHome, @@ -570,6 +529,9 @@ namespace OCPlatformTest TEST(NotifyAllObserverTest, NotifyAllObserversWithMidQos) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHome = RegisterResource(std::string("/a/obs3"), std::string("core.obs")); EXPECT_EQ(OC_STACK_NO_OBSERVERS, OCPlatform::notifyAllObservers(resourceHome, @@ -578,6 +540,9 @@ namespace OCPlatformTest TEST(NotifyAllObserverTest, NotifyAllObserversWithNaQos) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHome = RegisterResource(std::string("/a/obs4"), std::string("core.obs")); EXPECT_EQ(OC_STACK_NO_OBSERVERS, OCPlatform::notifyAllObservers(resourceHome, @@ -586,6 +551,9 @@ namespace OCPlatformTest TEST(NotifyAllObserverTest, NotifyAllObserversWithHighQos) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHome = RegisterResource(std::string("/a/obs5"), std::string("core.obs")); EXPECT_EQ(OC_STACK_NO_OBSERVERS, OCPlatform::notifyAllObservers(resourceHome, @@ -598,6 +566,9 @@ namespace OCPlatformTest TEST(NotifyAllObserverTest, NotifyListOfObservers) #endif { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHome = RegisterResource(std::string("/a/obs6"), std::string("core.obs")); @@ -613,6 +584,9 @@ namespace OCPlatformTest TEST(NotifyAllObserverTest, NotifyListOfObserversWithLowQos) #endif { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHome = RegisterResource(std::string("/a/obs7"), std::string("core.obs")); @@ -628,6 +602,9 @@ namespace OCPlatformTest TEST(NotifyAllObserverTest, NotifyListOfObserversWithMidQos) #endif { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHome = RegisterResource(std::string("/a/obs8"), std::string("core.obs")); @@ -643,6 +620,9 @@ namespace OCPlatformTest TEST(NotifyAllObserverTest, NotifyListOfObserversWithNaQos) #endif { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHome = RegisterResource(std::string("/a/obs9"), std::string("core.obs")); @@ -658,6 +638,9 @@ namespace OCPlatformTest TEST(NotifyAllObserverTest, NotifyListOfObserversWithHighQos) #endif { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCResourceHandle resourceHome = RegisterResource(std::string("/a/obs10"), std::string("core.obs")); @@ -670,6 +653,9 @@ namespace OCPlatformTest //DeviceEntityHandlerTest TEST(DeviceEntityHandlerTest, SetDefaultDeviceEntityHandler) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + EXPECT_EQ(OC_STACK_OK, OCPlatform::setDefaultDeviceEntityHandler(entityHandler)); EXPECT_EQ(OC_STACK_OK, OCPlatform::setDefaultDeviceEntityHandler(nullptr)); } @@ -678,10 +664,13 @@ namespace OCPlatformTest //FindResource test TEST(FindResourceTest, DISABLED_FindResourceValid) { - std::ostringstream requestURI; - requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.light"; - EXPECT_EQ(OC_STACK_OK, OCPlatform::findResource("", requestURI.str(), - CT_DEFAULT, &foundResource)); + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + + std::ostringstream requestURI; + requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.light"; + EXPECT_EQ(OC_STACK_OK, OCPlatform::findResource("", requestURI.str(), + CT_DEFAULT, &foundResource)); } #if defined (_MSC_VER) @@ -690,8 +679,11 @@ namespace OCPlatformTest TEST(FindResourceTest, FindResourceNullResourceURI) #endif { - EXPECT_ANY_THROW(OCPlatform::findResource("", nullptr, - CT_DEFAULT, &foundResource)); + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + + EXPECT_ANY_THROW(OCPlatform::findResource("", nullptr, + CT_DEFAULT, &foundResource)); } @@ -701,10 +693,13 @@ namespace OCPlatformTest TEST(FindResourceTest, FindResourceNullResourceURI1) #endif { - std::ostringstream requestURI; - requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.light"; - EXPECT_ANY_THROW(OCPlatform::findResource(nullptr, requestURI.str(), - CT_DEFAULT, &foundResource)); + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + + std::ostringstream requestURI; + requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.light"; + EXPECT_ANY_THROW(OCPlatform::findResource(nullptr, requestURI.str(), + CT_DEFAULT, &foundResource)); } #if defined (_MSC_VER) @@ -713,22 +708,31 @@ namespace OCPlatformTest TEST(FindResourceTest, FindResourceNullHost) #endif { - std::ostringstream requestURI; - requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.light"; - EXPECT_ANY_THROW(OCPlatform::findResource(nullptr, requestURI.str(), - CT_DEFAULT, &foundResource)); + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + + std::ostringstream requestURI; + requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.light"; + EXPECT_ANY_THROW(OCPlatform::findResource(nullptr, requestURI.str(), + CT_DEFAULT, &foundResource)); } TEST(FindResourceTest, FindResourceNullresourceHandler) { - std::ostringstream requestURI; - requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.light"; - EXPECT_THROW(OCPlatform::findResource("", requestURI.str(), - CT_DEFAULT, nullptr), OC::OCException); + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + + std::ostringstream requestURI; + requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.light"; + EXPECT_THROW(OCPlatform::findResource("", requestURI.str(), + CT_DEFAULT, nullptr), OC::OCException); } TEST(FindResourceTest, DISABLED_FindResourceWithLowQoS) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::ostringstream requestURI; requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.light"; EXPECT_EQ(OC_STACK_OK, @@ -738,6 +742,9 @@ namespace OCPlatformTest TEST(FindResourceTest, DISABLED_FindResourceWithMidQos) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::ostringstream requestURI; requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.light"; EXPECT_EQ(OC_STACK_OK, @@ -747,6 +754,9 @@ namespace OCPlatformTest TEST(FindResourceTest, DISABLED_FindResourceWithHighQos) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::ostringstream requestURI; requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.light"; EXPECT_EQ(OC_STACK_OK, @@ -756,6 +766,9 @@ namespace OCPlatformTest TEST(FindResourceTest, DISABLED_FindResourceWithNaQos) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::ostringstream requestURI; requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.light"; EXPECT_EQ(OC_STACK_OK, @@ -766,9 +779,10 @@ namespace OCPlatformTest //GetDeviceInfo Test TEST(GetDeviceInfoTest, DISABLED_GetDeviceInfoWithValidParameters) { + Framework framework(OC::ServiceType::InProc, OC::ModeType::Both); + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string deviceDiscoveryURI = "/oic/d"; - PlatformConfig cfg; - OCPlatform::Configure(cfg); std::ostringstream requestURI; requestURI << OC_MULTICAST_PREFIX << deviceDiscoveryURI; EXPECT_EQ(OC_STACK_OK, @@ -781,17 +795,19 @@ namespace OCPlatformTest TEST(GetDeviceInfoTest, GetDeviceInfoNullDeviceURI) #endif { - PlatformConfig cfg; - OCPlatform::Configure(cfg); + Framework framework(OC::ServiceType::InProc, OC::ModeType::Both); + ASSERT_TRUE(OC_STACK_OK == framework.start()); + EXPECT_ANY_THROW( OCPlatform::getDeviceInfo("", nullptr, CT_DEFAULT, &receivedDeviceInfo)); } TEST(GetDeviceInfoTest, GetDeviceInfoWithNullDeviceInfoHandler) { + Framework framework(OC::ServiceType::InProc, OC::ModeType::Both); + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string deviceDiscoveryURI = "/oic/d"; - PlatformConfig cfg; - OCPlatform::Configure(cfg); std::ostringstream requestURI; requestURI << OC_MULTICAST_PREFIX << deviceDiscoveryURI; EXPECT_THROW( @@ -801,9 +817,10 @@ namespace OCPlatformTest TEST(GetDeviceInfoTest, DISABLED_GetDeviceInfoWithLowQos) { + Framework framework(OC::ServiceType::InProc, OC::ModeType::Both); + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string deviceDiscoveryURI = "/oic/d"; - PlatformConfig cfg; - OCPlatform::Configure(cfg); std::ostringstream requestURI; requestURI << OC_MULTICAST_PREFIX << deviceDiscoveryURI; EXPECT_EQ(OC_STACK_OK, @@ -813,9 +830,10 @@ namespace OCPlatformTest TEST(GetDeviceInfoTest, DISABLED_GetDeviceInfoWithMidQos) { + Framework framework(OC::ServiceType::InProc, OC::ModeType::Both); + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string deviceDiscoveryURI = "/oic/d"; - PlatformConfig cfg; - OCPlatform::Configure(cfg); std::ostringstream requestURI; requestURI << OC_MULTICAST_PREFIX << deviceDiscoveryURI; EXPECT_EQ(OC_STACK_OK, @@ -825,9 +843,10 @@ namespace OCPlatformTest TEST(GetDeviceInfoTest, DISABLED_GetDeviceInfoWithHighQos) { + Framework framework(OC::ServiceType::InProc, OC::ModeType::Both); + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string deviceDiscoveryURI = "/oic/d"; - PlatformConfig cfg; - OCPlatform::Configure(cfg); std::ostringstream requestURI; requestURI << OC_MULTICAST_PREFIX << deviceDiscoveryURI; EXPECT_EQ(OC_STACK_OK, @@ -837,9 +856,10 @@ namespace OCPlatformTest TEST(GetDeviceInfoTest, DISABLED_GetDeviceInfoWithNaQos) { + Framework framework(OC::ServiceType::InProc, OC::ModeType::Both); + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string deviceDiscoveryURI = "/oic/d"; - PlatformConfig cfg; - OCPlatform::Configure(cfg); std::ostringstream requestURI; requestURI << OC_MULTICAST_PREFIX << deviceDiscoveryURI; EXPECT_EQ(OC_STACK_OK, @@ -856,6 +876,9 @@ namespace OCPlatformTest //RegisterDeviceInfo test TEST(RegisterDeviceInfoTest, RegisterDeviceInfoWithValidParameters) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCDeviceInfo deviceInfo; DuplicateString(&deviceInfo.deviceName, "myDeviceName"); deviceInfo.types = NULL; @@ -873,12 +896,18 @@ namespace OCPlatformTest TEST(RegisterDeviceInfoTest, RegisterDeviceInfoWithEmptyObject) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCDeviceInfo di = {0, 0, 0, 0}; EXPECT_ANY_THROW(OCPlatform::registerDeviceInfo(di)); } TEST(RegisterDeviceInfoTest, RegisterDeviceInfoWithSetPropertyValue) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string deviceName = "myDeviceName"; EXPECT_EQ(OC_STACK_OK, OCPlatform::setPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, deviceName)); @@ -899,6 +928,9 @@ namespace OCPlatformTest TEST(RegisterDeviceInfoTest, RegisterDeviceInfoWithGetPropertyValue) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + EXPECT_EQ(OC_STACK_OK, OCPlatform::setPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, "myDeviceName")); EXPECT_EQ(OC_STACK_OK, OCPlatform::setPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SPEC_VERSION, @@ -922,12 +954,14 @@ namespace OCPlatformTest EXPECT_STREQ("myDataModelVersions", dmv[0].c_str()); EXPECT_STREQ("oic.wk.d", OCGetResourceTypeName(handle, 0)); - EXPECT_STREQ("oic.d.tv", OCGetResourceTypeName(handle, 1)); - EXPECT_STREQ("oic.wk.tv", OCGetResourceTypeName(handle, 2)); + EXPECT_STREQ("oic.wk.tv", OCGetResourceTypeName(handle, 1)); } //SubscribePresence Test TEST(SubscribePresenceTest, DISABLED_SubscribePresenceWithValidParameters) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string hostAddress = "192.168.1.2:5000"; OCPlatform::OCPresenceHandle presenceHandle = nullptr; @@ -941,8 +975,10 @@ namespace OCPlatformTest TEST(SubscribePresenceTest, SubscribePresenceWithNullHost) #endif { - OCPlatform::OCPresenceHandle presenceHandle = nullptr; + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCPlatform::OCPresenceHandle presenceHandle = nullptr; EXPECT_ANY_THROW(OCPlatform::subscribePresence(presenceHandle, nullptr, CT_DEFAULT, &presenceHandler)); } @@ -953,6 +989,9 @@ namespace OCPlatformTest TEST(SubscribePresenceTest, SubscribePresenceWithNullPresenceHandler) #endif { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCPlatform::OCPresenceHandle presenceHandle = nullptr; EXPECT_ANY_THROW(OCPlatform::subscribePresence(presenceHandle, nullptr, @@ -961,6 +1000,9 @@ namespace OCPlatformTest TEST(SubscribePresenceTest, DISABLED_SubscribePresenceWithResourceType) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCPlatform::OCPresenceHandle presenceHandle = nullptr; EXPECT_EQ(OC_STACK_OK, OCPlatform::subscribePresence(presenceHandle, @@ -973,6 +1015,9 @@ namespace OCPlatformTest TEST(SubscribePresenceTest, SubscribePresenceWithNullResourceType) #endif { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCPlatform::OCPresenceHandle presenceHandle = nullptr; EXPECT_ANY_THROW(OCPlatform::subscribePresence(presenceHandle, @@ -981,6 +1026,9 @@ namespace OCPlatformTest TEST(SubscribePresenceTest, DISABLED_UnsubscribePresenceWithValidHandleAndRT) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCPlatform::OCPresenceHandle presenceHandle = nullptr; EXPECT_EQ(OC_STACK_OK, OCPlatform::subscribePresence(presenceHandle, @@ -990,12 +1038,18 @@ namespace OCPlatformTest TEST(SubscribePresenceTest, UnsubscribePresenceWithNullHandle) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCPlatform::OCPresenceHandle presenceHandle = nullptr; EXPECT_ANY_THROW(OCPlatform::unsubscribePresence(presenceHandle)); } TEST(SubscribePresenceTest, DISABLED_UnsubscribePresenceWithValidHandle) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCPlatform::OCPresenceHandle presenceHandle = nullptr; EXPECT_EQ(OC_STACK_OK, OCPlatform::subscribePresence(presenceHandle, @@ -1007,6 +1061,9 @@ namespace OCPlatformTest // SubscribeDevicePresence Test TEST(SubscribeDevicePresenceTest, DISABLED_SubscribeDevicePresenceWithValidParameters) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string hostAddress = "192.168.1.2:5000"; OCPlatform::OCPresenceHandle presenceHandle = nullptr; std::vector di; @@ -1017,6 +1074,9 @@ namespace OCPlatformTest TEST(SubscribeDevicePresenceTest, SubscribeDevicePresenceWithNullHost) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCPlatform::OCPresenceHandle presenceHandle = nullptr; std::vector di; @@ -1026,6 +1086,9 @@ namespace OCPlatformTest TEST(SubscribeDevicePresenceTest, SubscribeDevicePresenceWithNullOnObserve) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string hostAddress = "192.168.1.2:5000"; OCPlatform::OCPresenceHandle presenceHandle = nullptr; std::vector di; @@ -1036,6 +1099,9 @@ namespace OCPlatformTest TEST(SubscribeDevicePresenceTest, DISABLED_UnsubscribePresenceWithValidHandle) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + std::string hostAddress = "192.168.1.2:5000"; OCPlatform::OCPresenceHandle presenceHandle = nullptr; std::vector di; @@ -1048,21 +1114,30 @@ namespace OCPlatformTest TEST(FindDirectPairingTest, FindDirectPairingNullCallback) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); EXPECT_ANY_THROW(OCPlatform::findDirectPairingDevices(1, nullptr)); } TEST(FindDirectPairingTest, FindDirectPairingZeroTimeout) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); EXPECT_ANY_THROW(OCPlatform::findDirectPairingDevices(0, &pairedHandler)); } TEST(GetDirectPairedTest, GetDirectPairedNullCallback) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); EXPECT_ANY_THROW(OCPlatform::getDirectPairedDevices(nullptr)); } TEST(DoDirectPairingTest, DoDirectPairingNullCallback) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCDPDev_t peer; OCPrm_t pmSel = DP_PRE_CONFIGURED; std::string pin(""); @@ -1072,6 +1147,9 @@ namespace OCPlatformTest TEST(DoDirectPairingTest, DoDirectPairingNullPeer) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCDPDev_t peer; OCPrm_t pmSel = DP_PRE_CONFIGURED; std::string pin(""); @@ -1081,6 +1159,9 @@ namespace OCPlatformTest TEST(DoDirectPairingTest, DoDirectPairingNullPeerNullCallback) { + Framework framework; + ASSERT_TRUE(OC_STACK_OK == framework.start()); + OCDPDev_t peer; OCPrm_t pmSel = DP_PRE_CONFIGURED; std::string pin(""); diff --git a/resource/unittests/OCRepresentationEncodingTest.cpp b/resource/unittests/OCRepresentationEncodingTest.cpp index f2e2df5..6ddbed5 100644 --- a/resource/unittests/OCRepresentationEncodingTest.cpp +++ b/resource/unittests/OCRepresentationEncodingTest.cpp @@ -1602,6 +1602,8 @@ namespace OCRepresentationEncodingTest EXPECT_STREQ("if.firstitem", parsedPayload->interfaces->value); EXPECT_EQ(NULL, parsedPayload->interfaces->next); + OCRepPayloadValue *originalRootValues = parsedPayload->values; + // To make sure rt and if are not duplicated. EXPECT_STREQ("BoolAttr", parsedPayload->values->name); EXPECT_EQ(true, parsedPayload->values->b); @@ -1629,6 +1631,9 @@ namespace OCRepresentationEncodingTest EXPECT_EQ(NULL, parsedPayload->values); + // Recover the original value to ensure a proper cleanup. + parsedPayload->values = originalRootValues; + OICFree(cborData); OCRepPayloadDestroy(repPayload); OCPayloadDestroy(cparsed); diff --git a/tools/scons/RunTest.py b/tools/scons/RunTest.py index fbf1ebd..fee90aa 100644 --- a/tools/scons/RunTest.py +++ b/tools/scons/RunTest.py @@ -60,8 +60,10 @@ def run_test(env, xml_file, test, test_targets = ['test']): # Valgrind suppressions file. suppression_file = env.File('#tools/valgrind/iotivity.supp').srcnode().path - # Set up to run the test under Valgrind. - test_cmd = '%s valgrind --leak-check=full --suppressions=%s --xml=yes --xml-file=%s %s' % (valgrind_environment, suppression_file, xml_file, test_cmd) + # Set up to run the test under Valgrind. The "--num-callers" option specifies the + # callstack depth (default, if not specified, is 12). We are increasing it here to + # allow unit test name to be visible in the leak report. + test_cmd = '%s valgrind --leak-check=full --suppressions=%s --num-callers=24 --xml=yes --xml-file=%s %s' % (valgrind_environment, suppression_file, xml_file, test_cmd) if env.get('TARGET_OS') in ['linux']: env.Depends('ut' + test , os.path.join(build_dir, test)) ut = env.Command('ut' + test, None, test_cmd)