new stuff

This commit is contained in:
Tarion 2026-07-03 03:41:25 +02:00
parent 8998bc3936
commit 64c8492e5c
No known key found for this signature in database
6907 changed files with 3401899 additions and 0 deletions

View file

@ -0,0 +1,46 @@
cmake_minimum_required(VERSION 3.14)
find_package(Sanitizers)
# tests
set(test_write_out test_write.out)
add_executable(${test_write_out} test_write.c)
target_link_libraries(${test_write_out} zip)
add_test(NAME ${test_write_out} COMMAND ${test_write_out})
add_sanitizers(${test_write_out})
set(test_append_out test_append.out)
add_executable(${test_append_out} test_append.c)
target_link_libraries(${test_append_out} zip)
add_test(NAME ${test_append_out} COMMAND ${test_append_out})
add_sanitizers(${test_append_out})
set(test_read_out test_read.out)
add_executable(${test_read_out} test_read.c)
target_link_libraries(${test_read_out} zip)
add_test(NAME ${test_read_out} COMMAND ${test_read_out})
add_sanitizers(${test_read_out})
set(test_extract_out test_extract.out)
add_executable(${test_extract_out} test_extract.c)
target_link_libraries(${test_extract_out} zip)
add_test(NAME ${test_extract_out} COMMAND ${test_extract_out})
add_sanitizers(${test_extract_out})
set(test_entry_out test_entry.out)
add_executable(${test_entry_out} test_entry.c)
target_link_libraries(${test_entry_out} zip)
add_test(NAME ${test_entry_out} COMMAND ${test_entry_out})
add_sanitizers(${test_entry_out})
set(test_permissions_out test_permissions.out)
add_executable(${test_permissions_out} test_permissions.c)
target_link_libraries(${test_permissions_out} zip)
add_test(NAME ${test_permissions_out} COMMAND ${test_permissions_out})
add_sanitizers(${test_permissions_out})
set(test_open_out test_open.out)
add_executable(${test_open_out} test_open.c)
target_link_libraries(${test_open_out} zip)
add_test(NAME ${test_open_out} COMMAND ${test_open_out})
add_sanitizers(${test_open_out})

View file

