Skip to content

Commit 417cb44

Browse files
committed
zstd: tests: Add a test case for streaming decompression
Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
1 parent 9f9c8b4 commit 417cb44

File tree

1 file changed

+156
-0
lines changed

1 file changed

+156
-0
lines changed

tests/internal/zstd.c

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <fluent-bit/flb_info.h>
44
#include <fluent-bit/flb_mem.h>
55
#include <fluent-bit/flb_zstd.h>
6+
#include <fluent-bit/flb_compression.h>
67
#include "flb_tests_internal.h"
78

89
/* try a small string */
@@ -163,12 +164,167 @@ static void test_decompress_unknown_size()
163164
flb_free(decompressed_data);
164165
}
165166

167+
static void append_to_context(struct flb_decompression_context *ctx, const void *data, size_t size)
168+
{
169+
uint8_t *append_ptr;
170+
size_t available_space;
171+
172+
available_space = flb_decompression_context_get_available_space(ctx);
173+
174+
if (size > available_space) {
175+
size_t required_size = ctx->input_buffer_length + size;
176+
flb_decompression_context_resize_buffer(ctx, required_size);
177+
}
178+
179+
/* Get pointer to the write location */
180+
append_ptr = flb_decompression_context_get_append_buffer(ctx);
181+
TEST_CHECK(append_ptr != NULL);
182+
183+
/* Copy the data */
184+
memcpy(append_ptr, data, size);
185+
186+
ctx->input_buffer_length += size;
187+
}
188+
189+
static void *compress_with_checksum(const void *original_data, size_t original_len,
190+
size_t *compressed_len)
191+
{
192+
ZSTD_CCtx* cctx;
193+
void *compressed_buffer;
194+
size_t bound;
195+
size_t ret;
196+
197+
/* Create a compression context */
198+
cctx = ZSTD_createCCtx();
199+
TEST_CHECK(cctx != NULL);
200+
201+
/*
202+
* THIS IS THE KEY: Explicitly enable content checksums in the frame.
203+
*/
204+
ret = ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1);
205+
TEST_CHECK(!ZSTD_isError(ret));
206+
207+
/* Compress the data */
208+
bound = ZSTD_compressBound(original_len);
209+
compressed_buffer = flb_malloc(bound);
210+
TEST_CHECK(compressed_buffer != NULL);
211+
212+
*compressed_len = ZSTD_compress2(cctx,
213+
compressed_buffer, bound,
214+
original_data, original_len);
215+
216+
TEST_CHECK(!ZSTD_isError(*compressed_len));
217+
218+
ZSTD_freeCCtx(cctx);
219+
220+
return compressed_buffer;
221+
}
222+
223+
void test_zstd_streaming_decompress_multi_chunk(void)
224+
{
225+
struct flb_decompression_context *ctx;
226+
char *output_buf;
227+
size_t output_len;
228+
size_t total_written = 0;
229+
int ret;
230+
size_t chunk1_size = 0;
231+
size_t chunk2_size = 0;
232+
size_t chunk3_size = 0;
233+
char *original_text = "zstd streaming is a feature that must be tested with multiple, uneven chunks!";
234+
size_t original_len;
235+
void *compressed_buf = NULL;
236+
size_t compressed_len = 0;
237+
238+
original_len = strlen(original_text);
239+
compressed_buf = compress_with_checksum(original_text, original_len, &compressed_len);
240+
TEST_CHECK(compressed_buf != NULL);
241+
242+
ctx = flb_decompression_context_create(FLB_COMPRESSION_ALGORITHM_ZSTD, compressed_len);
243+
TEST_CHECK(ctx != NULL);
244+
output_buf = flb_malloc(original_len + 1);
245+
246+
chunk1_size = compressed_len / 3;
247+
chunk2_size = compressed_len / 2;
248+
chunk3_size = compressed_len - chunk1_size - chunk2_size;
249+
250+
append_to_context(ctx, compressed_buf, chunk1_size);
251+
output_len = original_len;
252+
ret = flb_decompress(ctx, output_buf, &output_len);
253+
TEST_CHECK(ret == FLB_DECOMPRESSOR_SUCCESS);
254+
total_written += output_len;
255+
256+
append_to_context(ctx, (char *)compressed_buf + chunk1_size, chunk2_size);
257+
output_len = original_len - total_written;
258+
ret = flb_decompress(ctx, output_buf + total_written, &output_len);
259+
TEST_CHECK(ret == FLB_DECOMPRESSOR_SUCCESS);
260+
total_written += output_len;
261+
262+
append_to_context(ctx, (char *)compressed_buf + chunk1_size + chunk2_size, chunk3_size);
263+
output_len = original_len - total_written;
264+
ret = flb_decompress(ctx, output_buf + total_written, &output_len);
265+
TEST_CHECK(ret == FLB_DECOMPRESSOR_SUCCESS);
266+
total_written += output_len;
267+
268+
TEST_CHECK(total_written == original_len);
269+
TEST_CHECK(memcmp(original_text, output_buf, original_len) == 0);
270+
271+
flb_free(compressed_buf);
272+
flb_free(output_buf);
273+
flb_decompression_context_destroy(ctx);
274+
}
275+
276+
/* In tests/internal/zstd.c */
277+
278+
void test_zstd_streaming_decompress_corrupted_data(void)
279+
{
280+
struct flb_decompression_context *ctx;
281+
char *output_buf;
282+
size_t output_len;
283+
int ret;
284+
char *original_text = "this test ensures corrupted data with a checksum fails";
285+
size_t original_len = strlen(original_text);
286+
void *compressed_buf = NULL;
287+
size_t compressed_len = 0;
288+
char *corrupted_input;
289+
290+
compressed_buf = compress_with_checksum(original_text, original_len, &compressed_len);
291+
TEST_CHECK(compressed_buf != NULL);
292+
293+
ctx = flb_decompression_context_create(FLB_COMPRESSION_ALGORITHM_ZSTD, compressed_len);
294+
TEST_CHECK(ctx != NULL);
295+
296+
/* Create a corrupted copy of the input */
297+
corrupted_input = flb_malloc(compressed_len);
298+
TEST_CHECK(corrupted_input != NULL);
299+
memcpy(corrupted_input, compressed_buf, compressed_len);
300+
/* Corrupt a byte in the middle */
301+
corrupted_input[compressed_len / 2]++;
302+
303+
append_to_context(ctx, corrupted_input, compressed_len);
304+
305+
output_buf = flb_malloc(original_len + 1);
306+
output_len = original_len;
307+
308+
ret = flb_decompress(ctx, output_buf, &output_len);
309+
310+
TEST_CHECK(ret == FLB_DECOMPRESSOR_FAILURE);
311+
TEST_CHECK(ctx->state == FLB_DECOMPRESSOR_STATE_FAILED);
312+
313+
flb_free(compressed_buf);
314+
flb_free(corrupted_input);
315+
flb_free(output_buf);
316+
flb_decompression_context_destroy(ctx);
317+
}
318+
319+
166320
TEST_LIST = {
167321
{ "compress_small_string", test_compress_small_string },
168322
{ "decompress_small_string", test_decompress_small_string },
169323
{ "compress_empty_input", test_compress_empty_input },
170324
{ "decompress_invalid_data", test_decompress_invalid_data },
171325
{ "compress_decompress_large_data", test_compress_decompress_large_data },
172326
{ "decompress_unknown_size", test_decompress_unknown_size },
327+
{ "streaming_decompress_multi_chunk", test_zstd_streaming_decompress_multi_chunk },
328+
{ "streaming_decompress_corrupted_data", test_zstd_streaming_decompress_corrupted_data },
173329
{ NULL, NULL }
174330
};

0 commit comments

Comments
 (0)