brewery
notashelf /
5258a0b492c3c1c298ea19f120d4b539d97162d9

chroma

public

Lightweight wallpaper daemon for Wayland

Star0tarball
clone
ssh://git@git.notashelf.dev:33/notashelf/chroma.git
tests/test.cC253 lines7.8 KB
1
#include "test_common.h"
2
#include <stdio.h>
3
#include <stdlib.h>
4
5
int test_failures = 0;
6
int test_total = 0;
7
8
static int test_null_image_handling(void) {
9
    uint8_t *result = downsample_image(NULL, 100, 100, 4, NULL, NULL, 0.5f);
10
    TEST_ASSERT(result == NULL, "Null image should return NULL");
11
    return TEST_PASSED;
12
}
13
14
static int test_zero_dimensions(void) {
15
    int dw, dh;
16
    uint8_t *result = downsample_image(NULL, 0, 0, 4, &dw, &dh, 0.5f);
17
    TEST_ASSERT(result == NULL, "Zero dimensions should return NULL");
18
    return TEST_PASSED;
19
}
20
21
static int test_scale_one_preserves_size(void) {
22
    uint8_t *src = create_uniform_image(100, 100, 128, 64, 255);
23
    TEST_ASSERT_PTR_NOT_NULL(src, "Source image allocation");
24
25
    int dw, dh;
26
    uint8_t *dst = downsample_image(src, 100, 100, 4, &dw, &dh, 1.0f);
27
    TEST_ASSERT_PTR_NOT_NULL(dst, "Scale 1.0 result");
28
29
    TEST_ASSERT_EQ(dw, 100, "Width preserved at scale 1.0");
30
    TEST_ASSERT_EQ(dh, 100, "Height preserved at scale 1.0");
31
32
    int match = compare_images(src, dst, 100, 100, 4, 0.01f);
33
    TEST_ASSERT(match == 1, "Image data preserved at scale 1.0");
34
35
    free(src);
36
    free(dst);
37
    return TEST_PASSED;
38
}
39
40
static int test_downsample_half_size(void) {
41
    uint8_t *src = create_gradient_image(100, 100);
42
    TEST_ASSERT_PTR_NOT_NULL(src, "Gradient source");
43
44
    int dw, dh;
45
    uint8_t *dst = downsample_image(src, 100, 100, 4, &dw, &dh, 0.5f);
46
    TEST_ASSERT_PTR_NOT_NULL(dst, "Downsample result");
47
48
    TEST_ASSERT_EQ(dw, 50, "Width halved at 0.5 scale");
49
    TEST_ASSERT_EQ(dh, 50, "Height halved at 0.5 scale");
50
51
    free(src);
52
    free(dst);
53
    return TEST_PASSED;
54
}
55
56
static int test_minimum_one_pixel(void) {
57
    uint8_t *src = create_uniform_image(1, 1, 100, 100, 100);
58
    TEST_ASSERT_PTR_NOT_NULL(src, "Single pixel source");
59
60
    int dw, dh;
61
    uint8_t *dst = downsample_image(src, 1, 1, 4, &dw, &dh, 0.01f);
62
    TEST_ASSERT_PTR_NOT_NULL(dst, "Minimum size result");
63
64
    TEST_ASSERT_EQ(dw, 1, "Width minimum 1 pixel");
65
    TEST_ASSERT_EQ(dh, 1, "Height minimum 1 pixel");
66
67
    free(src);
68
    free(dst);
69
    return TEST_PASSED;
70
}
71
72
static int test_large_image_handling(void) {
73
    uint8_t *src = create_noise_image(4096, 4096, 42);
74
    TEST_ASSERT_PTR_NOT_NULL(src, "Large image allocation");
75
76
    int dw, dh;
77
    uint8_t *dst = downsample_image(src, 4096, 4096, 4, &dw, &dh, 0.25f);
78
    TEST_ASSERT_PTR_NOT_NULL(dst, "Large image downsample");
79
80
    TEST_ASSERT_EQ(dw, 1024, "Correct width at 0.25 scale");
81
    TEST_ASSERT_EQ(dh, 1024, "Correct height at 0.25 scale");
82
83
    free(src);
84
    free(dst);
85
    return TEST_PASSED;
86
}
87
88
static int test_alpha_channel_preserved(void) {
89
    uint8_t *src = create_uniform_image(50, 50, 255, 0, 0);
90
    TEST_ASSERT_PTR_NOT_NULL(src, "Red source");
91
92
    int dw, dh;
93
    uint8_t *dst = downsample_image(src, 50, 50, 4, &dw, &dh, 0.5f);
94
    TEST_ASSERT_PTR_NOT_NULL(dst, "Downsample with alpha");
95
96
    TEST_ASSERT_EQ(dw, 25, "Width halved");
97
    TEST_ASSERT_EQ(dh, 25, "Height halved");
98
99
    TEST_ASSERT(dst[0 * 4 + 3] == 255, "Alpha channel preserved");
100
101
    free(src);
102
    free(dst);
103
    return TEST_PASSED;
104
}
105
106
static int test_uniform_color_accuracy(void) {
107
    uint8_t *src = create_uniform_image(100, 100, 200, 100, 50);
108
    TEST_ASSERT_PTR_NOT_NULL(src, "Uniform color source");
109
110
    int dw, dh;
111
    uint8_t *dst = downsample_image(src, 100, 100, 4, &dw, &dh, 0.25f);
112
    TEST_ASSERT_PTR_NOT_NULL(dst, "Uniform color downsample");
113
114
    int correct = 1;
115
    for (int i = 0; i < dw * dh; i++) {
116
        if (dst[i * 4 + 0] != 200 || dst[i * 4 + 1] != 100 || dst[i * 4 + 2] != 50) {
117
            correct = 0;
118
            break;
119
        }
120
    }
121
    TEST_ASSERT(correct == 1, "Uniform color preserved in downsampling");
122
123
    free(src);
124
    free(dst);
125
    return TEST_PASSED;
126
}
127
128
static int test_gradient_smoothness(void) {
129
    uint8_t *src = create_gradient_image(100, 100);
130
    TEST_ASSERT_PTR_NOT_NULL(src, "Gradient source");
131
132
    int dw, dh;
133
    uint8_t *dst = downsample_image(src, 100, 100, 4, &dw, &dh, 0.5f);
134
    TEST_ASSERT_PTR_NOT_NULL(dst, "Gradient downsample");
135
136
    float psnr = compute_psnr(src, dst, dw, dh, 4);
137
    TEST_ASSERT_FTZ(psnr, 9.0f, 5.0f, "Gradient PSNR within expected range");
138
139
    free(src);
140
    free(dst);
141
    return TEST_PASSED;
142
}
143
144
static int test_checkerboard_no_aliasing(void) {
145
    uint8_t *src = create_checkerboard(100, 100, 10);
146
    TEST_ASSERT_PTR_NOT_NULL(src, "Checkerboard source");
147
148
    int dw, dh;
149
    uint8_t *dst = downsample_image(src, 100, 100, 4, &dw, &dh, 0.5f);
150
    TEST_ASSERT_PTR_NOT_NULL(dst, "Checkerboard downsample");
151
152
    TEST_ASSERT_EQ(dw, 50, "Width halved");
153
    TEST_ASSERT_EQ(dh, 50, "Height halved");
154
155
    free(src);
156
    free(dst);
157
    return TEST_PASSED;
158
}
159
160
static TestCase tests[] = {
161
    {"null_image_handling", test_null_image_handling},
162
    {"zero_dimensions", test_zero_dimensions},
163
    {"scale_one_preserves_size", test_scale_one_preserves_size},
164
    {"downsample_half_size", test_downsample_half_size},
165
    {"minimum_one_pixel", test_minimum_one_pixel},
166
    {"large_image_handling", test_large_image_handling},
167
    {"alpha_channel_preserved", test_alpha_channel_preserved},
168
    {"uniform_color_accuracy", test_uniform_color_accuracy},
169
    {"gradient_smoothness", test_gradient_smoothness},
170
    {"checkerboard_no_aliasing", test_checkerboard_no_aliasing},
171
};
172
173
int main(int argc, char **argv) {
174
    int profile = 0;
175
    for (int i = 1; i < argc; i++) {
176
        if (strcmp(argv[i], "--profile") == 0) {
177
            profile = 1;
178
        }
179
    }
180
181
    if (profile) {
182
        const char *scenarios[] = {"No_Downsampling", "1080p_Target", "1440p_Target", "4K_Target"};
183
        float scales[] = {1.0f, 0.5f, 0.42f, 0.25f};
184
185
        for (int s = 0; s < 4; s++) {
186
            char filename[256];
187
            snprintf(filename, sizeof(filename), "/tmp/chroma_memory_%s.csv", scenarios[s]);
188
189
            FILE *f = fopen(filename, "w");
190
            if (!f) {
191
                fprintf(stderr, "Failed to create %s\n", filename);
192
                continue;
193
            }
194
195
            fprintf(f, "Resolution,OriginalSizeMB,DownsampledSizeMB,MemorySavingsPercent\n");
196
197
            const char *res_names[] = {"1080p", "1440p", "4K", "5K", "6K", "8K"};
198
            int widths[] = {1920, 2560, 3840, 5120, 6016, 7680};
199
            int heights[] = {1080, 1440, 2160, 2880, 3200, 4320};
200
201
            for (int r = 0; r < 6; r++) {
202
                int w = widths[r];
203
                int h = heights[r];
204
                size_t original_bytes = (size_t)w * (size_t)h * 4u;
205
                double original_mb = (double)original_bytes / (1024.0 * 1024.0);
206
207
                int dw, dh;
208
                uint8_t *src = create_noise_image(w, h, 42);
209
                uint8_t *dst = downsample_image(src, w, h, 4, &dw, &dh, scales[s]);
210
                size_t downsampled_bytes = (size_t)dw * (size_t)dh * 4u;
211
                double downsampled_mb = (double)downsampled_bytes / (1024.0 * 1024.0);
212
213
                double savings = 0.0;
214
                if (original_mb > 0) {
215
                    savings = ((original_mb - downsampled_mb) / original_mb) * 100.0;
216
                }
217
218
                fprintf(f, "%s,%.2f,%.2f,%.1f\n", res_names[r], original_mb, downsampled_mb, savings);
219
220
                free(src);
221
                free(dst);
222
            }
223
224
            fclose(f);
225
            printf("Generated: %s\n", filename);
226
        }
227
        return 0;
228
    }
229
230
    (void)argc;
231
    (void)argv;
232
233
    printf("Chroma Unit Tests\n");
234
    printf("=================\n\n");
235
236
    test_failures = 0;
237
    test_total = 0;
238
239
    for (int i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
240
        int result = tests[i].fn();
241
        test_total++;
242
        if (result == TEST_PASSED) {
243
            printf("  [PASS] %s\n", tests[i].name);
244
        } else {
245
            printf("  [FAIL] %s\n", tests[i].name);
246
        }
247
    }
248
249
    printf("\n-----------------\n");
250
    printf("Results: %d/%d passed\n", test_total - test_failures, test_total);
251
252
    return test_failures > 0 ? 1 : 0;
253
}