@ -0,0 +1,370 @@
/*
* Copyright (c) 2012 David Siñuela Pastor, siu.4coders@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef MINUNIT_MINUNIT_H
#define MINUNIT_MINUNIT_H
#ifdef __cplusplus
extern "C" {
#endif
#if defined(_WIN32)
#include <Windows.h>
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#define __func__ __FUNCTION__
#endif
#elif defined(__unix__) || defined(__unix) || defined(unix) || \
(defined(__APPLE__) && defined(__MACH__))
/* Change POSIX C SOURCE version for pure c99 compilers */
#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200112L
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#endif
#include <string.h>
#include <sys/resource.h>
#include <sys/time.h> /* gethrtime(), gettimeofday() */
#include <sys/times.h>
#include <time.h> /* clock_gettime(), time() */
#include <unistd.h> /* POSIX flags */
#if defined(__MACH__) && defined(__APPLE__)
#include <mach/mach.h>
#include <mach/mach_time.h>
#endif
#if __GNUC__ >= 5 && !defined(__STDC_VERSION__)
#define __func__ __extension__ __FUNCTION__
#endif
#else
#error "Unable to define timers for an unknown OS."
#endif
#include <math.h>
#include <stdio.h>
/* Maximum length of last message */
#define MINUNIT_MESSAGE_LEN 1024
/* Accuracy with which floats are compared */
#define MINUNIT_EPSILON 1E-12
/* Misc. counters */
static int minunit_run = 0;
static int minunit_assert = 0;
static int minunit_fail = 0;
static int minunit_status = 0;
/* Timers */
static double minunit_real_timer = 0;
static double minunit_proc_timer = 0;
/* Last message */
static char minunit_last_message[MINUNIT_MESSAGE_LEN];
/* Test setup and teardown function pointers */
static void (*minunit_setup)(void) = NULL;
static void (*minunit_teardown)(void) = NULL;
/* Definitions */
#define MU_TEST(method_name) static void method_name(void)
#define MU_TEST_SUITE(suite_name) static void suite_name(void)
#define MU__SAFE_BLOCK(block) \
do { \
block \
} while (0)
/* Run test suite and unset setup and teardown functions */
#define MU_RUN_SUITE(suite_name) \
MU__SAFE_BLOCK(suite_name(); minunit_setup = NULL; minunit_teardown = NULL;)
/* Configure setup and teardown functions */
#define MU_SUITE_CONFIGURE(setup_fun, teardown_fun) \
MU__SAFE_BLOCK(minunit_setup = setup_fun; minunit_teardown = teardown_fun;)
/* Test runner */
#define MU_RUN_TEST(test) \
MU__SAFE_BLOCK( \
if (minunit_real_timer == 0 && minunit_proc_timer == 0) { \
minunit_real_timer = mu_timer_real(); \
minunit_proc_timer = mu_timer_cpu(); \
} if (minunit_setup) (*minunit_setup)(); \
minunit_status = 0; test(); minunit_run++; if (minunit_status) { \
minunit_fail++; \
printf("F"); \
printf("\n%s\n", minunit_last_message); \
} fflush(stdout); \
if (minunit_teardown)(*minunit_teardown)();)
/* Report */
#define MU_REPORT() \
MU__SAFE_BLOCK( \
double minunit_end_real_timer; double minunit_end_proc_timer; \
printf("\n\n%d tests, %d assertions, %d failures\n", minunit_run, \
minunit_assert, minunit_fail); \
minunit_end_real_timer = mu_timer_real(); \
minunit_end_proc_timer = mu_timer_cpu(); \
printf("\nFinished in %.8f seconds (real) %.8f seconds (proc)\n\n", \
minunit_end_real_timer - minunit_real_timer, \
minunit_end_proc_timer - minunit_proc_timer);)
#define MU_EXIT_CODE minunit_fail
/* Assertions */
#define mu_check(test) \
MU__SAFE_BLOCK( \
minunit_assert++; if (!(test)) { \
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, \
"%s failed:\n\t%s:%d: %s", __func__, __FILE__, __LINE__, \
#test); \
minunit_status = 1; \
return; \
} else { printf("."); })
#define mu_fail(message) \
MU__SAFE_BLOCK(minunit_assert++; \
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, \
"%s failed:\n\t%s:%d: %s", __func__, __FILE__, \
__LINE__, message); \
minunit_status = 1; return;)
#define mu_assert(test, message) \
MU__SAFE_BLOCK( \
minunit_assert++; if (!(test)) { \
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, \
"%s failed:\n\t%s:%d: %s", __func__, __FILE__, __LINE__, \
message); \
minunit_status = 1; \
return; \
} else { printf("."); })
#define mu_assert_int_eq(expected, result) \
MU__SAFE_BLOCK( \
int minunit_tmp_e; int minunit_tmp_r; minunit_assert++; \
minunit_tmp_e = (expected); minunit_tmp_r = (result); \
if (minunit_tmp_e != minunit_tmp_r) { \
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, \
"%s failed:\n\t%s:%d: %d expected but was %d", __func__, \
__FILE__, __LINE__, minunit_tmp_e, minunit_tmp_r); \
minunit_status = 1; \
return; \
} else { printf("."); })
#define mu_assert_double_eq(expected, result) \
MU__SAFE_BLOCK( \
double minunit_tmp_e; double minunit_tmp_r; minunit_assert++; \
minunit_tmp_e = (expected); minunit_tmp_r = (result); \
if (fabs(minunit_tmp_e - minunit_tmp_r) > MINUNIT_EPSILON) { \
int minunit_significant_figures = 1 - log10(MINUNIT_EPSILON); \
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, \
"%s failed:\n\t%s:%d: %.*g expected but was %.*g", __func__, \
__FILE__, __LINE__, minunit_significant_figures, \
minunit_tmp_e, minunit_significant_figures, minunit_tmp_r); \
minunit_status = 1; \
return; \
} else { printf("."); })
#define mu_assert_string_eq(expected, result) \
MU__SAFE_BLOCK( \
const char *minunit_tmp_e = expected; \
const char *minunit_tmp_r = result; minunit_assert++; \
if (!minunit_tmp_e) { \
minunit_tmp_e = "<null pointer>"; \
} if (!minunit_tmp_r) { \
minunit_tmp_r = "<null pointer>"; \
} if (strcmp(minunit_tmp_e, minunit_tmp_r)) { \
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, \
"%s failed:\n\t%s:%d: '%s' expected but was '%s'", __func__, \
__FILE__, __LINE__, minunit_tmp_e, minunit_tmp_r); \
minunit_status = 1; \
return; \
} else { printf("."); })
/*
* The following two functions were written by David Robert Nadeau
* from http://NadeauSoftware.com/ and distributed under the
* Creative Commons Attribution 3.0 Unported License
*/
/**
* Returns the real time, in seconds, or -1.0 if an error occurred.
*
* Time is measured since an arbitrary and OS-dependent start time.
* The returned real time is only useful for computing an elapsed time
* between two calls to this function.
*/
static double mu_timer_real(void) {
#if defined(_WIN32)
/* Windows 2000 and later. ---------------------------------- */
LARGE_INTEGER Time;
LARGE_INTEGER Frequency;
QueryPerformanceFrequency(&Frequency);
QueryPerformanceCounter(&Time);
Time.QuadPart *= 1000000;
Time.QuadPart /= Frequency.QuadPart;
return (double)Time.QuadPart / 1000000.0;
#elif (defined(__hpux) || defined(hpux)) || \
((defined(__sun__) || defined(__sun) || defined(sun)) && \
(defined(__SVR4) || defined(__svr4__)))
/* HP-UX, Solaris. ------------------------------------------ */
return (double)gethrtime() / 1000000000.0;
#elif defined(__MACH__) && defined(__APPLE__)
/* OSX. ----------------------------------------------------- */
static double timeConvert = 0.0;
if (timeConvert == 0.0) {
mach_timebase_info_data_t timeBase;
(void)mach_timebase_info(&timeBase);
timeConvert =
(double)timeBase.numer / (double)timeBase.denom / 1000000000.0;
}
return (double)mach_absolute_time() * timeConvert;
#elif defined(_POSIX_VERSION)
/* POSIX. --------------------------------------------------- */
struct timeval tm;
#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
{
struct timespec ts;
#if defined(CLOCK_MONOTONIC_PRECISE)
/* BSD. --------------------------------------------- */
const clockid_t id = CLOCK_MONOTONIC_PRECISE;
#elif defined(CLOCK_MONOTONIC_RAW)
/* Linux. ------------------------------------------- */
const clockid_t id = CLOCK_MONOTONIC_RAW;
#elif defined(CLOCK_HIGHRES)
/* Solaris. ----------------------------------------- */
const clockid_t id = CLOCK_HIGHRES;
#elif defined(CLOCK_MONOTONIC)
/* AIX, BSD, Linux, POSIX, Solaris. ----------------- */
const clockid_t id = CLOCK_MONOTONIC;
#elif defined(CLOCK_REALTIME)
/* AIX, BSD, HP-UX, Linux, POSIX. ------------------- */
const clockid_t id = CLOCK_REALTIME;
#else
const clockid_t id = (clockid_t)-1; /* Unknown. */
#endif /* CLOCK_* */
if (id != (clockid_t)-1 && clock_gettime(id, &ts) != -1)
return (double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0;
/* Fall thru. */
}
#endif /* _POSIX_TIMERS */
/* AIX, BSD, Cygwin, HP-UX, Linux, OSX, POSIX, Solaris. ----- */
gettimeofday(&tm, NULL);
return (double)tm.tv_sec + (double)tm.tv_usec / 1000000.0;
#else
return -1.0; /* Failed. */
#endif
}
/**
* Returns the amount of CPU time used by the current process,
* in seconds, or -1.0 if an error occurred.
*/
static double mu_timer_cpu(void) {
#if defined(_WIN32)
/* Windows -------------------------------------------------- */
FILETIME createTime;
FILETIME exitTime;
FILETIME kernelTime;
FILETIME userTime;
/* This approach has a resolution of 1/64 second. Unfortunately, Windows' API
* does not offer better */
if (GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime,
&userTime) != 0) {
ULARGE_INTEGER userSystemTime;
memcpy(&userSystemTime, &userTime, sizeof(ULARGE_INTEGER));
return (double)userSystemTime.QuadPart / 10000000.0;
}
#elif defined(__unix__) || defined(__unix) || defined(unix) || \
(defined(__APPLE__) && defined(__MACH__))
/* AIX, BSD, Cygwin, HP-UX, Linux, OSX, and Solaris --------- */
#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
/* Prefer high-res POSIX timers, when available. */
{
clockid_t id;
struct timespec ts;
#if _POSIX_CPUTIME > 0
/* Clock ids vary by OS. Query the id, if possible. */
if (clock_getcpuclockid(0, &id) == -1)
#endif
#if defined(CLOCK_PROCESS_CPUTIME_ID)
/* Use known clock id for AIX, Linux, or Solaris. */
id = CLOCK_PROCESS_CPUTIME_ID;
#elif defined(CLOCK_VIRTUAL)
/* Use known clock id for BSD or HP-UX. */
id = CLOCK_VIRTUAL;
#else
id = (clockid_t)-1;
#endif
if (id != (clockid_t)-1 && clock_gettime(id, &ts) != -1)
return (double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0;
}
#endif
#if defined(RUSAGE_SELF)
{
struct rusage rusage;
if (getrusage(RUSAGE_SELF, &rusage) != -1)
return (double)rusage.ru_utime.tv_sec +
(double)rusage.ru_utime.tv_usec / 1000000.0;
}
#endif
#if defined(_SC_CLK_TCK)
{
const double ticks = (double)sysconf(_SC_CLK_TCK);
struct tms tms;
if (times(&tms) != (clock_t)-1)
return (double)tms.tms_utime / ticks;
}
#endif
#if defined(CLOCKS_PER_SEC)
{
clock_t cl = clock();
if (cl != (clock_t)-1)
return (double)cl / (double)CLOCKS_PER_SEC;
}
#endif
#endif
return -1; /* Failed. */
}
#ifdef __cplusplus
}
#endif
#endif /* MINUNIT_MINUNIT_H */

