Implement Google test framework.

This commit is contained in:
Nathan Moinvaziri 2022-08-06 06:24:38 -07:00
parent 03613f46f8
commit d03ca72a25
13 changed files with 1206 additions and 1355 deletions

View file

@ -11,6 +11,7 @@ jobs:
- name: Ubuntu 18 GCC 4.8
os: ubuntu-18.04
compiler: gcc
cxx-compiler: g++
cmake-args: -DMZ_CODE_COVERAGE=ON
version: "4.8"
codecov: ubuntu_18_gcc_48
@ -18,12 +19,14 @@ jobs:
- name: Ubuntu 18 GCC
os: ubuntu-18.04
compiler: gcc
cxx-compiler: g++
cmake-args: -DMZ_CODE_COVERAGE=ON
codecov: ubuntu_18_gcc
- name: Ubuntu 18 Clang 3.9
os: ubuntu-18.04
compiler: clang
cxx-compiler: clang++
cmake-args: -DMZ_CODE_COVERAGE=ON
codecov: ubuntu_18_clang_39
version: "3.7"
@ -34,18 +37,21 @@ jobs:
- name: Ubuntu 18 Clang
os: ubuntu-18.04
compiler: clang
cxx-compiler: clang++
deploy: true
deploy-name: linux
- name: Ubuntu GCC
os: ubuntu-latest
compiler: gcc
cxx-compiler: g++
cmake-args: -DMZ_CODE_COVERAGE=ON
codecov: ubuntu_gcc
- name: Ubuntu GCC OSB
os: ubuntu-latest
compiler: gcc
cxx-compiler: g++
build-dir: ../build
build-src-dir: ../minizip-ng
cmake-args: -DMZ_CODE_COVERAGE=ON
@ -54,6 +60,7 @@ jobs:
- name: Ubuntu Clang
os: ubuntu-latest
compiler: clang
cxx-compiler: clang++
cmake-args: -DMZ_CODE_COVERAGE=ON
codecov: ubuntu_clang
packages: llvm-6.0
@ -62,6 +69,7 @@ jobs:
- name: Ubuntu Clang No Zlib
os: ubuntu-latest
compiler: clang
cxx-compiler: clang++
cmake-args: -DMZ_CODE_COVERAGE=ON -DMZ_ZLIB=OFF
codecov: ubuntu_clang_no_zlib
packages: llvm-6.0
@ -70,6 +78,7 @@ jobs:
- name: Ubuntu Clang No Bzip2
os: ubuntu-latest
compiler: clang
cxx-compiler: clang++
cmake-args: -DMZ_CODE_COVERAGE=ON -DMZ_BZIP=OFF
codecov: ubuntu_clang_no_bzip2
packages: llvm-6.0
@ -78,6 +87,7 @@ jobs:
- name: Ubuntu Clang No LZMA
os: ubuntu-latest
compiler: clang
cxx-compiler: clang++
cmake-args: -DMZ_CODE_COVERAGE=ON -DMZ_LZMA=OFF
codecov: ubuntu_clang_no_lzma
packages: llvm-6.0
@ -86,6 +96,7 @@ jobs:
- name: Ubuntu Clang No Zstd
os: ubuntu-latest
compiler: clang
cxx-compiler: clang++
cmake-args: -DMZ_CODE_COVERAGE=ON -DMZ_ZSTD=OFF
codecov: ubuntu_clang_no_zstd
packages: llvm-6.0
@ -94,6 +105,7 @@ jobs:
- name: Ubuntu Clang No Pkcrypt
os: ubuntu-latest
compiler: clang
cxx-compiler: clang++
cmake-args: -DMZ_CODE_COVERAGE=ON -DMZ_PKCRYPT=OFF
codecov: ubuntu_clang_no_pkcrypt
packages: llvm-6.0
@ -102,6 +114,7 @@ jobs:
- name: Ubuntu Clang No Winzip AES
os: ubuntu-latest
compiler: clang
cxx-compiler: clang++
cmake-args: -DMZ_CODE_COVERAGE=ON -DMZ_WZAES=OFF
codecov: ubuntu_clang_no_winzip_aes
packages: llvm-6.0
@ -110,6 +123,7 @@ jobs:
- name: Ubuntu Clang No Encryption
os: ubuntu-latest
compiler: clang
cxx-compiler: clang++
cmake-args: -DMZ_CODE_COVERAGE=ON -DMZ_PKCRYPT=OFF -DMZ_WZAES=OFF
codecov: ubuntu_clang_no_encryption
packages: llvm-6.0
@ -118,6 +132,7 @@ jobs:
- name: Ubuntu Clang Compress Only
os: ubuntu-latest
compiler: clang
cxx-compiler: clang++
cmake-args: -DMZ_CODE_COVERAGE=ON -DMZ_COMPRESS_ONLY=ON
codecov: ubuntu_clang_compress_only
packages: llvm-6.0
@ -126,6 +141,7 @@ jobs:
- name: Ubuntu Clang Decompress Only
os: ubuntu-latest
compiler: clang
cxx-compiler: clang++
cmake-args: -DMZ_CODE_COVERAGE=ON -DMZ_DECOMPRESS_ONLY=ON
codecov: ubuntu_clang_decompress_only
packages: llvm-6.0
@ -134,6 +150,7 @@ jobs:
- name: Ubuntu Clang OpenSSL
os: ubuntu-latest
compiler: clang
cxx-compiler: clang++
cmake-args: -DMZ_CODE_COVERAGE=ON -DMZ_OPENSSL=ON
codecov: ubuntu_clang_openssl
packages: llvm-6.0
@ -151,6 +168,7 @@ jobs:
- name: Windows GCC
os: windows-latest
compiler: gcc
cxx-compiler: g++
# Don't use find_package for 3rd party libraries which are installed incorrectly on GitHub CI instances
cmake-args: -DMZ_CODE_COVERAGE=ON -DMZ_FORCE_FETCH_LIBS=ON -G Ninja
codecov: windows_gcc
@ -207,6 +225,7 @@ jobs:
cmake ${{ matrix.build-src-dir || '.' }} -DMZ_BUILD_TESTS=ON -DMZ_BUILD_UNIT_TESTS=ON -DCMAKE_BUILD_TYPE=Release ${{ matrix.cmake-args }}
env:
CC: ${{ matrix.compiler }}
CXX: ${{ matrix.cxx-compiler }}
CFLAGS: ${{ matrix.cflags }}
LDFLAGS: ${{ matrix.ldflags }}

View file

