diff --git a/api/oc_platform.c b/api/oc_platform.c index 4f69aa71f..b02a88fff 100644 --- a/api/oc_platform.c +++ b/api/oc_platform.c @@ -21,8 +21,10 @@ #include "api/oc_platform_internal.h" #include "api/oc_ri_internal.h" #include "oc_api.h" +#include "oc_build_info.h" #include "util/oc_compiler.h" #include "util/oc_secure_string_internal.h" +#include "util/oc_macros_internal.h" #include #include @@ -34,8 +36,8 @@ static struct bool initialized; } g_platform; -static void -platform_encode(oc_resource_t *resource, oc_interface_mask_t iface) +static int +platform_encode(const oc_resource_t *resource, oc_interface_mask_t iface) { oc_rep_start_root_object(); @@ -49,11 +51,13 @@ platform_encode(oc_resource_t *resource, oc_interface_mask_t iface) oc_rep_set_text_string(root, pi, pi); oc_rep_set_text_string_v1(root, mnmn, oc_string(g_platform.info.mfg_name), oc_string_len(g_platform.info.mfg_name)); + oc_rep_set_int(root, x.org.iotivity.version, IOTIVITY_LITE_VERSION); if (g_platform.info.init_platform_cb != NULL) { g_platform.info.init_platform_cb(g_platform.info.data); } oc_rep_end_root_object(); + return oc_rep_get_cbor_errno(); } static void @@ -61,7 +65,11 @@ platform_resource_get(oc_request_t *request, oc_interface_mask_t iface, void *data) { (void)data; - platform_encode(request->resource, iface); + CborError err = platform_encode(request->resource, iface); + if (err != CborNoError) { + OC_ERR("encoding platform resource failed(error=%d)", (int)err); + return; + } oc_send_response_with_callback(request, OC_STATUS_OK, true); } diff --git a/api/unittest/platformtest.cpp b/api/unittest/platformtest.cpp index 4e890d976..c9af1489e 100644 --- a/api/unittest/platformtest.cpp +++ b/api/unittest/platformtest.cpp @@ -20,11 +20,13 @@ #include "api/oc_platform_internal.h" #include "api/oc_ri_internal.h" #include "api/oc_runtime_internal.h" +#include "oc_build_info.h" #include "oc_rep.h" +#include "oc_uuid.h" #include "port/oc_network_event_handler_internal.h" #include "tests/gtest/Device.h" #include "tests/gtest/RepPool.h" -#include "oc_uuid.h" +#include "util/oc_secure_string_internal.h" #ifdef OC_HAS_FEATURE_PUSH #include "api/oc_push_internal.h" @@ -33,6 +35,7 @@ #include #include #include +#include static const std::string kManufacturerName{ "Samsung" }; @@ -77,9 +80,22 @@ TEST_F(TestPlatform, CoreInitPlatform_P) EXPECT_EQ(kManufacturerName.length(), oc_string_len(oc_platform_info->mfg_name)); + // trying to initiaze an already initialized platform should be ignored and + // the original platform should remain + oc_platform_init("fail", nullptr, nullptr); + EXPECT_EQ(kManufacturerName.length(), + oc_string_len(oc_platform_info->mfg_name)); + oc_platform_deinit(); } +TEST_F(TestPlatform, CoreInitPlatform_F) +{ + std::vector manufacturerName(OC_MAX_STRING_LENGTH + 1, 'a'); + EXPECT_EQ(nullptr, + oc_platform_init(manufacturerName.data(), nullptr, nullptr)); +} + TEST_F(TestPlatform, CoreGetResourceV1_P) { oc_platform_init(kManufacturerName.c_str(), nullptr, nullptr); @@ -105,6 +121,7 @@ struct platformBaseData { std::string pi; std::string manufacturerName; + uint64_t version; }; static platformBaseData @@ -122,6 +139,11 @@ parsePlatform(const oc_rep_t *rep) if (oc_rep_get_string(rep, "mnmn", &str, &str_len)) { pData.manufacturerName = std::string(str, str_len); } + // x.org.iotivity.version: uint64_t + if (int64_t version; + oc_rep_get_int(rep, "x.org.iotivity.version", &version)) { + pData.version = static_cast(version); + } return pData; } @@ -144,11 +166,12 @@ getRequestWithQuery(const std::string &query) std::array uuid{}; oc_uuid_to_str(&oc_core_get_platform_info()->pi, &uuid[0], uuid.size()); EXPECT_STREQ(uuid.data(), pbd.pi.c_str()); + EXPECT_EQ(IOTIVITY_LITE_VERSION, pbd.version); }; auto timeout = 1s; bool invoked = false; - EXPECT_TRUE(oc_do_get_with_timeout( + ASSERT_TRUE(oc_do_get_with_timeout( OCF_PLATFORM_URI, &ep, query.empty() ? nullptr : query.c_str(), timeout.count(), get_handler, HIGH_QOS, &invoked)); oc::TestDevice::PoolEventsMsV1(timeout, true); @@ -165,6 +188,71 @@ TEST_F(TestPlatformWithServer, GetRequestBaseline) getRequestWithQuery("if=" OC_IF_BASELINE_STR); } +TEST_F(TestPlatformWithServer, GetRequestWithCustomProperties) +{ + oc_platform_deinit(); + + struct customProperties + { + std::string question; + int answer; + }; + static customProperties props = { + "What is the answer to life, the universe, and " + "everything?", + 42 + }; + auto encodeCustomProperties = [](void *data) { + const customProperties *props = static_cast(data); + oc_rep_set_text_string_v1(root, question, props->question.c_str(), + props->question.length()); + oc_rep_set_int(root, answer, props->answer); + }; + oc_platform_init(kManufacturerName.c_str(), encodeCustomProperties, &props); + + auto epOpt = oc::TestDevice::GetEndpoint(kDeviceID); + ASSERT_TRUE(epOpt.has_value()); + auto ep = std::move(*epOpt); + + auto get_handler = [](oc_client_response_t *data) { + oc::TestDevice::Terminate(); + EXPECT_EQ(OC_STATUS_OK, data->code); + *static_cast(data->user_data) = true; + OC_DBG("GET payload: %s", oc::RepPool::GetJson(data->payload).data()); + platformBaseData pbd = parsePlatform(data->payload); + EXPECT_STREQ(oc_string(oc_core_get_platform_info()->mfg_name), + pbd.manufacturerName.c_str()); + std::array uuid{}; + oc_uuid_to_str(&oc_core_get_platform_info()->pi, &uuid[0], uuid.size()); + EXPECT_STREQ(uuid.data(), pbd.pi.c_str()); + EXPECT_EQ(IOTIVITY_LITE_VERSION, pbd.version); + + char *str; + size_t str_len; + // question: string + EXPECT_TRUE(oc_rep_get_string(data->payload, "question", &str, &str_len)); + EXPECT_EQ(props.question.length(), str_len); + EXPECT_STREQ(props.question.c_str(), str); + + // answer: int + int64_t answer; + EXPECT_TRUE(oc_rep_get_int(data->payload, "answer", &answer)); + EXPECT_EQ(props.answer, answer); + }; + + auto timeout = 1s; + bool invoked = false; + ASSERT_TRUE(oc_do_get_with_timeout(OCF_PLATFORM_URI, &ep, nullptr, + timeout.count(), get_handler, HIGH_QOS, + &invoked)); + oc::TestDevice::PoolEventsMsV1(timeout, true); + EXPECT_TRUE(invoked); + + // restore defaults + oc_platform_deinit(); + oc_platform_init(kManufacturerName.c_str(), nullptr, nullptr); +} + TEST_F(TestPlatformWithServer, PostRequest_FailMethodNotSupported) { auto epOpt = oc::TestDevice::GetEndpoint(kDeviceID);