View file

@ -0,0 +1,104 @@
#include <stdio.h>
#include <stdlib.h>
#include <zip.h>
#include "minunit.h"
#if defined(_WIN32) || defined(_WIN64)
#define MKTEMP _mktemp
#define UNLINK _unlink
#else
#define MKTEMP mkstemp
#define UNLINK unlink
#endif
static char ZIPNAME[L_tmpnam + 1] = {0};
static int total_entries = 0;
#define TESTDATA1 "Some test data 1...\0"
void test_setup(void) {
strncpy(ZIPNAME, "z-XXXXXX\0", L_tmpnam);
MKTEMP(ZIPNAME);
struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
zip_entry_open(zip, "test/test-1.txt");
zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1));
zip_entry_close(zip);
++total_entries;
zip_close(zip);
}
void test_teardown(void) { UNLINK(ZIPNAME); }
#define TESTDATA2 "Some test data 2...\0"
#define CRC32DATA2 2532008468
MU_TEST(test_append) {
struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'a');
mu_check(zip != NULL);
mu_assert_int_eq(0, zip_entry_open(zip, "test\\test-2.txt"));
mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/test-2.txt"));
mu_assert_int_eq(total_entries, zip_entry_index(zip));
mu_assert_int_eq(0, zip_entry_write(zip, TESTDATA2, strlen(TESTDATA2)));
mu_assert_int_eq(strlen(TESTDATA2), zip_entry_size(zip));
mu_check(CRC32DATA2 == zip_entry_crc32(zip));
mu_assert_int_eq(0, zip_entry_close(zip));
++total_entries;
zip_close(zip);
zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'a');
mu_assert_int_eq(0, zip_entry_open(zip, "test\\empty/"));
mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/empty/"));
mu_assert_int_eq(0, zip_entry_size(zip));
mu_assert_int_eq(0, zip_entry_crc32(zip));
mu_assert_int_eq(total_entries, zip_entry_index(zip));
mu_assert_int_eq(0, zip_entry_close(zip));
++total_entries;
zip_close(zip);
zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'a');
mu_assert_int_eq(0, zip_entry_open(zip, "empty/"));
mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "empty/"));
mu_assert_int_eq(0, zip_entry_size(zip));
mu_assert_int_eq(0, zip_entry_crc32(zip));
mu_assert_int_eq(total_entries, zip_entry_index(zip));
mu_assert_int_eq(0, zip_entry_close(zip));
++total_entries;
mu_assert_int_eq(0, zip_entry_open(zip, "dotfiles/.test"));
mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "dotfiles/.test"));
mu_assert_int_eq(0, zip_entry_size(zip));
mu_assert_int_eq(0, zip_entry_crc32(zip));
mu_assert_int_eq(0, zip_entry_write(zip, TESTDATA2, strlen(TESTDATA2)));
mu_assert_int_eq(strlen(TESTDATA2), zip_entry_size(zip));
mu_check(CRC32DATA2 == zip_entry_crc32(zip));
mu_assert_int_eq(total_entries, zip_entry_index(zip));
mu_assert_int_eq(0, zip_entry_close(zip));
++total_entries;
mu_assert_int_eq(total_entries, zip_entries_total(zip));
zip_close(zip);
}
MU_TEST_SUITE(test_append_suite) {
MU_SUITE_CONFIGURE(&test_setup, &test_teardown);
MU_RUN_TEST(test_append);
}
#define UNUSED(x) (void)x
int main(int argc, char *argv[]) {
UNUSED(argc);
UNUSED(argv);
MU_RUN_SUITE(test_append_suite);
MU_REPORT();
return MU_EXIT_CODE;
}

View file

