2
0

test.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. * Copyright (c) Facebook, Inc.
  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. #include <linux/zstd.h>
  15. #define CONTROL(x) \
  16. do { \
  17. if (!(x)) { \
  18. fprintf(stderr, "%s:%u: %s failed!\n", __FUNCTION__, __LINE__, #x); \
  19. abort(); \
  20. } \
  21. } while (0)
  22. typedef struct {
  23. char *data;
  24. char *data2;
  25. size_t dataSize;
  26. char *comp;
  27. size_t compSize;
  28. } test_data_t;
  29. static test_data_t create_test_data(void) {
  30. test_data_t data;
  31. data.dataSize = 128 * 1024;
  32. data.data = (char*)malloc(data.dataSize);
  33. CONTROL(data.data != NULL);
  34. data.data2 = (char*)malloc(data.dataSize);
  35. CONTROL(data.data2 != NULL);
  36. data.compSize = zstd_compress_bound(data.dataSize);
  37. data.comp = (char*)malloc(data.compSize);
  38. CONTROL(data.comp != NULL);
  39. memset(data.data, 0, data.dataSize);
  40. return data;
  41. }
  42. static void free_test_data(test_data_t const *data) {
  43. free(data->data);
  44. free(data->data2);
  45. free(data->comp);
  46. }
  47. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  48. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  49. static void test_btrfs(test_data_t const *data) {
  50. size_t const size = MIN(data->dataSize, 128 * 1024);
  51. fprintf(stderr, "testing btrfs use cases... ");
  52. for (int level = -1; level < 16; ++level) {
  53. zstd_parameters params = zstd_get_params(level, size);
  54. size_t const workspaceSize =
  55. MAX(zstd_cstream_workspace_bound(&params.cParams),
  56. zstd_dstream_workspace_bound(size));
  57. void *workspace = malloc(workspaceSize);
  58. char const *ip = data->data;
  59. char const *iend = ip + size;
  60. char *op = data->comp;
  61. char *oend = op + data->compSize;
  62. CONTROL(params.cParams.windowLog <= 17);
  63. CONTROL(workspace != NULL);
  64. {
  65. zstd_cstream *cctx = zstd_init_cstream(&params, size, workspace, workspaceSize);
  66. zstd_out_buffer out = {NULL, 0, 0};
  67. zstd_in_buffer in = {NULL, 0, 0};
  68. CONTROL(cctx != NULL);
  69. for (;;) {
  70. if (in.pos == in.size) {
  71. in.src = ip;
  72. in.size = MIN(4096, iend - ip);
  73. in.pos = 0;
  74. ip += in.size;
  75. }
  76. if (out.pos == out.size) {
  77. out.dst = op;
  78. out.size = MIN(4096, oend - op);
  79. out.pos = 0;
  80. op += out.size;
  81. }
  82. if (ip != iend || in.pos < in.size) {
  83. CONTROL(!zstd_is_error(zstd_compress_stream(cctx, &out, &in)));
  84. } else {
  85. size_t const ret = zstd_end_stream(cctx, &out);
  86. CONTROL(!zstd_is_error(ret));
  87. if (ret == 0) {
  88. break;
  89. }
  90. }
  91. }
  92. op += out.pos;
  93. }
  94. ip = data->comp;
  95. iend = op;
  96. op = data->data2;
  97. oend = op + size;
  98. {
  99. zstd_dstream *dctx = zstd_init_dstream(1ULL << params.cParams.windowLog, workspace, workspaceSize);
  100. zstd_out_buffer out = {NULL, 0, 0};
  101. zstd_in_buffer in = {NULL, 0, 0};
  102. CONTROL(dctx != NULL);
  103. for (;;) {
  104. if (in.pos == in.size) {
  105. in.src = ip;
  106. in.size = MIN(4096, iend - ip);
  107. in.pos = 0;
  108. ip += in.size;
  109. }
  110. if (out.pos == out.size) {
  111. out.dst = op;
  112. out.size = MIN(4096, oend - op);
  113. out.pos = 0;
  114. op += out.size;
  115. }
  116. {
  117. size_t const ret = zstd_decompress_stream(dctx, &out, &in);
  118. CONTROL(!zstd_is_error(ret));
  119. if (ret == 0) {
  120. break;
  121. }
  122. }
  123. }
  124. }
  125. CONTROL((size_t)(op - data->data2) == data->dataSize);
  126. CONTROL(!memcmp(data->data, data->data2, data->dataSize));
  127. free(workspace);
  128. }
  129. fprintf(stderr, "Ok\n");
  130. }
  131. static void test_decompress_unzstd(test_data_t const *data) {
  132. size_t cSize;
  133. fprintf(stderr, "Testing decompress unzstd... ");
  134. {
  135. zstd_parameters params = zstd_get_params(19, 0);
  136. size_t const wkspSize = zstd_cctx_workspace_bound(&params.cParams);
  137. void* wksp = malloc(wkspSize);
  138. zstd_cctx* cctx = zstd_init_cctx(wksp, wkspSize);
  139. CONTROL(wksp != NULL);
  140. CONTROL(cctx != NULL);
  141. cSize = zstd_compress_cctx(cctx, data->comp, data->compSize, data->data, data->dataSize, &params);
  142. CONTROL(!zstd_is_error(cSize));
  143. free(wksp);
  144. }
  145. {
  146. size_t const wkspSize = zstd_dctx_workspace_bound();
  147. void* wksp = malloc(wkspSize);
  148. zstd_dctx* dctx = zstd_init_dctx(wksp, wkspSize);
  149. CONTROL(wksp != NULL);
  150. CONTROL(dctx != NULL);
  151. {
  152. size_t const dSize = zstd_decompress_dctx(dctx, data->data2, data->dataSize, data->comp, cSize);
  153. CONTROL(!zstd_is_error(dSize));
  154. CONTROL(dSize == data->dataSize);
  155. }
  156. CONTROL(!memcmp(data->data, data->data2, data->dataSize));
  157. free(wksp);
  158. }
  159. fprintf(stderr, "Ok\n");
  160. }
  161. static void test_f2fs(void) {
  162. fprintf(stderr, "testing f2fs uses... ");
  163. CONTROL(zstd_min_clevel() < 0);
  164. CONTROL(zstd_max_clevel() == 22);
  165. fprintf(stderr, "Ok\n");
  166. }
  167. static char *g_stack = NULL;
  168. static void __attribute__((noinline)) use(void *x) {
  169. asm volatile("" : "+r"(x));
  170. }
  171. static void __attribute__((noinline)) set_stack(void) {
  172. char stack[8192];
  173. g_stack = stack;
  174. memset(g_stack, 0x33, 8192);
  175. use(g_stack);
  176. }
  177. static void __attribute__((noinline)) check_stack(void) {
  178. size_t cleanStack = 0;
  179. while (cleanStack < 8192 && g_stack[cleanStack] == 0x33) {
  180. ++cleanStack;
  181. }
  182. {
  183. size_t const stackSize = 8192 - cleanStack;
  184. fprintf(stderr, "Maximum stack size: %zu\n", stackSize);
  185. CONTROL(stackSize <= 2048 + 512);
  186. }
  187. }
  188. static void test_stack_usage(test_data_t const *data) {
  189. set_stack();
  190. test_f2fs();
  191. test_btrfs(data);
  192. test_decompress_unzstd(data);
  193. check_stack();
  194. }
  195. int main(void) {
  196. test_data_t data = create_test_data();
  197. test_f2fs();
  198. test_btrfs(&data);
  199. test_decompress_unzstd(&data);
  200. test_stack_usage(&data);
  201. free_test_data(&data);
  202. return 0;
  203. }