From ccbd7b09465446bd8f3f41a9afc63aa76e771a01 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Thu, 14 Dec 2023 22:20:10 +0800 Subject: [PATCH] Add error injection for dyn_interface. --- libs/dfi/CMakeLists.txt | 7 ++ libs/dfi/gtest/CMakeLists.txt | 12 ++++ libs/dfi/gtest/src/dyn_interface_ei_tests.cc | 68 ++++++++++++++++++ libs/dfi/gtest/src/dyn_interface_tests.cpp | 2 - libs/dfi/src/dyn_interface.c | 72 ++++++++++---------- 5 files changed, 122 insertions(+), 39 deletions(-) create mode 100644 libs/dfi/gtest/src/dyn_interface_ei_tests.cc diff --git a/libs/dfi/CMakeLists.txt b/libs/dfi/CMakeLists.txt index f82aca3a2..b5eb65e9c 100644 --- a/libs/dfi/CMakeLists.txt +++ b/libs/dfi/CMakeLists.txt @@ -60,6 +60,13 @@ if (CELIX_DFI) add_subdirectory(error_injector) endif () if (ENABLE_TESTING) + add_library(dfi_cut STATIC ${SOURCES}) + target_compile_definitions(dfi_cut PUBLIC CELIX_DFI_STATIC_DEFINE) + target_include_directories(dfi_cut PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/include + ${CMAKE_BINARY_DIR}/celix/gen/includes/dfi + ) + target_link_libraries(dfi_cut PUBLIC libffi::libffi jansson::jansson Celix::utils) add_subdirectory(gtest) endif(ENABLE_TESTING) endif (CELIX_DFI) diff --git a/libs/dfi/gtest/CMakeLists.txt b/libs/dfi/gtest/CMakeLists.txt index e0206df13..07df1dbbf 100644 --- a/libs/dfi/gtest/CMakeLists.txt +++ b/libs/dfi/gtest/CMakeLists.txt @@ -37,3 +37,15 @@ file(COPY ${CMAKE_CURRENT_LIST_DIR}/descriptors DESTINATION ${CMAKE_CURRENT_BINA add_test(NAME run_test_dfi COMMAND test_dfi) setup_target_for_coverage(test_dfi SCAN_DIR ..) +if (EI_TESTS) + add_executable(test_dfi_with_ei + src/dyn_interface_ei_tests.cc + ) + target_link_libraries(test_dfi_with_ei PRIVATE + dfi_cut + Celix::malloc_ei + GTest::gtest GTest::gtest_main + ) + add_test(NAME run_test_dfi_with_ei COMMAND test_dfi_with_ei) + setup_target_for_coverage(test_dfi_with_ei SCAN_DIR ..) +endif () diff --git a/libs/dfi/gtest/src/dyn_interface_ei_tests.cc b/libs/dfi/gtest/src/dyn_interface_ei_tests.cc new file mode 100644 index 000000000..dce4a70cd --- /dev/null +++ b/libs/dfi/gtest/src/dyn_interface_ei_tests.cc @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 "dyn_interface.h" +#include "malloc_ei.h" +#include "celix_err.h" +#include "celix_stdio_cleanup.h" + +#include + +class DynInterfaceErrorInjectionTestSuite : public ::testing::Test { +public: + DynInterfaceErrorInjectionTestSuite() = default; + + ~DynInterfaceErrorInjectionTestSuite() override { + celix_ei_expect_calloc(nullptr, 0, nullptr); + } +}; + +TEST_F(DynInterfaceErrorInjectionTestSuite, ParseError) { + int status = 0; + dyn_interface_type *dynIntf = NULL; + celix_autoptr(FILE) desc = fopen("descriptors/example1.descriptor", "r"); + ASSERT_NE(nullptr, desc); + + // not enough memory for dyn_interface_type + celix_ei_expect_calloc((void*) dynInterface_parse, 0, nullptr); + status = dynInterface_parse(desc, &dynIntf); + ASSERT_NE(0, status); + ASSERT_STREQ("Error allocating memory for dynamic interface", celix_err_popLastError()); + + rewind(desc); + // not enough memory for namval_entry when parsing header section + celix_ei_expect_calloc((void*) dynInterface_parse, 3, nullptr, 1); + status = dynInterface_parse(desc, &dynIntf); + ASSERT_NE(0, status); + ASSERT_STREQ("Error allocating memory for namval entry", celix_err_popLastError()); + + rewind(desc); + // not enough memory for type_entry when parsing types section + celix_ei_expect_calloc((void*) dynInterface_parse, 2, nullptr, 1); + status = dynInterface_parse(desc, &dynIntf); + ASSERT_NE(0, status); + ASSERT_STREQ("Error allocating memory for type entry", celix_err_popLastError()); + + rewind(desc); + // not enough memory for method_entry when parsing methods section + celix_ei_expect_calloc((void*) dynInterface_parse, 2, nullptr, 2); + status = dynInterface_parse(desc, &dynIntf); + ASSERT_NE(0, status); + ASSERT_STREQ("Error allocating memory for method entry", celix_err_popLastError()); +} \ No newline at end of file diff --git a/libs/dfi/gtest/src/dyn_interface_tests.cpp b/libs/dfi/gtest/src/dyn_interface_tests.cpp index ab9688fab..eef8e3fe4 100644 --- a/libs/dfi/gtest/src/dyn_interface_tests.cpp +++ b/libs/dfi/gtest/src/dyn_interface_tests.cpp @@ -19,8 +19,6 @@ #include "gtest/gtest.h" -#include - extern "C" { diff --git a/libs/dfi/src/dyn_interface.c b/libs/dfi/src/dyn_interface.c index aab77bf8e..554cd06a4 100644 --- a/libs/dfi/src/dyn_interface.c +++ b/libs/dfi/src/dyn_interface.c @@ -44,52 +44,50 @@ static int dynInterface_getEntryForHead(struct namvals_head *head, const char *n int dynInterface_parse(FILE *descriptor, dyn_interface_type **out) { int status = OK; - dyn_interface_type *intf = calloc(1, sizeof(*intf)); - if (intf != NULL) { - TAILQ_INIT(&intf->header); - TAILQ_INIT(&intf->annotations); - TAILQ_INIT(&intf->types); - TAILQ_INIT(&intf->methods); - - char peek = (char)fgetc(descriptor); - while (peek == ':') { - ungetc(peek, descriptor); - status = dynInterface_parseSection(intf, descriptor); - if (status == OK) { - peek = (char)fgetc(descriptor); - } else { - break; - } - } + celix_autoptr(dyn_interface_type) intf = calloc(1, sizeof(*intf)); + if (intf == NULL) { + celix_err_pushf("Error allocating memory for dynamic interface"); + return ERROR; + } - if (status == OK) { - status = dynCommon_eatChar(descriptor, EOF); - } + TAILQ_INIT(&intf->header); + TAILQ_INIT(&intf->annotations); + TAILQ_INIT(&intf->types); + TAILQ_INIT(&intf->methods); + char peek = (char)fgetc(descriptor); + while (peek == ':') { + ungetc(peek, descriptor); + status = dynInterface_parseSection(intf, descriptor); if (status == OK) { - status = dynInterface_checkInterface(intf); + peek = (char)fgetc(descriptor); + } else { + break; } + } - if (status == OK) { /* We are sure that version field is present in the header */ - char* version = NULL; - dynInterface_getVersionString(intf,&version); - if (version != NULL){ - intf->version = celix_version_createVersionFromString(version); - status = intf->version != NULL ? OK : ERROR; - } - if (status == ERROR) { - celix_err_pushf("Invalid version (%s) in parsed descriptor\n",version); - } + if (status == OK) { + status = dynCommon_eatChar(descriptor, EOF); + } + + if (status == OK) { + status = dynInterface_checkInterface(intf); + } + + if (status == OK) { /* We are sure that version field is present in the header */ + char* version = NULL; + dynInterface_getVersionString(intf,&version); + if (version != NULL){ + intf->version = celix_version_createVersionFromString(version); + status = intf->version != NULL ? OK : ERROR; + } + if (status == ERROR) { + celix_err_pushf("Invalid version (%s) in parsed descriptor\n",version); } - } else { - status = ERROR; - celix_err_pushf("Error allocating memory for dynamic interface\n"); } if (status == OK) { - *out = intf; - } else if (intf != NULL) { - dynInterface_destroy(intf); + *out = celix_steal_ptr(intf); } return status; }