@ -0,0 +1,438 @@
#include <stdio.h>
#include <stdlib.h>
#include <zip.h>
#include "minunit.h"
#if defined(_WIN32) || defined(_WIN64)
#define MKTEMP _mktemp
#define UNLINK _unlink
#else
#define MKTEMP mkstemp
#define UNLINK unlink
#endif
#define MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE \
(sizeof(unsigned short) * 2 + sizeof(unsigned long long) * 3)
#define MZ_ZIP_LOCAL_DIR_HEADER_SIZE 30
static char ZIPNAME[L_tmpnam + 1] = {0};
#define CRC32DATA1 2220805626
#define TESTDATA1 "Some test data 1...\0"
#define TESTDATA2 "Some test data 2...\0"
#define CRC32DATA2 2532008468
static int total_entries = 0;
void test_setup(void) {
strncpy(ZIPNAME, "z-XXXXXX\0", L_tmpnam);
MKTEMP(ZIPNAME);
struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
zip_entry_open(zip, "test/test-1.txt");
zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1));
zip_entry_close(zip);
++total_entries;
zip_entry_open(zip, "test\\test-2.txt");
zip_entry_write(zip, TESTDATA2, strlen(TESTDATA2));
zip_entry_close(zip);
++total_entries;
zip_entry_open(zip, "test\\empty/");
zip_entry_close(zip);
++total_entries;
zip_entry_open(zip, "empty/");
zip_entry_close(zip);
++total_entries;
zip_entry_open(zip, "dotfiles/.test");
zip_entry_write(zip, TESTDATA2, strlen(TESTDATA2));
zip_entry_close(zip);
++total_entries;
zip_entry_open(zip, "delete.me");
zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1));
zip_entry_close(zip);
++total_entries;
zip_entry_open(zip, "_");
zip_entry_write(zip, TESTDATA2, strlen(TESTDATA2));
zip_entry_close(zip);
++total_entries;
zip_entry_open(zip, "delete/file.1");
zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1));
zip_entry_close(zip);
++total_entries;
zip_entry_open(zip, "delete/file.2");
zip_entry_write(zip, TESTDATA2, strlen(TESTDATA2));
zip_entry_close(zip);
++total_entries;
zip_entry_open(zip, "deleteme/file.3");
zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1));
zip_entry_close(zip);
++total_entries;
zip_entry_open(zip, "delete/file.4");
zip_entry_write(zip, TESTDATA2, strlen(TESTDATA2));
zip_entry_close(zip);
++total_entries;
zip_close(zip);
}
void test_teardown(void) {
total_entries = 0;
UNLINK(ZIPNAME);
}
MU_TEST(test_entry_name) {
struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
mu_check(zip != NULL);
mu_check(zip_entry_name(zip) == NULL);
mu_assert_int_eq(0, zip_entry_open(zip, "test\\test-1.txt"));
mu_check(NULL != zip_entry_name(zip));
mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/test-1.txt"));
mu_assert_int_eq(strlen(TESTDATA1), zip_entry_size(zip));
mu_check(CRC32DATA1 == zip_entry_crc32(zip));
mu_assert_int_eq(0, zip_entry_index(zip));
mu_assert_int_eq(0, zip_entry_close(zip));
mu_assert_int_eq(0, zip_entry_open(zip, "test/test-2.txt"));
mu_check(NULL != zip_entry_name(zip));
mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/test-2.txt"));
mu_assert_int_eq(strlen(TESTDATA2), zip_entry_size(zip));
mu_check(CRC32DATA2 == zip_entry_crc32(zip));
mu_assert_int_eq(1, zip_entry_index(zip));
mu_assert_int_eq(0, zip_entry_close(zip));
zip_close(zip);
}
MU_TEST(test_entry_opencasesensitive) {
struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
mu_check(zip != NULL);
mu_check(zip_entry_name(zip) == NULL);
mu_assert_int_eq(0, zip_entry_open(zip, "test/TEST-1.TXT"));
mu_check(NULL != zip_entry_name(zip));
mu_assert_int_eq(0, zip_entry_close(zip));
mu_assert_int_eq(ZIP_ENOENT,
zip_entry_opencasesensitive(zip, "test/TEST-1.TXT"));
zip_close(zip);
}
MU_TEST(test_entry_index) {
struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
mu_check(zip != NULL);
mu_assert_int_eq(0, zip_entry_open(zip, "test\\test-1.txt"));
mu_assert_int_eq(0, zip_entry_index(zip));
mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/test-1.txt"));
mu_assert_int_eq(strlen(TESTDATA1), zip_entry_size(zip));
mu_check(CRC32DATA1 == zip_entry_crc32(zip));
mu_assert_int_eq(0, zip_entry_close(zip));
mu_assert_int_eq(0, zip_entry_open(zip, "test/test-2.txt"));
mu_assert_int_eq(1, zip_entry_index(zip));
mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/test-2.txt"));
mu_assert_int_eq(strlen(TESTDATA2), zip_entry_size(zip));
mu_check(CRC32DATA2 == zip_entry_crc32(zip));
mu_assert_int_eq(0, zip_entry_close(zip));
zip_close(zip);
}
MU_TEST(test_entry_openbyindex) {
struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
mu_check(zip != NULL);
mu_assert_int_eq(0, zip_entry_openbyindex(zip, 1));
mu_assert_int_eq(1, zip_entry_index(zip));
mu_assert_int_eq(strlen(TESTDATA2), zip_entry_size(zip));
mu_check(CRC32DATA2 == zip_entry_crc32(zip));
mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/test-2.txt"));
mu_assert_int_eq(0, zip_entry_close(zip));
mu_assert_int_eq(0, zip_entry_openbyindex(zip, 0));
mu_assert_int_eq(0, zip_entry_index(zip));
mu_assert_int_eq(strlen(TESTDATA1), zip_entry_size(zip));
mu_check(CRC32DATA1 == zip_entry_crc32(zip));
mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/test-1.txt"));
mu_assert_int_eq(0, zip_entry_close(zip));
zip_close(zip);
}
MU_TEST(test_entry_read) {
char *bufencode1 = NULL;
char *bufencode2 = NULL;
char *buf = NULL;
size_t bufsize;
struct zip_t *zip =
zip_stream_open(NULL, 0, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
mu_check(zip != NULL);
mu_assert_int_eq(0, zip_entry_open(zip, "test/test-1.txt"));
mu_assert_int_eq(0, zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1)));
mu_assert_int_eq(0, zip_entry_close(zip));
ssize_t n = zip_stream_copy(zip, (void **)&bufencode1, NULL);
zip_stream_copy(zip, (void **)&bufencode2, &bufsize);
mu_assert_int_eq(0, strncmp(bufencode1, bufencode2, bufsize));
zip_stream_close(zip);
struct zip_t *zipstream = zip_stream_open(bufencode1, n, 0, 'r');
mu_check(zipstream != NULL);
mu_assert_int_eq(0, zip_entry_open(zipstream, "test/test-1.txt"));
n = zip_entry_read(zipstream, (void **)&buf, NULL);
mu_assert_int_eq(0, strncmp(buf, TESTDATA1, (size_t)n));
mu_assert_int_eq(0, zip_entry_close(zipstream));
zip_stream_close(zipstream);
free(buf);
free(bufencode1);
free(bufencode2);
}
MU_TEST(test_list_entries) {
struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
mu_check(zip != NULL);
int i = 0, n = zip_entries_total(zip);
for (; i < n; ++i) {
mu_assert_int_eq(0, zip_entry_openbyindex(zip, i));
fprintf(stdout, "[%d]: %s", i, zip_entry_name(zip));
if (zip_entry_isdir(zip)) {
fprintf(stdout, " (DIR)");
}
fprintf(stdout, "\n");
mu_assert_int_eq(0, zip_entry_close(zip));
}
zip_close(zip);
}
MU_TEST(test_entries_deletebyindex) {
size_t entries[] = {5, 6, 7, 9, 8};
struct zip_t *zip = zip_open(ZIPNAME, 0, 'd');
mu_check(zip != NULL);
mu_assert_int_eq(5, zip_entries_deletebyindex(zip, entries, 5));
zip_close(zip);
zip = zip_open(ZIPNAME, 0, 'r');
mu_check(zip != NULL);
mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "delete.me"));
mu_assert_int_eq(0, zip_entry_close(zip));
fprintf(stdout, "delete.me: %s\n", zip_strerror(ZIP_ENOENT));
mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "_"));
mu_assert_int_eq(0, zip_entry_close(zip));
fprintf(stdout, "_: %s\n", zip_strerror(ZIP_ENOENT));
mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "delete/file.1"));
mu_assert_int_eq(0, zip_entry_close(zip));
fprintf(stdout, "delete/file.1: %s\n", zip_strerror(ZIP_ENOENT));
mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "deleteme/file.3"));
mu_assert_int_eq(0, zip_entry_close(zip));
fprintf(stdout, "delete/file.3: %s\n", zip_strerror(ZIP_ENOENT));
mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "delete/file.2"));
mu_assert_int_eq(0, zip_entry_close(zip));
fprintf(stdout, "delete/file.2: %s\n", zip_strerror(ZIP_ENOENT));
mu_assert_int_eq(total_entries - 5, zip_entries_total(zip));
mu_assert_int_eq(0, zip_entry_open(zip, "delete/file.4"));
size_t buftmp = 0;
char *buf = NULL;
ssize_t bufsize = zip_entry_read(zip, (void **)&buf, &buftmp);
mu_assert_int_eq(bufsize, strlen(TESTDATA2));
mu_assert_int_eq((size_t)bufsize, buftmp);
mu_assert_int_eq(0, strncmp(buf, TESTDATA2, bufsize));
mu_assert_int_eq(0, zip_entry_close(zip));
free(buf);
buf = NULL;
zip_close(zip);
}
MU_TEST(test_entries_deleteinvalid) {
size_t entries[] = {111, 222, 333, 444};
struct zip_t *zip = zip_open(ZIPNAME, 0, 'd');
mu_check(zip != NULL);
mu_assert_int_eq(0, zip_entries_deletebyindex(zip, entries, 4));
zip_close(zip);
zip = zip_open(ZIPNAME, 0, 'r');
mu_check(zip != NULL);
mu_assert_int_eq(0, zip_entry_open(zip, "delete.me"));
mu_assert_int_eq(0, zip_entry_close(zip));
mu_assert_int_eq(0, zip_entry_open(zip, "_"));
mu_assert_int_eq(0, zip_entry_close(zip));
mu_assert_int_eq(0, zip_entry_open(zip, "delete/file.1"));
mu_assert_int_eq(0, zip_entry_close(zip));
mu_assert_int_eq(0, zip_entry_open(zip, "deleteme/file.3"));
mu_assert_int_eq(0, zip_entry_close(zip));
mu_assert_int_eq(0, zip_entry_open(zip, "delete/file.2"));
mu_assert_int_eq(0, zip_entry_close(zip));
mu_assert_int_eq(total_entries, zip_entries_total(zip));
mu_assert_int_eq(0, zip_entry_open(zip, "delete/file.4"));
size_t buftmp = 0;
char *buf = NULL;
ssize_t bufsize = zip_entry_read(zip, (void **)&buf, &buftmp);
mu_assert_int_eq(bufsize, strlen(TESTDATA2));
mu_assert_int_eq((size_t)bufsize, buftmp);
mu_assert_int_eq(0, strncmp(buf, TESTDATA2, bufsize));
mu_assert_int_eq(0, zip_entry_close(zip));
free(buf);
buf = NULL;
zip_close(zip);
}
MU_TEST(test_entries_delete) {
char *entries[] = {"delete.me", "_", "delete/file.1", "deleteme/file.3",
"delete/file.2"};
struct zip_t *zip = zip_open(ZIPNAME, 0, 'd');
mu_check(zip != NULL);
mu_assert_int_eq(5, zip_entries_delete(zip, entries, 5));
zip_close(zip);
zip = zip_open(ZIPNAME, 0, 'r');
mu_check(zip != NULL);
mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "delete.me"));
mu_assert_int_eq(0, zip_entry_close(zip));
fprintf(stdout, "delete.me: %s\n", zip_strerror(ZIP_ENOENT));
mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "_"));
mu_assert_int_eq(0, zip_entry_close(zip));
fprintf(stdout, "_: %s\n", zip_strerror(ZIP_ENOENT));
mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "delete/file.1"));
mu_assert_int_eq(0, zip_entry_close(zip));
fprintf(stdout, "delete/file.1: %s\n", zip_strerror(ZIP_ENOENT));
mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "deleteme/file.3"));
mu_assert_int_eq(0, zip_entry_close(zip));
fprintf(stdout, "delete/file.3: %s\n", zip_strerror(ZIP_ENOENT));
mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "delete/file.2"));
mu_assert_int_eq(0, zip_entry_close(zip));
fprintf(stdout, "delete/file.2: %s\n", zip_strerror(ZIP_ENOENT));
mu_assert_int_eq(total_entries - 5, zip_entries_total(zip));
mu_assert_int_eq(0, zip_entry_open(zip, "delete/file.4"));
size_t buftmp = 0;
char *buf = NULL;
ssize_t bufsize = zip_entry_read(zip, (void **)&buf, &buftmp);
mu_assert_int_eq(bufsize, strlen(TESTDATA2));
mu_assert_int_eq((size_t)bufsize, buftmp);
mu_assert_int_eq(0, strncmp(buf, TESTDATA2, bufsize));
mu_assert_int_eq(0, zip_entry_close(zip));
free(buf);
buf = NULL;
zip_close(zip);
}
MU_TEST(test_entry_offset) {
struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
mu_check(zip != NULL);
unsigned long long off = 0ULL;
int i = 0, n = zip_entries_total(zip);
for (; i < n; i++) {
mu_assert_int_eq(0, zip_entry_openbyindex(zip, i));
mu_assert_int_eq(i, zip_entry_index(zip));
mu_assert_int_eq(off, zip_entry_header_offset(zip));
off = zip_entry_header_offset(zip) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
strlen(zip_entry_name(zip)) + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE +
zip_entry_comp_size(zip);
fprintf(stdout, "\n[%d: %s]: header: %llu, dir: %llu, size: %llu (%llu)\n",
i, zip_entry_name(zip), zip_entry_header_offset(zip),
zip_entry_dir_offset(zip), zip_entry_comp_size(zip), off);
mu_assert_int_eq(0, zip_entry_close(zip));
}
zip_close(zip);
}
MU_TEST_SUITE(test_entry_suite) {
MU_SUITE_CONFIGURE(&test_setup, &test_teardown);
MU_RUN_TEST(test_entry_name);
MU_RUN_TEST(test_entry_opencasesensitive);
MU_RUN_TEST(test_entry_index);
MU_RUN_TEST(test_entry_openbyindex);
MU_RUN_TEST(test_entry_read);
MU_RUN_TEST(test_list_entries);
MU_RUN_TEST(test_entries_deletebyindex);
MU_RUN_TEST(test_entries_delete);
MU_RUN_TEST(test_entry_offset);
}
#define UNUSED(x) (void)x
int main(int argc, char *argv[]) {
UNUSED(argc);
UNUSED(argv);
MU_RUN_SUITE(test_entry_suite);
MU_REPORT();
return MU_EXIT_CODE;
}

