git subrepo pull (merge) --force deps/libchdr
[pcsx_rearmed.git] / deps / libchdr / deps / zstd-1.5.5 / contrib / linux-kernel / test / test.c
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  * All rights reserved.
4  *
5  * This source code is licensed under both the BSD-style license (found in the
6  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7  * in the COPYING file in the root directory of this source tree).
8  * You may select, at your option, one of the above-listed licenses.
9  */
10 #include <stddef.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include <linux/zstd.h>
16
17 #define CONTROL(x)                                                             \
18   do {                                                                         \
19     if (!(x)) {                                                                \
20       fprintf(stderr, "%s:%u: %s failed!\n", __FUNCTION__, __LINE__, #x);      \
21       abort();                                                                 \
22     }                                                                          \
23   } while (0)
24
25 typedef struct {
26   char *data;
27   char *data2;
28   size_t dataSize;
29   char *comp;
30   size_t compSize;
31 } test_data_t;
32
33 static test_data_t create_test_data(void) {
34   test_data_t data;
35   data.dataSize = 128 * 1024;
36   data.data = (char*)malloc(data.dataSize);
37   CONTROL(data.data != NULL);
38   data.data2 = (char*)malloc(data.dataSize);
39   CONTROL(data.data2 != NULL);
40   data.compSize = zstd_compress_bound(data.dataSize);
41   data.comp = (char*)malloc(data.compSize);
42   CONTROL(data.comp != NULL);
43   memset(data.data, 0, data.dataSize);
44   return data;
45 }
46
47 static void free_test_data(test_data_t const *data) {
48   free(data->data);
49   free(data->data2);
50   free(data->comp);
51 }
52
53 #define MIN(a, b) ((a) < (b) ? (a) : (b))
54 #define MAX(a, b) ((a) > (b) ? (a) : (b))
55
56 static void test_btrfs(test_data_t const *data) {
57   size_t const size = MIN(data->dataSize, 128 * 1024);
58   fprintf(stderr, "testing btrfs use cases... ");
59   for (int level = -1; level < 16; ++level) {
60     zstd_parameters params = zstd_get_params(level, size);
61     size_t const workspaceSize =
62         MAX(zstd_cstream_workspace_bound(&params.cParams),
63             zstd_dstream_workspace_bound(size));
64     void *workspace = malloc(workspaceSize);
65
66     char const *ip = data->data;
67     char const *iend = ip + size;
68     char *op = data->comp;
69     char *oend = op + data->compSize;
70
71     CONTROL(params.cParams.windowLog <= 17);
72     CONTROL(workspace != NULL);
73     {
74       zstd_cstream *cctx = zstd_init_cstream(&params, size, workspace, workspaceSize);
75       zstd_out_buffer out = {NULL, 0, 0};
76       zstd_in_buffer in = {NULL, 0, 0};
77       CONTROL(cctx != NULL);
78       for (;;) {
79         if (in.pos == in.size) {
80           in.src = ip;
81           in.size = MIN(4096, iend - ip);
82           in.pos = 0;
83           ip += in.size;
84         }
85
86         if (out.pos == out.size) {
87           out.dst = op;
88           out.size = MIN(4096, oend - op);
89           out.pos = 0;
90           op += out.size;
91         }
92
93         if (ip != iend || in.pos < in.size) {
94           CONTROL(!zstd_is_error(zstd_compress_stream(cctx, &out, &in)));
95         } else {
96           size_t const ret = zstd_end_stream(cctx, &out);
97           CONTROL(!zstd_is_error(ret));
98           if (ret == 0) {
99             break;
100           }
101         }
102       }
103       op += out.pos;
104     }
105
106     ip = data->comp;
107     iend = op;
108     op = data->data2;
109     oend = op + size;
110     {
111       zstd_dstream *dctx = zstd_init_dstream(1ULL << params.cParams.windowLog, workspace, workspaceSize);
112       zstd_out_buffer out = {NULL, 0, 0};
113       zstd_in_buffer in = {NULL, 0, 0};
114       CONTROL(dctx != NULL);
115       for (;;) {
116         if (in.pos == in.size) {
117           in.src = ip;
118           in.size = MIN(4096, iend - ip);
119           in.pos = 0;
120           ip += in.size;
121         }
122
123         if (out.pos == out.size) {
124           out.dst = op;
125           out.size = MIN(4096, oend - op);
126           out.pos = 0;
127           op += out.size;
128         }
129         {
130           size_t const ret = zstd_decompress_stream(dctx, &out, &in);
131           CONTROL(!zstd_is_error(ret));
132           if (ret == 0) {
133             break;
134           }
135         }
136       }
137     }
138     CONTROL((size_t)(op - data->data2) == data->dataSize);
139     CONTROL(!memcmp(data->data, data->data2, data->dataSize));
140     free(workspace);
141   }
142   fprintf(stderr, "Ok\n");
143 }
144
145 static void test_decompress_unzstd(test_data_t const *data) {
146     size_t cSize;
147     fprintf(stderr, "Testing decompress unzstd... ");
148     {
149         zstd_parameters params = zstd_get_params(19, 0);
150         size_t const wkspSize = zstd_cctx_workspace_bound(&params.cParams);
151         void* wksp = malloc(wkspSize);
152         zstd_cctx* cctx = zstd_init_cctx(wksp, wkspSize);
153         CONTROL(wksp != NULL);
154         CONTROL(cctx != NULL);
155         cSize = zstd_compress_cctx(cctx, data->comp, data->compSize, data->data, data->dataSize, &params);
156         CONTROL(!zstd_is_error(cSize));
157         free(wksp);
158     }
159     {
160         size_t const wkspSize = zstd_dctx_workspace_bound();
161         void* wksp = malloc(wkspSize);
162         zstd_dctx* dctx = zstd_init_dctx(wksp, wkspSize);
163         CONTROL(wksp != NULL);
164         CONTROL(dctx != NULL);
165         {
166           size_t const dSize = zstd_decompress_dctx(dctx, data->data2, data->dataSize, data->comp, cSize);
167           CONTROL(!zstd_is_error(dSize));
168           CONTROL(dSize == data->dataSize);
169         }
170         CONTROL(!memcmp(data->data, data->data2, data->dataSize));
171         free(wksp);
172     }
173     fprintf(stderr, "Ok\n");
174 }
175
176 static void test_f2fs(void) {
177   fprintf(stderr, "testing f2fs uses... ");
178   CONTROL(zstd_min_clevel() < 0);
179   CONTROL(zstd_max_clevel() == 22);
180   fprintf(stderr, "Ok\n");
181 }
182
183 static char *g_stack = NULL;
184
185 static void __attribute__((noinline)) use(void *x) {
186   asm volatile("" : "+r"(x));
187 }
188
189 static void __attribute__((noinline)) fill_stack(void) {
190   memset(g_stack, 0x33, 8192);
191 }
192
193 static void __attribute__((noinline)) set_stack(void) {
194
195   char stack[8192];
196   g_stack = stack;
197   use(g_stack);
198 }
199
200 static void __attribute__((noinline)) check_stack(void) {
201   size_t cleanStack = 0;
202   while (cleanStack < 8192 && g_stack[cleanStack] == 0x33) {
203     ++cleanStack;
204   }
205   {
206     size_t const stackSize = 8192 - cleanStack;
207     fprintf(stderr, "Maximum stack size: %zu\n", stackSize);
208     CONTROL(stackSize <= 2048 + 512);
209   }
210 }
211
212 static void test_stack_usage(test_data_t const *data) {
213   set_stack();
214   fill_stack();
215   test_f2fs();
216   test_btrfs(data);
217   test_decompress_unzstd(data);
218   check_stack();
219 }
220
221 int main(void) {
222   test_data_t data = create_test_data();
223   test_f2fs();
224   test_btrfs(&data);
225   test_decompress_unzstd(&data);
226   test_stack_usage(&data);
227   free_test_data(&data);
228   return 0;
229 }