diff options
author | Way Vadhanasin <wayvad@microsoft.com> | 2017-03-06 16:09:50 -0800 |
---|---|---|
committer | Dan Mihai <Daniel.Mihai@microsoft.com> | 2017-03-09 15:09:26 +0000 |
commit | 656e46dc35baa8b6bf89912bf23b60e9f39885ae (patch) | |
tree | 780cb5ce577db44c4459cde14897b896f89aa413 | |
parent | f0c792a3c34467e7719849d2e6b39d8c03bb1313 (diff) | |
download | iotivity-656e46dc35baa8b6bf89912bf23b60e9f39885ae.tar.gz iotivity-656e46dc35baa8b6bf89912bf23b60e9f39885ae.tar.bz2 iotivity-656e46dc35baa8b6bf89912bf23b60e9f39885ae.zip |
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 <wayvad@microsoft.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/17685
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Dan Mihai <Daniel.Mihai@microsoft.com>
38 files changed, 709 insertions, 506 deletions
diff --git a/resource/csdk/connectivity/src/ip_adapter/caipadapter.c b/resource/csdk/connectivity/src/ip_adapter/caipadapter.c index 91cdfd8b3..edf96c134 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 2f90135e6..0bd6cca40 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 2fa77f4f1..2141dd081 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 cc1abd02e..92c311f7d 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 25250d3e8..03e36d00d 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<std::mutex> lock(blocker); cv.wait(lock, []{return false;}); + OC_VERIFY(OCPlatform::stop() == OC_STACK_OK); + }catch(OCException& e) { std::cerr << "Failure in main thread: "<<e.reason()<<std::endl; diff --git a/resource/examples/devicediscoveryserver.cpp b/resource/examples/devicediscoveryserver.cpp index 692317206..e709c71b7 100644 --- a/resource/examples/devicediscoveryserver.cpp +++ b/resource/examples/devicediscoveryserver.cpp @@ -156,12 +156,11 @@ 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); + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); std::cout<<"Starting server & setting platform info\n"; @@ -196,9 +195,8 @@ int main() std::unique_lock<std::mutex> 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 703c3781c..6185e13eb 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 bbbc7481f..e562883b1 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 9ab20d758..2ce63ba51 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 9a91da98e..a8c8f9379 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<std::mutex> 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 f333d45a5..e8238ef0f 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 cde8eb20b..ef146ab8c 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 f4b5e4dd7..13cb475fd 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 127b858d4..a9b605bd9 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 0f07e8676..d9017e7ad 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<std::mutex> 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 72b672a90..3603162e5 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..."<<std::endl; OCPlatform::OCPresenceHandle presenceHandle = nullptr; @@ -359,6 +359,7 @@ int main(int argc, char* argv[]) { std::unique_lock<std::mutex> 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 da1d93785..a6b731179 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 5960fa23d..074e5e090 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 6d04a7db3..c23e84678 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<std::mutex> 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 8295401ae..65eefa84c 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 6c287becb..62cdc7e00 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>(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<std::mutex> 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/simpleclientHQ.cpp b/resource/examples/simpleclientHQ.cpp index 6d631d3d6..6219b2ce1 100644 --- a/resource/examples/simpleclientHQ.cpp +++ b/resource/examples/simpleclientHQ.cpp @@ -450,15 +450,17 @@ int main(int argc, char* argv[]) { PlatformConfig cfg { OC::ServiceType::InProc, OC::ModeType::Client, - "0.0.0.0", - 0, - OC::QualityOfService::HighQos + nullptr }; + + cfg.QoS = OC::QualityOfService::HighQos; OCPlatform::Configure(cfg); try { + OC_VERIFY(OCPlatform::start() == OC_STACK_OK); + // Find all resources requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.light"; @@ -482,6 +484,8 @@ int main(int argc, char* argv[]) { std::unique_lock<std::mutex> 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 596b37f5f..d5fcd362a 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 b232827e1..006216f82 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>(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 3c61b71d3..78c5412e5 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<std::mutex> 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 1b892cdf6..ac299ea52 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 b052e4e93..53288ee26 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 <memory> -#include <mutex> -#include <map> -#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<OCResource> 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<OCResource> 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<OCResourceIdentifier, std::shared_ptr<OCResource>> DiscoveredResourceMap; - - OCPersistentStorage persistentStorage; - Media mymedia; - DiscoveredResourceMap discoveredResources; - std::shared_ptr<OCResource> 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 <memory>
+#include <mutex>
+#include <map>
+#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<OCResource> 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<OCResource> 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<OCResourceIdentifier, std::shared_ptr<OCResource>> DiscoveredResourceMap;
+
+ OCPersistentStorage persistentStorage;
+ Media mymedia;
+ DiscoveredResourceMap discoveredResources;
+ std::shared_ptr<OCResource> 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 c6921ce9e..730f89977 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 2d200f3da..c8250e59c 100644 --- a/resource/include/OCApi.h +++ b/resource/include/OCApi.h @@ -31,6 +31,8 @@ #include <functional> #endif +#include "iotivity_debug.h" + #include "octypes.h" #include "OCHeaderOption.h" #include <OCException.h> @@ -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 e51d5df37..9891fe875 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 6637c16e1..bfbab036f 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<std::recursive_mutex> 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 5e06e02fd..0a4eb7e95 100644 --- a/resource/include/WrapperFactory.h +++ b/resource/include/WrapperFactory.h @@ -40,9 +40,11 @@ namespace OC typedef std::shared_ptr<IWrapperFactory> Ptr; virtual IClientWrapper::Ptr CreateClientWrapper( - std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg) =0; + std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg, + OCStackResult *result) =0; virtual IServerWrapper::Ptr CreateServerWrapper( - std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg) =0; + std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg, + OCStackResult *result) =0; virtual ~IWrapperFactory(){} }; @@ -53,30 +55,53 @@ namespace OC WrapperFactory(){} virtual IClientWrapper::Ptr CreateClientWrapper( - std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg) + std::weak_ptr<std::recursive_mutex> 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<InProcClientWrapper>(csdkLock, cfg); case ServiceType::OutOfProc: + if (result) + { + *result = OC_STACK_OK; + } return std::make_shared<OutOfProcClientWrapper>(csdkLock, cfg); + default: + break; } - return nullptr; + return nullptr; } virtual IServerWrapper::Ptr CreateServerWrapper( - std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg) + std::weak_ptr<std::recursive_mutex> 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<InProcServerWrapper>(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 194cb5c42..c67e9a5ad 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<OCTransportFlags>(m_cfg.serverConnectivity & CT_MASK_FLAGS); - OCTransportFlags clientFlags = - static_cast<OCTransportFlags>(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 67a44ca42..7d7c20069 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<OCTransportFlags>(m_cfg.serverConnectivity & CT_MASK_FLAGS); - OCTransportFlags clientFlags = - static_cast<OCTransportFlags>(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 b04e14eae..0908d1f95 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<std::mutex> 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<OCTransportFlags>(m_cfg.serverConnectivity & CT_MASK_FLAGS); + OCTransportFlags clientFlags = + static_cast<OCTransportFlags>(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<std::mutex> 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<WrapperFactory>() }, - m_csdkLock { std::make_shared<std::recursive_mutex>() } + m_csdkLock { std::make_shared<std::recursive_mutex>() }, + 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 b71b6277d..ae74b110c 100644 --- a/resource/unittests/OCPlatformTest.cpp +++ b/resource/unittests/OCPlatformTest.cpp @@ -21,6 +21,7 @@ #include <OCPlatform.h> #include <OCApi.h> #include <oic_malloc.h> +#include <iotivity_debug.h> #include <gtest/gtest.h> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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 f2e2df5b1..6ddbed5f8 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 fbf1ebdf0..fee90aa60 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) |