View file

@ -0,0 +1,161 @@
#include <stdio.h>
#include <stdlib.h>
#include <zip.h>
#include "minunit.h"
#if defined(_WIN32) || defined(_WIN64)
#define MKTEMP _mktemp
#define UNLINK _unlink
#else
#define MKTEMP mkstemp
#define UNLINK unlink
#endif
static char ZIPNAME[L_tmpnam + 1] = {0};
#define TESTDATA1 "Some test data 1...\0"
#define TESTDATA2 "Some test data 2...\0"
void test_setup(void) {
strncpy(ZIPNAME, "z-XXXXXX\0", L_tmpnam);
MKTEMP(ZIPNAME);
struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
zip_entry_open(zip, "test/test-1.txt");
zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1));
zip_entry_close(zip);
zip_entry_open(zip, "test\\test-2.txt");
zip_entry_write(zip, TESTDATA2, strlen(TESTDATA2));
zip_entry_close(zip);
zip_entry_open(zip, "test\\empty/");
zip_entry_close(zip);
zip_entry_open(zip, "empty/");
zip_entry_close(zip);
zip_entry_open(zip, "dotfiles/.test");
zip_entry_write(zip, TESTDATA2, strlen(TESTDATA2));
zip_entry_close(zip);
zip_close(zip);
}
void test_teardown(void) {
UNLINK("test/test-1.txt");
UNLINK("test/test-2.txt");
UNLINK("test/empty");
UNLINK("test");
UNLINK("empty");
UNLINK("dotfiles/.test");
UNLINK("dotfiles");
UNLINK(ZIPNAME);
}
#define UNUSED(x) (void)x
struct buffer_t {
char *data;
size_t size;
};
static size_t on_extract(void *arg, uint64_t offset, const void *data,
size_t size) {
UNUSED(offset);
struct buffer_t *buf = (struct buffer_t *)arg;
buf->data = realloc(buf->data, buf->size + size + 1);
memcpy(&(buf->data[buf->size]), data, size);
buf->size += size;
buf->data[buf->size] = 0;
return size;
}
MU_TEST(test_extract) {
struct buffer_t buf;
struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
mu_check(zip != NULL);
memset((void *)&buf, 0, sizeof(struct buffer_t));
mu_assert_int_eq(0, zip_entry_open(zip, "test/test-1.txt"));
mu_assert_int_eq(0, zip_entry_extract(zip, on_extract, &buf));
mu_assert_int_eq(strlen(TESTDATA1), buf.size);
mu_assert_int_eq(0, strncmp(buf.data, TESTDATA1, buf.size));
mu_assert_int_eq(0, zip_entry_close(zip));
free(buf.data);
buf.data = NULL;
buf.size = 0;
memset((void *)&buf, 0, sizeof(struct buffer_t));
mu_assert_int_eq(0, zip_entry_open(zip, "dotfiles/.test"));
mu_assert_int_eq(0, zip_entry_extract(zip, on_extract, &buf));
mu_assert_int_eq(strlen(TESTDATA2), buf.size);
mu_assert_int_eq(0, strncmp(buf.data, TESTDATA2, buf.size));
mu_assert_int_eq(0, zip_entry_close(zip));
free(buf.data);
buf.data = NULL;
buf.size = 0;
zip_close(zip);
}
MU_TEST(test_extract_stream) {
mu_assert_int_eq(
ZIP_ENOINIT,
zip_extract("non_existing_directory/non_existing_archive.zip", ".", NULL,
NULL));
mu_assert_int_eq(ZIP_ENOINIT, zip_stream_extract("", 0, ".", NULL, NULL));
fprintf(stdout, "zip_stream_extract: %s\n", zip_strerror(ZIP_ENOINIT));
FILE *fp = NULL;
#if defined(_MSC_VER)
if (0 != fopen_s(&fp, ZIPNAME, "rb+"))
#else
if (!(fp = fopen(ZIPNAME, "rb+")))
#endif
{
mu_fail("Cannot open filename\n");
}
fseek(fp, 0L, SEEK_END);
size_t filesize = ftell(fp);
fseek(fp, 0L, SEEK_SET);
char *stream = (char *)malloc(filesize * sizeof(char));
memset(stream, 0, filesize);
size_t size = fread(stream, sizeof(char), filesize, fp);
mu_assert_int_eq(filesize, size);
mu_assert_int_eq(0, zip_stream_extract(stream, size, ".", NULL, NULL));
free(stream);
fclose(fp);
}
MU_TEST_SUITE(test_extract_suite) {
MU_SUITE_CONFIGURE(&test_setup, &test_teardown);
MU_RUN_TEST(test_extract);
MU_RUN_TEST(test_extract_stream);
}
int main(int argc, char *argv[]) {
UNUSED(argc);
UNUSED(argv);
MU_RUN_SUITE(test_extract_suite);
MU_REPORT();
return MU_EXIT_CODE;
}

