diff --git a/.github/workflows/c_bindings.yml b/.github/workflows/c_bindings.yml index fd189ee..98873ab 100644 --- a/.github/workflows/c_bindings.yml +++ b/.github/workflows/c_bindings.yml @@ -16,17 +16,11 @@ jobs: - name: Checkout repo uses: actions/checkout@v4 - - name: Make C test programs + - name: Make C test program run: make -C c_bindings BUILD_MODE=release - - name: Test MIO0 - run: ./c_bindings/tests/test_mio0.sh - - - name: Test Yay0 - run: ./c_bindings/tests/test_yay0.sh - - - name: Test Yaz0 - run: ./c_bindings/tests/test_yaz0.sh + - name: Run tests + run: c_bindings/tests.elf release: name: Release ${{ matrix.crate-type }} for ${{ matrix.target }} diff --git a/.github/workflows/python_bindings.yml b/.github/workflows/python_bindings.yml index 808d960..7a3ff67 100644 --- a/.github/workflows/python_bindings.yml +++ b/.github/workflows/python_bindings.yml @@ -21,11 +21,5 @@ jobs: - name: Install local crunch64 run: python3 -m pip install ./lib - - name: Test MIO0 - run: python3 ./python_bindings/tests/test_mio0.py - - - name: Test Yay0 - run: python3 ./python_bindings/tests/test_yay0.py - - - name: Test Yaz0 - run: python3 ./python_bindings/tests/test_yaz0.py + - name: Run tests + run: python3 ./python_bindings/tests.py diff --git a/.gitignore b/.gitignore index fb5e26f..0b7379e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.venv/ target/ *.bin *.Yay0 diff --git a/c_bindings/Makefile b/c_bindings/Makefile index 871bff9..3b7dfcc 100644 --- a/c_bindings/Makefile +++ b/c_bindings/Makefile @@ -14,13 +14,13 @@ IINC := -I include WARNINGS := -Wall -Wextra -Wshadow -Werror -C_BINDINGS_TESTS := $(wildcard tests/test_*.c) -C_BINDINGS_ELFS := $(C_BINDINGS_TESTS:.c=.elf) +C_BINDINGS_TESTS := tests.c +C_BINDINGS_ELF := tests.elf -all: $(C_BINDINGS_ELFS) +all: $(C_BINDINGS_ELF) clean: - $(RM) -rf $(C_BINDINGS_ELFS) tests/*.elf + $(RM) $(C_BINDINGS_ELF) .PHONY: all clean .DEFAULT_GOAL := all @@ -32,8 +32,8 @@ endif $(shell cargo build --lib --features c_bindings $(CARGO_FLAGS)) -%.elf: %.c $(LIB) - $(CC) $(CSTD) $(CFLAGS) $(IINC) $(WARNINGS) -o $@ tests/utils.c $< -L ../target/$(BUILD_MODE) -Wl,-Bstatic -l crunch64 -Wl,-Bdynamic +$(C_BINDINGS_ELF): $(C_BINDINGS_TESTS) $(LIB) + $(CC) $(CSTD) $(CFLAGS) $(IINC) $(WARNINGS) -o $@ $< -L ../target/$(BUILD_MODE) -Wl,-Bstatic -l crunch64 -Wl,-Bdynamic # Print target for debugging print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true diff --git a/c_bindings/tests.c b/c_bindings/tests.c new file mode 100644 index 0000000..ac03066 --- /dev/null +++ b/c_bindings/tests.c @@ -0,0 +1,255 @@ +#include "crunch64.h" + +#include +#include +#include +#include +#include +#include +#include + +typedef Crunch64Error (*compress_bound_fn)(size_t *dst_size, size_t src_len, const uint8_t *const src); +typedef Crunch64Error (*compress_fn)(size_t *dst_size, uint8_t *dst, size_t src_size, const uint8_t *src); + +const char *const crunch64_error_str[] = { + [Crunch64Error_Okay] = "Okay", + [Crunch64Error_InvalidYay0Header] = "Invalid Yay0 header", + [Crunch64Error_InvalidYaz0Header] = "Invalid Yaz0 header", + [Crunch64Error_InvalidMio0Header] = "Invalid Mio0 header", + [Crunch64Error_UnsupportedCompressionType] = "Unsupported compression type", + [Crunch64Error_UnalignedRead] = "Unaligned read", + [Crunch64Error_ByteConversion] = "Byte conversion", + [Crunch64Error_OutOfBounds] = "Out of bounds", + [Crunch64Error_NullPointer] = "Null pointer", +}; + +const char *get_crunch64_error_str(Crunch64Error error) { + return crunch64_error_str[error]; +} + +bool has_suffix(const char *str, const char *suffix) { + size_t str_len = strlen(str); + size_t suffix_len = strlen(suffix); + return str_len >= suffix_len && strcmp(str + str_len - suffix_len, suffix) == 0; +} + +uint8_t *read_binary_file(const char *path, size_t *size) { + assert(path != NULL); + assert(size != NULL); + + FILE *f = fopen(path, "rb"); + if (f == NULL) { + return NULL; + } + + fseek(f, 0, SEEK_END); + *size = ftell(f); + fseek(f, 0, SEEK_SET); + + uint8_t *data = malloc(*size * sizeof(uint8_t)); + if (data == NULL) { + fclose(f); + return NULL; + } + + size_t count = fread(data, sizeof(uint8_t), *size, f); + if (count != *size) { + free(data); + fclose(f); + return NULL; + } + + fclose(f); + return data; +} + +bool write_binary_file(const char *path, uint8_t *data, size_t size) { + assert(path != NULL); + assert(data != NULL); + + FILE *f = fopen(path, "wb"); + if (f == NULL) { + return false; + } + + size_t count = fwrite(data, sizeof(uint8_t), size, f); + if (count != size) { + return false; + } + + fclose(f); + + return true; +} + +bool compare_buffers(size_t a_size, const uint8_t *a, size_t b_size, const uint8_t *b) { + if (a_size != b_size) { + fprintf(stderr, " sizes don't match\n"); + return false; + } + + if (memcmp(a, b, a_size) != 0) { + fprintf(stderr, " data doesn't match\n"); + return false; + } + + fprintf(stderr, " OK\n"); + + return true; +} + +bool test_matching_decompression(compress_bound_fn decompress_bound, compress_fn decompress, size_t bin_size, + uint8_t *bin, size_t compressed_size, uint8_t *compressed_data) { + fprintf(stderr, "Testing matching decompression:\n"); + + fprintf(stderr, " decompressing: "); + size_t decompressed_size; + uint8_t *decompressed_data = NULL; + + Crunch64Error size_request_ok = decompress_bound(&decompressed_size, compressed_size, compressed_data); + if (size_request_ok != Crunch64Error_Okay) { + fprintf(stderr, " failed to request size for buffer. Reason: %s\n", get_crunch64_error_str(size_request_ok)); + return false; + } + + decompressed_data = malloc(decompressed_size * sizeof(uint8_t)); + if (decompressed_data == NULL) { + fprintf(stderr, " malloc fail: 0x%zX bytes\n", decompressed_size * sizeof(uint8_t)); + return false; + } + + Crunch64Error decompress_ok = decompress(&decompressed_size, decompressed_data, compressed_size, compressed_data); + if (decompress_ok != Crunch64Error_Okay) { + fprintf(stderr, " failed to decompress data. Reason: %s\n", get_crunch64_error_str(decompress_ok)); + free(decompressed_data); + return false; + } + + fprintf(stderr, " OK\n"); + + fprintf(stderr, " validating data: "); + bool matches = compare_buffers(decompressed_size, decompressed_data, bin_size, bin); + if (!matches) { + free(decompressed_data); + return false; + } + + free(decompressed_data); + return true; +} + +bool test_matching_compression(compress_bound_fn compress_bound, compress_fn compress, size_t bin_size, uint8_t *bin, + size_t compressed_size, uint8_t *compressed_data) { + fprintf(stderr, "Testing matching compression:\n"); + fprintf(stderr, " compressing: "); + + size_t recompressed_size; + uint8_t *recompressed_data = NULL; + + Crunch64Error size_request_ok = compress_bound(&recompressed_size, bin_size, bin); + if (size_request_ok != Crunch64Error_Okay) { + fprintf(stderr, " failed to request size for buffer. Reason: %s\n", get_crunch64_error_str(size_request_ok)); + return false; + } + + recompressed_data = malloc(recompressed_size * sizeof(uint8_t)); + if (recompressed_data == NULL) { + fprintf(stderr, " malloc fail: 0x%zX bytes\n", recompressed_size * sizeof(uint8_t)); + return false; + } + + Crunch64Error compress_ok = compress(&recompressed_size, recompressed_data, bin_size, bin); + if (compress_ok != Crunch64Error_Okay) { + fprintf(stderr, " failed to decompress data. Reason: %s\n", get_crunch64_error_str(compress_ok)); + free(recompressed_data); + return false; + } + + fprintf(stderr, " OK\n"); + + fprintf(stderr, " validating data: "); + bool matches = compare_buffers(recompressed_size, recompressed_data, compressed_size, compressed_data); + if (!matches) { + free(recompressed_data); + return false; + } + + free(recompressed_data); + return true; +} + +int errors = 0; + +void run_tests(const char *name, const char *file_extension, compress_bound_fn compress_bound, compress_fn compress, + compress_bound_fn decompress_bound, compress_fn decompress) { + struct dirent *entry; + DIR *dir = opendir("test_data"); + if (!dir) { + fprintf(stderr, "Could not open test_data directory\n"); + errors++; + return; + } + + fprintf(stderr, "Running tests for %s\n", name); + fprintf(stderr, "\n"); + + bool found_tests = false; + while ((entry = readdir(dir)) != NULL) { + if (!has_suffix(entry->d_name, file_extension)) { + continue; + } + + found_tests = true; + + char bin_path[512]; + snprintf(bin_path, sizeof(bin_path), "test_data/%s", entry->d_name); + bin_path[strlen(bin_path) - strlen(file_extension)] = '\0'; // remove file extension + + char compressed_path[512]; + snprintf(compressed_path, sizeof(compressed_path), "test_data/%s", entry->d_name); + + fprintf(stderr, "Reading file %s\n", bin_path); + size_t bin_size = 0; + uint8_t *bin = read_binary_file(bin_path, &bin_size); + assert(bin_size > 0); + assert(bin != NULL); + + fprintf(stderr, "Reading file %s\n", compressed_path); + size_t compressed_data_size = 0; + uint8_t *compressed_data = read_binary_file(compressed_path, &compressed_data_size); + assert(compressed_data_size > 0); + assert(compressed_data != NULL); + + if (!test_matching_decompression(decompress_bound, decompress, bin_size, bin, compressed_data_size, compressed_data)) { + errors++; + } + if (!test_matching_compression(compress_bound, compress, bin_size, bin, compressed_data_size, compressed_data)) { + errors++; + } + + fprintf(stderr, "\n"); + + free(bin); + free(compressed_data); + } + + if (!found_tests) { + fprintf(stderr, "No test files found for %s\n", name); + errors++; + return; + } +} + +int main(void) { + run_tests("yay0", ".Yay0", crunch64_yay0_compress_bound, crunch64_yay0_compress, crunch64_yay0_decompress_bound, crunch64_yay0_decompress); + run_tests("yaz0", ".Yaz0", crunch64_yaz0_compress_bound, crunch64_yaz0_compress, crunch64_yaz0_decompress_bound, crunch64_yaz0_decompress); + run_tests("mio0", ".MIO0", crunch64_mio0_compress_bound, crunch64_mio0_compress, crunch64_mio0_decompress_bound, crunch64_mio0_decompress); + + if (errors == 0) { + fprintf(stderr, "All tests passed\n"); + return 0; + } else { + fprintf(stderr, "%d tests failed\n", errors); + return 1; + } +} diff --git a/c_bindings/tests/test_mio0.c b/c_bindings/tests/test_mio0.c deleted file mode 100644 index e27ba7b..0000000 --- a/c_bindings/tests/test_mio0.c +++ /dev/null @@ -1,137 +0,0 @@ -#include "crunch64.h" - -#include -#include -#include - -#include "utils.h" - -bool decompress(size_t *dst_size, uint8_t **dst, size_t src_size, const uint8_t *src) -{ - size_t decompressed_size; - uint8_t *decompressed_data = NULL; - - Crunch64Error size_request_ok = crunch64_mio0_decompress_bound(&decompressed_size, src_size, src); - if (size_request_ok != Crunch64Error_Okay) - { - fprintf(stderr, " failed to request size for buffer. Reason: %s\n", get_crunch64_error_str(size_request_ok)); - return false; - } - - decompressed_data = malloc(decompressed_size * sizeof(uint8_t)); - if (decompressed_data == NULL) - { - fprintf(stderr, " malloc fail: 0x%zX bytes\n", decompressed_size * sizeof(uint8_t)); - return false; - } - - Crunch64Error decompress_ok = crunch64_mio0_decompress(&decompressed_size, decompressed_data, src_size, src); - if (decompress_ok != Crunch64Error_Okay) - { - fprintf(stderr, " failed to decompress data. Reason: %s\n", get_crunch64_error_str(decompress_ok)); - free(decompressed_data); - return false; - } - - *dst_size = decompressed_size; - *dst = decompressed_data; - - fprintf(stderr, " OK\n"); - return true; -} - -bool compress(size_t *dst_size, uint8_t **dst, size_t src_size, const uint8_t *src) -{ - size_t compressed_size; - uint8_t *compressed_data = NULL; - - assert(dst_size != NULL); - assert(dst != NULL); - assert(src != NULL); - - Crunch64Error size_request_ok = crunch64_mio0_compress_bound(&compressed_size, src_size, src); - if (size_request_ok != Crunch64Error_Okay) - { - fprintf(stderr, " failed to request size for buffer. Reason: %s\n", get_crunch64_error_str(size_request_ok)); - return false; - } - - compressed_data = malloc(compressed_size * sizeof(uint8_t)); - if (compressed_data == NULL) - { - fprintf(stderr, " malloc fail: 0x%zX bytes\n", compressed_size * sizeof(uint8_t)); - return false; - } - - Crunch64Error compress_ok = crunch64_mio0_compress(&compressed_size, compressed_data, src_size, src); - if (compress_ok != Crunch64Error_Okay) - { - fprintf(stderr, " failed to decompress data. Reason: %s\n", get_crunch64_error_str(compress_ok)); - free(compressed_data); - return false; - } - - *dst_size = compressed_size; - *dst = compressed_data; - - fprintf(stderr, " OK\n"); - - return true; -} - -void print_usage(int argc, char *argv[]) -{ - (void)argc; - - fprintf(stderr, "Usage: %s bin_file compressed_file\n", argv[0]); - fprintf(stderr, "\n"); - fprintf(stderr, "This programs tests compression and decompression produces matching output\n"); -} - -int main(int argc, char *argv[]) -{ - int ret = 0; - - if (argc < 2) - { - print_usage(argc, argv); - return -1; - } - - const char *bin_path = argv[1]; - const char *compressed_path = argv[2]; - - fprintf(stderr, "Reading file %s\n", bin_path); - size_t bin_size = 0; - uint8_t *bin = read_binary_file(bin_path, &bin_size); - assert(bin_size > 0); - assert(bin != NULL); - - fprintf(stderr, "Reading file %s\n", compressed_path); - size_t compressed_data_size = 0; - uint8_t *compressed_data = read_binary_file(compressed_path, &compressed_data_size); - assert(compressed_data_size > 0); - assert(compressed_data != NULL); - - if (!test_matching_decompression(bin_size, bin, compressed_data_size, compressed_data)) - { - ret++; - } - if (!test_matching_compression(bin_size, bin, compressed_data_size, compressed_data)) - { - ret++; - } - if (!test_cycle_decompressed(bin_size, bin)) - { - ret++; - } - if (!test_cycle_compressed(compressed_data_size, compressed_data)) - { - ret++; - } - - free(bin); - free(compressed_data); - - return ret; -} diff --git a/c_bindings/tests/test_mio0.sh b/c_bindings/tests/test_mio0.sh deleted file mode 100755 index 291b2ca..0000000 --- a/c_bindings/tests/test_mio0.sh +++ /dev/null @@ -1,14 +0,0 @@ -#! /usr/bin/env bash - -set -e - -for i in test_data/*.MIO0; do - [ -f "$i" ] || break - echo "Processing:" $i - - # Remove the extension - BIN_PATH=$(echo $i | sed 's/.MIO0//') - - c_bindings/tests/test_mio0.elf $BIN_PATH $i - echo -done diff --git a/c_bindings/tests/test_yay0.c b/c_bindings/tests/test_yay0.c deleted file mode 100644 index 6301ad4..0000000 --- a/c_bindings/tests/test_yay0.c +++ /dev/null @@ -1,137 +0,0 @@ -#include "crunch64.h" - -#include -#include -#include - -#include "utils.h" - -bool decompress(size_t *dst_size, uint8_t **dst, size_t src_size, const uint8_t *src) -{ - size_t decompressed_size; - uint8_t *decompressed_data = NULL; - - Crunch64Error size_request_ok = crunch64_yay0_decompress_bound(&decompressed_size, src_size, src); - if (size_request_ok != Crunch64Error_Okay) - { - fprintf(stderr, " failed to request size for buffer. Reason: %s\n", get_crunch64_error_str(size_request_ok)); - return false; - } - - decompressed_data = malloc(decompressed_size * sizeof(uint8_t)); - if (decompressed_data == NULL) - { - fprintf(stderr, " malloc fail: 0x%zX bytes\n", decompressed_size * sizeof(uint8_t)); - return false; - } - - Crunch64Error decompress_ok = crunch64_yay0_decompress(&decompressed_size, decompressed_data, src_size, src); - if (decompress_ok != Crunch64Error_Okay) - { - fprintf(stderr, " failed to decompress data. Reason: %s\n", get_crunch64_error_str(decompress_ok)); - free(decompressed_data); - return false; - } - - *dst_size = decompressed_size; - *dst = decompressed_data; - - fprintf(stderr, " OK\n"); - return true; -} - -bool compress(size_t *dst_size, uint8_t **dst, size_t src_size, const uint8_t *src) -{ - size_t compressed_size; - uint8_t *compressed_data = NULL; - - assert(dst_size != NULL); - assert(dst != NULL); - assert(src != NULL); - - Crunch64Error size_request_ok = crunch64_yay0_compress_bound(&compressed_size, src_size, src); - if (size_request_ok != Crunch64Error_Okay) - { - fprintf(stderr, " failed to request size for buffer. Reason: %s\n", get_crunch64_error_str(size_request_ok)); - return false; - } - - compressed_data = malloc(compressed_size * sizeof(uint8_t)); - if (compressed_data == NULL) - { - fprintf(stderr, " malloc fail: 0x%zX bytes\n", compressed_size * sizeof(uint8_t)); - return false; - } - - Crunch64Error compress_ok = crunch64_yay0_compress(&compressed_size, compressed_data, src_size, src); - if (compress_ok != Crunch64Error_Okay) - { - fprintf(stderr, " failed to decompress data. Reason: %s\n", get_crunch64_error_str(compress_ok)); - free(compressed_data); - return false; - } - - *dst_size = compressed_size; - *dst = compressed_data; - - fprintf(stderr, " OK\n"); - - return true; -} - -void print_usage(int argc, char *argv[]) -{ - (void)argc; - - fprintf(stderr, "Usage: %s bin_file compressed_file\n", argv[0]); - fprintf(stderr, "\n"); - fprintf(stderr, "This programs tests compression and decompression produces matching output\n"); -} - -int main(int argc, char *argv[]) -{ - int ret = 0; - - if (argc < 2) - { - print_usage(argc, argv); - return -1; - } - - const char *bin_path = argv[1]; - const char *compressed_path = argv[2]; - - fprintf(stderr, "Reading file %s\n", bin_path); - size_t bin_size = 0; - uint8_t *bin = read_binary_file(bin_path, &bin_size); - assert(bin_size > 0); - assert(bin != NULL); - - fprintf(stderr, "Reading file %s\n", compressed_path); - size_t compressed_data_size = 0; - uint8_t *compressed_data = read_binary_file(compressed_path, &compressed_data_size); - assert(compressed_data_size > 0); - assert(compressed_data != NULL); - - if (!test_matching_decompression(bin_size, bin, compressed_data_size, compressed_data)) - { - ret++; - } - if (!test_matching_compression(bin_size, bin, compressed_data_size, compressed_data)) - { - ret++; - } - if (!test_cycle_decompressed(bin_size, bin)) - { - ret++; - } - if (!test_cycle_compressed(compressed_data_size, compressed_data)) - { - ret++; - } - - free(bin); - free(compressed_data); - - return ret; -} diff --git a/c_bindings/tests/test_yay0.sh b/c_bindings/tests/test_yay0.sh deleted file mode 100755 index 36a6237..0000000 --- a/c_bindings/tests/test_yay0.sh +++ /dev/null @@ -1,14 +0,0 @@ -#! /usr/bin/env bash - -set -e - -for i in test_data/*.Yay0; do - [ -f "$i" ] || break - echo "Processing:" $i - - # Remove the extension - BIN_PATH=$(echo $i | sed 's/.Yay0//') - - c_bindings/tests/test_yay0.elf $BIN_PATH $i - echo -done diff --git a/c_bindings/tests/test_yaz0.c b/c_bindings/tests/test_yaz0.c deleted file mode 100644 index 028a625..0000000 --- a/c_bindings/tests/test_yaz0.c +++ /dev/null @@ -1,137 +0,0 @@ -#include "crunch64.h" - -#include -#include -#include - -#include "utils.h" - -bool decompress(size_t *dst_size, uint8_t **dst, size_t src_size, const uint8_t *src) -{ - size_t decompressed_size; - uint8_t *decompressed_data = NULL; - - Crunch64Error size_request_ok = crunch64_yaz0_decompress_bound(&decompressed_size, src_size, src); - if (size_request_ok != Crunch64Error_Okay) - { - fprintf(stderr, " failed to request size for buffer. Reason: %s\n", get_crunch64_error_str(size_request_ok)); - return false; - } - - decompressed_data = malloc(decompressed_size * sizeof(uint8_t)); - if (decompressed_data == NULL) - { - fprintf(stderr, " malloc fail: 0x%zX bytes\n", decompressed_size * sizeof(uint8_t)); - return false; - } - - Crunch64Error decompress_ok = crunch64_yaz0_decompress(&decompressed_size, decompressed_data, src_size, src); - if (decompress_ok != Crunch64Error_Okay) - { - fprintf(stderr, " failed to decompress data. Reason: %s\n", get_crunch64_error_str(decompress_ok)); - free(decompressed_data); - return false; - } - - *dst_size = decompressed_size; - *dst = decompressed_data; - - fprintf(stderr, " OK\n"); - return true; -} - -bool compress(size_t *dst_size, uint8_t **dst, size_t src_size, const uint8_t *src) -{ - size_t compressed_size; - uint8_t *compressed_data = NULL; - - assert(dst_size != NULL); - assert(dst != NULL); - assert(src != NULL); - - Crunch64Error size_request_ok = crunch64_yaz0_compress_bound(&compressed_size, src_size, src); - if (size_request_ok != Crunch64Error_Okay) - { - fprintf(stderr, " failed to request size for buffer. Reason: %s\n", get_crunch64_error_str(size_request_ok)); - return false; - } - - compressed_data = malloc(compressed_size * sizeof(uint8_t)); - if (compressed_data == NULL) - { - fprintf(stderr, " malloc fail: 0x%zX bytes\n", compressed_size * sizeof(uint8_t)); - return false; - } - - Crunch64Error compress_ok = crunch64_yaz0_compress(&compressed_size, compressed_data, src_size, src); - if (compress_ok != Crunch64Error_Okay) - { - fprintf(stderr, " failed to decompress data. Reason: %s\n", get_crunch64_error_str(compress_ok)); - free(compressed_data); - return false; - } - - *dst_size = compressed_size; - *dst = compressed_data; - - fprintf(stderr, " OK\n"); - - return true; -} - -void print_usage(int argc, char *argv[]) -{ - (void)argc; - - fprintf(stderr, "Usage: %s bin_file compressed_file\n", argv[0]); - fprintf(stderr, "\n"); - fprintf(stderr, "This programs tests compression and decompression produces matching output\n"); -} - -int main(int argc, char *argv[]) -{ - int ret = 0; - - if (argc < 2) - { - print_usage(argc, argv); - return -1; - } - - const char *bin_path = argv[1]; - const char *compressed_path = argv[2]; - - fprintf(stderr, "Reading file %s\n", bin_path); - size_t bin_size = 0; - uint8_t *bin = read_binary_file(bin_path, &bin_size); - assert(bin_size > 0); - assert(bin != NULL); - - fprintf(stderr, "Reading file %s\n", compressed_path); - size_t compressed_data_size = 0; - uint8_t *compressed_data = read_binary_file(compressed_path, &compressed_data_size); - assert(compressed_data_size > 0); - assert(compressed_data != NULL); - - if (!test_matching_decompression(bin_size, bin, compressed_data_size, compressed_data)) - { - ret++; - } - if (!test_matching_compression(bin_size, bin, compressed_data_size, compressed_data)) - { - ret++; - } - if (!test_cycle_decompressed(bin_size, bin)) - { - ret++; - } - if (!test_cycle_compressed(compressed_data_size, compressed_data)) - { - ret++; - } - - free(bin); - free(compressed_data); - - return ret; -} diff --git a/c_bindings/tests/test_yaz0.sh b/c_bindings/tests/test_yaz0.sh deleted file mode 100755 index 0e92255..0000000 --- a/c_bindings/tests/test_yaz0.sh +++ /dev/null @@ -1,14 +0,0 @@ -#! /usr/bin/env bash - -set -e - -for i in test_data/*.Yaz0; do - [ -f "$i" ] || break - echo "Processing:" $i - - # Remove the extension - BIN_PATH=$(echo $i | sed 's/.Yaz0//') - - c_bindings/tests/test_yaz0.elf $BIN_PATH $i - echo -done diff --git a/c_bindings/tests/utils.c b/c_bindings/tests/utils.c deleted file mode 100644 index 2510906..0000000 --- a/c_bindings/tests/utils.c +++ /dev/null @@ -1,232 +0,0 @@ -#include "utils.h" - -#include -#include -#include -#include - -uint8_t *read_binary_file(const char *path, size_t *size) -{ - assert(path != NULL); - assert(size != NULL); - - FILE *f = fopen(path, "rb"); - if (f == NULL) - { - return NULL; - } - - fseek(f, 0, SEEK_END); - *size = ftell(f); - fseek(f, 0, SEEK_SET); - - uint8_t *data = malloc(*size * sizeof(uint8_t)); - if (data == NULL) - { - fclose(f); - return NULL; - } - - size_t count = fread(data, sizeof(uint8_t), *size, f); - if (count != *size) - { - free(data); - fclose(f); - return NULL; - } - - fclose(f); - return data; -} - -bool write_binary_file(const char *path, uint8_t *data, size_t size) -{ - assert(path != NULL); - assert(data != NULL); - - FILE *f = fopen(path, "wb"); - if (f == NULL) - { - return false; - } - - size_t count = fwrite(data, sizeof(uint8_t), size, f); - if (count != size) - { - return false; - } - - fclose(f); - - return true; -} - -bool compare_buffers(size_t a_size, const uint8_t *a, size_t b_size, const uint8_t *b) -{ - if (a_size != b_size) - { - fprintf(stderr, " sizes don't match\n"); - return false; - } - - if (memcmp(a, b, a_size) != 0) - { - fprintf(stderr, " data doesn't match\n"); - return false; - } - - fprintf(stderr, " OK\n"); - - return true; -} - -bool test_matching_decompression(size_t bin_size, uint8_t *bin, size_t compressed_data_size, uint8_t *compressed_data) -{ - fprintf(stderr, "Testing matching decompression:\n"); - - size_t buffer_size; - uint8_t *buffer; - - fprintf(stderr, " decompressing: "); - bool decompress_ok = decompress(&buffer_size, &buffer, compressed_data_size, compressed_data); - - if (!decompress_ok) - { - return false; - } - - fprintf(stderr, " validating data: "); - bool matches = compare_buffers(buffer_size, buffer, bin_size, bin); - if (!matches) - { - free(buffer); - return false; - } - - free(buffer); - return true; -} - -bool test_matching_compression(size_t bin_size, uint8_t *bin, size_t uncompressed_data_size, uint8_t *uncompressed_data) -{ - fprintf(stderr, "Testing matching compression:\n"); - - size_t buffer_size; - uint8_t *buffer; - - fprintf(stderr, " compressing: "); - bool compress_ok = compress(&buffer_size, &buffer, bin_size, bin); - - if (!compress_ok) - { - return false; - } - - fprintf(stderr, " validating data: "); - bool matches = compare_buffers(buffer_size, buffer, uncompressed_data_size, uncompressed_data); - if (!matches) - { - free(buffer); - return false; - } - - free(buffer); - return true; -} - -bool test_cycle_decompressed(size_t bin_size, uint8_t *bin) -{ - fprintf(stderr, "Testing cycle decompression:\n"); - - size_t buffer_size; - uint8_t *buffer; - { - size_t temp_buffer_size; - uint8_t *temp_buffer; - - fprintf(stderr, " compressing: "); - bool compress_ok = compress(&temp_buffer_size, &temp_buffer, bin_size, bin); - if (!compress_ok) - { - return false; - } - - fprintf(stderr, " decompressing: "); - bool decompress_ok = decompress(&buffer_size, &buffer, temp_buffer_size, temp_buffer); - if (!decompress_ok) - { - free(temp_buffer); - return false; - } - - free(temp_buffer); - } - - fprintf(stderr, " validating data: "); - bool matches = compare_buffers(buffer_size, buffer, bin_size, bin); - if (!matches) - { - free(buffer); - return false; - } - - free(buffer); - return true; -} - -bool test_cycle_compressed(size_t compressed_data_size, uint8_t *compressed_data) -{ - fprintf(stderr, "Testing cycle compression:\n"); - - size_t buffer_size; - uint8_t *buffer; - { - size_t temp_buffer_size; - uint8_t *temp_buffer; - - fprintf(stderr, " decompressing: "); - bool decompress_ok = decompress(&temp_buffer_size, &temp_buffer, compressed_data_size, compressed_data); - if (!decompress_ok) - { - return false; - } - - fprintf(stderr, " compressing: "); - bool compress_ok = compress(&buffer_size, &buffer, temp_buffer_size, temp_buffer); - if (!compress_ok) - { - free(temp_buffer); - return false; - } - - free(temp_buffer); - } - - fprintf(stderr, " validating data: "); - bool matches = compare_buffers(buffer_size, buffer, compressed_data_size, compressed_data); - if (!matches) - { - free(buffer); - return false; - } - - free(buffer); - return true; -} - - -const char *const crunch64_error_str[] = { - [Crunch64Error_Okay] = "Okay", - [Crunch64Error_InvalidYay0Header] = "Invalid Yay0 header", - [Crunch64Error_InvalidYaz0Header] = "Invalid Yaz0 header", - [Crunch64Error_InvalidMio0Header] = "Invalid Mio0 header", - [Crunch64Error_UnsupportedCompressionType] = "Unsupported compression type", - [Crunch64Error_UnalignedRead] = "Unaligned read", - [Crunch64Error_ByteConversion] = "Byte conversion", - [Crunch64Error_OutOfBounds] = "Out of bounds", - [Crunch64Error_NullPointer] = "Null pointer", -}; - -const char *get_crunch64_error_str(Crunch64Error error) { - return crunch64_error_str[error]; -} diff --git a/c_bindings/tests/utils.h b/c_bindings/tests/utils.h deleted file mode 100644 index 549c98f..0000000 --- a/c_bindings/tests/utils.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef UTILS_H -#define UTILS_H - -#include -#include -#include - -#include "crunch64.h" - -uint8_t *read_binary_file(const char *path, size_t *size); -bool write_binary_file(const char *path, uint8_t *data, size_t size); - -bool compare_buffers(size_t a_size, const uint8_t *a, size_t b_size, const uint8_t *b); - -bool test_matching_decompression(size_t bin_size, uint8_t *bin, size_t compressed_data_size, uint8_t *compressed_data); -bool test_matching_compression(size_t bin_size, uint8_t *bin, size_t uncompressed_data_size, uint8_t *uncompressed_data); - -bool test_cycle_decompressed(size_t bin_size, uint8_t *bin); -bool test_cycle_compressed(size_t compressed_data_size, uint8_t *compressed_data); - -// These should be provided by the specific test C file -bool decompress(size_t *dst_size, uint8_t **dst, size_t src_size, const uint8_t *src); -bool compress(size_t *dst_size, uint8_t **dst, size_t src_size, const uint8_t *src); - -const char *get_crunch64_error_str(Crunch64Error error); - -#endif diff --git a/python_bindings/tests.py b/python_bindings/tests.py new file mode 100755 index 0000000..a90e195 --- /dev/null +++ b/python_bindings/tests.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 + +from __future__ import annotations + +import crunch64 +from pathlib import Path +from typing import Callable + + +def test_matching_decompression( + decompress: Callable[[bytes], bytes], bin_data: bytes, comp_data: bytes +) -> bool: + print("Testing matching decompression:") + + print(" Decompressing: ", end="") + decompressed = decompress(comp_data) + print(" OK") + + print(" Validating: ", end="") + equal = decompressed == bin_data + if equal: + print(" OK") + else: + print(" data doesn't match") + return equal + + +def test_matching_compression( + compress: Callable[[bytes], bytes], bin_data: bytes, comp_data: bytes +) -> bool: + print("Testing matching decompression:") + + print(" Compressing: ", end="") + compressed = compress(bin_data) + print(" OK") + + print(" Validating: ", end="") + equal = compressed == comp_data + if equal: + print(" OK") + else: + print(" data doesn't match") + return equal + + +errors = 0 + + +def run_tests( + name: str, + file_extension: str, + compress: Callable[[bytes], bytes], + decompress: Callable[[bytes], bytes], +): + global errors + + comp_paths = list(sorted(Path("test_data").glob(f"*{file_extension}"))) + if not comp_paths: + print(f"No test files found for {name}") + errors += 1 + return + + print(f"Testing {name}") + print() + + for comp_path in comp_paths: + bin_path = comp_path.with_suffix("") + + print(f"Reading {bin_path}") + bin_data = bin_path.read_bytes() + + print(f"Reading {comp_path}") + comp_data = comp_path.read_bytes() + + if not test_matching_decompression(decompress, bin_data, comp_data): + errors += 1 + if not test_matching_compression(compress, bin_data, comp_data): + errors += 1 + + print() + + +run_tests("yaz0", ".Yaz0", crunch64.yaz0.compress, crunch64.yaz0.decompress) +run_tests("yay0", ".Yay0", crunch64.yay0.compress, crunch64.yay0.decompress) +run_tests("mio0", ".MIO0", crunch64.mio0.compress, crunch64.mio0.decompress) + +if not errors: + print("All tests passed") + exit(0) +else: + print(f"{errors} tests failed") + exit(1) diff --git a/python_bindings/tests/test_mio0.py b/python_bindings/tests/test_mio0.py deleted file mode 100755 index af33539..0000000 --- a/python_bindings/tests/test_mio0.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env python3 - -from __future__ import annotations - -import crunch64 -from pathlib import Path - - -def test_matching_decompression(bin_data: bytes, comp_data: bytes) -> bool: - print("Testing matching decompression:") - - print(" Decompressing: ", end="") - decompressed = crunch64.mio0.decompress(comp_data) - print(" OK") - - print(" Validating: ", end="") - equal = decompressed == bin_data - if equal: - print(" OK") - else: - print(" data doesn't match") - return equal - - -def test_matching_compression(bin_data: bytes, comp_data: bytes) -> bool: - print("Testing matching decompression:") - - print(" Compressing: ", end="") - compressed = crunch64.mio0.compress(bin_data) - print(" OK") - - print(" Validating: ", end="") - equal = compressed == comp_data - if equal: - print(" OK") - else: - print(" data doesn't match") - return equal - - -def test_cycle_decompressed(bin_data: bytes) -> bool: - print("Testing cycle decompression:") - - print(" Compressing: ", end="") - compressed = crunch64.mio0.compress(bin_data) - print(" OK") - - print(" Decompressing: ", end="") - dec = crunch64.mio0.decompress(compressed) - print(" OK") - - print(" Validating: ", end="") - equal = dec == bin_data - if equal: - print(" OK") - else: - print(" data doesn't match") - return equal - - -def test_cycle_compressed(comp_data: bytes) -> bool: - print("Testing cycle compression:") - - print(" Decompressing: ", end="") - dec = crunch64.mio0.decompress(comp_data) - print(" OK") - - print(" Compressing: ", end="") - compressed = crunch64.mio0.compress(dec) - print(" OK") - - print(" Validating: ", end="") - equal = compressed == comp_data - if equal: - print(" OK") - else: - print(" data doesn't match") - return equal - - -loop_run = False -errors = 0 -for comp_path in Path("test_data").glob("*.MIO0"): - loop_run = True - bin_path = comp_path.with_suffix("") - - print(f"Reading {bin_path}") - bin_data = bin_path.read_bytes() - - print(f"Reading {comp_path}") - comp_data = comp_path.read_bytes() - - if not test_matching_decompression(bin_data, comp_data): - errors += 1 - if not test_matching_compression(bin_data, comp_data): - errors += 1 - if not test_cycle_decompressed(bin_data): - errors += 1 - if not test_cycle_compressed(comp_data): - errors += 1 - - print() - -if not loop_run: - exit(-1) - -exit(errors) diff --git a/python_bindings/tests/test_yay0.py b/python_bindings/tests/test_yay0.py deleted file mode 100755 index f9d1688..0000000 --- a/python_bindings/tests/test_yay0.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env python3 - -from __future__ import annotations - -import crunch64 -from pathlib import Path - - -def test_matching_decompression(bin_data: bytes, comp_data: bytes) -> bool: - print("Testing matching decompression:") - - print(" Decompressing: ", end="") - decompressed = crunch64.yay0.decompress(comp_data) - print(" OK") - - print(" Validating: ", end="") - equal = decompressed == bin_data - if equal: - print(" OK") - else: - print(" data doesn't match") - return equal - - -def test_matching_compression(bin_data: bytes, comp_data: bytes) -> bool: - print("Testing matching decompression:") - - print(" Compressing: ", end="") - compressed = crunch64.yay0.compress(bin_data) - print(" OK") - - print(" Validating: ", end="") - equal = compressed == comp_data - if equal: - print(" OK") - else: - print(" data doesn't match") - return equal - - -def test_cycle_decompressed(bin_data: bytes) -> bool: - print("Testing cycle decompression:") - - print(" Compressing: ", end="") - compressed = crunch64.yay0.compress(bin_data) - print(" OK") - - print(" Decompressing: ", end="") - dec = crunch64.yay0.decompress(compressed) - print(" OK") - - print(" Validating: ", end="") - equal = dec == bin_data - if equal: - print(" OK") - else: - print(" data doesn't match") - return equal - - -def test_cycle_compressed(comp_data: bytes) -> bool: - print("Testing cycle compression:") - - print(" Decompressing: ", end="") - dec = crunch64.yay0.decompress(comp_data) - print(" OK") - - print(" Compressing: ", end="") - compressed = crunch64.yay0.compress(dec) - print(" OK") - - print(" Validating: ", end="") - equal = compressed == comp_data - if equal: - print(" OK") - else: - print(" data doesn't match") - return equal - - -loop_run = False -errors = 0 -for comp_path in Path("test_data").glob("*.Yay0"): - loop_run = True - bin_path = comp_path.with_suffix("") - - print(f"Reading {bin_path}") - bin_data = bin_path.read_bytes() - - print(f"Reading {comp_path}") - comp_data = comp_path.read_bytes() - - if not test_matching_decompression(bin_data, comp_data): - errors += 1 - if not test_matching_compression(bin_data, comp_data): - errors += 1 - if not test_cycle_decompressed(bin_data): - errors += 1 - if not test_cycle_compressed(comp_data): - errors += 1 - - print() - -if not loop_run: - exit(-1) - -exit(errors) diff --git a/python_bindings/tests/test_yaz0.py b/python_bindings/tests/test_yaz0.py deleted file mode 100755 index 9dbb6a9..0000000 --- a/python_bindings/tests/test_yaz0.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env python3 - -from __future__ import annotations - -import crunch64 -from pathlib import Path - - -def test_matching_decompression(bin_data: bytes, comp_data: bytes) -> bool: - print("Testing matching decompression:") - - print(" Decompressing: ", end="") - decompressed = crunch64.yaz0.decompress(comp_data) - print(" OK") - - print(" Validating: ", end="") - equal = decompressed == bin_data - if equal: - print(" OK") - else: - print(" data doesn't match") - return equal - - -def test_matching_compression(bin_data: bytes, comp_data: bytes) -> bool: - print("Testing matching decompression:") - - print(" Compressing: ", end="") - compressed = crunch64.yaz0.compress(bin_data) - print(" OK") - - print(" Validating: ", end="") - equal = compressed == comp_data - if equal: - print(" OK") - else: - print(" data doesn't match") - return equal - - -def test_cycle_decompressed(bin_data: bytes) -> bool: - print("Testing cycle decompression:") - - print(" Compressing: ", end="") - compressed = crunch64.yaz0.compress(bin_data) - print(" OK") - - print(" Decompressing: ", end="") - dec = crunch64.yaz0.decompress(compressed) - print(" OK") - - print(" Validating: ", end="") - equal = dec == bin_data - if equal: - print(" OK") - else: - print(" data doesn't match") - return equal - - -def test_cycle_compressed(comp_data: bytes) -> bool: - print("Testing cycle compression:") - - print(" Decompressing: ", end="") - dec = crunch64.yaz0.decompress(comp_data) - print(" OK") - - print(" Compressing: ", end="") - compressed = crunch64.yaz0.compress(dec) - print(" OK") - - print(" Validating: ", end="") - equal = compressed == comp_data - if equal: - print(" OK") - else: - print(" data doesn't match") - return equal - - -loop_run = False -errors = 0 -for comp_path in Path("test_data").glob("*.Yaz0"): - loop_run = True - bin_path = comp_path.with_suffix("") - - print(f"Reading {bin_path}") - bin_data = bin_path.read_bytes() - - print(f"Reading {comp_path}") - comp_data = comp_path.read_bytes() - - if not test_matching_decompression(bin_data, comp_data): - errors += 1 - if not test_matching_compression(bin_data, comp_data): - errors += 1 - if not test_cycle_decompressed(bin_data): - errors += 1 - if not test_cycle_compressed(comp_data): - errors += 1 - - print() - -if not loop_run: - exit(-1) - -exit(errors)