| /* test_stream.cc - Test basic streaming functionality |
| part of the minizip-ng project |
| |
| Copyright (C) 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++) { |
| mem_stream = mz_stream_mem_create(); |
| ASSERT_NE(mem_stream, nullptr); |
| 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++) { |
| mem_stream = mz_stream_mem_create(); |
| ASSERT_NE(mem_stream, nullptr); |
| 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++) { |
| mem_stream = mz_stream_mem_create(); |
| ASSERT_NE(mem_stream, nullptr); |
| 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++) { |
| mem_stream = mz_stream_mem_create(); |
| ASSERT_NE(mem_stream, nullptr); |
| 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 ¶m) { |
| 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 ¶m = 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); |
| } |