View file

@ -0,0 +1,68 @@
#include <stdio.h>
#include <stdlib.h>
#include <zip.h>
#include "minunit.h"
#if defined(_WIN32) || defined(_WIN64)
#define MKTEMP _mktemp
#else
#define MKTEMP mkstemp
#endif
static char ZIPNAME[L_tmpnam + 1] = {0};
void test_setup(void) {
strncpy(ZIPNAME, "z-XXXXXX\0", L_tmpnam);
MKTEMP(ZIPNAME);
}
void test_teardown(void) { remove(ZIPNAME); }
MU_TEST(test_openwitherror) {
int errnum;
struct zip_t *zip =
zip_openwitherror(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'r', &errnum);
mu_check(zip == NULL);
mu_assert_int_eq(ZIP_ERINIT, errnum);
zip = zip_openwitherror(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w', &errnum);
mu_check(zip != NULL);
mu_assert_int_eq(0, errnum);
zip_close(zip);
}
MU_TEST(test_stream_openwitherror) {
int errnum;
struct zip_t *zip = zip_stream_openwitherror(
NULL, 0, ZIP_DEFAULT_COMPRESSION_LEVEL, 'r', &errnum);
mu_check(zip == NULL);
mu_assert_int_eq(ZIP_EINVMODE, errnum);
zip = zip_stream_openwitherror(NULL, 0, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w',
&errnum);
mu_check(zip != NULL);
mu_assert_int_eq(0, errnum);
zip_stream_close(zip);
}
MU_TEST_SUITE(test_entry_suite) {
MU_SUITE_CONFIGURE(&test_setup, &test_teardown);
MU_RUN_TEST(test_openwitherror);
MU_RUN_TEST(test_stream_openwitherror);
}
#define UNUSED(x) (void)x
int main(int argc, char *argv[]) {
UNUSED(argc);
UNUSED(argv);
MU_RUN_SUITE(test_entry_suite);
MU_REPORT();
return MU_EXIT_CODE;
}

View file

@ -0,0 +1,191 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <zip.h>
#include "minunit.h"
#if defined(_WIN32) || defined(_WIN64)
#define MKTEMP _mktemp
#define UNLINK _unlink
#else
#define MKTEMP mkstemp
#define UNLINK unlink
#endif
static char ZIPNAME[L_tmpnam + 1] = {0};
static char XFILE[L_tmpnam + 1] = {0};
static char RFILE[L_tmpnam + 1] = {0};
static char WFILE[L_tmpnam + 1] = {0};
void test_setup(void) {
strncpy(ZIPNAME, "z-XXXXXX\0", L_tmpnam);
strncpy(XFILE, "x-XXXXXX\0", L_tmpnam);
strncpy(RFILE, "r-XXXXXX\0", L_tmpnam);
strncpy(WFILE, "w-XXXXXX\0", L_tmpnam);
MKTEMP(ZIPNAME);
MKTEMP(XFILE);
MKTEMP(RFILE);
MKTEMP(WFILE);
}
void test_teardown(void) {
UNLINK(WFILE);
UNLINK(RFILE);
UNLINK(XFILE);
UNLINK(ZIPNAME);
}
#if defined(_MSC_VER) || defined(__MINGW32__)
#define MZ_FILE_STAT_STRUCT _stat
#define MZ_FILE_STAT _stat
#else
#define MZ_FILE_STAT_STRUCT stat
#define MZ_FILE_STAT stat
#endif
#define XMODE 0100777
#define RMODE 0100444
#define WMODE 0100666
#define UNIXMODE 0100600
MU_TEST(test_exe_permissions) {
struct MZ_FILE_STAT_STRUCT file_stats;
const char *filenames[] = {XFILE};
FILE *f = fopen(XFILE, "w");
fclose(f);
chmod(XFILE, XMODE);
mu_assert_int_eq(0, zip_create(ZIPNAME, filenames, 1));
remove(XFILE);
mu_assert_int_eq(0, zip_extract(ZIPNAME, ".", NULL, NULL));
mu_assert_int_eq(0, MZ_FILE_STAT(XFILE, &file_stats));
mu_assert_int_eq(XMODE, file_stats.st_mode);
}
MU_TEST(test_read_permissions) {
struct MZ_FILE_STAT_STRUCT file_stats;
const char *filenames[] = {RFILE};
FILE *f = fopen(RFILE, "w");
fclose(f);
chmod(RFILE, RMODE);
mu_assert_int_eq(0, zip_create(ZIPNAME, filenames, 1));
remove(RFILE);
mu_assert_int_eq(0, zip_extract(ZIPNAME, ".", NULL, NULL));
mu_assert_int_eq(0, MZ_FILE_STAT(RFILE, &file_stats));
mu_assert_int_eq(RMODE, file_stats.st_mode);
// chmod from 444 to 666 to be able delete the file on windows
chmod(RFILE, WMODE);
}
MU_TEST(test_write_permissions) {
struct MZ_FILE_STAT_STRUCT file_stats;
const char *filenames[] = {WFILE};
FILE *f = fopen(WFILE, "w");
fclose(f);
chmod(WFILE, WMODE);
mu_assert_int_eq(0, zip_create(ZIPNAME, filenames, 1));
remove(WFILE);
mu_assert_int_eq(0, zip_extract(ZIPNAME, ".", NULL, NULL));
mu_assert_int_eq(0, MZ_FILE_STAT(WFILE, &file_stats));
mu_assert_int_eq(WMODE, file_stats.st_mode);
}
#define TESTDATA1 "Some test data 1...\0"
MU_TEST(test_unix_permissions) {
// UNIX or APPLE
struct MZ_FILE_STAT_STRUCT file_stats;
struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
mu_check(zip != NULL);
mu_assert_int_eq(0, zip_entry_open(zip, RFILE));
mu_assert_int_eq(0, zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1)));
mu_assert_int_eq(0, zip_entry_close(zip));
zip_close(zip);
mu_assert_int_eq(0, zip_extract(ZIPNAME, ".", NULL, NULL));
mu_assert_int_eq(0, MZ_FILE_STAT(RFILE, &file_stats));
mu_assert_int_eq(UNIXMODE, file_stats.st_mode);
}
MU_TEST(test_mtime) {
struct MZ_FILE_STAT_STRUCT file_stat1, file_stat2;
const char *filename = "test.data";
FILE *stream = NULL;
struct zip_t *zip = NULL;
#if defined(_MSC_VER)
if (0 != fopen_s(&stream, filename, "w+"))
#else
if (!(stream = fopen(filename, "w+")))
#endif
{
mu_fail("Cannot open filename\n");
}
fwrite(TESTDATA1, sizeof(char), strlen(TESTDATA1), stream);
mu_assert_int_eq(0, fclose(stream));
memset(&file_stat1, 0, sizeof(file_stat1));
memset(&file_stat2, 0, sizeof(file_stat2));
zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
mu_check(zip != NULL);
mu_assert_int_eq(0, zip_entry_open(zip, filename));
mu_assert_int_eq(0, zip_entry_fwrite(zip, filename));
mu_assert_int_eq(0, zip_entry_close(zip));
zip_close(zip);
mu_assert_int_eq(0, MZ_FILE_STAT(filename, &file_stat1));
remove(filename);
mu_assert_int_eq(0, zip_extract(ZIPNAME, ".", NULL, NULL));
mu_assert_int_eq(0, MZ_FILE_STAT(filename, &file_stat2));
remove(filename);
fprintf(stdout, "file_stat1.st_mtime: %lu\n", file_stat1.st_mtime);
fprintf(stdout, "file_stat2.st_mtime: %lu\n", file_stat2.st_mtime);
mu_check(labs(file_stat1.st_mtime - file_stat2.st_mtime) <= 1);
}
MU_TEST_SUITE(test_permissions_suite) {
MU_SUITE_CONFIGURE(&test_setup, &test_teardown);
#if defined(_WIN32) || defined(__WIN32__)
#else
MU_RUN_TEST(test_exe_permissions);
MU_RUN_TEST(test_read_permissions);
MU_RUN_TEST(test_write_permissions);
MU_RUN_TEST(test_unix_permissions);
#endif
MU_RUN_TEST(test_mtime);
}
#define UNUSED(x) (void)x
int main(int argc, char *argv[]) {
UNUSED(argc);
UNUSED(argv);
MU_RUN_SUITE(test_permissions_suite);
MU_REPORT();
return MU_EXIT_CODE;
}

