Skip to content

Commit

Permalink
Add error injection for dyn_interface.
Browse files Browse the repository at this point in the history
  • Loading branch information
PengZheng committed Dec 14, 2023
1 parent ba39703 commit ccbd7b0
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 39 deletions.
7 changes: 7 additions & 0 deletions libs/dfi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
12 changes: 12 additions & 0 deletions libs/dfi/gtest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 ()
68 changes: 68 additions & 0 deletions libs/dfi/gtest/src/dyn_interface_ei_tests.cc
Original file line number Diff line number Diff line change
@@ -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 <gtest/gtest.h>

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());
}
2 changes: 0 additions & 2 deletions libs/dfi/gtest/src/dyn_interface_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@

#include "gtest/gtest.h"

#include <stdarg.h>


extern "C" {

Expand Down
72 changes: 35 additions & 37 deletions libs/dfi/src/dyn_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down

0 comments on commit ccbd7b0

Please sign in to comment.