Skip to content

Commit fc682f1

Browse files
committed
crit: add tests for compress and decompress commands
Add five tests covering compress and decompress round-trips using compress_pages02 which exercises all eight mapping types (anonymous, zeros, shared, file-backed, memfd, read-only, guard pages). Test 1: compressed dump, decompress with crit, restore and verify Test 2: uncompressed dump, compress with crit, restore and verify Test 3: compress already compressed, decompress already decompressed Test 4: compress, decompress, compress -- verify pages are identical Test 5: decompress, compress, decompress -- verify pages are identical Each restore runs the test process which verifies all memory regions byte-by-byte. The round-trip tests also compare md5 checksums of the raw pages data across cycles. When lz4 or CRIU compression support is not available, the tests are skipped gracefully. Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
1 parent 523bae0 commit fc682f1

6 files changed

Lines changed: 215 additions & 4 deletions

File tree

criu/config.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "cpu.h"
1717
#include "crtools.h"
1818
#include "cr_options.h"
19+
#include "compression.h"
1920
#include "filesystems.h"
2021
#include "file-lock.h"
2122
#include "image.h"
@@ -824,8 +825,9 @@ int parse_options(int argc, char **argv, bool *usage_error, bool *has_exec_cmd,
824825
char *endptr;
825826
long accel = strtol(optarg, &endptr, 10);
826827

827-
if (*endptr != '\0' || accel < 1 || accel > 65537) {
828-
pr_err("Invalid --compress-acceleration value '%s' (must be 1..65537)\n", optarg);
828+
if (*endptr != '\0' || accel < 1 || accel > LZ4_MAX_ACCELERATION) {
829+
pr_err("Invalid --compress-acceleration value '%s' (must be 1..%d)\n",
830+
optarg, LZ4_MAX_ACCELERATION);
829831
return 1;
830832
}
831833
opts.compress_acceleration = accel;

criu/include/compression.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
* Higher values skip more match candidates, resulting in
1515
* faster compression but fewer and shorter matches.
1616
* Decompression speed is not affected (~4970 MB/s always).
17-
* Valid range: 1 to LZ4_ACCELERATION_MAX (65537).
17+
* Valid range: 1 to LZ4_MAX_ACCELERATION.
1818
*/
19+
#define LZ4_MAX_ACCELERATION 65537
1920
#define LZ4_DEFAULT_ACCELERATION 1
2021

2122
/*

criu/include/cr_options.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ struct cr_options {
223223
/*
224224
* LZ4 acceleration level for page compression.
225225
* 0 = auto (acceleration 1 for dump, higher for pre-dump).
226-
* 1..65537 = explicit LZ4 acceleration (higher = faster, lower ratio).
226+
* 1..LZ4_MAX_ACCELERATION = explicit LZ4 acceleration (higher = faster, lower ratio).
227227
*/
228228
int compress_acceleration;
229229

test/others/crit/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,7 @@
33
*.txt
44
stats-*
55
*.json
6+
comp/
7+
uncomp/
8+
cdc/
9+
dcd/

test/others/crit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ run: clean
44

55
clean:
66
rm -f *.img *.log *.txt stats-* *.json
7+
rm -rf comp/ uncomp/ cdc/ dcd/

test/others/crit/test.sh

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,211 @@ function run_test2 {
101101
${CRIT} x ./ rss || exit 1
102102
}
103103

104+
ZDTM_DIR="${BASE_DIR}/test/zdtm/static"
105+
106+
function dump_test_process {
107+
# Dump compress_pages02 (covers 8 mapping types: anonymous,
108+
# zero-filled, shared anonymous, file-backed private/shared,
109+
# memfd, read-only, PROT_NONE guard) into the given directory.
110+
# Prints the PID on success.
111+
local dir=$1; shift
112+
local pid
113+
114+
make -C "$ZDTM_DIR" compress_pages02 > /dev/null 2>&1
115+
116+
# Clean stale marker files and run from the test directory
117+
# so zdtm pidfile rename works (same filesystem).
118+
rm -f "$dir"/test.out* "$dir"/test.pid "$dir"/test.file
119+
120+
(cd "$dir" && "$ZDTM_DIR/compress_pages02" \
121+
--pidfile=test.pid \
122+
--outfile=test.out \
123+
--filename=test.file)
124+
125+
# Wait for pidfile
126+
local i=0
127+
while [ $i -lt 50 ]; do
128+
if [ -f "$dir/test.pid" ]; then
129+
break
130+
fi
131+
sleep 0.1
132+
i=$((i + 1))
133+
done
134+
135+
pid=$(cat "$dir/test.pid" 2>/dev/null)
136+
if [ -z "$pid" ] || ! kill -0 "$pid" 2>/dev/null; then
137+
echo "FAIL: test process didn't start"
138+
cat "$dir/test.out" 2>/dev/null
139+
exit 1
140+
fi
141+
142+
if ! $CRIU dump -v4 -o dump.log -D "$dir" -t "$pid" --shell-job "$@"; then
143+
echo "FAIL: dump into $dir"
144+
cat "$dir/dump.log"
145+
kill -9 "$pid" 2>/dev/null
146+
exit 1
147+
fi
148+
echo "$pid"
149+
}
150+
151+
function restore_and_verify {
152+
# Restore from directory, send SIGTERM so compress_pages02
153+
# verifies its own memory, then check the test output for PASS.
154+
local dir=$1
155+
local pid
156+
157+
if ! $CRIU restore -v4 -o restore.log -D "$dir" --shell-job -d; then
158+
echo "FAIL: restore from $dir"
159+
cat "$dir/restore.log"
160+
exit 1
161+
fi
162+
163+
# Get the root PID from the pstree image
164+
pid=$($CRIT decode -i "$dir/pstree.img" 2>/dev/null |
165+
grep -o '"pid": [0-9]*' | head -1 | grep -o '[0-9]*')
166+
167+
if [ -z "$pid" ] || ! kill -0 "$pid" 2>/dev/null; then
168+
echo "FAIL: restored process not running from $dir (pid=$pid)"
169+
exit 1
170+
fi
171+
172+
# Send SIGTERM so compress_pages02 verifies all memory
173+
# regions (zero, pattern, shared, file, memfd, readonly,
174+
# guard) then writes PASS/FAIL to its output file.
175+
kill -TERM "$pid" 2>/dev/null
176+
wait "$pid" 2>/dev/null
177+
sleep 0.5
178+
179+
if ! grep -q PASS "$dir/test.out" 2>/dev/null; then
180+
echo "FAIL: memory verification failed after restore from $dir"
181+
cat "$dir/test.out" 2>/dev/null
182+
exit 1
183+
fi
184+
}
185+
186+
function pages_checksum {
187+
# Print md5sum of all pages-*.img files in a directory.
188+
# This captures the raw page content for comparison.
189+
cat "$1"/pages-*.img | md5sum | awk '{print $1}'
190+
}
191+
192+
function run_test_compress {
193+
echo "=== compress/decompress tests ==="
194+
195+
# -------------------------------------------------------
196+
# Test 1: dump --compress -> decompress -> restore
197+
# -------------------------------------------------------
198+
echo " -- Test 1: compressed dump -> decompress -> restore"
199+
dump_test_process comp/ --compress > /dev/null
200+
201+
$CRIT decompress comp/ || exit 1
202+
203+
# Verify backup files exist
204+
ls comp/pages-*.img.bak > /dev/null 2>&1 || { echo "FAIL: no pages backup"; exit 1; }
205+
ls comp/pagemap-*.img.bak > /dev/null 2>&1 || { echo "FAIL: no pagemap backup"; exit 1; }
206+
ls comp/inventory.img.bak > /dev/null 2>&1 || { echo "FAIL: no inventory backup"; exit 1; }
207+
208+
restore_and_verify comp/
209+
echo " PASS"
210+
211+
# -------------------------------------------------------
212+
# Test 2: dump uncompressed -> compress -> restore
213+
# -------------------------------------------------------
214+
echo " -- Test 2: uncompressed dump -> compress -> restore"
215+
dump_test_process uncomp/ > /dev/null
216+
217+
$CRIT compress uncomp/ --in-place || exit 1
218+
219+
# Verify no backup files with --in-place
220+
if ls uncomp/*.bak > /dev/null 2>&1; then
221+
echo "FAIL: backup files created with --in-place"
222+
exit 1
223+
fi
224+
225+
restore_and_verify uncomp/
226+
echo " PASS"
227+
228+
# -------------------------------------------------------
229+
# Test 3: compress already compressed, decompress already decompressed
230+
# -------------------------------------------------------
231+
echo " -- Test 3: compress already compressed, decompress already decompressed"
232+
$CRIT compress uncomp/ --in-place 2>&1 | grep -q "already compressed" || {
233+
echo "FAIL: compress should report already compressed"
234+
exit 1
235+
}
236+
$CRIT decompress comp/ 2>&1 | grep -q "already decompressed" || {
237+
echo "FAIL: decompress should report already decompressed"
238+
exit 1
239+
}
240+
echo " PASS"
241+
242+
# -------------------------------------------------------
243+
# Test 4: compress -> decompress -> compress produces same pages
244+
# -------------------------------------------------------
245+
echo " -- Test 4: compress -> decompress -> compress stability"
246+
rm -rf cdc/
247+
mkdir -p cdc/
248+
dump_test_process cdc/ > /dev/null
249+
250+
$CRIT compress cdc/ --in-place || exit 1
251+
local sum1
252+
sum1=$(pages_checksum cdc/)
253+
254+
$CRIT decompress cdc/ --in-place || exit 1
255+
$CRIT compress cdc/ --in-place || exit 1
256+
local sum2
257+
sum2=$(pages_checksum cdc/)
258+
259+
if [ "$sum1" != "$sum2" ]; then
260+
echo "FAIL: compress->decompress->compress changed pages data"
261+
echo " first: $sum1"
262+
echo " second: $sum2"
263+
exit 1
264+
fi
265+
266+
restore_and_verify cdc/
267+
echo " PASS"
268+
269+
# -------------------------------------------------------
270+
# Test 5: decompress -> compress -> decompress produces same pages
271+
# -------------------------------------------------------
272+
echo " -- Test 5: decompress -> compress -> decompress stability"
273+
rm -rf dcd/
274+
mkdir -p dcd/
275+
dump_test_process dcd/ --compress > /dev/null
276+
277+
$CRIT decompress dcd/ --in-place || exit 1
278+
local sum3
279+
sum3=$(pages_checksum dcd/)
280+
281+
$CRIT compress dcd/ --in-place || exit 1
282+
$CRIT decompress dcd/ --in-place || exit 1
283+
local sum4
284+
sum4=$(pages_checksum dcd/)
285+
286+
if [ "$sum3" != "$sum4" ]; then
287+
echo "FAIL: decompress->compress->decompress changed pages data"
288+
echo " first: $sum3"
289+
echo " second: $sum4"
290+
exit 1
291+
fi
292+
293+
restore_and_verify dcd/
294+
echo " PASS"
295+
296+
echo "=== compress/decompress: ALL PASS ==="
297+
}
298+
104299
${CRIT} --version
105300

106301
gen_imgs
107302
run_test1
108303
run_test2
304+
305+
# Skip compress/decompress tests if lz4 or CRIU compression is unavailable
306+
if python3 -c "import lz4.block" 2>/dev/null && $CRIU check --feature compress 2>/dev/null; then
307+
mkdir -p comp/ uncomp/
308+
run_test_compress
309+
else
310+
echo "=== Skipping compress/decompress tests (lz4 or CRIU compression not available) ==="
311+
fi

0 commit comments

Comments
 (0)