View file

@ -0,0 +1,146 @@
#include <stdio.h>
#include <stdlib.h>
#include <zip.h>
#include "minunit.h"
#if defined(_WIN32) || defined(_WIN64)
#define MKTEMP _mktemp
#else
#define MKTEMP mkstemp
#endif
static char ZIPNAME[L_tmpnam + 1] = {0};
#define CRC32DATA1 2220805626
#define TESTDATA1 "Some test data 1...\0"
#define TESTDATA2 "Some test data 2...\0"
#define CRC32DATA2 2532008468
void test_setup(void) {
strncpy(ZIPNAME, "z-XXXXXX\0", L_tmpnam);
MKTEMP(ZIPNAME);
struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
zip_entry_open(zip, "test/test-1.txt");
zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1));
zip_entry_close(zip);
zip_entry_open(zip, "test\\test-2.txt");
zip_entry_write(zip, TESTDATA2, strlen(TESTDATA2));
zip_entry_close(zip);
zip_entry_open(zip, "test\\empty/");
zip_entry_close(zip);
zip_entry_open(zip, "empty/");
zip_entry_close(zip);
zip_entry_open(zip, "dotfiles/.test");
zip_entry_write(zip, TESTDATA2, strlen(TESTDATA2));
zip_entry_close(zip);
zip_close(zip);
}
void test_teardown(void) { remove(ZIPNAME); }
MU_TEST(test_read) {
char *buf = NULL;
ssize_t bufsize;
size_t buftmp;
struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
mu_check(zip != NULL);
mu_assert_int_eq(1, zip_is64(zip));
mu_assert_int_eq(0, zip_entry_open(zip, "test\\test-1.txt"));
mu_assert_int_eq(strlen(TESTDATA1), zip_entry_size(zip));
mu_check(CRC32DATA1 == zip_entry_crc32(zip));
bufsize = zip_entry_read(zip, (void **)&buf, &buftmp);
mu_assert_int_eq(strlen(TESTDATA1), bufsize);
mu_assert_int_eq((size_t)bufsize, buftmp);
mu_assert_int_eq(0, strncmp(buf, TESTDATA1, bufsize));
mu_assert_int_eq(0, zip_entry_close(zip));
free(buf);
buf = NULL;
mu_assert_int_eq(0, zip_entry_open(zip, "test/test-2.txt"));
mu_assert_int_eq(strlen(TESTDATA2), zip_entry_size(zip));
mu_check(CRC32DATA2 == zip_entry_crc32(zip));
bufsize = zip_entry_read(zip, (void **)&buf, NULL);
mu_assert_int_eq(strlen(TESTDATA2), (size_t)bufsize);
mu_assert_int_eq(0, strncmp(buf, TESTDATA2, (size_t)bufsize));
mu_assert_int_eq(0, zip_entry_close(zip));
free(buf);
buf = NULL;
mu_assert_int_eq(0, zip_entry_open(zip, "test\\empty/"));
mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/empty/"));
mu_assert_int_eq(0, zip_entry_size(zip));
mu_assert_int_eq(0, zip_entry_crc32(zip));
mu_assert_int_eq(0, zip_entry_close(zip));
zip_close(zip);
}
MU_TEST(test_noallocread) {
ssize_t bufsize;
size_t buftmp = strlen(TESTDATA2);
char *buf = calloc(buftmp, sizeof(char));
struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
mu_check(zip != NULL);
mu_assert_int_eq(1, zip_is64(zip));
mu_assert_int_eq(0, zip_entry_open(zip, "test/test-2.txt"));
bufsize = zip_entry_noallocread(zip, (void *)buf, buftmp);
mu_assert_int_eq(buftmp, (size_t)bufsize);
mu_assert_int_eq(0, strncmp(buf, TESTDATA2, buftmp));
mu_assert_int_eq(0, zip_entry_close(zip));
free(buf);
buf = NULL;
buftmp = strlen(TESTDATA1);
buf = calloc(buftmp, sizeof(char));
mu_assert_int_eq(0, zip_entry_open(zip, "test/test-1.txt"));
bufsize = zip_entry_noallocread(zip, (void *)buf, buftmp);
mu_assert_int_eq(buftmp, (size_t)bufsize);
mu_assert_int_eq(0, strncmp(buf, TESTDATA1, buftmp));
mu_assert_int_eq(0, zip_entry_close(zip));
free(buf);
buf = NULL;
buftmp = strlen(TESTDATA2);
buf = calloc(buftmp, sizeof(char));
mu_assert_int_eq(0, zip_entry_open(zip, "dotfiles/.test"));
bufsize = zip_entry_noallocread(zip, (void *)buf, buftmp);
mu_assert_int_eq(buftmp, (size_t)bufsize);
mu_assert_int_eq(0, strncmp(buf, TESTDATA2, buftmp));
mu_assert_int_eq(0, zip_entry_close(zip));
free(buf);
buf = NULL;
zip_close(zip);
}
MU_TEST_SUITE(test_read_suite) {
MU_SUITE_CONFIGURE(&test_setup, &test_teardown);
MU_RUN_TEST(test_read);
MU_RUN_TEST(test_noallocread);
}
#define UNUSED(x) (void)x
int main(int argc, char *argv[]) {
UNUSED(argc);
UNUSED(argv);
MU_RUN_SUITE(test_read_suite);
MU_REPORT();
return MU_EXIT_CODE;
}

