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