/* 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 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 {}; 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); }