From 3aa722b790a0a00ae4d0a0727971557a0e26cc4b Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Fri, 15 Mar 2024 11:02:55 +0100 Subject: [PATCH] Fix issues reported by SonarCloud and add tests --- api/unittest/etagtest.cpp | 12 +- docker/apps/Dockerfile.cloud-server | 14 +- docker/apps/Dockerfile.cloud-server-debug | 13 +- .../apps/Dockerfile.cloud-server-debug-clang | 21 +-- include/oc_rep.h | 20 +-- port/unittest/clocktest.cpp | 2 +- security/unittest/keypairtest.cpp | 21 +-- util/oc_atomic.h | 16 +-- util/unittest/memblocktest.cpp | 124 ++++++++++++++++++ 9 files changed, 184 insertions(+), 59 deletions(-) create mode 100644 util/unittest/memblocktest.cpp diff --git a/api/unittest/etagtest.cpp b/api/unittest/etagtest.cpp index 1ca058c54b..8c31989eda 100644 --- a/api/unittest/etagtest.cpp +++ b/api/unittest/etagtest.cpp @@ -594,13 +594,9 @@ isETagStorageEmpty(size_t device, bool platform = false) std::string store = platform ? OC_ETAG_PLATFORM_STORE_NAME : OC_ETAG_STORE_NAME; - long ret = oc_storage_data_load( - store.c_str(), device, [](const oc_rep_t *, size_t, void *) { return 0; }, - nullptr); - if (ret > 0) { - return false; - } - return true; + return oc_storage_data_load( + store.c_str(), device, + [](const oc_rep_t *, size_t, void *) { return 0; }, nullptr) <= 0; } TEST_F(TestETagWithServer, DumpAndLoad) @@ -688,7 +684,7 @@ TEST_F(TestETagWithServer, DumpAndLoad) #ifdef OC_SECURITY static bool -isPlatformResourceURI(const std::string &uri) +isPlatformResourceURI(std::string_view uri) { return uri == "/oic/p" #ifdef OC_HAS_FEATURE_PLGD_TIME diff --git a/docker/apps/Dockerfile.cloud-server b/docker/apps/Dockerfile.cloud-server index 619bc8a5fa..43c6f713a3 100644 --- a/docker/apps/Dockerfile.cloud-server +++ b/docker/apps/Dockerfile.cloud-server @@ -1,21 +1,23 @@ -FROM alpine:latest AS build +FROM alpine:3.19 AS build ARG BUILD_TYPE=Release ARG BUILD_ARGS RUN apk add --no-cache cmake curl git build-base gcc linux-headers patch perl python3 COPY ./ /iotivity-lite/ -RUN cd /iotivity-lite/ && git submodule update --recursive -RUN mkdir /iotivity-lite/build && \ - cd /iotivity-lite/build && \ - cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_TESTING=OFF -DOC_CLOUD_ENABLED=ON ${BUILD_ARGS} .. && \ +WORKDIR /iotivity-lite +RUN git submodule update --recursive +RUN mkdir /iotivity-lite/build +WORKDIR /iotivity-lite/build +RUN cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_TESTING=OFF -DOC_CLOUD_ENABLED=ON ${BUILD_ARGS} .. && \ cmake --build . --target cloud_server # install libfaketime +WORKDIR / # enable struct stat64 by adding -D__USE_LARGEFILE64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE RUN git clone https://github.com/wolfcw/libfaketime.git && \ cd /libfaketime/src && \ make install FAKETIME_COMPILE_CFLAGS="-DFAKE_SETTIME -DFAKE_STATELESS -D__USE_LARGEFILE64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE" -FROM alpine:latest AS service +FROM alpine:3.19 AS service RUN apk add --no-cache bash COPY --from=build /iotivity-lite/build/apps/cloud_server /iotivity-lite/port/linux/service COPY --from=build /usr/local/lib/faketime/libfaketimeMT.so.1 /usr/local/lib/faketime/libfaketimeMT.so.1 diff --git a/docker/apps/Dockerfile.cloud-server-debug b/docker/apps/Dockerfile.cloud-server-debug index 4f00bf3313..1690fcecdd 100644 --- a/docker/apps/Dockerfile.cloud-server-debug +++ b/docker/apps/Dockerfile.cloud-server-debug @@ -2,16 +2,19 @@ FROM ubuntu:22.04 AS service ARG BUILD_TYPE=Release ARG BUILD_ARGS RUN apt-get update -y && \ - DEBIAN_FRONTEND="noninteractive" apt-get install -y bash ca-certificates cmake curl gdb git-core gcovr g++ make patch python3 --no-install-recommends + DEBIAN_FRONTEND="noninteractive" apt-get install --no-install-recommends -y bash ca-certificates cmake curl gdb git-core gcovr g++ make patch python3 && \ + apt-get clean COPY ./ /iotivity-lite/ -RUN cd /iotivity-lite/ && git submodule update --recursive -RUN mkdir /iotivity-lite/build && \ - cd /iotivity-lite/build && \ - cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_TESTING=OFF -DOC_CLOUD_ENABLED=ON ${BUILD_ARGS} .. && \ +WORKDIR /iotivity-lite +RUN git submodule update --recursive +RUN mkdir /iotivity-lite/build +WORKDIR /iotivity-lite/build +RUN cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_TESTING=OFF -DOC_CLOUD_ENABLED=ON ${BUILD_ARGS} .. && \ cmake --build . --target cloud_server RUN cp /iotivity-lite/build/apps/cloud_server /iotivity-lite/port/linux/service # install libfaketime +WORKDIR / RUN git clone https://github.com/wolfcw/libfaketime.git && \ cd /libfaketime/src && \ make install FAKETIME_COMPILE_CFLAGS="-DFAKE_SETTIME -DFAKE_STATELESS" diff --git a/docker/apps/Dockerfile.cloud-server-debug-clang b/docker/apps/Dockerfile.cloud-server-debug-clang index 9ddadb3267..c74c174821 100644 --- a/docker/apps/Dockerfile.cloud-server-debug-clang +++ b/docker/apps/Dockerfile.cloud-server-debug-clang @@ -3,22 +3,27 @@ FROM ubuntu:22.04 AS service ARG BUILD_TYPE=Release ARG BUILD_ARGS RUN apt-get update -y && \ - DEBIAN_FRONTEND="noninteractive" apt-get install -y bash ca-certificates cmake curl gdb git-core gcovr g++ make patch python3 --no-install-recommends -RUN DEBIAN_FRONTEND="noninteractive" apt-get install -y clang-15 -RUN update-alternatives --install /usr/bin/clang clang /usr/bin/clang-15 100 && \ + DEBIAN_FRONTEND="noninteractive" apt-get install --no-install-recommends -y bash ca-certificates cmake gdb git-core make patch python3 && \ + apt-get clean +# install clang +RUN DEBIAN_FRONTEND="noninteractive" apt-get install --no-install-recommends -y clang-15 && \ + apt-get clean && \ + update-alternatives --install /usr/bin/clang clang /usr/bin/clang-15 100 && \ update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-15 100 COPY ./ /iotivity-lite/ -RUN cd /iotivity-lite/ && git submodule update --recursive -RUN mkdir /iotivity-lite/build && \ - cd /iotivity-lite/build && \ - cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DBUILD_TESTING=OFF -DOC_CLOUD_ENABLED=ON ${BUILD_ARGS} .. && \ +WORKDIR /iotivity-lite +RUN git submodule update --recursive +RUN mkdir /iotivity-lite/build +WORKDIR /iotivity-lite/build +RUN cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DBUILD_TESTING=OFF -DOC_CLOUD_ENABLED=ON ${BUILD_ARGS} .. && \ cmake --build . --target cloud_server RUN cp /iotivity-lite/build/apps/cloud_server /iotivity-lite/port/linux/service # install libfaketime +WORKDIR / RUN git clone https://github.com/wolfcw/libfaketime.git && \ cd /libfaketime/src && \ - make install FAKETIME_COMPILE_CFLAGS="-DFAKE_SETTIME -DFAKE_STATELESS" + make CC=clang install FAKETIME_COMPILE_CFLAGS="-DFAKE_SETTIME -DFAKE_STATELESS" COPY /docker/logbt /usr/local/bin/logbt RUN logbt --version diff --git a/include/oc_rep.h b/include/oc_rep.h index a05cfb24fc..4f1c88e1a4 100644 --- a/include/oc_rep.h +++ b/include/oc_rep.h @@ -1189,20 +1189,22 @@ typedef enum { OC_REP_OBJECT_ARRAY = 0x0E } oc_rep_value_type_t; +typedef union oc_rep_value { + int64_t integer; + bool boolean; + double double_p; + oc_string_t string; + oc_array_t array; + struct oc_rep_s *object; + struct oc_rep_s *object_array; +} oc_rep_value_t; + typedef struct oc_rep_s { oc_rep_value_type_t type; struct oc_rep_s *next; oc_string_t name; - union oc_rep_value { - int64_t integer; - bool boolean; - double double_p; - oc_string_t string; - oc_array_t array; - struct oc_rep_s *object; - struct oc_rep_s *object_array; - } value; + oc_rep_value_t value; } oc_rep_t; /** diff --git a/port/unittest/clocktest.cpp b/port/unittest/clocktest.cpp index 47ce9a241e..32e5b56d50 100644 --- a/port/unittest/clocktest.cpp +++ b/port/unittest/clocktest.cpp @@ -69,7 +69,7 @@ TEST_F(TestClock, oc_clock_wait) oc_clock_wait(wait_time); oc_clock_time_t cur_stamp = oc_clock_time(); - int seconds = (cur_stamp - prev_stamp) / OC_CLOCK_SECOND; + long seconds = static_cast((cur_stamp - prev_stamp) / OC_CLOCK_SECOND); EXPECT_EQ(1, seconds); } diff --git a/security/unittest/keypairtest.cpp b/security/unittest/keypairtest.cpp index 2a6ce8118e..362f71c4f9 100644 --- a/security/unittest/keypairtest.cpp +++ b/security/unittest/keypairtest.cpp @@ -276,25 +276,18 @@ TEST_F(TestKeyPair, GenerateForDevice) { auto generate_keypair = [](mbedtls_ecp_group_id grpid) { OC_DBG("generate ecdsa keypair with elliptic-curve %d", (int)grpid); - EXPECT_EQ(0, oc_sec_ecdsa_count_keypairs()) - << "error for ec(" << grpid << ")"; + EXPECT_EQ(0, oc_sec_ecdsa_count_keypairs()); EXPECT_TRUE( oc_sec_ecdsa_update_or_generate_keypair_for_device(grpid, - /*device*/ 0)) - << "error for ec(" << grpid << ")"; - EXPECT_EQ(1, oc_sec_ecdsa_count_keypairs()) - << "error for ec(" << grpid << ")"; + /*device*/ 0)); + EXPECT_EQ(1, oc_sec_ecdsa_count_keypairs()); EXPECT_TRUE( oc_sec_ecdsa_update_or_generate_keypair_for_device(grpid, - /*device*/ 0)) - << "error for ec(" << grpid << ")"; - EXPECT_EQ(1, oc_sec_ecdsa_count_keypairs()) - << "error for ec(" << grpid << ")"; + /*device*/ 0)); + EXPECT_EQ(1, oc_sec_ecdsa_count_keypairs()); - EXPECT_NE(nullptr, oc_sec_ecdsa_get_keypair(/*device*/ 0)) - << "error for ec(" << grpid << ")"; - EXPECT_EQ(nullptr, oc_sec_ecdsa_get_keypair(/*device*/ 1)) - << "error for ec(" << grpid << ")"; + EXPECT_NE(nullptr, oc_sec_ecdsa_get_keypair(/*device*/ 0)); + EXPECT_EQ(nullptr, oc_sec_ecdsa_get_keypair(/*device*/ 1)); oc_sec_ecdsa_free_keypairs(); }; diff --git a/util/oc_atomic.h b/util/oc_atomic.h index b7b7823ce5..4fd0e7dda2 100644 --- a/util/oc_atomic.h +++ b/util/oc_atomic.h @@ -38,10 +38,10 @@ extern "C" { (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))) #define OC_ATOMIC -#define OC_ATOMIC_INT8_T int8_t -#define OC_ATOMIC_UINT8_T uint8_t -#define OC_ATOMIC_INT32_T int32_t -#define OC_ATOMIC_UINT32_T uint32_t +typedef int8_t OC_ATOMIC_INT8_T; +typedef uint8_t OC_ATOMIC_UINT8_T; +typedef int32_t OC_ATOMIC_INT32_T; +typedef uint32_t OC_ATOMIC_UINT32_T; #define OC_ATOMIC_LOAD32(x) __atomic_load_n(&(x), __ATOMIC_SEQ_CST) @@ -80,10 +80,10 @@ extern "C" { #include #define OC_ATOMIC -#define OC_ATOMIC_INT8_T int8_t -#define OC_ATOMIC_UINT8_T uint8_t -#define OC_ATOMIC_INT32_T int32_t -#define OC_ATOMIC_UINT32_T uint32_t +typedef int8_t OC_ATOMIC_INT8_T; +typedef uint8_t OC_ATOMIC_UINT8_T; +typedef int32_t OC_ATOMIC_INT32_T; +typedef uint32_t OC_ATOMIC_UINT32_T; #define OC_ATOMIC_LOAD8(x) _InterlockedOr8((&x), 0) #define OC_ATOMIC_LOAD32(x) _InterlockedOr((&x), 0) diff --git a/util/unittest/memblocktest.cpp b/util/unittest/memblocktest.cpp new file mode 100644 index 0000000000..aa43d67303 --- /dev/null +++ b/util/unittest/memblocktest.cpp @@ -0,0 +1,124 @@ +/**************************************************************************** + * + * Copyright (c) 2024 plgd.dev s.r.o. + * + * 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. + * + ****************************************************************************/ + +#include "util/oc_memb.h" + +#include +#include + +struct test_data_t +{ + int a; + int b; +}; + +class TestMemoryBlock : public testing::Test { +public: +}; + +TEST_F(TestMemoryBlock, Init) +{ + OC_MEMB_LOCAL(oc_test_data, test_data_t, 13); + EXPECT_EQ(oc_test_data.size, sizeof(test_data_t)); + oc_memb_init(&oc_test_data); +#ifdef OC_DYNAMIC_ALLOCATION + EXPECT_EQ(oc_test_data.num, 0); +#else /* !OC_DYNAMIC_ALLOCATION */ + EXPECT_EQ(oc_test_data.num, 13); +#endif /* OC_DYNAMIC_ALLOCATION */ +} + +TEST_F(TestMemoryBlock, Alloc_Fail) +{ + EXPECT_EQ(nullptr, oc_memb_alloc(nullptr)); +} + +TEST_F(TestMemoryBlock, Alloc) +{ + OC_MEMB_LOCAL(oc_test_data, test_data_t, 13); + oc_memb_init(&oc_test_data); + auto *block1 = static_cast(oc_memb_alloc(&oc_test_data)); + EXPECT_NE(nullptr, block1); + auto *block2 = static_cast(oc_memb_alloc(&oc_test_data)); + EXPECT_NE(nullptr, block2); + EXPECT_NE(block1, block2); + // Add more assertions as necessary to test initialization of allocated blocks + EXPECT_FALSE(oc_memb_free(&oc_test_data, block2)); + EXPECT_FALSE(oc_memb_free(&oc_test_data, block1)); +} + +TEST_F(TestMemoryBlock, Dealloc_Fail) +{ + EXPECT_EQ(-1, oc_memb_free(nullptr, nullptr)); +} + +TEST_F(TestMemoryBlock, AllocExceedsLimit) +{ + OC_MEMB_LOCAL(oc_test_data, test_data_t, 13); + oc_memb_init(&oc_test_data); + std::array blocks; + for (int i = 0; i < 13; ++i) { + blocks[i] = static_cast(oc_memb_alloc(&oc_test_data)); + EXPECT_NE(nullptr, blocks[i]); + } + blocks[13] = static_cast(oc_memb_alloc(&oc_test_data)); +#ifdef OC_DYNAMIC_ALLOCATION + EXPECT_NE(nullptr, blocks[13]); // Expecting the allocation to succeed + oc_memb_free(&oc_test_data, blocks[13]); +#else /* !OC_DYNAMIC_ALLOCATION */ + EXPECT_EQ(nullptr, + blocks[13]); // Expecting the allocation to fail beyond the limit +#endif /* OC_DYNAMIC_ALLOCATION */ + for (int i = 0; i < 13; ++i) { + oc_memb_free(&oc_test_data, blocks[i]); + } +} + +#ifndef OC_DYNAMIC_ALLOCATION + +TEST_F(TestMemoryBlock, Realloc) +{ + OC_MEMB_LOCAL(oc_test_data, test_data_t, 13); + oc_memb_init(&oc_test_data); + auto *block = static_cast(oc_memb_alloc(&oc_test_data)); + EXPECT_NE(block, nullptr); + oc_memb_free(&oc_test_data, block); + auto *block_realloc = + static_cast(oc_memb_alloc(&oc_test_data)); + EXPECT_EQ(block, block_realloc); + oc_memb_free(&oc_test_data, block_realloc); +} + +TEST_F(TestMemoryBlock, InBlock) +{ + OC_MEMB_LOCAL(oc_test_data1, test_data_t, 13); + oc_memb_init(&oc_test_data1); + OC_MEMB_LOCAL(oc_test_data2, test_data_t, 37); + oc_memb_init(&oc_test_data2); + auto td1 = static_cast(oc_memb_alloc(&oc_test_data1)); + EXPECT_TRUE(oc_memb_inmemb(&oc_test_data1, td1)); + EXPECT_FALSE(oc_memb_inmemb(&oc_test_data2, td1)); + auto td2 = static_cast(oc_memb_alloc(&oc_test_data2)); + EXPECT_TRUE(oc_memb_inmemb(&oc_test_data2, td2)); + EXPECT_FALSE(oc_memb_inmemb(&oc_test_data1, td2)); + + oc_memb_free(&oc_test_data2, td2); + oc_memb_free(&oc_test_data1, td1); +} + +#endif /* !OC_DYNAMIC_ALLOCATION */