@ -786,18 +786,12 @@ if(MZ_BUILD_TESTS)
if(NOT SKIP_INSTALL_BINARIES AND NOT SKIP_INSTALL_ALL)
install(TARGETS minizip_cmd RUNTIME DESTINATION "bin")
endif()
add_executable(test_cmd test/test.c test/test.h)
target_compile_definitions(test_cmd PRIVATE ${STDLIB_DEF} ${MINIZIP_DEF})
if(MZ_COMPAT)
target_compile_definitions(test_cmd PRIVATE -DHAVE_COMPAT)
endif()
target_include_directories(test_cmd PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(test_cmd ${PROJECT_NAME})
endif()
if(MZ_BUILD_TESTS AND MZ_BUILD_UNIT_TESTS)
enable_testing()
add_subdirectory(test)
# Can't disable zlib testing so ctest tries to run zlib example app
if(MZ_ZLIB AND NOT MZ_LIBCOMP AND NOT ZLIB_FOUND)
@ -811,8 +805,6 @@ if(MZ_BUILD_TESTS AND MZ_BUILD_UNIT_TESTS)
set(TEST_TEMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary)
add_test(NAME test_cmd COMMAND test_cmd WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
function(create_compress_tests EXTRA_NAME EXTRA_ARGS)
if(MZ_DECOMPRESS_ONLY)
return()

68
test/CMakeLists.txt Normal file
View file

@ -0,0 +1,68 @@
cmake_minimum_required(VERSION 3.12)
include(FetchContent)
enable_language(CXX)
if(NOT TARGET GTest::GTest)
# Prevent overriding the parent project's compiler/linker settings for Windows
set(gtest_force_shared_crt ON CACHE BOOL
"Use shared (DLL) run-time lib even when Google Test is built as static lib." FORCE)
# Allow specifying alternative Google test repository
if(NOT DEFINED GTEST_REPOSITORY)
set(GTEST_REPOSITORY https://github.com/google/googletest.git)
endif()
if(NOT DEFINED GTEST_TAG)
# Use older version of Google test to support older versions of GCC
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS_EQUAL 5.3)
set(GTEST_TAG release-1.10.0)
else()
set(GTEST_TAG release-1.11.0)
endif()
endif()
# Fetch Google test source code from official repository
FetchContent_Declare(googletest
GIT_REPOSITORY ${GTEST_REPOSITORY}
GIT_TAG ${GTEST_TAG})
FetchContent_GetProperties(googletest)
if(NOT googletest_POPULATED)
FetchContent_Populate(googletest)
add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
add_library(GTest::GTest ALIAS gtest)
endif()
set(TEST_SRCS
test_crypt.cc
test_encoding.cc
test_path.cc
test_stream.cc
test_stream_crypt.cc
)
if(NOT MZ_COMPRESS_ONLY AND NOT MZ_DECOMPRESS_ONLY)
if(MZ_COMPAT)
list(APPEND TEST_SRCS test_compat.cc)
endif()
list(APPEND TEST_SRCS test_stream_compress.cc)
endif()
add_executable(gtest_minizip test_main.cc ${TEST_SRCS})
target_compile_definitions(gtest_minizip PRIVATE ${STDLIB_DEF} ${MINIZIP_DEF})
target_include_directories(gtest_minizip PRIVATE
${CMAKE_SOURCE_DIR}
${CMAKE_BINARY_DIR})
target_link_libraries(gtest_minizip MINIZIP::minizip GTest::GTest)
if(MSVC)
set_target_properties(gtest_minizip PROPERTIES
VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
endif()
add_test(NAME gtest_minizip
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:gtest_minizip>
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})

File diff suppressed because it is too large Load diff

View file

@ -1,28 +0,0 @@
#ifndef _MZ_TEST_H
#define _MZ_TEST_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
int32_t test_stream_bzip(void);
int32_t test_stream_pkcrypt(void);
int32_t test_stream_wzaes(void);
int32_t test_stream_zlib(void);
int32_t test_stream_zlib_mem(void);
int32_t test_stream_find(void);
int32_t test_stream_find_reverse(void);
int32_t test_crypt_sha(void);
int32_t test_crypt_aes(void);
int32_t test_crypt_hmac(void);
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

304
test/test_compat.cc Normal file
View file

@ -0,0 +1,304 @@
/* test_compat.cc - Test compatibility layer
part of the minizip-ng project
Copyright (C) 2018-2022 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_os.h"
#include "mz_zip.h"
#include "mz_compat.h"
#include <gtest/gtest.h>
#ifdef HAVE_ZLIB
static void test_zip_compat(zipFile zip, const char *filename, int32_t level) {
int32_t err = ZIP_OK;
zip_fileinfo file_info;
const char *buffer = "test data";
memset(&file_info, 0, sizeof(file_info));
file_info.dosDate = mz_zip_time_t_to_dos_date(1588561637);
EXPECT_EQ(err = zipOpenNewFileInZip(zip, filename, &file_info, NULL, 0, NULL, 0, "test local comment",
Z_DEFLATED, level), ZIP_OK)
<< "failed to open new file in zip (err: " << err << ")";
if (err != ZIP_OK)
return;
EXPECT_EQ(err = zipWriteInFileInZip(zip, buffer, (uint32_t)strlen(buffer)), ZIP_OK)
<< "failed to write to file in zip (err: " << err << ")";
EXPECT_EQ(err = zipCloseFileInZip(zip), ZIP_OK)
<< "failed to close file in zip (err: " << err << ")";
}
TEST(compat, zip) {
zipFile zip;
zip = zipOpen64("compat.zip", APPEND_STATUS_CREATE);
ASSERT_NE(zip, nullptr) << "cannot create test zip file";
test_zip_compat(zip, "test.txt", 1);
test_zip_compat(zip, "test2.txt", 0);
zipClose(zip, "test global comment");
}
static void test_unzip_compat(unzFile unzip) {
unz_global_info64 global_info64;
unz_global_info global_info;
unz_file_info64 file_info64;
unz_file_info file_info;
unz_file_pos file_pos;
int32_t err = UNZ_OK;
int32_t bytes_read = 0;
char comment[120];
char filename[120];
char buffer[120];
const char *test_data = "test data";
memset(&file_info, 0, sizeof(file_info));
memset(&file_info64, 0, sizeof(file_info64));
memset(&global_info, 0, sizeof(global_info));
memset(&global_info64, 0, sizeof(global_info64));
comment[0] = 0;
filename[0] = 0;
EXPECT_EQ(err = unzGetGlobalComment(unzip, comment, sizeof(comment)), UNZ_OK)
<< "global comment (err: " << err << ")";
EXPECT_STREQ(comment, "test global comment");
EXPECT_EQ(err = unzGetGlobalInfo(unzip, &global_info), UNZ_OK)
<< "global info (err: " << err << ")";
EXPECT_EQ(err = unzGetGlobalInfo64(unzip, &global_info64), UNZ_OK)
<< "global info l info 64-bit (err: " << err << ")";
EXPECT_EQ(global_info.number_entry, 2)
<< "invalid number of entries";
EXPECT_EQ(global_info64.number_entry, 2)
<< "invalid number of entries 64-bit";
EXPECT_EQ(global_info.number_disk_with_CD, 0)
<< "invalid disk with cd";
EXPECT_EQ(global_info64.number_disk_with_CD, 0)
<< "invalid disk with cd 64-bit";
EXPECT_EQ(err = unzLocateFile(unzip, "test.txt", (unzFileNameComparer)(void *)1), UNZ_OK)
<< "cannot locate test file (err: " << err << ")";
EXPECT_EQ(err = unzGoToFirstFile(unzip), UNZ_OK);
if (err != UNZ_OK)
return;
EXPECT_EQ(err = unzGetCurrentFileInfo64(unzip, &file_info64, filename, sizeof(filename), NULL, 0, NULL, 0), UNZ_OK)
<< "failed to get current file info 64-bit (err: " << err << ")";
EXPECT_EQ(err = unzOpenCurrentFile(unzip), UNZ_OK)
<< "failed to open current file (err: " << err << ")";
EXPECT_EQ(bytes_read = unzReadCurrentFile(unzip, buffer, sizeof(buffer)), (int32_t)strlen(test_data))
<< "failed to read zip entry data (err: " << err << ")";
EXPECT_EQ(unzEndOfFile(unzip), 1)
<< "end of zip not reported correctly";
EXPECT_EQ(err = unzCloseCurrentFile(unzip), UNZ_OK)
<< "failed to close current file (err: " << err << ")";
EXPECT_EQ(unztell(unzip), bytes_read)
<< "unzip position not reported correctly";
EXPECT_EQ(err = unzGoToNextFile(unzip), UNZ_OK);
if (err != UNZ_OK)
return;
comment[0] = 0;
EXPECT_EQ(err = unzGetCurrentFileInfo(unzip, &file_info, filename, sizeof(filename), NULL, 0, comment, sizeof(comment)), UNZ_OK)
<< "failed to get current file info (err: " << err << ")";
EXPECT_STREQ(comment, "test local comment");
EXPECT_EQ(err = unzGetFilePos(unzip, &file_pos), UNZ_OK)
<< "unexpected file position (err: " << err << ")";
EXPECT_EQ(file_pos.num_of_file, 1)
<< "invalid file position";
EXPECT_GT(unzGetOffset(unzip), 0)
<< "invalid offset";
EXPECT_EQ(err = unzSeek64(unzip, 0, SEEK_SET), UNZ_OK)
<< "cannot seek to beginning (err: " << err << ")";
EXPECT_EQ(err = unzGoToNextFile(unzip), UNZ_END_OF_LIST_OF_FILE)
<< "failed to reach end of list of files (err: " << err << ")";
EXPECT_EQ(err = unzSeek64(unzip, 0, SEEK_SET), UNZ_PARAMERROR)
<< "cannot seek to beginning (err: " << err << ")";
unzCloseCurrentFile(unzip);
}
#ifndef MZ_FILE32_API
# ifndef NO_FSEEKO
# define ftello64 ftello
# define fseeko64 fseeko
# elif defined(_MSC_VER) && (_MSC_VER >= 1400)
# define ftello64 _ftelli64
# define fseeko64 _fseeki64
# endif
#endif
#ifndef ftello64
# define ftello64 ftell
#endif
#ifndef fseeko64
# define fseeko64 fseek
#endif
static void *ZCALLBACK fopen_file_func(void *opaque, const char *filename, int mode) {
FILE* file = NULL;
const char* mode_fopen = NULL;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
mode_fopen = "rb";
else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
mode_fopen = "r+b";
else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
mode_fopen = "wb";
if ((filename != NULL) && (mode_fopen != NULL))
file = fopen(filename, mode_fopen);
return file;
}
static unsigned long ZCALLBACK fread_file_func(void *opaque, void *stream, void *buf, unsigned long size) {
return (unsigned long)fread(buf, 1, (size_t)size, (FILE *)stream);
}
static unsigned long ZCALLBACK fwrite_file_func(void *opaque, void *stream, const void *buf, unsigned long size) {
return (unsigned long)fwrite(buf, 1, (size_t)size, (FILE *)stream);
}
static long ZCALLBACK ftell_file_func(void *opaque, void *stream) {
return ftell((FILE *)stream);
}
static ZPOS64_T ZCALLBACK ftell64_file_func(void *opaque, void *stream) {
return ftello64((FILE *)stream);
}
static long ZCALLBACK fseek_file_func(void *opaque, void *stream, unsigned long offset, int origin) {
int fseek_origin = 0;
long ret = 0;
switch (origin)
{
case ZLIB_FILEFUNC_SEEK_CUR:
fseek_origin = SEEK_CUR;
break;
case ZLIB_FILEFUNC_SEEK_END:
fseek_origin = SEEK_END;
break;
case ZLIB_FILEFUNC_SEEK_SET:
fseek_origin = SEEK_SET;
break;
default:
return -1;
}
if (fseek((FILE *)stream, offset, fseek_origin) != 0)
ret = -1;
return ret;
}
static long ZCALLBACK fseek64_file_func(void *opaque, void *stream, ZPOS64_T offset, int origin) {
int fseek_origin = 0;
long ret = 0;
switch (origin)
{
case ZLIB_FILEFUNC_SEEK_CUR:
fseek_origin = SEEK_CUR;
break;
case ZLIB_FILEFUNC_SEEK_END:
fseek_origin = SEEK_END;
break;
case ZLIB_FILEFUNC_SEEK_SET:
fseek_origin = SEEK_SET;
break;
default:
return -1;
}
if (fseeko64((FILE *)stream, offset, fseek_origin) != 0)
ret = -1;
return ret;
}
static int ZCALLBACK fclose_file_func(void *opaque, void *stream) {
return fclose((FILE *)stream);
}
static int ZCALLBACK ferror_file_func(void *opaque, void *stream) {
return ferror((FILE *)stream);
}
void fill_ioapi32_filefunc(zlib_filefunc_def *pzlib_filefunc_def) {
pzlib_filefunc_def->zopen_file = fopen_file_func;
pzlib_filefunc_def->zread_file = fread_file_func;
pzlib_filefunc_def->zwrite_file = fwrite_file_func;
pzlib_filefunc_def->ztell_file = ftell_file_func;
pzlib_filefunc_def->zseek_file = fseek_file_func;
pzlib_filefunc_def->zclose_file = fclose_file_func;
pzlib_filefunc_def->zerror_file = ferror_file_func;
pzlib_filefunc_def->opaque = NULL;
}
void fill_ioapi64_filefunc(zlib_filefunc64_def *pzlib_filefunc_def) {
pzlib_filefunc_def->zopen64_file = (open64_file_func)fopen_file_func;
pzlib_filefunc_def->zread_file = fread_file_func;
pzlib_filefunc_def->zwrite_file = fwrite_file_func;
pzlib_filefunc_def->ztell64_file = ftell64_file_func;
pzlib_filefunc_def->zseek64_file = fseek64_file_func;
pzlib_filefunc_def->zclose_file = fclose_file_func;
pzlib_filefunc_def->zerror_file = ferror_file_func;
pzlib_filefunc_def->opaque = NULL;
}
TEST(compat, unzip) {
unzFile unzip;
unzip = unzOpen("compat.zip");
ASSERT_NE(unzip, nullptr) << "cannot open test zip file";
test_unzip_compat(unzip);
unzClose(unzip);
}
TEST(compat, unzip32) {
unzFile unzip;
zlib_filefunc_def zlib_filefunc_def;
fill_ioapi32_filefunc(&zlib_filefunc_def);
unzip = unzOpen2("compat.zip", &zlib_filefunc_def);
ASSERT_NE(unzip, nullptr) << "cannot open test zip file";
test_unzip_compat(unzip);
unzClose(unzip);
}
TEST(compat, unzip64) {
unzFile unzip;
zlib_filefunc64_def zlib_filefunc_def;
fill_ioapi64_filefunc(&zlib_filefunc_def);
unzip = unzOpen2_64("compat.zip", &zlib_filefunc_def);
ASSERT_NE(unzip, nullptr) << "cannot open test zip file";
test_unzip_compat(unzip);
unzClose(unzip);
}
#endif

221
test/test_crypt.cc Normal file
View file

@ -0,0 +1,221 @@
/* test_crypt.cc - Test cryptography implementation
part of the minizip-ng project
Copyright (C) 2018-2022 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_os.h"
#include "mz_crypt.h"
#include <gtest/gtest.h>
#include <stdio.h> /* printf, snprintf */
#ifndef MZ_ZIP_NO_CRYPTO
static const char *hash_test_string = "the quick and lazy fox did his thang";
static void convert_buffer_to_hex_string(uint8_t *buf, int32_t buf_size, char *hex_string, int32_t max_hex_string) {
int32_t p = 0;
int32_t i = 0;
if (max_hex_string > 0)
hex_string[0] = 0;
for (i = 0, p = 0; i < (int32_t)buf_size && p < max_hex_string; i += 1, p += 2)
snprintf(hex_string + p, max_hex_string - p, "%02x", buf[i]);
if (p < max_hex_string)
hex_string[p] = 0;
}
TEST(crypt, sha1) {
void *sha1 = NULL;
uint8_t hash1[MZ_HASH_SHA1_SIZE];
char computed_hash[256];
memset(hash1, 0, sizeof(hash1));
mz_crypt_sha_create(&sha1);
mz_crypt_sha_set_algorithm(sha1, MZ_HASH_SHA1);
mz_crypt_sha_begin(sha1);
mz_crypt_sha_update(sha1, hash_test_string, (int32_t)strlen(hash_test_string));
mz_crypt_sha_end(sha1, hash1, sizeof(hash1));
mz_crypt_sha_delete(&sha1);
convert_buffer_to_hex_string(hash1, sizeof(hash1), computed_hash, sizeof(computed_hash));
EXPECT_STREQ(computed_hash, "3efb8392b6cd8e14bd76bd08081521dc73df418c");
}
TEST(crypt, sha224) {
void *sha224 = NULL;
uint8_t hash224[MZ_HASH_SHA224_SIZE];
char computed_hash[256];
memset(hash224, 0, sizeof(hash224));
mz_crypt_sha_create(&sha224);
mz_crypt_sha_set_algorithm(sha224, MZ_HASH_SHA224);
mz_crypt_sha_begin(sha224);
mz_crypt_sha_update(sha224, hash_test_string, (int32_t)strlen(hash_test_string));
mz_crypt_sha_end(sha224, hash224, sizeof(hash224));
mz_crypt_sha_delete(&sha224);
convert_buffer_to_hex_string(hash224, sizeof(hash224), computed_hash, sizeof(computed_hash));
EXPECT_STREQ(computed_hash, "9e444f5f0b6582a923bd48696155f4a2f0d914e044cb64b8729a6600");
}
TEST(crypt, sha256) {
void *sha256 = NULL;
uint8_t hash256[MZ_HASH_SHA256_SIZE];
char computed_hash[256];
memset(hash256, 0, sizeof(hash256));
mz_crypt_sha_create(&sha256);
mz_crypt_sha_set_algorithm(sha256, MZ_HASH_SHA256);
mz_crypt_sha_begin(sha256);
mz_crypt_sha_update(sha256, hash_test_string, (int32_t)strlen(hash_test_string));
mz_crypt_sha_end(sha256, hash256, sizeof(hash256));
mz_crypt_sha_delete(&sha256);
convert_buffer_to_hex_string(hash256, sizeof(hash256), computed_hash, sizeof(computed_hash));
EXPECT_STREQ(computed_hash, "7a31ea0848525f7ebfeec9ee532bcc5d6d26772427e097b86cf440a56546541c");
}
TEST(crypt, sha384) {
void *sha384 = NULL;
uint8_t hash384[MZ_HASH_SHA384_SIZE];
char computed_hash[256];
memset(hash384, 0, sizeof(hash384));
mz_crypt_sha_create(&sha384);
mz_crypt_sha_set_algorithm(sha384, MZ_HASH_SHA384);
mz_crypt_sha_begin(sha384);
mz_crypt_sha_update(sha384, hash_test_string, (int32_t)strlen(hash_test_string));
mz_crypt_sha_end(sha384, hash384, sizeof(hash384));
mz_crypt_sha_delete(&sha384);
convert_buffer_to_hex_string(hash384, sizeof(hash384), computed_hash, sizeof(computed_hash));
EXPECT_STREQ(computed_hash, "e1e42e5977965bb3621231a5df3a1e83c471fa91fde33b6a30c8c4fa0d8be29ba7171c7c9487db91e9ee7e85049f7b41");
}
TEST(crypt, sha512) {
void *sha512 = NULL;
uint8_t hash512[MZ_HASH_SHA512_SIZE];
char computed_hash[256];
memset(hash512, 0, sizeof(hash512));
mz_crypt_sha_create(&sha512);
mz_crypt_sha_set_algorithm(sha512, MZ_HASH_SHA512);
mz_crypt_sha_begin(sha512);
mz_crypt_sha_update(sha512, hash_test_string, (int32_t)strlen(hash_test_string));
mz_crypt_sha_end(sha512, hash512, sizeof(hash512));
mz_crypt_sha_delete(&sha512);
convert_buffer_to_hex_string(hash512, sizeof(hash512), computed_hash, sizeof(computed_hash));
EXPECT_STREQ(computed_hash, "6627e7643ee7ce633e03f52d22329c3a32597364247c5275d4369985e1518626da46f595ad327667346479d246359b8b381af791ce2ac8c53a4788050eea11fe");
}
TEST(crypt, aes) {
void *aes = NULL;
const char *key = "awesomekeythisis";
const char *test = "youknowitsogrowi";
char computed_hash[320];
int32_t key_length = 0;
int32_t test_length = 0;
uint8_t buf[120];
uint8_t hash[MZ_HASH_SHA256_SIZE];
memset(hash, 0, sizeof(hash));
key_length = (int32_t)strlen(key);
test_length = (int32_t)strlen(test);
strncpy((char *)buf, test, sizeof(buf));
convert_buffer_to_hex_string(buf, test_length, computed_hash, sizeof(computed_hash));
mz_crypt_aes_create(&aes);
mz_crypt_aes_set_mode(aes, MZ_AES_ENCRYPTION_MODE_256);
mz_crypt_aes_set_encrypt_key(aes, key, key_length);
mz_crypt_aes_encrypt(aes, buf, test_length);
mz_crypt_aes_delete(&aes);
convert_buffer_to_hex_string(buf, test_length, computed_hash, sizeof(computed_hash));
mz_crypt_aes_create(&aes);
mz_crypt_aes_set_mode(aes, MZ_AES_ENCRYPTION_MODE_256);
mz_crypt_aes_set_decrypt_key(aes, key, key_length);
mz_crypt_aes_decrypt(aes, buf, test_length);
mz_crypt_aes_delete(&aes);
convert_buffer_to_hex_string(buf, test_length, computed_hash, sizeof(computed_hash));
EXPECT_STREQ((char *)buf, test);
}
TEST(crypt, hmac_sha1) {
void *hmac;
const char *key = "hm123";
const char *test = "12345678";
char computed_hash[256];
uint8_t hash1[MZ_HASH_SHA1_SIZE];
mz_crypt_hmac_create(&hmac);
mz_crypt_hmac_set_algorithm(hmac, MZ_HASH_SHA1);
mz_crypt_hmac_init(hmac, key, (int32_t)strlen(key));
mz_crypt_hmac_update(hmac, test, (int32_t)strlen(test));
mz_crypt_hmac_end(hmac, hash1, sizeof(hash1));
mz_crypt_hmac_delete(&hmac);
convert_buffer_to_hex_string(hash1, sizeof(hash1), computed_hash, sizeof(computed_hash));
EXPECT_STREQ(computed_hash, "c785a02ff303c886c304d9a4c06073dfe4c24aa9");
}
TEST(crypt, hmac_sha256) {
void *hmac;
const char *key = "hm123";
const char *test = "12345678";
char computed_hash[256];
uint8_t hash256[MZ_HASH_SHA256_SIZE];
mz_crypt_hmac_create(&hmac);
mz_crypt_hmac_set_algorithm(hmac, MZ_HASH_SHA256);
mz_crypt_hmac_init(hmac, key, (int32_t)strlen(key));
mz_crypt_hmac_update(hmac, test, (int32_t)strlen(test));
mz_crypt_hmac_end(hmac, hash256, sizeof(hash256));
mz_crypt_hmac_delete(&hmac);
convert_buffer_to_hex_string(hash256, sizeof(hash256), computed_hash, sizeof(computed_hash));
EXPECT_STREQ(computed_hash, "fb22a9c715a47a06bad4f6cee9badc31c921562f5d6b24adf2be009f73181f7a");
}
#ifdef HAVE_WZAES
TEST(crypt, pbkdf2) {
int32_t iteration_count = 1000;
uint8_t key[MZ_HASH_SHA1_SIZE];
char key_hex[256];
const char *password = "passwordpasswordpasswordpassword";
const char *salt = "8F3472E4EA57F56E36F30246DC22C173";
EXPECT_EQ(mz_crypt_pbkdf2((uint8_t *)password, (int32_t)strlen(password),
(uint8_t *)salt, (int32_t)strlen(salt), iteration_count, key, sizeof(key)), MZ_OK);
convert_buffer_to_hex_string(key, sizeof(key), key_hex, sizeof(key_hex));
EXPECT_STREQ(key_hex, "852c7b71a104aaa8d8996c840c3d4d5d0db780aa");
}
#endif
#endif

26
test/test_encoding.cc Normal file
View file

@ -0,0 +1,26 @@
/* test_encoding.cc - Test string encoding
part of the minizip-ng project
Copyright (C) 2018-2022 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_os.h"
#include <gtest/gtest.h>
TEST(os, utf8_unicode_string) {
const char *test_string = "Heiz<EFBFBD>lr<EFBFBD>cksto<EFBFBD>abd<EFBFBD>mpfung";
uint8_t *utf8_string = mz_os_utf8_string_create(test_string, MZ_ENCODING_CODEPAGE_950);
ASSERT_NE(utf8_string, nullptr);
#if defined(_WIN32)
wchar_t *unicode_string = mz_os_unicode_string_create((const char *)utf8_string, MZ_ENCODING_UTF8);
ASSERT_NE(unicode_string, nullptr);
mz_os_unicode_string_delete(&unicode_string);
#endif
mz_os_utf8_string_delete(&utf8_string);
}

11
test/test_main.cc Normal file
View file

@ -0,0 +1,11 @@
/* test_main.cc - Main entry point for test framework */
#include <stdio.h>
#include "gtest/gtest.h"
GTEST_API_ int main(int argc, char **argv) {
printf("Running main() from %s\n", __FILE__);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

61
test/test_path.cc Normal file
View file

@ -0,0 +1,61 @@
/* test_path.cc - Test path functionality
part of the minizip-ng project
Copyright (C) 2018-2022 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_os.h"
#include <gtest/gtest.h>
struct resolve_path_param {
const char *path;
const char *expected_path;
friend std::ostream &operator<<(std::ostream &os, const resolve_path_param &param) {
return os << "path: " << param.path;
}
};
constexpr resolve_path_param resolve_path_tests[] = {
{ "c:\\test\\.", "c:\\test\\" },
{ "c:\\test\\.\\", "c:\\test\\" },
{ "c:\\test\\.\\.", "c:\\test\\" },
{ "c:\\test\\..", "c:\\" },
{ "c:\\test\\..\\", "c:\\" },
{ "c:\\test\\.\\..", "c:\\" },
{ "c:\\test\\.\\\\..", "c:\\" },
{ ".", "." },
{ ".\\", "" },
{ "..", "" },
{ "..\\", "" },
{ ".\\test\\123", "test\\123" },
{ ".\\..\\test\\123", "test\\123" },
{ "..\\..\\test\\123", "test\\123" },
{ "test\\.abc.txt", "test\\.abc.txt" },
{ "c:\\test\\123\\.\\abc.txt", "c:\\test\\123\\abc.txt" },
{ "c:\\test\\123\\..\\abc.txt", "c:\\test\\abc.txt" },
{ "c:\\test\\123\\..\\..\\abc.txt", "c:\\abc.txt" },
{ "c:\\test\\123\\..\\..\\..\\abc.txt", "abc.txt" },
{ "c:\\test\\123\\..\\.\\..\\abc.txt", "c:\\abc.txt" },
};
class path_resolve : public ::testing::TestWithParam<resolve_path_param> {
};
INSTANTIATE_TEST_SUITE_P(os, path_resolve, testing::ValuesIn(resolve_path_tests));
TEST_P(path_resolve, os) {
const auto &param = GetParam();
char output[256];
memset(output, 'z', sizeof(output));
mz_path_resolve(param.path, output, sizeof(output));
EXPECT_STREQ(output, param.expected_path);
}

235
test/test_stream.cc Normal file
View file

@ -0,0 +1,235 @@
/* test_stream.cc - Test basic streaming functionality
part of the minizip-ng project
Copyright (C) 2018-2022 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_strm.h"
#include "mz_strm_mem.h"
#include <gtest/gtest.h>
typedef void (*stream_test_cb)(const char *name, int32_t count, const uint8_t *find, int32_t find_size,
mz_stream_find_cb find_cb);
static void test_stream_find_begin(const char *name, int32_t count, const uint8_t *find, int32_t find_size,
mz_stream_find_cb find_cb) {
void *mem_stream = NULL;
int32_t i = 0;
int32_t x = 0;
int64_t last_pos = 0;
int64_t position = 0;
MZ_UNUSED(name);
ASSERT_GT(find_size, 0);
ASSERT_NE(find, nullptr);
ASSERT_NE(find_cb, nullptr);
for (i = 0; i < count; i++) {
mz_stream_mem_create(&mem_stream);
mz_stream_mem_open(mem_stream, NULL, MZ_OPEN_MODE_CREATE);
/* Find when the needle is at the beginning of the stream */
for (x = 0; x < i && x < find_size; x++)
mz_stream_write_uint8(mem_stream, find[x]);
while (x++ < i)
mz_stream_write_uint8(mem_stream, 0);
if (find_cb == mz_stream_find)
mz_stream_seek(mem_stream, 0, MZ_SEEK_SET);
find_cb(mem_stream, (const void *)find, find_size, i, &position);
/* Should always find at the start of the stream if entire needle
was written to stream */
EXPECT_EQ(position, (i < find_size) ? -1 : 0)
<< "name: " << name << std::endl
<< "find_size: " << find_size << std::endl
<< "index: " << i << std::endl;
mz_stream_seek(mem_stream, 0, MZ_SEEK_END);
last_pos = mz_stream_tell(mem_stream);
mz_stream_mem_delete(&mem_stream);
/* Shouldn't be at the end of the stream */
EXPECT_NE(position, last_pos);
}
}
static void test_stream_find_end(const char *name, int32_t count, const uint8_t *find, int32_t find_size,
mz_stream_find_cb find_cb) {
void *mem_stream = NULL;
int32_t i = 0;
int32_t x = 0;
int32_t y = 0;
int64_t last_pos = 0;
int64_t position = 0;
MZ_UNUSED(name);
ASSERT_GT(find_size, 0);
ASSERT_NE(find, nullptr);
ASSERT_NE(find_cb, nullptr);
for (i = 0; i < count; i++) {
mz_stream_mem_create(&mem_stream);
mz_stream_mem_open(mem_stream, NULL, MZ_OPEN_MODE_CREATE);
/* Find when the needle is at the end of the stream */
for (x = 0; x < i - find_size; x++)
mz_stream_write_uint8(mem_stream, 0);
for (y = 0; x + y < i && y < find_size; y++)
mz_stream_write_uint8(mem_stream, find[y]);
if (find_cb == mz_stream_find)
mz_stream_seek(mem_stream, 0, MZ_SEEK_SET);
find_cb(mem_stream, (const void *)find, find_size, i, &position);
/* Should always find after zeros if entire needle
was written to stream */
EXPECT_EQ(position, (i < find_size) ? -1 : (i - find_size))
<< "name: " << name << std::endl
<< "find_size: " << find_size << std::endl
<< "index: " << i << std::endl;
mz_stream_seek(mem_stream, 0, MZ_SEEK_END);
last_pos = mz_stream_tell(mem_stream);
mz_stream_mem_delete(&mem_stream);
/* Shouldn't be at the end of the stream */
EXPECT_NE(position, last_pos);
}
}
static void test_stream_find_middle(const char *name, int32_t count, const uint8_t *find, int32_t find_size,
mz_stream_find_cb find_cb) {
void *mem_stream = NULL;
int32_t i = 0;
int32_t x = 0;
int64_t last_pos = 0;
int64_t position = 0;
MZ_UNUSED(name);
ASSERT_GT(find_size, 0);
ASSERT_NE(find, nullptr);
ASSERT_NE(find_cb, nullptr);
for (i = 0; i < count; i++) {
mz_stream_mem_create(&mem_stream);
mz_stream_mem_open(mem_stream, NULL, MZ_OPEN_MODE_CREATE);
/* Find when the neddle is in the middle of the stream */
for (x = 0; x < i; x++)
mz_stream_write_uint8(mem_stream, 0);
mz_stream_write(mem_stream, find, find_size);
for (x = 0; x < i; x++)
mz_stream_write_uint8(mem_stream, 0);
if (find_cb == mz_stream_find)
mz_stream_seek(mem_stream, 0, MZ_SEEK_SET);
find_cb(mem_stream, (const void *)find, find_size, i + find_size+ i, &position);
/* Should always find after initial set of zeros */
EXPECT_EQ(position, i)
<< "name: " << name << std::endl
<< "find_size: " << find_size << std::endl
<< "index: " << i << std::endl;
mz_stream_seek(mem_stream, 0, MZ_SEEK_END);
last_pos = mz_stream_tell(mem_stream);
mz_stream_mem_delete(&mem_stream);
/* Shouldn't be at the end of the stream */
EXPECT_NE(position, last_pos);
}
}
static void test_stream_find_middle_odd(const char *name, int32_t count, const uint8_t *find, int32_t find_size,
mz_stream_find_cb find_cb) {
void *mem_stream = NULL;
int32_t i = 0;
int32_t x = 0;
int64_t last_pos = 0;
int64_t position = 0;
MZ_UNUSED(name);
ASSERT_GT(find_size, 0);
ASSERT_NE(find, nullptr);
ASSERT_NE(find_cb, nullptr);
for (i = 0; i < count; i++) {
mz_stream_mem_create(&mem_stream);
mz_stream_mem_open(mem_stream, NULL, MZ_OPEN_MODE_CREATE);
/* Find when the needle is in the middle of the stream */
for (x = 0; x < i; x++)
mz_stream_write_uint8(mem_stream, 0);
mz_stream_write(mem_stream, find, find_size);
for (x = 0; x < i + 1; x++)
mz_stream_write_uint8(mem_stream, 0);
if (find_cb == mz_stream_find)
mz_stream_seek(mem_stream, 0, MZ_SEEK_SET);
find_cb(mem_stream, (const void *)find, find_size, i + find_size + i + 1, &position);
/* Should always find after initial set of zeros */
EXPECT_EQ(position, i)
<< "name: " << name << std::endl
<< "find_size: " << find_size << std::endl
<< "index: " << i << std::endl;
mz_stream_seek(mem_stream, 0, MZ_SEEK_END);
last_pos = mz_stream_tell(mem_stream);
mz_stream_mem_delete(&mem_stream);
/* Shouldn't be at the end of the stream */
EXPECT_NE(position, last_pos);
}
}
struct stream_find_param {
const char *name;
stream_test_cb test_cb;
mz_stream_find_cb find_cb;
friend std::ostream &operator<<(std::ostream &os, const stream_find_param &param) {
return os << "name: " << param.name;
}
};
constexpr stream_find_param find_tests[] = {
{ "begin", test_stream_find_begin, mz_stream_find },
{ "begin reverse", test_stream_find_begin, mz_stream_find_reverse },
{ "end", test_stream_find_end, mz_stream_find },
{ "end reverse", test_stream_find_end, mz_stream_find_reverse },
{ "middle", test_stream_find_middle, mz_stream_find },
{ "middle reverse", test_stream_find_middle, mz_stream_find_reverse },
{ "middle odd", test_stream_find_middle_odd, mz_stream_find },
{ "middle odd reverse", test_stream_find_middle_odd, mz_stream_find_reverse }
};
class stream_find : public ::testing::TestWithParam<stream_find_param> {
};
INSTANTIATE_TEST_SUITE_P(stream, stream_find, testing::ValuesIn(find_tests));
TEST_P(stream_find, find) {
const auto &param = GetParam();
const char *find = "0123456789";
int32_t c = 1;
for (c = 1; c < (int32_t)strlen(find); c += 1)
param.test_cb(param.name, 2096, (const uint8_t *)find, c, param.find_cb);
}

View file

@ -0,0 +1,143 @@
/* test_stream_compress.cc - Test basic compression
part of the minizip-ng project
Copyright (C) 2018-2022 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_os.h"
#include "mz_strm.h"
#include "mz_strm_mem.h"
#include "mz_strm_os.h"
#ifdef HAVE_BZIP2
# include "mz_strm_bzip.h"
#endif
#ifdef HAVE_LZMA
# include "mz_strm_lzma.h"
#endif
#ifdef HAVE_ZLIB
# include "mz_strm_zlib.h"
#endif
#ifdef HAVE_ZSTD
# include "mz_strm_zstd.h"
#endif
#include <gtest/gtest.h>
static void test_compare_stream_to_end(void *source1, void *source2) {
uint8_t source1_buf[4096];
uint8_t source2_buf[4096];
int32_t source1_read = 0;
int32_t source2_read = 0;
do {
source1_read = mz_stream_read(source1, source1_buf, sizeof(source1_buf));
source2_read = mz_stream_read(source2, source2_buf, sizeof(source2_buf));
EXPECT_EQ(source1_read, source2_read);
if (source1_read <= 0)
break;
EXPECT_EQ(memcmp(source1_buf, source2_buf, source1_read), 0);
} while (1);
}
static void test_compress(const char *method, mz_stream_create_cb create_compress) {
int64_t total_in = 0;
int64_t total_out = 0;
void *org_stream = NULL;
void *compress_stream = NULL;
void *uncompress_stream = NULL;
void *deflate_stream = NULL;
void *inflate_stream = NULL;
/* Open file to be compressed */
mz_stream_os_create(&org_stream);
ASSERT_EQ(mz_stream_os_open(org_stream, "LICENSE", MZ_OPEN_MODE_READ), MZ_OK);
/* Compress data into memory stream */
mz_stream_mem_create(&compress_stream);
ASSERT_EQ(mz_stream_mem_open(compress_stream, NULL, MZ_OPEN_MODE_CREATE), MZ_OK);
create_compress(&deflate_stream);
mz_stream_set_base(deflate_stream, compress_stream);
/* Copy data from file stream and write to compression stream */
mz_stream_open(deflate_stream, NULL, MZ_OPEN_MODE_WRITE);
mz_stream_copy_stream_to_end(deflate_stream, NULL, org_stream, NULL);
mz_stream_close(deflate_stream);
mz_stream_get_prop_int64(deflate_stream, MZ_STREAM_PROP_TOTAL_IN, &total_in);
EXPECT_EQ(total_in, mz_stream_tell(org_stream));
mz_stream_get_prop_int64(deflate_stream, MZ_STREAM_PROP_TOTAL_OUT, &total_out);
EXPECT_EQ(total_out, mz_stream_tell(compress_stream));
mz_stream_delete(&deflate_stream);
printf("%s compressed from %u to %u\n", method, (uint32_t)total_in, (uint32_t)total_out);
/* Decompress data into memory stream */
mz_stream_mem_create(&uncompress_stream);
ASSERT_EQ(mz_stream_mem_open(uncompress_stream, NULL, MZ_OPEN_MODE_CREATE), MZ_OK);
mz_stream_seek(compress_stream, 0, MZ_SEEK_SET);
create_compress(&inflate_stream);
mz_stream_set_base(inflate_stream, compress_stream);
mz_stream_open(inflate_stream, NULL, MZ_OPEN_MODE_READ);
mz_stream_copy_stream_to_end(uncompress_stream, NULL, inflate_stream, NULL);
mz_stream_close(inflate_stream);
mz_stream_get_prop_int64(inflate_stream, MZ_STREAM_PROP_TOTAL_IN, &total_in);
EXPECT_EQ(total_in, mz_stream_tell(compress_stream));
mz_stream_get_prop_int64(inflate_stream, MZ_STREAM_PROP_TOTAL_OUT, &total_out);
EXPECT_EQ(total_out, mz_stream_tell(uncompress_stream));
mz_stream_delete(&inflate_stream);
printf("%s uncompressed from %u to %u\n", method, (uint32_t)total_in, (uint32_t)total_out);
/* Compare uncompress stream to original file stream */
mz_stream_seek(org_stream, 0, MZ_SEEK_SET);
mz_stream_seek(uncompress_stream, 0, MZ_SEEK_SET);
test_compare_stream_to_end(org_stream, uncompress_stream);
mz_stream_mem_close(uncompress_stream);
mz_stream_mem_delete(&uncompress_stream);
mz_stream_mem_close(compress_stream);
mz_stream_mem_delete(&compress_stream);
mz_stream_os_close(org_stream);
mz_stream_os_delete(&org_stream);
}
#ifdef HAVE_BZIP2
TEST(stream, bzip) {
return test_compress("bzip", mz_stream_bzip_create);
}
#endif
#ifdef HAVE_LZMA
TEST(stream, lzma) {
return test_compress("lzma", mz_stream_lzma_create);
}
#endif
#ifdef HAVE_ZLIB
TEST(stream, zlib) {
return test_compress("zlib", mz_stream_zlib_create);
}
#endif
#ifdef HAVE_ZSTD
TEST(stream, zstd) {
return test_compress("zstd", mz_stream_zstd_create);
}
#endif

