This is an automated email from the ASF dual-hosted git repository.
pengzheng pushed a commit to branch feature/refactor_bundle_cache
in repository https://gitbox.apache.org/repos/asf/celix.git
The following commit(s) were added to refs/heads/feature/refactor_bundle_cache
by this push:
new b4dbbd76 Test celix_utils_extractZipInternal thoroughly.
b4dbbd76 is described below
commit b4dbbd76e7680504166c2fb090763ea79bb7fab2
Author: PengZheng <[email protected]>
AuthorDate: Tue Mar 28 21:52:08 2023 +0800
Test celix_utils_extractZipInternal thoroughly.
---
libs/error_injector/CMakeLists.txt | 2 +
.../celix_utils/src/celix_utils_ei.cc | 5 +-
libs/error_injector/{ => stdio}/CMakeLists.txt | 20 ++---
libs/error_injector/stdio/include/stdio_ei.h | 36 ++++++++
libs/error_injector/stdio/src/stdio_ei.cc | 42 ++++++++++
libs/error_injector/{ => zip}/CMakeLists.txt | 22 ++---
libs/error_injector/zip/include/zip_ei.h | 38 +++++++++
libs/error_injector/zip/src/zip_ei.cc | 52 ++++++++++++
libs/framework/CMakeLists.txt | 5 +-
libs/utils/CMakeLists.txt | 69 +++++++--------
libs/utils/gtest/CMakeLists.txt | 15 ++++
.../gtest/src/FileUtilsErrorInjectionTestSuite.cc | 97 ++++++++++++++++++++++
libs/utils/gtest/src/FileUtilsTestSuite.cc | 12 +++
libs/utils/src/celix_file_utils.c | 67 +++++++++------
14 files changed, 396 insertions(+), 86 deletions(-)
diff --git a/libs/error_injector/CMakeLists.txt
b/libs/error_injector/CMakeLists.txt
index a771f2c3..ae2c2ec2 100644
--- a/libs/error_injector/CMakeLists.txt
+++ b/libs/error_injector/CMakeLists.txt
@@ -27,3 +27,5 @@ add_subdirectory(malloc)
add_subdirectory(asprintf)
add_subdirectory(celix_properties)
add_subdirectory(celix_utils)
+add_subdirectory(zip)
+add_subdirectory(stdio)
diff --git a/libs/error_injector/celix_utils/src/celix_utils_ei.cc
b/libs/error_injector/celix_utils/src/celix_utils_ei.cc
index d073000a..2db67233 100644
--- a/libs/error_injector/celix_utils/src/celix_utils_ei.cc
+++ b/libs/error_injector/celix_utils/src/celix_utils_ei.cc
@@ -17,8 +17,9 @@
under the License.
*/
-#include <cstdarg>
#include "celix_utils_ei.h"
+#include <cstdarg>
+#include <errno.h>
extern "C" {
@@ -58,7 +59,9 @@ celix_status_t __wrap_celix_utils_deleteDirectory(const char*
path, const char**
CELIX_EI_DEFINE(celix_utils_writeOrCreateString, char *)
char* __wrap_celix_utils_writeOrCreateString(char* buffer, size_t bufferSize,
const char* format, ...) {
+ errno = ENOMEM;
CELIX_EI_IMPL(celix_utils_writeOrCreateString);
+ errno = 0;
va_list args;
va_start(args, format);
char *ret = celix_utils_writeOrCreateVString(buffer, bufferSize, format,
args);
diff --git a/libs/error_injector/CMakeLists.txt
b/libs/error_injector/stdio/CMakeLists.txt
similarity index 59%
copy from libs/error_injector/CMakeLists.txt
copy to libs/error_injector/stdio/CMakeLists.txt
index a771f2c3..44882882 100644
--- a/libs/error_injector/CMakeLists.txt
+++ b/libs/error_injector/stdio/CMakeLists.txt
@@ -15,15 +15,13 @@
# specific language governing permissions and limitations
# under the License.
-add_library(error_injector INTERFACE)
-target_include_directories(error_injector INTERFACE
${CMAKE_CURRENT_LIST_DIR}/api)
-# get caller address of the target function, into which errors are injected
-target_link_libraries(error_injector INTERFACE dl)
-target_link_options(error_injector INTERFACE -rdynamic)
-target_compile_options(error_injector INTERFACE -Wno-frame-address)
-add_library(Celix::error_injector ALIAS error_injector)
+add_library(stdio_ei STATIC src/stdio_ei.cc)
-add_subdirectory(malloc)
-add_subdirectory(asprintf)
-add_subdirectory(celix_properties)
-add_subdirectory(celix_utils)
+target_include_directories(stdio_ei PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
+target_link_libraries(stdio_ei PUBLIC Celix::error_injector)
+# It plays nicely with address sanitizer this way.
+target_link_options(stdio_ei INTERFACE
+ LINKER:--wrap,fopen
+ LINKER:--wrap,fwrite
+ )
+add_library(Celix::stdio_ei ALIAS stdio_ei)
diff --git a/libs/error_injector/stdio/include/stdio_ei.h
b/libs/error_injector/stdio/include/stdio_ei.h
new file mode 100644
index 00000000..f528e40d
--- /dev/null
+++ b/libs/error_injector/stdio/include/stdio_ei.h
@@ -0,0 +1,36 @@
+/*
+ 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.
+ */
+
+#ifndef CELIX_STDIO_EI_H
+#define CELIX_STDIO_EI_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "celix_error_injector.h"
+#include <stdio.h>
+
+CELIX_EI_DECLARE(fopen, FILE *);
+
+CELIX_EI_DECLARE(fwrite, size_t);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //CELIX_STDIO_EI_H
diff --git a/libs/error_injector/stdio/src/stdio_ei.cc
b/libs/error_injector/stdio/src/stdio_ei.cc
new file mode 100644
index 00000000..8165c5fd
--- /dev/null
+++ b/libs/error_injector/stdio/src/stdio_ei.cc
@@ -0,0 +1,42 @@
+/*
+ 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 <errno.h>
+#include "stdio_ei.h"
+
+extern "C" {
+FILE *__real_fopen (const char *__filename, const char *__modes);
+CELIX_EI_DEFINE(fopen, FILE *)
+FILE *__wrap_fopen (const char *__filename, const char *__modes) {
+ errno = EMFILE;
+ CELIX_EI_IMPL(fopen);
+ errno = 0;
+ return __real_fopen(__filename, __modes);
+}
+
+
+size_t __real_fwrite (const void *__restrict __ptr, size_t __size, size_t __n,
FILE *__restrict __s);
+CELIX_EI_DEFINE(fwrite, size_t)
+size_t __wrap_fwrite (const void *__restrict __ptr, size_t __size, size_t __n,
FILE *__restrict __s) {
+ errno = ENOSPC;
+ CELIX_EI_IMPL(fwrite);
+ errno = 0;
+ return __real_fwrite(__ptr, __size, __n, __s);
+}
+}
\ No newline at end of file
diff --git a/libs/error_injector/CMakeLists.txt
b/libs/error_injector/zip/CMakeLists.txt
similarity index 59%
copy from libs/error_injector/CMakeLists.txt
copy to libs/error_injector/zip/CMakeLists.txt
index a771f2c3..d9689907 100644
--- a/libs/error_injector/CMakeLists.txt
+++ b/libs/error_injector/zip/CMakeLists.txt
@@ -15,15 +15,15 @@
# specific language governing permissions and limitations
# under the License.
-add_library(error_injector INTERFACE)
-target_include_directories(error_injector INTERFACE
${CMAKE_CURRENT_LIST_DIR}/api)
-# get caller address of the target function, into which errors are injected
-target_link_libraries(error_injector INTERFACE dl)
-target_link_options(error_injector INTERFACE -rdynamic)
-target_compile_options(error_injector INTERFACE -Wno-frame-address)
-add_library(Celix::error_injector ALIAS error_injector)
+add_library(zip_ei STATIC src/zip_ei.cc)
-add_subdirectory(malloc)
-add_subdirectory(asprintf)
-add_subdirectory(celix_properties)
-add_subdirectory(celix_utils)
+target_include_directories(zip_ei PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
+target_link_libraries(zip_ei PUBLIC Celix::error_injector libzip::libzip)
+# It plays nicely with address sanitizer this way.
+
+target_link_options(zip_ei INTERFACE
+ LINKER:--wrap,zip_stat_index
+ LINKER:--wrap,zip_fopen_index
+ LINKER:--wrap,zip_fread
+ )
+add_library(Celix::zip_ei ALIAS zip_ei)
diff --git a/libs/error_injector/zip/include/zip_ei.h
b/libs/error_injector/zip/include/zip_ei.h
new file mode 100644
index 00000000..401af7c8
--- /dev/null
+++ b/libs/error_injector/zip/include/zip_ei.h
@@ -0,0 +1,38 @@
+/*
+ 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.
+ */
+
+#ifndef CELIX_ZIP_EI_H
+#define CELIX_ZIP_EI_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "celix_error_injector.h"
+#include <zip.h>
+
+CELIX_EI_DECLARE(zip_stat_index, int);
+
+CELIX_EI_DECLARE(zip_fopen_index, zip_file_t *);
+
+CELIX_EI_DECLARE(zip_fread, zip_int64_t);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //CELIX_ZIP_EI_H
diff --git a/libs/error_injector/zip/src/zip_ei.cc
b/libs/error_injector/zip/src/zip_ei.cc
new file mode 100644
index 00000000..5bbd8947
--- /dev/null
+++ b/libs/error_injector/zip/src/zip_ei.cc
@@ -0,0 +1,52 @@
+/*
+ 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 "zip_ei.h"
+
+extern "C" {
+
+int __real_zip_stat_index(zip_t *, zip_uint64_t, zip_flags_t, zip_stat_t *);
+CELIX_EI_DEFINE(zip_stat_index, int)
+int __wrap_zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags,
zip_stat_t *st) {
+ zip_error_set(zip_get_error(za), ZIP_ER_MEMORY, 0);
+ CELIX_EI_IMPL(zip_stat_index);
+ zip_error_clear(za);
+ return __real_zip_stat_index(za, index, flags, st);
+}
+
+
+zip_file_t * __real_zip_fopen_index(zip_t *, zip_uint64_t, zip_flags_t);
+CELIX_EI_DEFINE(zip_fopen_index, zip_file_t *)
+zip_file_t * __wrap_zip_fopen_index(zip_t *za, zip_uint64_t index, zip_flags_t
flags) {
+ zip_error_set(zip_get_error(za), ZIP_ER_MEMORY, 0);
+ CELIX_EI_IMPL(zip_fopen_index);
+ zip_error_clear(za);
+ return __real_zip_fopen_index(za, index, flags);
+}
+
+
+zip_int64_t __real_zip_fread(zip_file_t *, void *, zip_uint64_t);
+CELIX_EI_DEFINE(zip_fread, zip_int64_t)
+zip_int64_t __wrap_zip_fread(zip_file_t *zf, void *buf, zip_uint64_t len) {
+ zip_error_set(zip_file_get_error(zf), ZIP_ER_INTERNAL, 0);
+ CELIX_EI_IMPL(zip_fread);
+ zip_error_set(zip_file_get_error(zf), 0, 0);
+ return __real_zip_fread(zf, buf, len);
+}
+}
\ No newline at end of file
diff --git a/libs/framework/CMakeLists.txt b/libs/framework/CMakeLists.txt
index c2de1601..297e7bbd 100644
--- a/libs/framework/CMakeLists.txt
+++ b/libs/framework/CMakeLists.txt
@@ -51,12 +51,9 @@ target_link_libraries(framework PUBLIC framework_obj)
set_target_properties(framework PROPERTIES OUTPUT_NAME "celix_framework")
set_target_properties(framework PROPERTIES "SOVERSION" ${CELIX_MAJOR})
-target_link_libraries(framework PUBLIC Celix::utils
${CELIX_OPTIONAL_EXTRA_LIBS})
-target_link_libraries(framework PUBLIC libuuid::libuuid CURL::libcurl
ZLIB::ZLIB)
-target_link_libraries(framework PRIVATE ${CMAKE_DL_LIBS})
-
celix_deprecated_utils_headers(framework)
+# By omitting OBJECTS DESTINATION, object files will NOT be installed.
install(TARGETS framework framework_obj EXPORT celix LIBRARY DESTINATION
${CMAKE_INSTALL_LIBDIR} COMPONENT framework
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/celix)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/celix
COMPONENT framework)
diff --git a/libs/utils/CMakeLists.txt b/libs/utils/CMakeLists.txt
index ff498e66..f88f0f3e 100644
--- a/libs/utils/CMakeLists.txt
+++ b/libs/utils/CMakeLists.txt
@@ -28,53 +28,55 @@ if (NOT OPEN_MEMSTREAM_EXISTS)
install(DIRECTORY include/memstream/ DESTINATION
${CMAKE_INSTALL_INCLUDEDIR}/celix/memstream COMPONENT framework)
endif()
-add_library(utils SHARED
- src/array_list.c
- src/hash_map.c
- src/linked_list.c
- src/linked_list_iterator.c
- src/celix_threads.c
- src/version.c
- src/version_range.c
- src/properties.c
- src/utils.c
- src/ip_utils.c
- src/filter.c
- src/celix_log_utils.c
- src/celix_hash_map.c
- src/celix_file_utils.c
- src/celix_convert_utils.c
- ${MEMSTREAM_SOURCES}
-)
-set_target_properties(utils PROPERTIES OUTPUT_NAME "celix_utils")
-target_link_libraries(utils PRIVATE libzip::libzip)
-
+add_library(utils_obj OBJECT
+ src/array_list.c
+ src/hash_map.c
+ src/linked_list.c
+ src/linked_list_iterator.c
+ src/celix_threads.c
+ src/version.c
+ src/version_range.c
+ src/properties.c
+ src/utils.c
+ src/ip_utils.c
+ src/filter.c
+ src/celix_log_utils.c
+ src/celix_hash_map.c
+ src/celix_file_utils.c
+ src/celix_convert_utils.c
+ ${MEMSTREAM_SOURCES}
+ )
+target_link_libraries(utils_obj PRIVATE libzip::libzip)
if (NOT OPEN_MEMSTREAM_EXISTS)
- target_compile_definitions(utils PUBLIC
-DCELIX_UTILS_NO_MEMSTREAM_AVAILABLE)
+ target_compile_definitions(utils_obj PUBLIC
-DCELIX_UTILS_NO_MEMSTREAM_AVAILABLE)
endif ()
if (ANDROID)
- target_compile_definitions(utils PRIVATE -DUSE_FILE32API)
+ target_compile_definitions(utils_obj PRIVATE -DUSE_FILE32API)
endif ()
-if (NOT APPLE)
- target_link_libraries(utils PUBLIC -lrt)
+if (NOT APPLE)
+ target_link_libraries(utils_obj PUBLIC -lrt)
endif ()
-target_include_directories(utils PUBLIC
+target_include_directories(utils_obj PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
$<BUILD_INTERFACE:${MEMSTREAM_INCLUDE_DIR}>
-)
-target_include_directories(utils PRIVATE src include_deprecated)
-set_target_properties(utils PROPERTIES "SOVERSION" 2)
-
+ )
+target_include_directories(utils_obj PRIVATE src include_deprecated)
IF(UNIX AND NOT ANDROID)
- target_link_libraries(utils PRIVATE m pthread)
+ target_link_libraries(utils_obj PRIVATE m pthread)
ELSEIF(ANDROID)
- target_link_libraries(utils PRIVATE m)
+ target_link_libraries(utils_obj PRIVATE m)
ENDIF()
-install(TARGETS utils EXPORT celix DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT framework
+add_library(utils SHARED)
+target_link_libraries(utils PUBLIC utils_obj)
+set_target_properties(utils PROPERTIES OUTPUT_NAME "celix_utils")
+set_target_properties(utils PROPERTIES "SOVERSION" 2)
+
+# By omitting OBJECTS DESTINATION, object files will NOT be installed.
+install(TARGETS utils utils_obj EXPORT celix LIBRARY DESTINATION
${CMAKE_INSTALL_LIBDIR} COMPONENT framework
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/celix)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/celix
COMPONENT framework
PATTERN memstream* EXCLUDE)
@@ -85,6 +87,7 @@ endif ()
#Alias setup to match external usage
add_library(Celix::utils ALIAS utils)
+add_library(Celix::utils_obj ALIAS utils_obj)
if (ENABLE_TESTING)
diff --git a/libs/utils/gtest/CMakeLists.txt b/libs/utils/gtest/CMakeLists.txt
index 4b871129..9be3ff24 100644
--- a/libs/utils/gtest/CMakeLists.txt
+++ b/libs/utils/gtest/CMakeLists.txt
@@ -75,6 +75,21 @@ endif ()
add_test(NAME test_utils COMMAND test_utils)
setup_target_for_coverage(test_utils SCAN_DIR ..)
+
+if (LINKER_WRAP_SUPPORTED)
+ add_executable(test_utils_with_ei
+ src/FileUtilsErrorInjectionTestSuite.cc
+ )
+ target_link_libraries(test_utils_with_ei PRIVATE Celix::zip_ei
Celix::stdio_ei Celix::utils_obj Celix::utils_ei GTest::gtest GTest::gtest_main)
+ target_include_directories(test_utils_with_ei PRIVATE ../src) #for
version_private (needs refactoring of test)
+ celix_deprecated_utils_headers(test_utils_with_ei)
+ add_dependencies(test_utils_with_ei test_utils_resources)
+ target_compile_definitions(test_utils_with_ei PRIVATE
-DTEST_ZIP_LOCATION=\"${TEST_ZIP_FILE}\")
+ target_compile_definitions(test_utils_with_ei PRIVATE
-DTEST_A_DIR_LOCATION=\"${CMAKE_CURRENT_SOURCE_DIR}\")
+ add_test(NAME test_utils_with_ei COMMAND test_utils_with_ei)
+ setup_target_for_coverage(test_utils_with_ei SCAN_DIR ..)
+endif ()
+
if (ENABLE_TESTING_FOR_CXX14)
#Setting standard to C++14 and testing C++ Properties.h, Filter.h and
Utils.h to ensure that C++14 is supported.
set(CMAKE_CXX_STANDARD 14)
diff --git a/libs/utils/gtest/src/FileUtilsErrorInjectionTestSuite.cc
b/libs/utils/gtest/src/FileUtilsErrorInjectionTestSuite.cc
new file mode 100644
index 00000000..6000c21e
--- /dev/null
+++ b/libs/utils/gtest/src/FileUtilsErrorInjectionTestSuite.cc
@@ -0,0 +1,97 @@
+/*
+ * 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 <gtest/gtest.h>
+#include <stdlib.h>
+#include <string>
+#include <thread>
+#include <unistd.h>
+#include <vector>
+
+#include "celix_file_utils.h"
+#include "celix_properties.h"
+#include "celix_utils_ei.h"
+#include "stdio_ei.h"
+#include "zip_ei.h"
+
+class FileUtilsWithErrorInjectionTestSuite : public ::testing::Test {
+public:
+ ~FileUtilsWithErrorInjectionTestSuite() override {
+ celix_ei_expect_zip_stat_index(nullptr, 0, -1);
+ celix_ei_expect_zip_fopen_index(nullptr, 0, nullptr);
+ celix_ei_expect_zip_fread(nullptr, 0, -1);
+ celix_ei_expect_celix_utils_writeOrCreateString(nullptr, 0, nullptr);
+ celix_ei_expect_fopen(nullptr, 0, nullptr);
+ celix_ei_expect_fwrite(nullptr, 0, 0);
+ }
+};
+
+TEST_F(FileUtilsWithErrorInjectionTestSuite, ExtractZipFileTest) {
+ const char* error = nullptr;
+ std::cout << "Using test zip location " << TEST_ZIP_LOCATION << std::endl;
+ const char* extractLocation = "extract_location";
+
+ // Fail to query file status in zip file
+ celix_utils_deleteDirectory(extractLocation, nullptr);
+ EXPECT_FALSE(celix_utils_fileExists(extractLocation));
+ celix_ei_expect_zip_stat_index(CELIX_EI_UNKNOWN_CALLER, 0, -1);
+ auto status = celix_utils_extractZipFile(TEST_ZIP_LOCATION,
extractLocation, &error);
+ EXPECT_EQ(status, CELIX_ERROR_MAKE(CELIX_FACILITY_ZIP,ZIP_ER_MEMORY));
+ EXPECT_NE(error, nullptr);
+
+ // Fail to create file path
+ celix_utils_deleteDirectory(extractLocation, nullptr);
+ EXPECT_FALSE(celix_utils_fileExists(extractLocation));
+ celix_ei_expect_celix_utils_writeOrCreateString(CELIX_EI_UNKNOWN_CALLER,
0, nullptr);
+ status = celix_utils_extractZipFile(TEST_ZIP_LOCATION, extractLocation,
&error);
+ EXPECT_EQ(status, CELIX_ENOMEM);
+ EXPECT_NE(error, nullptr);
+
+ // Fail to open output file
+ celix_utils_deleteDirectory(extractLocation, nullptr);
+ EXPECT_FALSE(celix_utils_fileExists(extractLocation));
+ celix_ei_expect_fopen(CELIX_EI_UNKNOWN_CALLER, 0, nullptr);
+ status = celix_utils_extractZipFile(TEST_ZIP_LOCATION, extractLocation,
&error);
+ EXPECT_EQ(status, CELIX_ERROR_MAKE(CELIX_FACILITY_CERRNO,EMFILE));
+ EXPECT_NE(error, nullptr);
+
+ // Fail to open file in zip
+ celix_utils_deleteDirectory(extractLocation, nullptr);
+ EXPECT_FALSE(celix_utils_fileExists(extractLocation));
+ celix_ei_expect_zip_fopen_index(CELIX_EI_UNKNOWN_CALLER, 0, nullptr);
+ status = celix_utils_extractZipFile(TEST_ZIP_LOCATION, extractLocation,
&error);
+ EXPECT_EQ(status, CELIX_ERROR_MAKE(CELIX_FACILITY_ZIP,ZIP_ER_MEMORY));
+ EXPECT_NE(error, nullptr);
+
+ // Fail to read file in zip
+ celix_utils_deleteDirectory(extractLocation, nullptr);
+ EXPECT_FALSE(celix_utils_fileExists(extractLocation));
+ celix_ei_expect_zip_fread(CELIX_EI_UNKNOWN_CALLER, 0, -1);
+ status = celix_utils_extractZipFile(TEST_ZIP_LOCATION, extractLocation,
&error);
+ EXPECT_EQ(status, CELIX_ERROR_MAKE(CELIX_FACILITY_ZIP,ZIP_ER_INTERNAL));
+ EXPECT_NE(error, nullptr);
+
+ // Fail to write file
+ celix_utils_deleteDirectory(extractLocation, nullptr);
+ EXPECT_FALSE(celix_utils_fileExists(extractLocation));
+ celix_ei_expect_fwrite(CELIX_EI_UNKNOWN_CALLER, 0, 0);
+ status = celix_utils_extractZipFile(TEST_ZIP_LOCATION, extractLocation,
&error);
+ EXPECT_EQ(status, CELIX_ERROR_MAKE(CELIX_FACILITY_CERRNO,ENOSPC));
+ EXPECT_NE(error, nullptr);
+}
\ No newline at end of file
diff --git a/libs/utils/gtest/src/FileUtilsTestSuite.cc
b/libs/utils/gtest/src/FileUtilsTestSuite.cc
index dc900fd0..cdb412bb 100644
--- a/libs/utils/gtest/src/FileUtilsTestSuite.cc
+++ b/libs/utils/gtest/src/FileUtilsTestSuite.cc
@@ -23,6 +23,7 @@
#include <thread>
#include <unistd.h>
#include <vector>
+#include <zip.h>
#include "celix_file_utils.h"
#include "celix_properties.h"
@@ -249,6 +250,17 @@ TEST_F(FileUtilsTestSuite, ExtractBadZipDataTest) {
}
#endif
+TEST_F(FileUtilsTestSuite, ExtractNullZipDataTest) {
+ const char* extractLocation = "extract_location";
+ celix_utils_deleteDirectory(extractLocation, nullptr);
+
+ EXPECT_FALSE(celix_utils_fileExists(extractLocation));
+ const char* error = nullptr;
+ auto status = celix_utils_extractZipData(nullptr, 1, extractLocation,
&error);
+ EXPECT_EQ(status, CELIX_ERROR_MAKE(CELIX_FACILITY_ZIP,ZIP_ER_INVAL));
+ EXPECT_NE(error, nullptr);
+}
+
TEST_F(FileUtilsTestSuite, LastModifiedTest) {
//create test dir and test file
const char* testDir = "file_utils_test_dir";
diff --git a/libs/utils/src/celix_file_utils.c
b/libs/utils/src/celix_file_utils.c
index 861f4439..18203e54 100644
--- a/libs/utils/src/celix_file_utils.c
+++ b/libs/utils/src/celix_file_utils.c
@@ -34,6 +34,7 @@ static const char * const DIRECTORY_ALREADY_EXISTS_ERROR =
"Directory already ex
static const char * const FILE_ALREADY_EXISTS_AND_NOT_DIR_ERROR = "File
already exists, but is not a directory.";
static const char * const CANNOT_DELETE_DIRECTORY_PATH_IS_FILE = "Cannot
delete directory; Path points to a file.";
static const char * const ERROR_OPENING_ZIP = "Error opening zip file.";
+static const char * const ERROR_QUERYING_FILE_ZIP = "Error querying file in
zip.";
static const char * const ERROR_OPENING_FILE_ZIP = "Error opening file in
zip.";
static const char * const ERROR_READING_FILE_ZIP = "Error reading file in
zip.";
@@ -190,38 +191,52 @@ static celix_status_t
celix_utils_extractZipInternal(zip_t *zip, const char* ext
for (zip_int64_t i = 0; status == CELIX_SUCCESS && i < nrOfEntries; ++i) {
zip_stat_t st;
- zip_stat_index(zip, i, 0, &st);
-
+ if(zip_stat_index(zip, i, 0, &st) == -1) {
+ status = CELIX_ERROR_MAKE(CELIX_FACILITY_ZIP,
zip_error_code_zip(zip_get_error(zip)));
+ *errorOut = ERROR_QUERYING_FILE_ZIP;
+ continue;
+ }
char* path = celix_utils_writeOrCreateString(buf, bufSize, "%s/%s",
extractToDir, st.name);
+ if (path == NULL) {
+ status = CELIX_ERROR_MAKE(CELIX_FACILITY_CERRNO,errno);
+ *errorOut = strerror(errno);
+ continue;
+ }
if (st.name[strlen(st.name) - 1] == '/') {
status = celix_utils_createDirectory(path, false, errorOut);
- } else {
- //file
- zip_file_t *zf = zip_fopen_index(zip, i, 0);
- if (!zf) {
- status = CELIX_ERROR_MAKE(CELIX_FACILITY_ZIP,
zip_error_code_zip(zip_get_error(zip)));
- *errorOut = ERROR_OPENING_FILE_ZIP;
- } else {
- FILE* f = fopen(path, "w+");
- if (f) {
- zip_int64_t read = zip_fread(zf, buf, bufSize);
- while (read > 0) {
- fwrite(buf, read, 1, f);
- read = zip_fread(zf, buf, bufSize);
- }
- if (read < 0) {
+ goto clean_string_buf;
+ }
+ FILE* f = fopen(path, "w+");
+ if (f == NULL) {
+ status = CELIX_ERROR_MAKE(CELIX_FACILITY_CERRNO,errno);
+ *errorOut = strerror(errno);
+ goto clean_string_buf;
+ }
- status = CELIX_ERROR_MAKE(CELIX_FACILITY_ZIP,
zip_error_code_zip(zip_file_get_error(zf)));
- *errorOut = ERROR_READING_FILE_ZIP;
- }
- fclose(f);
- } else {
- status = CELIX_ERROR_MAKE(CELIX_FACILITY_CERRNO,errno);
- *errorOut = strerror(errno);
- }
- zip_fclose(zf);
+ zip_file_t *zf = zip_fopen_index(zip, i, 0);
+ if (!zf) {
+ status = CELIX_ERROR_MAKE(CELIX_FACILITY_ZIP,
zip_error_code_zip(zip_get_error(zip)));
+ *errorOut = ERROR_OPENING_FILE_ZIP;
+ goto close_output_file;
+ }
+ zip_int64_t read = zip_fread(zf, buf, bufSize);
+ while (read > 0) {
+ if (fwrite(buf, read, 1, f) == 0) {
+ status = CELIX_ERROR_MAKE(CELIX_FACILITY_CERRNO,errno);
+ *errorOut = strerror(errno);
+ goto close_zip_file;
}
+ read = zip_fread(zf, buf, bufSize);
+ }
+ if (read < 0) {
+ status = CELIX_ERROR_MAKE(CELIX_FACILITY_ZIP,
zip_error_code_zip(zip_file_get_error(zf)));
+ *errorOut = ERROR_READING_FILE_ZIP;
}
+close_zip_file:
+ zip_fclose(zf);
+close_output_file:
+ fclose(f);
+clean_string_buf:
celix_utils_freeStringIfNotEqual(buf, path);
}
return status;