Files
zstd-rs/tests/rustLibSmoke.c
ddidderr 23d45378bd feat(compress): route complete stream frames through Rust
Route ordinary complete-input ZSTD_compressStream2 calls through the Rust frame compressor while retaining the C state machine for partial, advanced, and dictionary-backed streams. Track explicit maxBlockSize requests so the migrated path preserves the original byte-identical default behavior, and extend the C archive smoke test across context reuse and fallback cases.

Test Plan:

- cargo clippy --manifest-path rust/Cargo.toml

- cargo clippy --manifest-path rust/Cargo.toml --benches

- cargo clippy --manifest-path rust/Cargo.toml --tests

- cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression (133 passed)

- make -B -C tests -j2 test-rust-lib-smoke and ./tests/rustLibSmoke

- make -B -C tests -j2 test-zstream (passed, including both APIs and maxBlockSize case 78)
2026-07-18 01:52:28 +02:00

166 lines
5.8 KiB
C

/*
* Link and run through the installed-style static archive, rather than the
* direct C-object-plus-Rust-archive test path used by the other test tools.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zstd.h"
static int checkError(size_t result, const char* operation)
{
if (!ZSTD_isError(result)) return 0;
fprintf(stderr, "%s: %s\n", operation, ZSTD_getErrorName(result));
return 1;
}
int main(void)
{
enum { sourceSize = 64 * 1024 };
unsigned char source[sourceSize];
size_t const compressedCapacity = ZSTD_compressBound(sourceSize);
void* compressed = malloc(compressedCapacity);
void* restored = malloc(sourceSize);
size_t compressedSize;
size_t restoredSize;
ZSTD_CCtx* cctx = NULL;
ZSTD_DDict* ddict;
size_t index;
if (compressed == NULL || restored == NULL) {
fputs("allocation failed\n", stderr);
free(restored);
free(compressed);
return 1;
}
for (index = 0; index < sourceSize; ++index) {
source[index] = (unsigned char)((index * 13 + index / 97) & 0x1F);
}
compressedSize = ZSTD_compress(compressed, compressedCapacity,
source, sourceSize, 3);
if (checkError(compressedSize, "ZSTD_compress")) goto cleanup;
restoredSize = ZSTD_decompress(restored, sourceSize, compressed, compressedSize);
if (checkError(restoredSize, "ZSTD_decompress")) goto cleanup;
if (restoredSize != sourceSize || memcmp(source, restored, sourceSize) != 0) {
fputs("round trip mismatch\n", stderr);
goto cleanup;
}
cctx = ZSTD_createCCtx();
if (cctx == NULL) {
fputs("CCtx creation failed\n", stderr);
goto cleanup;
}
{
ZSTD_inBuffer input = { source, sourceSize, 0 };
ZSTD_outBuffer output = { compressed, compressedCapacity, 0 };
size_t const remaining = ZSTD_compressStream2(
cctx, &output, &input, ZSTD_e_end);
if (checkError(remaining, "ZSTD_compressStream2")
|| remaining != 0
|| input.pos != input.size) {
fputs("streaming end call did not complete\n", stderr);
goto cleanup;
}
restoredSize = ZSTD_decompress(
restored, sourceSize, compressed, output.pos);
if (checkError(restoredSize, "ZSTD_decompress(stream)")
|| restoredSize != sourceSize
|| memcmp(source, restored, sourceSize) != 0) {
fputs("streaming round trip mismatch\n", stderr);
goto cleanup;
}
}
/* The Rust end path resets the C-owned session before returning. */
{
ZSTD_inBuffer input = { source, sourceSize, 0 };
ZSTD_outBuffer output = { compressed, compressedCapacity, 0 };
size_t const remaining = ZSTD_compressStream2(
cctx, &output, &input, ZSTD_e_end);
if (checkError(remaining, "ZSTD_compressStream2(reuse)")
|| remaining != 0
|| input.pos != input.size) {
fputs("streaming context reuse failed\n", stderr);
goto cleanup;
}
}
if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1))) {
fputs("advanced parameter setup failed\n", stderr);
goto cleanup;
}
{
ZSTD_inBuffer input = { source, sourceSize, 0 };
ZSTD_outBuffer output = { compressed, compressedCapacity, 0 };
size_t const remaining = ZSTD_compressStream2(
cctx, &output, &input, ZSTD_e_end);
if (checkError(remaining, "ZSTD_compressStream2(checksum)")
|| remaining != 0
|| input.pos != input.size) {
fputs("advanced stream fallback did not complete\n", stderr);
goto cleanup;
}
restoredSize = ZSTD_decompress(
restored, sourceSize, compressed, output.pos);
if (checkError(restoredSize, "ZSTD_decompress(checksum)")
|| restoredSize != sourceSize
|| memcmp(source, restored, sourceSize) != 0) {
fputs("advanced stream fallback mismatch\n", stderr);
goto cleanup;
}
}
if (ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters) != 0) {
fputs("CCtx parameter reset failed\n", stderr);
goto cleanup;
}
if (ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters) != 0) {
fputs("CCtx parameter reset failed\n", stderr);
goto cleanup;
}
{
ZSTD_inBuffer input = { source, sourceSize, 0 };
ZSTD_outBuffer output = { compressed, compressedCapacity - 1, 0 };
size_t const remaining = ZSTD_compressStream2(
cctx, &output, &input, ZSTD_e_end);
if (checkError(remaining, "ZSTD_compressStream2(short output)")
|| remaining != 0
|| input.pos != input.size) {
fputs("short-output stream fallback did not complete\n", stderr);
goto cleanup;
}
restoredSize = ZSTD_decompress(
restored, sourceSize, compressed, output.pos);
if (checkError(restoredSize, "ZSTD_decompress(short output)")
|| restoredSize != sourceSize
|| memcmp(source, restored, sourceSize) != 0) {
fputs("short-output stream fallback mismatch\n", stderr);
goto cleanup;
}
}
if (ZSTD_freeCCtx(cctx) != 0) {
fputs("CCtx cleanup failed\n", stderr);
cctx = NULL;
goto cleanup;
}
cctx = NULL;
/* This must pull the Rust DDict object and resolve its C helper cycle. */
ddict = ZSTD_createDDict(NULL, 0);
if (ddict == NULL || ZSTD_freeDDict(ddict) != 0) {
fputs("DDict lifecycle failed\n", stderr);
goto cleanup;
}
free(restored);
free(compressed);
return 0;
cleanup:
ZSTD_freeCCtx(cctx);
free(restored);
free(compressed);
return 1;
}