123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- /*
- * Copyright (c) Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
- #include <stddef.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <linux/zstd.h>
- #define CONTROL(x) \
- do { \
- if (!(x)) { \
- fprintf(stderr, "%s:%u: %s failed!\n", __FUNCTION__, __LINE__, #x); \
- abort(); \
- } \
- } while (0)
- typedef struct {
- char *data;
- char *data2;
- size_t dataSize;
- char *comp;
- size_t compSize;
- } test_data_t;
- static test_data_t create_test_data(void) {
- test_data_t data;
- data.dataSize = 128 * 1024;
- data.data = (char*)malloc(data.dataSize);
- CONTROL(data.data != NULL);
- data.data2 = (char*)malloc(data.dataSize);
- CONTROL(data.data2 != NULL);
- data.compSize = zstd_compress_bound(data.dataSize);
- data.comp = (char*)malloc(data.compSize);
- CONTROL(data.comp != NULL);
- memset(data.data, 0, data.dataSize);
- return data;
- }
- static void free_test_data(test_data_t const *data) {
- free(data->data);
- free(data->data2);
- free(data->comp);
- }
- #define MIN(a, b) ((a) < (b) ? (a) : (b))
- #define MAX(a, b) ((a) > (b) ? (a) : (b))
- static void test_btrfs(test_data_t const *data) {
- size_t const size = MIN(data->dataSize, 128 * 1024);
- fprintf(stderr, "testing btrfs use cases... ");
- for (int level = -1; level < 16; ++level) {
- zstd_parameters params = zstd_get_params(level, size);
- size_t const workspaceSize =
- MAX(zstd_cstream_workspace_bound(¶ms.cParams),
- zstd_dstream_workspace_bound(size));
- void *workspace = malloc(workspaceSize);
- char const *ip = data->data;
- char const *iend = ip + size;
- char *op = data->comp;
- char *oend = op + data->compSize;
- CONTROL(params.cParams.windowLog <= 17);
- CONTROL(workspace != NULL);
- {
- zstd_cstream *cctx = zstd_init_cstream(¶ms, size, workspace, workspaceSize);
- zstd_out_buffer out = {NULL, 0, 0};
- zstd_in_buffer in = {NULL, 0, 0};
- CONTROL(cctx != NULL);
- for (;;) {
- if (in.pos == in.size) {
- in.src = ip;
- in.size = MIN(4096, iend - ip);
- in.pos = 0;
- ip += in.size;
- }
- if (out.pos == out.size) {
- out.dst = op;
- out.size = MIN(4096, oend - op);
- out.pos = 0;
- op += out.size;
- }
- if (ip != iend || in.pos < in.size) {
- CONTROL(!zstd_is_error(zstd_compress_stream(cctx, &out, &in)));
- } else {
- size_t const ret = zstd_end_stream(cctx, &out);
- CONTROL(!zstd_is_error(ret));
- if (ret == 0) {
- break;
- }
- }
- }
- op += out.pos;
- }
- ip = data->comp;
- iend = op;
- op = data->data2;
- oend = op + size;
- {
- zstd_dstream *dctx = zstd_init_dstream(1ULL << params.cParams.windowLog, workspace, workspaceSize);
- zstd_out_buffer out = {NULL, 0, 0};
- zstd_in_buffer in = {NULL, 0, 0};
- CONTROL(dctx != NULL);
- for (;;) {
- if (in.pos == in.size) {
- in.src = ip;
- in.size = MIN(4096, iend - ip);
- in.pos = 0;
- ip += in.size;
- }
- if (out.pos == out.size) {
- out.dst = op;
- out.size = MIN(4096, oend - op);
- out.pos = 0;
- op += out.size;
- }
- {
- size_t const ret = zstd_decompress_stream(dctx, &out, &in);
- CONTROL(!zstd_is_error(ret));
- if (ret == 0) {
- break;
- }
- }
- }
- }
- CONTROL((size_t)(op - data->data2) == data->dataSize);
- CONTROL(!memcmp(data->data, data->data2, data->dataSize));
- free(workspace);
- }
- fprintf(stderr, "Ok\n");
- }
- static void test_decompress_unzstd(test_data_t const *data) {
- size_t cSize;
- fprintf(stderr, "Testing decompress unzstd... ");
- {
- zstd_parameters params = zstd_get_params(19, 0);
- size_t const wkspSize = zstd_cctx_workspace_bound(¶ms.cParams);
- void* wksp = malloc(wkspSize);
- zstd_cctx* cctx = zstd_init_cctx(wksp, wkspSize);
- CONTROL(wksp != NULL);
- CONTROL(cctx != NULL);
- cSize = zstd_compress_cctx(cctx, data->comp, data->compSize, data->data, data->dataSize, ¶ms);
- CONTROL(!zstd_is_error(cSize));
- free(wksp);
- }
- {
- size_t const wkspSize = zstd_dctx_workspace_bound();
- void* wksp = malloc(wkspSize);
- zstd_dctx* dctx = zstd_init_dctx(wksp, wkspSize);
- CONTROL(wksp != NULL);
- CONTROL(dctx != NULL);
- {
- size_t const dSize = zstd_decompress_dctx(dctx, data->data2, data->dataSize, data->comp, cSize);
- CONTROL(!zstd_is_error(dSize));
- CONTROL(dSize == data->dataSize);
- }
- CONTROL(!memcmp(data->data, data->data2, data->dataSize));
- free(wksp);
- }
- fprintf(stderr, "Ok\n");
- }
- static void test_f2fs(void) {
- fprintf(stderr, "testing f2fs uses... ");
- CONTROL(zstd_min_clevel() < 0);
- CONTROL(zstd_max_clevel() == 22);
- fprintf(stderr, "Ok\n");
- }
- static char *g_stack = NULL;
- static void __attribute__((noinline)) use(void *x) {
- asm volatile("" : "+r"(x));
- }
- static void __attribute__((noinline)) set_stack(void) {
- char stack[8192];
- g_stack = stack;
- memset(g_stack, 0x33, 8192);
- use(g_stack);
- }
- static void __attribute__((noinline)) check_stack(void) {
- size_t cleanStack = 0;
- while (cleanStack < 8192 && g_stack[cleanStack] == 0x33) {
- ++cleanStack;
- }
- {
- size_t const stackSize = 8192 - cleanStack;
- fprintf(stderr, "Maximum stack size: %zu\n", stackSize);
- CONTROL(stackSize <= 2048 + 512);
- }
- }
- static void test_stack_usage(test_data_t const *data) {
- set_stack();
- test_f2fs();
- test_btrfs(data);
- test_decompress_unzstd(data);
- check_stack();
- }
- int main(void) {
- test_data_t data = create_test_data();
- test_f2fs();
- test_btrfs(&data);
- test_decompress_unzstd(&data);
- test_stack_usage(&data);
- free_test_data(&data);
- return 0;
- }
|