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;

Reply via email to