| 1 | #ifndef TEST_COMMON_H |
| 2 | #define TEST_COMMON_H |
| 3 | |
| 4 | #include <stdio.h> |
| 5 | #include <stdlib.h> |
| 6 | #include <stdint.h> |
| 7 | #include <string.h> |
| 8 | #include <math.h> |
| 9 | #include <time.h> |
| 10 | |
| 11 | #define TEST_PASSED 0 |
| 12 | #define TEST_FAILED 1 |
| 13 | |
| 14 | typedef struct { |
| 15 | const char *name; |
| 16 | int (*fn)(void); |
| 17 | } TestCase; |
| 18 | |
| 19 | typedef struct { |
| 20 | const char *name; |
| 21 | double (*fn)(void); |
| 22 | } BenchCase; |
| 23 | |
| 24 | extern int test_failures; |
| 25 | extern int test_total; |
| 26 | |
| 27 | #define TEST_ASSERT(cond, msg) do { \ |
| 28 | if (!(cond)) { \ |
| 29 | fprintf(stderr, " [FAIL] %s\n", msg); \ |
| 30 | test_failures++; \ |
| 31 | return TEST_FAILED; \ |
| 32 | } \ |
| 33 | } while (0) |
| 34 | |
| 35 | #define TEST_ASSERT_EQ(actual, expected, msg) do { \ |
| 36 | if ((actual) != (expected)) { \ |
| 37 | fprintf(stderr, " [FAIL] %s: expected %ld, got %ld\n", msg, (long)(expected), (long)(actual)); \ |
| 38 | test_failures++; \ |
| 39 | return TEST_FAILED; \ |
| 40 | } \ |
| 41 | } while (0) |
| 42 | |
| 43 | #define TEST_ASSERT_FTZ(actual, expected, tol, msg) do { \ |
| 44 | double _actual = (double)(actual); \ |
| 45 | double _expected = (double)(expected); \ |
| 46 | double _tol = (double)(tol); \ |
| 47 | double _diff = fabs(_actual - _expected); \ |
| 48 | if (_diff > _tol) { \ |
| 49 | fprintf(stderr, " [FAIL] %s: expected %.6f, got %.6f (diff %.6f)\n", msg, _expected, _actual, _diff); \ |
| 50 | test_failures++; \ |
| 51 | return TEST_FAILED; \ |
| 52 | } \ |
| 53 | } while (0) |
| 54 | |
| 55 | #define TEST_ASSERT_PTR_NOT_NULL(ptr, msg) do { \ |
| 56 | if ((ptr) == NULL) { \ |
| 57 | fprintf(stderr, " [FAIL] %s: pointer is NULL\n", msg); \ |
| 58 | test_failures++; \ |
| 59 | return TEST_FAILED; \ |
| 60 | } \ |
| 61 | } while (0) |
| 62 | |
| 63 | #define RUN_TEST(tests, name) do { \ |
| 64 | int _result = (name)(); \ |
| 65 | test_total++; \ |
| 66 | if (_result == TEST_PASSED) { \ |
| 67 | printf(" [PASS] %s\n", #name); \ |
| 68 | } \ |
| 69 | } while (0) |
| 70 | |
| 71 | #define RUN_BENCH(benchmarks, name, iter) do { \ |
| 72 | double _time = run_benchmark((name), (iter)); \ |
| 73 | printf(" [BENCH] %-40s %.3f ms\n", #name, _time); \ |
| 74 | } while (0) |
| 75 | |
| 76 | extern int test_failures; |
| 77 | extern int test_total; |
| 78 | |
| 79 | uint8_t *load_image(const char *path, int *width, int *height, int *channels); |
| 80 | int save_image(const char *path, uint8_t *data, int width, int height, int channels); |
| 81 | uint8_t *downsample_image(uint8_t *src, int sw, int sh, int sc, int *dw, int *dh, float scale); |
| 82 | double get_time_ms(void); |
| 83 | double run_benchmark(double (*fn)(void), int iterations); |
| 84 | int compare_images(uint8_t *a, uint8_t *b, int w, int h, int ch, float threshold); |
| 85 | float compute_psnr(uint8_t *a, uint8_t *b, int w, int h, int ch); |
| 86 | uint8_t *create_gradient_image(int w, int h); |
| 87 | uint8_t *create_noise_image(int w, int h, unsigned int seed); |
| 88 | uint8_t *create_uniform_image(int w, int h, uint8_t r, uint8_t g, uint8_t b); |
| 89 | uint8_t *create_checkerboard(int w, int h, int check_size); |
| 90 | |
| 91 | #endif |