From eec10374c51a88f6b5baced5524eda99a10df60a Mon Sep 17 00:00:00 2001 From: Mathis Rosenhauer <rosenhauer@dkrz.de> Date: Tue, 4 Apr 2023 17:08:12 +0200 Subject: [PATCH] Test aec_buffer_seek() --- include/libaec.h.in | 3 + tests/CMakeLists.txt | 3 + tests/Makefile.am | 7 +- tests/check_seeking.c | 232 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 243 insertions(+), 2 deletions(-) create mode 100644 tests/check_seeking.c diff --git a/include/libaec.h.in b/include/libaec.h.in index a38bc70..85b3de3 100644 --- a/include/libaec.h.in +++ b/include/libaec.h.in @@ -160,6 +160,9 @@ LIBAEC_DLL_EXPORTED int aec_decode_end(struct aec_stream *strm); /***************************************************************/ LIBAEC_DLL_EXPORTED int aec_buffer_encode(struct aec_stream *strm); LIBAEC_DLL_EXPORTED int aec_buffer_decode(struct aec_stream *strm); +LIBAEC_DLL_EXPORTED int aec_buffer_seek(struct aec_stream *strm, + size_t byte_offset, + unsigned char bit_offset); #ifdef __cplusplus } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 52d36ff..77f4918 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,6 +6,9 @@ add_test(NAME check_code_options COMMAND check_code_options) add_executable(check_buffer_sizes check_buffer_sizes.c) target_link_libraries(check_buffer_sizes PUBLIC check_aec aec) add_test(NAME check_buffer_sizes COMMAND check_buffer_sizes) +add_executable(check_seeking check_seeking.c) +target_link_libraries(check_seeking PUBLIC check_aec aec) +add_test(NAME check_seeking COMMAND check_seeking) add_executable(check_long_fs check_long_fs.c) target_link_libraries(check_long_fs PUBLIC check_aec aec) add_test(NAME check_long_fs COMMAND check_long_fs) diff --git a/tests/Makefile.am b/tests/Makefile.am index d66304e..f2bfd4d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,13 +1,13 @@ AUTOMAKE_OPTIONS = color-tests AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include TESTS = check_code_options check_buffer_sizes check_long_fs \ -szcomp.sh sampledata.sh +check_seeking szcomp.sh sampledata.sh TEST_EXTENSIONS = .sh CLEANFILES = test.dat test.rz check_LTLIBRARIES = libcheck_aec.la libcheck_aec_la_SOURCES = check_aec.c check_aec.h check_PROGRAMS = check_code_options check_buffer_sizes check_long_fs \ -check_szcomp +check_szcomp check_seeking check_code_options_SOURCES = check_code_options.c check_aec.h \ $(top_builddir)/include/libaec.h @@ -18,6 +18,9 @@ $(top_builddir)/include/libaec.h check_long_fs_SOURCES = check_long_fs.c check_aec.h \ $(top_builddir)/include/libaec.h +check_seeking_SOURCES = check_seeking.c check_aec.h \ +$(top_builddir)/include/libaec.h + check_szcomp_SOURCES = check_szcomp.c $(top_srcdir)/include/szlib.h LDADD = libcheck_aec.la $(top_builddir)/src/libaec.la diff --git a/tests/check_seeking.c b/tests/check_seeking.c new file mode 100644 index 0000000..2cb9d83 --- /dev/null +++ b/tests/check_seeking.c @@ -0,0 +1,232 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "check_aec.h" + +#define BUF_SIZE 1024 * 3 + +void shift_cdata(struct test_state *state, unsigned char *cbuf_unshifted, + int byte_offset, int bit_offset) +{ + struct aec_stream *strm = state->strm; + unsigned char *dst = state->cbuf + byte_offset; + + memset(state->cbuf, 0, state->buf_len); + for (int i = 0; i < strm->avail_in; i++) { + dst[i] |= cbuf_unshifted[i] >> bit_offset; + dst[i + 1] |= cbuf_unshifted[i] << (8 - bit_offset); + } +} + +int encode_decode_large_seek(struct test_state *state) +{ + int status; + int bflags = 0; + int c_len; + size_t to; + char fbase[1024]; + unsigned char *cbuf_unshifted; + struct aec_stream *strm = state->strm; + + strm->avail_in = state->ibuf_len; + strm->avail_out = state->cbuf_len; + strm->next_in = state->ubuf; + strm->next_out = state->cbuf; + + status = aec_encode_init(strm); + if (status != AEC_OK) { + printf("Init failed.\n"); + return 99; + } + if (state->dump) { + char fname[1024 + 4]; + FILE *fp; + snprintf(fbase, sizeof(fbase), "BPS%02iID%iBS%02iRSI%04iFLG%04i", + strm->bits_per_sample, + state->id, + strm->block_size, + strm->rsi, + strm->flags); + snprintf(fname, sizeof(fname), "%s.dat", fbase); + if ((fp = fopen(fname, "wb")) == NULL) { + fprintf(stderr, "ERROR: cannot open dump file %s\n", fname); + return 99; + } + fputc(strm->bits_per_sample, fp); + bflags = strm->block_size >> 8; + if (strm->flags | AEC_DATA_MSB) + bflags |= 0x80; + if (strm->flags | AEC_DATA_SIGNED) + bflags |= 0x40; + if (strm->flags | AEC_DATA_3BYTE) + bflags |= 0x10; + bflags |= 0x20; /* encode */ + fputc(bflags, fp); + fwrite(strm->next_in, strm->avail_in, 1, fp); + fclose(fp); + } + + status = aec_encode(strm, AEC_FLUSH); + if (status != AEC_OK) { + printf("Encode failed.\n"); + return 99; + } + + aec_encode_end(strm); + + if (state->dump) { + char fname[1024 + 3]; + FILE *fp; + snprintf(fname, sizeof(fname), "%s.rz", fbase); + if ((fp = fopen(fname, "wb")) == NULL) { + fprintf(stderr, "ERROR: cannot open dump file %s\n", fname); + return 99; + } + fputc(strm->bits_per_sample, fp); + bflags &= ~0x20; + fputc(bflags, fp); + fwrite(state->cbuf, strm->total_out, 1, fp); + fclose(fp); + } + + cbuf_unshifted = (unsigned char *)malloc(state->cbuf_len); + if (!cbuf_unshifted) { + fprintf(stderr, "Not enough memory.\n"); + return 99; + } + c_len = strm->total_out; + memcpy(cbuf_unshifted, state->cbuf, c_len); + + + for (int byte_offset = 0; byte_offset < 256; byte_offset++) { + for (int bit_offset = 0; bit_offset < 8; bit_offset++) { + + strm->avail_in = c_len; + strm->avail_out = state->buf_len; + strm->next_in = state->cbuf; + strm->next_out = state->obuf; + to = strm->total_out; + shift_cdata(state, cbuf_unshifted, byte_offset, bit_offset); + + status = aec_decode_init(strm); + if (status != AEC_OK) { + printf("Init failed.\n"); + return 99; + } + status = aec_buffer_seek(strm, byte_offset, bit_offset); + if (status != AEC_OK) { + printf("Seeking failed.\n"); + return 99; + } + status = aec_decode(strm, AEC_FLUSH); + if (status != AEC_OK) { + printf("Decode failed.\n"); + return 99; + } + + if (memcmp(state->ubuf, state->obuf, state->ibuf_len)) { + printf("\n%s: Uncompressed output differs from input.\n", + CHECK_FAIL); + + printf("\nuncompressed buf"); + for (int i = 0; i < 80; i++) { + if (i % 8 == 0) + printf("\n"); + printf("%02x ", state->ubuf[i]); + } + printf("\n\ncompressed buf len %zu", to); + for (int i = 0; i < 80; i++) { + if (i % 8 == 0) + printf("\n"); + printf("%02x ", state->cbuf[i]); + } + printf("\n\ndecompressed buf"); + for (int i = 0; i < 80; i++) { + if (i % 8 == 0) + printf("\n"); + printf("%02x ", state->obuf[i]); + } + printf("\n"); + return 99; + } + aec_decode_end(strm); + } + } + return 0; +} + +int check_block_sizes_seek(struct test_state *state) +{ + for (int bs = 8; bs <= 64; bs *= 2) { + int status; + state->strm->block_size = bs; + state->strm->rsi = (int)(state->buf_len + / (bs * state->bytes_per_sample)); + + status = encode_decode_large_seek(state); + if (status) + return status; + } + return 0; +} + +int check_rsi_seek(struct test_state *state) +{ + int status; + int size = state->bytes_per_sample; + + for (unsigned char *tmp = state->ubuf; + tmp < state->ubuf + state->buf_len; + tmp += 2 * state->bytes_per_sample) { + state->out(tmp, state->xmax - ((state->ubuf - tmp) % 64), size); + state->out(tmp + size, state->xmin, size); + } + + printf("Checking seeking ... "); + status = check_block_sizes_seek(state); + if (status) + return status; + + printf ("%s\n", CHECK_PASS); + return 0; +} + +int main (void) +{ + int status; + struct aec_stream strm; + struct test_state state; + + state.dump = 0; + state.buf_len = state.ibuf_len = BUF_SIZE; + state.cbuf_len = 3 * BUF_SIZE; + + state.ubuf = (unsigned char *)malloc(state.buf_len); + state.cbuf = (unsigned char *)malloc(state.cbuf_len); + state.obuf = (unsigned char *)malloc(state.buf_len); + + if (!state.ubuf || !state.cbuf || !state.obuf) { + printf("Not enough memory.\n"); + status = 99; + goto DESTRUCT; + } + + strm.flags = AEC_DATA_PREPROCESS; + state.strm = &strm; + strm.bits_per_sample = 32; + update_state(&state); + + status = check_rsi_seek(&state); + if (status) + goto DESTRUCT; + +DESTRUCT: + if (state.ubuf) + free(state.ubuf); + if (state.cbuf) + free(state.cbuf); + if (state.obuf) + free(state.obuf); + + return status; +} -- GitLab