116
test/test_stream_crypt.cc Normal file
View file

@ -0,0 +1,116 @@
/* test_stream_crypt.cc - Test encryption stream functionality
part of the minizip-ng project
Copyright (C) 2018-2022 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_strm.h"
#include "mz_strm_os.h"
#include "mz_strm_pkcrypt.h"
#include "mz_strm_wzaes.h"
#include <gtest/gtest.h>
#include <stdio.h> /* printf, snprintf */
#if defined(_MSC_VER) && (_MSC_VER < 1900)
# define snprintf _snprintf
#endif
static void test_encrypt(const char *path, const char *method, mz_stream_create_cb crypt_create, const char *password) {
char org_buf[4096];
char mod_buf[4096];
int32_t read = 0;
int32_t written = 0;
int64_t total_written = 0;
void *out_stream = NULL;
void *in_stream = NULL;
void *crypt_out_stream = NULL;
char encrypt_path[256];
char decrypt_path[256];
snprintf(encrypt_path, sizeof(encrypt_path), "%s.enc.%s", path, method);
snprintf(decrypt_path, sizeof(decrypt_path), "%s.dec.%s", path, method);
/* Read file to encrypt into memory buffer */
mz_stream_os_create(&in_stream);
EXPECT_EQ(mz_stream_os_open(in_stream, path, MZ_OPEN_MODE_READ), MZ_OK);
{
read = mz_stream_os_read(in_stream, org_buf, sizeof(org_buf));
mz_stream_os_close(in_stream);
}
mz_stream_os_delete(&in_stream);
EXPECT_GT(read, 0);
/* Encrypt data to disk */
mz_stream_os_create(&out_stream);
EXPECT_EQ(mz_stream_os_open(out_stream, encrypt_path, MZ_OPEN_MODE_CREATE | MZ_OPEN_MODE_WRITE), MZ_OK);
{
crypt_create(&crypt_out_stream);
mz_stream_set_base(crypt_out_stream, out_stream);
EXPECT_EQ(mz_stream_open(crypt_out_stream, password, MZ_OPEN_MODE_WRITE), MZ_OK);
{
written = mz_stream_write(crypt_out_stream, org_buf, read);
mz_stream_close(crypt_out_stream);
mz_stream_get_prop_int64(crypt_out_stream, MZ_STREAM_PROP_TOTAL_OUT, &total_written);
}
mz_stream_delete(&crypt_out_stream);
mz_stream_os_close(out_stream);
}
mz_stream_os_delete(&out_stream);
EXPECT_GT(written, 0);
/* Decrypt data from disk */
mz_stream_os_create(&in_stream);
EXPECT_EQ(mz_stream_os_open(in_stream, encrypt_path, MZ_OPEN_MODE_READ), MZ_OK);
{
crypt_create(&crypt_out_stream);
mz_stream_set_base(crypt_out_stream, in_stream);
mz_stream_set_prop_int64(crypt_out_stream, MZ_STREAM_PROP_TOTAL_IN_MAX, total_written);
EXPECT_EQ(mz_stream_open(crypt_out_stream, password, MZ_OPEN_MODE_READ), MZ_OK);
{
ASSERT_LE(read, sizeof(mod_buf));
read = mz_stream_read(crypt_out_stream, mod_buf, read);
mz_stream_close(crypt_out_stream);
}
mz_stream_delete(&crypt_out_stream);
mz_stream_os_close(in_stream);
}
mz_stream_os_delete(&in_stream);
EXPECT_GT(read, 0);
/* Write out decrypted contents to disk for debugging */
mz_stream_os_create(&out_stream);
EXPECT_EQ(mz_stream_os_open(out_stream, decrypt_path, MZ_OPEN_MODE_CREATE | MZ_OPEN_MODE_WRITE), MZ_OK);
{
mz_stream_os_write(out_stream, mod_buf, read);
mz_stream_os_close(out_stream);
}
mz_stream_os_delete(&out_stream);
/* Compare original and modified buffers */
EXPECT_EQ(memcmp(org_buf, mod_buf, read), 0);
}
#ifdef HAVE_PKCRYPT
TEST(encrypt, pkcrypt) {
test_encrypt("LICENSE", "pkcrypt", mz_stream_pkcrypt_create, "hello");
}
#endif
#ifdef HAVE_WZAES
TEST(encrypt, aes) {
test_encrypt("LICENSE", "aes", mz_stream_wzaes_create, "hello");
}
#endif