View file

@ -0,0 +1,113 @@
#include <stdio.h>
#include <stdlib.h>
#include <zip.h>
#include "minunit.h"
#if defined(_WIN32) || defined(_WIN64)
#define MKTEMP _mktemp
#define UNLINK _unlink
#else
#define MKTEMP mkstemp
#define UNLINK unlink
#endif
static char ZIPNAME[L_tmpnam + 1] = {0};
static char WFILE[L_tmpnam + 1] = {0};
void test_setup(void) {
strncpy(ZIPNAME, "z-XXXXXX\0", L_tmpnam);
strncpy(WFILE, "w-XXXXXX\0", L_tmpnam);
MKTEMP(ZIPNAME);
MKTEMP(WFILE);
}
void test_teardown(void) {
UNLINK(WFILE);
UNLINK(ZIPNAME);
}
#define CRC32DATA1 2220805626
#define TESTDATA1 "Some test data 1...\0"
MU_TEST(test_write) {
struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
mu_check(zip != NULL);
mu_assert_int_eq(0, zip_entry_open(zip, "test/test-1.txt"));
mu_assert_int_eq(0, zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1)));
mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/test-1.txt"));
mu_assert_int_eq(0, zip_entry_index(zip));
mu_assert_int_eq(strlen(TESTDATA1), zip_entry_size(zip));
mu_check(CRC32DATA1 == zip_entry_crc32(zip));
mu_assert_int_eq(0, zip_entry_close(zip));
mu_assert_int_eq(1, zip_is64(zip));
zip_close(zip);
}
MU_TEST(test_write_utf) {
struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
mu_check(zip != NULL);
mu_assert_int_eq(0, zip_entry_open(zip, "тест/Если-б-не-было-войны.txt"));
mu_assert_int_eq(0, zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1)));
mu_assert_int_eq(
0, strcmp(zip_entry_name(zip), "тест/Если-б-не-было-войны.txt"));
mu_assert_int_eq(0, zip_entry_index(zip));
mu_assert_int_eq(strlen(TESTDATA1), zip_entry_size(zip));
mu_check(CRC32DATA1 == zip_entry_crc32(zip));
mu_assert_int_eq(0, zip_entry_close(zip));
mu_assert_int_eq(1, zip_is64(zip));
zip_close(zip);
}
MU_TEST(test_fwrite) {
const char *filename = WFILE;
FILE *stream = NULL;
struct zip_t *zip = NULL;
#if defined(_MSC_VER)
if (0 != fopen_s(&stream, filename, "w+"))
#else
if (!(stream = fopen(filename, "w+")))
#endif
{
// Cannot open filename
mu_fail("Cannot open filename\n");
}
fwrite(TESTDATA1, sizeof(char), strlen(TESTDATA1), stream);
mu_assert_int_eq(0, fclose(stream));
zip = zip_open(ZIPNAME, 9, 'w');
mu_check(zip != NULL);
mu_assert_int_eq(0, zip_entry_open(zip, WFILE));
mu_assert_int_eq(0, zip_entry_fwrite(zip, WFILE));
mu_assert_int_eq(0, zip_entry_close(zip));
mu_assert_int_eq(1, zip_is64(zip));
zip_close(zip);
}
MU_TEST_SUITE(test_write_suite) {
MU_SUITE_CONFIGURE(&test_setup, &test_teardown);
MU_RUN_TEST(test_write);
MU_RUN_TEST(test_write_utf);
MU_RUN_TEST(test_fwrite);
}
#define UNUSED(x) (void)x
int main(int argc, char *argv[]) {
UNUSED(argc);
UNUSED(argv);
MU_RUN_SUITE(test_write_suite);
MU_REPORT();
return MU_EXIT_CODE;
}