1#!/bin/sh -e
2
3die() {
4    $ECHO "$@" 1>&2
5    exit 1
6}
7
8roundTripTest() {
9    if [ -n "$3" ]; then
10        cLevel="$3"
11        proba="$2"
12    else
13        cLevel="$2"
14        proba=""
15    fi
16    if [ -n "$4" ]; then
17        dLevel="$4"
18    else
19        dLevel="$cLevel"
20    fi
21
22    rm -f tmp1 tmp2
23    $ECHO "roundTripTest: ./datagen $1 $proba | $ZSTD -v$cLevel | $ZSTD -d$dLevel"
24    ./datagen $1 $proba | $MD5SUM > tmp1
25    ./datagen $1 $proba | $ZSTD --ultra -v$cLevel | $ZSTD -d$dLevel  | $MD5SUM > tmp2
26    $DIFF -q tmp1 tmp2
27}
28
29fileRoundTripTest() {
30    if [ -n "$3" ]; then
31        local_c="$3"
32        local_p="$2"
33    else
34        local_c="$2"
35        local_p=""
36    fi
37    if [ -n "$4" ]; then
38        local_d="$4"
39    else
40        local_d="$local_c"
41    fi
42
43    rm -f tmp.zstd tmp.md5.1 tmp.md5.2
44    $ECHO "fileRoundTripTest: ./datagen $1 $local_p > tmp && $ZSTD -v$local_c -c tmp | $ZSTD -d$local_d"
45    ./datagen $1 $local_p > tmp
46    < tmp $MD5SUM > tmp.md5.1
47    $ZSTD --ultra -v$local_c -c tmp | $ZSTD -d$local_d | $MD5SUM > tmp.md5.2
48    $DIFF -q tmp.md5.1 tmp.md5.2
49}
50
51truncateLastByte() {
52	dd bs=1 count=$(($(wc -c < "$1") - 1)) if="$1" status=none
53}
54
55UNAME=$(uname)
56
57isTerminal=false
58if [ -t 0 ] && [ -t 1 ]
59then
60    isTerminal=true
61fi
62
63isWindows=false
64INTOVOID="/dev/null"
65case "$UNAME" in
66  GNU) DEVDEVICE="/dev/random" ;;
67  *) DEVDEVICE="/dev/zero" ;;
68esac
69case "$OS" in
70  Windows*)
71    isWindows=true
72    INTOVOID="NUL"
73    DEVDEVICE="NUL"
74    ;;
75esac
76
77case "$UNAME" in
78  Darwin) MD5SUM="md5 -r" ;;
79  FreeBSD) MD5SUM="gmd5sum" ;;
80  OpenBSD) MD5SUM="md5" ;;
81  *) MD5SUM="md5sum" ;;
82esac
83
84DIFF="diff"
85case "$UNAME" in
86  SunOS) DIFF="gdiff" ;;
87esac
88
89ECHO="echo -e"
90case "$UNAME" in
91  Darwin) ECHO="echo" ;;
92esac
93
94$ECHO "\nStarting playTests.sh isWindows=$isWindows ZSTD='$ZSTD'"
95
96[ -n "$ZSTD" ] || die "ZSTD variable must be defined!"
97
98if [ -n "$(echo hello | $ZSTD -v -T2 2>&1 > $INTOVOID | grep 'multi-threading is disabled')" ]
99then
100    hasMT=""
101else
102    hasMT="true"
103fi
104
105
106
107$ECHO "\n===>  simple tests "
108
109./datagen > tmp
110$ECHO "test : basic compression "
111$ZSTD -f tmp                      # trivial compression case, creates tmp.zst
112$ECHO "test : basic decompression"
113$ZSTD -df tmp.zst                 # trivial decompression case (overwrites tmp)
114$ECHO "test : too large compression level => auto-fix"
115$ZSTD -99 -f tmp  # too large compression level, automatic sized down
116$ZSTD -5000000000 -f tmp && die "too large numeric value : must fail"
117$ECHO "test : --fast aka negative compression levels"
118$ZSTD --fast -f tmp  # == -1
119$ZSTD --fast=3 -f tmp  # == -3
120$ZSTD --fast=200000 -f tmp  # too low compression level, automatic fixed
121$ZSTD --fast=5000000000 -f tmp && die "too large numeric value : must fail"
122$ZSTD -c --fast=0 tmp > $INTOVOID && die "--fast must not accept value 0"
123$ECHO "test : too large numeric argument"
124$ZSTD --fast=9999999999 -f tmp  && die "should have refused numeric value"
125$ECHO "test : compress to stdout"
126$ZSTD tmp -c > tmpCompressed
127$ZSTD tmp --stdout > tmpCompressed       # long command format
128$ECHO "test : compress to named file"
129rm tmpCompressed
130$ZSTD tmp -o tmpCompressed
131test -f tmpCompressed   # file must be created
132$ECHO "test : -o must be followed by filename (must fail)"
133$ZSTD tmp -of tmpCompressed && die "-o must be followed by filename "
134$ECHO "test : force write, correct order"
135$ZSTD tmp -fo tmpCompressed
136$ECHO "test : forgotten argument"
137cp tmp tmp2
138$ZSTD tmp2 -fo && die "-o must be followed by filename "
139$ECHO "test : implied stdout when input is stdin"
140$ECHO bob | $ZSTD | $ZSTD -d
141if [ "$isTerminal" = true ]; then
142$ECHO "test : compressed data to terminal"
143$ECHO bob | $ZSTD && die "should have refused : compressed data to terminal"
144$ECHO "test : compressed data from terminal (a hang here is a test fail, zstd is wrongly waiting on data from terminal)"
145$ZSTD -d > $INTOVOID && die "should have refused : compressed data from terminal"
146fi
147$ECHO "test : null-length file roundtrip"
148$ECHO -n '' | $ZSTD - --stdout | $ZSTD -d --stdout
149$ECHO "test : ensure small file doesn't add 3-bytes null block"
150./datagen -g1 > tmp1
151$ZSTD tmp1 -c | wc -c | grep "14"
152$ZSTD < tmp1  | wc -c | grep "14"
153$ECHO "test : decompress file with wrong suffix (must fail)"
154$ZSTD -d tmpCompressed && die "wrong suffix error not detected!"
155$ZSTD -df tmp && die "should have refused : wrong extension"
156$ECHO "test : decompress into stdout"
157$ZSTD -d tmpCompressed -c > tmpResult    # decompression using stdout
158$ZSTD --decompress tmpCompressed -c > tmpResult
159$ZSTD --decompress tmpCompressed --stdout > tmpResult
160$ECHO "test : decompress from stdin into stdout"
161$ZSTD -dc   < tmp.zst > $INTOVOID   # combine decompression, stdin & stdout
162$ZSTD -dc - < tmp.zst > $INTOVOID
163$ZSTD -d    < tmp.zst > $INTOVOID   # implicit stdout when stdin is used
164$ZSTD -d  - < tmp.zst > $INTOVOID
165$ECHO "test : impose memory limitation (must fail)"
166$ZSTD -d -f tmp.zst -M2K -c > $INTOVOID && die "decompression needs more memory than allowed"
167$ZSTD -d -f tmp.zst --memlimit=2K -c > $INTOVOID && die "decompression needs more memory than allowed"  # long command
168$ZSTD -d -f tmp.zst --memory=2K -c > $INTOVOID && die "decompression needs more memory than allowed"  # long command
169$ZSTD -d -f tmp.zst --memlimit-decompress=2K -c > $INTOVOID && die "decompression needs more memory than allowed"  # long command
170$ECHO "test : overwrite protection"
171$ZSTD -q tmp && die "overwrite check failed!"
172$ECHO "test : force overwrite"
173$ZSTD -q -f tmp
174$ZSTD -q --force tmp
175$ECHO "test : overwrite readonly file"
176rm -f tmpro tmpro.zst
177$ECHO foo > tmpro.zst
178$ECHO foo > tmpro
179chmod 400 tmpro.zst
180$ZSTD -q tmpro && die "should have refused to overwrite read-only file"
181$ZSTD -q -f tmpro
182rm -f tmpro tmpro.zst
183
184
185$ECHO "test : file removal"
186$ZSTD -f --rm tmp
187test ! -f tmp  # tmp should no longer be present
188$ZSTD -f -d --rm tmp.zst
189test ! -f tmp.zst   # tmp.zst should no longer be present
190$ECHO "test : should quietly not remove non-regular file"
191$ECHO hello > tmp
192$ZSTD tmp -f -o "$DEVDEVICE" 2>tmplog > "$INTOVOID"
193grep -v "Refusing to remove non-regular file" tmplog
194rm -f tmplog
195$ZSTD tmp -f -o "$INTOVOID" 2>&1 | grep -v "Refusing to remove non-regular file"
196$ECHO "test : --rm on stdin"
197$ECHO a | $ZSTD --rm > $INTOVOID   # --rm should remain silent
198rm tmp
199$ZSTD -f tmp && die "tmp not present : should have failed"
200test ! -f tmp.zst  # tmp.zst should not be created
201$ECHO "test : -d -f do not delete destination when source is not present"
202touch tmp    # create destination file
203$ZSTD -d -f tmp.zst && die "attempt to decompress a non existing file"
204test -f tmp  # destination file should still be present
205$ECHO "test : -f do not delete destination when source is not present"
206rm tmp         # erase source file
207touch tmp.zst  # create destination file
208$ZSTD -f tmp && die "attempt to compress a non existing file"
209test -f tmp.zst  # destination file should still be present
210rm tmp*
211
212
213$ECHO "test : compress multiple files"
214$ECHO hello > tmp1
215$ECHO world > tmp2
216$ZSTD tmp1 tmp2 -o "$INTOVOID"
217$ZSTD tmp1 tmp2 -c | $ZSTD -t
218$ZSTD tmp1 tmp2 -o tmp.zst
219test ! -f tmp1.zst
220test ! -f tmp2.zst
221$ZSTD tmp1 tmp2
222$ZSTD -t tmp1.zst tmp2.zst
223$ZSTD -dc tmp1.zst tmp2.zst
224$ZSTD tmp1.zst tmp2.zst -o "$INTOVOID"
225$ZSTD -d tmp1.zst tmp2.zst -o tmp
226touch tmpexists
227$ZSTD tmp1 tmp2 -f -o tmpexists
228$ZSTD tmp1 tmp2 -o tmpexists && die "should have refused to overwrite"
229# Bug: PR #972
230if [ "$?" -eq 139 ]; then
231  die "should not have segfaulted"
232fi
233rm tmp*
234
235
236$ECHO "\n===>  Advanced compression parameters "
237$ECHO "Hello world!" | $ZSTD --zstd=windowLog=21,      - -o tmp.zst && die "wrong parameters not detected!"
238$ECHO "Hello world!" | $ZSTD --zstd=windowLo=21        - -o tmp.zst && die "wrong parameters not detected!"
239$ECHO "Hello world!" | $ZSTD --zstd=windowLog=21,slog  - -o tmp.zst && die "wrong parameters not detected!"
240test ! -f tmp.zst  # tmp.zst should not be created
241roundTripTest -g512K
242roundTripTest -g512K " --zstd=slen=3,tlen=48,strat=6"
243roundTripTest -g512K " --zstd=strat=6,wlog=23,clog=23,hlog=22,slog=6"
244roundTripTest -g512K " --zstd=windowLog=23,chainLog=23,hashLog=22,searchLog=6,searchLength=3,targetLength=48,strategy=6"
245roundTripTest -g512K " --single-thread --long --zstd=ldmHashLog=20,ldmSearchLength=64,ldmBucketSizeLog=1,ldmHashEveryLog=7"
246roundTripTest -g512K " --single-thread --long --zstd=ldmhlog=20,ldmslen=64,ldmblog=1,ldmhevery=7"
247roundTripTest -g512K 19
248
249
250$ECHO "\n===>  Pass-Through mode "
251$ECHO "Hello world 1!" | $ZSTD -df
252$ECHO "Hello world 2!" | $ZSTD -dcf
253$ECHO "Hello world 3!" > tmp1
254$ZSTD -dcf tmp1
255
256
257$ECHO "\n===>  frame concatenation "
258
259$ECHO "hello " > hello.tmp
260$ECHO "world!" > world.tmp
261cat hello.tmp world.tmp > helloworld.tmp
262$ZSTD -c hello.tmp > hello.zstd
263$ZSTD -c world.tmp > world.zstd
264cat hello.zstd world.zstd > helloworld.zstd
265$ZSTD -dc helloworld.zstd > result.tmp
266cat result.tmp
267$DIFF helloworld.tmp result.tmp
268$ECHO "frame concatenation without checksum"
269$ZSTD -c hello.tmp > hello.zstd --no-check
270$ZSTD -c world.tmp > world.zstd --no-check
271cat hello.zstd world.zstd > helloworld.zstd
272$ZSTD -dc helloworld.zstd > result.tmp
273$DIFF helloworld.tmp result.tmp
274$ECHO "testing zstdcat symlink"
275ln -sf $ZSTD zstdcat
276./zstdcat helloworld.zstd > result.tmp
277$DIFF helloworld.tmp result.tmp
278rm zstdcat
279rm result.tmp
280$ECHO "testing zcat symlink"
281ln -sf $ZSTD zcat
282./zcat helloworld.zstd > result.tmp
283$DIFF helloworld.tmp result.tmp
284rm zcat
285rm ./*.tmp ./*.zstd
286$ECHO "frame concatenation tests completed"
287
288
289if [ "$isWindows" = false ] && [ "$UNAME" != 'SunOS' ] && [ "$UNAME" != "OpenBSD" ] ; then
290$ECHO "\n**** flush write error test **** "
291
292$ECHO "$ECHO foo | $ZSTD > /dev/full"
293$ECHO foo | $ZSTD > /dev/full && die "write error not detected!"
294$ECHO "$ECHO foo | $ZSTD | $ZSTD -d > /dev/full"
295$ECHO foo | $ZSTD | $ZSTD -d > /dev/full && die "write error not detected!"
296
297
298$ECHO "\n===>  symbolic link test "
299
300rm -f hello.tmp world.tmp hello.tmp.zst world.tmp.zst
301$ECHO "hello world" > hello.tmp
302ln -s hello.tmp world.tmp
303$ZSTD world.tmp hello.tmp
304test -f hello.tmp.zst  # regular file should have been compressed!
305test ! -f world.tmp.zst  # symbolic link should not have been compressed!
306$ZSTD world.tmp hello.tmp -f
307test -f world.tmp.zst  # symbolic link should have been compressed with --force
308rm -f hello.tmp world.tmp hello.tmp.zst world.tmp.zst
309
310fi
311
312
313$ECHO "\n===>  test sparse file support "
314
315./datagen -g5M  -P100 > tmpSparse
316$ZSTD tmpSparse -c | $ZSTD -dv -o tmpSparseRegen
317$DIFF -s tmpSparse tmpSparseRegen
318$ZSTD tmpSparse -c | $ZSTD -dv --sparse -c > tmpOutSparse
319$DIFF -s tmpSparse tmpOutSparse
320$ZSTD tmpSparse -c | $ZSTD -dv --no-sparse -c > tmpOutNoSparse
321$DIFF -s tmpSparse tmpOutNoSparse
322ls -ls tmpSparse*  # look at file size and block size on disk
323./datagen -s1 -g1200007 -P100 | $ZSTD | $ZSTD -dv --sparse -c > tmpSparseOdd   # Odd size file (to not finish on an exact nb of blocks)
324./datagen -s1 -g1200007 -P100 | $DIFF -s - tmpSparseOdd
325ls -ls tmpSparseOdd  # look at file size and block size on disk
326$ECHO "\n Sparse Compatibility with Console :"
327$ECHO "Hello World 1 !" | $ZSTD | $ZSTD -d -c
328$ECHO "Hello World 2 !" | $ZSTD | $ZSTD -d | cat
329$ECHO "\n Sparse Compatibility with Append :"
330./datagen -P100 -g1M > tmpSparse1M
331cat tmpSparse1M tmpSparse1M > tmpSparse2M
332$ZSTD -v -f tmpSparse1M -o tmpSparseCompressed
333$ZSTD -d -v -f tmpSparseCompressed -o tmpSparseRegenerated
334$ZSTD -d -v -f tmpSparseCompressed -c >> tmpSparseRegenerated
335ls -ls tmpSparse*  # look at file size and block size on disk
336$DIFF tmpSparse2M tmpSparseRegenerated
337rm tmpSparse*
338
339
340$ECHO "\n===>  multiple files tests "
341
342./datagen -s1        > tmp1 2> $INTOVOID
343./datagen -s2 -g100K > tmp2 2> $INTOVOID
344./datagen -s3 -g1M   > tmp3 2> $INTOVOID
345$ECHO "compress tmp* : "
346$ZSTD -f tmp*
347ls -ls tmp*
348rm tmp1 tmp2 tmp3
349$ECHO "decompress tmp* : "
350$ZSTD -df *.zst
351ls -ls tmp*
352$ECHO "compress tmp* into stdout > tmpall : "
353$ZSTD -c tmp1 tmp2 tmp3 > tmpall
354ls -ls tmp*  # check size of tmpall (should be tmp1.zst + tmp2.zst + tmp3.zst)
355$ECHO "decompress tmpall* into stdout > tmpdec : "
356cp tmpall tmpall2
357$ZSTD -dc tmpall* > tmpdec
358ls -ls tmp* # check size of tmpdec (should be 2*(tmp1 + tmp2 + tmp3))
359$ECHO "compress multiple files including a missing one (notHere) : "
360$ZSTD -f tmp1 notHere tmp2 && die "missing file not detected!"
361
362
363$ECHO "\n===>  dictionary tests "
364
365$ECHO "- test with raw dict (content only) "
366./datagen > tmpDict
367./datagen -g1M | $MD5SUM > tmp1
368./datagen -g1M | $ZSTD -D tmpDict | $ZSTD -D tmpDict -dvq | $MD5SUM > tmp2
369$DIFF -q tmp1 tmp2
370$ECHO "- Create first dictionary "
371TESTFILE=../programs/zstdcli.c
372$ZSTD --train *.c ../programs/*.c -o tmpDict
373cp $TESTFILE tmp
374$ECHO "- Dictionary compression roundtrip"
375$ZSTD -f tmp -D tmpDict
376$ZSTD -d tmp.zst -D tmpDict -fo result
377$DIFF $TESTFILE result
378$ECHO "- Dictionary compression with btlazy2 strategy"
379$ZSTD -f tmp -D tmpDict --zstd=strategy=6
380$ZSTD -d tmp.zst -D tmpDict -fo result
381$DIFF $TESTFILE result
382if [ -n "$hasMT" ]
383then
384    $ECHO "- Test dictionary compression with multithreading "
385    ./datagen -g5M | $ZSTD -T2 -D tmpDict | $ZSTD -t -D tmpDict   # fails with v1.3.2
386fi
387$ECHO "- Create second (different) dictionary "
388$ZSTD --train *.c ../programs/*.c ../programs/*.h -o tmpDictC
389$ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!"
390$ECHO "- Create dictionary with short dictID"
391$ZSTD --train *.c ../programs/*.c --dictID=1 -o tmpDict1
392cmp tmpDict tmpDict1 && die "dictionaries should have different ID !"
393$ECHO "- Create dictionary with wrong dictID parameter order (must fail)"
394$ZSTD --train *.c ../programs/*.c --dictID -o 1 tmpDict1 && die "wrong order : --dictID must be followed by argument "
395$ECHO "- Create dictionary with size limit"
396$ZSTD --train *.c ../programs/*.c -o tmpDict2 --maxdict=4K -v
397$ECHO "- Create dictionary with small size limit"
398$ZSTD --train *.c ../programs/*.c -o tmpDict3 --maxdict=1K -v
399$ECHO "- Create dictionary with wrong parameter order (must fail)"
400$ZSTD --train *.c ../programs/*.c -o tmpDict3 --maxdict -v 4K && die "wrong order : --maxdict must be followed by argument "
401$ECHO "- Compress without dictID"
402$ZSTD -f tmp -D tmpDict1 --no-dictID
403$ZSTD -d tmp.zst -D tmpDict -fo result
404$DIFF $TESTFILE result
405$ECHO "- Compress with wrong argument order (must fail)"
406$ZSTD tmp -Df tmpDict1 -c > $INTOVOID && die "-D must be followed by dictionary name "
407$ECHO "- Compress multiple files with dictionary"
408rm -rf dirTestDict
409mkdir dirTestDict
410cp *.c dirTestDict
411cp ../programs/*.c dirTestDict
412cp ../programs/*.h dirTestDict
413$MD5SUM dirTestDict/* > tmph1
414$ZSTD -f --rm dirTestDict/* -D tmpDictC
415$ZSTD -d --rm dirTestDict/*.zst -D tmpDictC  # note : use internal checksum by default
416case "$UNAME" in
417  Darwin) $ECHO "md5sum -c not supported on OS-X : test skipped" ;;  # not compatible with OS-X's md5
418  *) $MD5SUM -c tmph1 ;;
419esac
420rm -rf dirTestDict
421$ECHO "- dictionary builder on bogus input"
422$ECHO "Hello World" > tmp
423$ZSTD --train-legacy -q tmp && die "Dictionary training should fail : not enough input source"
424./datagen -P0 -g10M > tmp
425$ZSTD --train-legacy -q tmp && die "Dictionary training should fail : source is pure noise"
426$ECHO "- Test -o before --train"
427rm -f tmpDict dictionary
428$ZSTD -o tmpDict --train *.c ../programs/*.c
429test -f tmpDict
430$ZSTD --train *.c ../programs/*.c
431test -f dictionary
432rm tmp* dictionary
433
434
435$ECHO "\n===>  fastCover dictionary builder : advanced options "
436
437TESTFILE=../programs/zstdcli.c
438./datagen > tmpDict
439$ECHO "- Create first dictionary"
440$ZSTD --train-fastcover=k=46,d=8,f=15,split=80 *.c ../programs/*.c -o tmpDict
441cp $TESTFILE tmp
442$ZSTD -f tmp -D tmpDict
443$ZSTD -d tmp.zst -D tmpDict -fo result
444$DIFF $TESTFILE result
445$ECHO "- Create second (different) dictionary"
446$ZSTD --train-fastcover=k=56,d=8 *.c ../programs/*.c ../programs/*.h -o tmpDictC
447$ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!"
448$ECHO "- Create dictionary with short dictID"
449$ZSTD --train-fastcover=k=46,d=8,f=15,split=80 *.c ../programs/*.c --dictID=1 -o tmpDict1
450cmp tmpDict tmpDict1 && die "dictionaries should have different ID !"
451$ECHO "- Create dictionary with size limit"
452$ZSTD --train-fastcover=steps=8 *.c ../programs/*.c -o tmpDict2 --maxdict=4K
453$ECHO "- Compare size of dictionary from 90% training samples with 80% training samples"
454$ZSTD --train-fastcover=split=90 -r *.c ../programs/*.c
455$ZSTD --train-fastcover=split=80 -r *.c ../programs/*.c
456$ECHO "- Create dictionary using all samples for both training and testing"
457$ZSTD --train-fastcover=split=100 -r *.c ../programs/*.c
458$ECHO "- Create dictionary using f=16"
459$ZSTD --train-fastcover=f=16 -r *.c ../programs/*.c
460$ECHO "- Create dictionary using accel=2"
461$ZSTD --train-fastcover=accel=2 -r *.c ../programs/*.c
462$ECHO "- Create dictionary using accel=10"
463$ZSTD --train-fastcover=accel=10 -r *.c ../programs/*.c
464$ECHO "- Create dictionary with multithreading"
465$ZSTD --train-fastcover -T4 -r *.c ../programs/*.c
466$ECHO "- Test -o before --train-fastcover"
467rm -f tmpDict dictionary
468$ZSTD -o tmpDict --train-fastcover *.c ../programs/*.c
469test -f tmpDict
470$ZSTD --train-fastcover *.c ../programs/*.c
471test -f dictionary
472rm tmp* dictionary
473
474
475$ECHO "\n===>  legacy dictionary builder "
476
477TESTFILE=../programs/zstdcli.c
478./datagen > tmpDict
479$ECHO "- Create first dictionary"
480$ZSTD --train-legacy=selectivity=8 *.c ../programs/*.c -o tmpDict
481cp $TESTFILE tmp
482$ZSTD -f tmp -D tmpDict
483$ZSTD -d tmp.zst -D tmpDict -fo result
484$DIFF $TESTFILE result
485$ECHO "- Create second (different) dictionary"
486$ZSTD --train-legacy=s=5 *.c ../programs/*.c ../programs/*.h -o tmpDictC
487$ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!"
488$ECHO "- Create dictionary with short dictID"
489$ZSTD --train-legacy -s5 *.c ../programs/*.c --dictID=1 -o tmpDict1
490cmp tmpDict tmpDict1 && die "dictionaries should have different ID !"
491$ECHO "- Create dictionary with size limit"
492$ZSTD --train-legacy -s9 *.c ../programs/*.c -o tmpDict2 --maxdict=4K
493$ECHO "- Test -o before --train-legacy"
494rm -f tmpDict dictionary
495$ZSTD -o tmpDict --train-legacy *.c ../programs/*.c
496test -f tmpDict
497$ZSTD --train-legacy *.c ../programs/*.c
498test -f dictionary
499rm tmp* dictionary
500
501
502$ECHO "\n===>  integrity tests "
503
504$ECHO "test one file (tmp1.zst) "
505./datagen > tmp1
506$ZSTD tmp1
507$ZSTD -t tmp1.zst
508$ZSTD --test tmp1.zst
509$ECHO "test multiple files (*.zst) "
510$ZSTD -t *.zst
511$ECHO "test bad files (*) "
512$ZSTD -t * && die "bad files not detected !"
513$ZSTD -t tmp1 && die "bad file not detected !"
514cp tmp1 tmp2.zst
515$ZSTD -t tmp2.zst && die "bad file not detected !"
516./datagen -g0 > tmp3
517$ZSTD -t tmp3 && die "bad file not detected !"   # detects 0-sized files as bad
518$ECHO "test --rm and --test combined "
519$ZSTD -t --rm tmp1.zst
520test -f tmp1.zst   # check file is still present
521split -b16384 tmp1.zst tmpSplit.
522$ZSTD -t tmpSplit.* && die "bad file not detected !"
523./datagen | $ZSTD -c | $ZSTD -t
524
525
526
527$ECHO "\n===>  golden files tests "
528
529$ZSTD -t -r files
530$ZSTD -c -r files | $ZSTD -t
531
532
533$ECHO "\n===>  benchmark mode tests "
534
535$ECHO "bench one file"
536./datagen > tmp1
537$ZSTD -bi0 tmp1
538$ECHO "bench multiple levels"
539$ZSTD -i0b0e3 tmp1
540$ECHO "bench negative level"
541$ZSTD -bi0 --fast tmp1
542$ECHO "with recursive and quiet modes"
543$ZSTD -rqi1b1e2 tmp1
544$ECHO "benchmark decompression only"
545$ZSTD -f tmp1
546$ZSTD -b -d -i1 tmp1.zst
547
548$ECHO "\n===>  zstd compatibility tests "
549
550./datagen > tmp
551rm -f tmp.zst
552$ZSTD --format=zstd -f tmp
553test -f tmp.zst
554
555$ECHO "\n===>  gzip compatibility tests "
556
557GZIPMODE=1
558$ZSTD --format=gzip -V || GZIPMODE=0
559if [ $GZIPMODE -eq 1 ]; then
560    $ECHO "gzip support detected"
561    GZIPEXE=1
562    gzip -V || GZIPEXE=0
563    if [ $GZIPEXE -eq 1 ]; then
564        ./datagen > tmp
565        $ZSTD --format=gzip -f tmp
566        gzip -t -v tmp.gz
567        gzip -f tmp
568        $ZSTD -d -f -v tmp.gz
569        rm tmp*
570    else
571        $ECHO "gzip binary not detected"
572    fi
573else
574    $ECHO "gzip mode not supported"
575fi
576
577
578$ECHO "\n===>  gzip frame tests "
579
580if [ $GZIPMODE -eq 1 ]; then
581    ./datagen > tmp
582    $ZSTD -f --format=gzip tmp
583    $ZSTD -f tmp
584    cat tmp.gz tmp.zst tmp.gz tmp.zst | $ZSTD -d -f -o tmp
585    truncateLastByte tmp.gz | $ZSTD -t > $INTOVOID && die "incomplete frame not detected !"
586    rm tmp*
587else
588    $ECHO "gzip mode not supported"
589fi
590
591if [ $GZIPMODE -eq 1 ]; then
592    ./datagen > tmp
593    rm -f tmp.zst
594    $ZSTD --format=gzip --format=zstd -f tmp
595    test -f tmp.zst
596fi
597
598$ECHO "\n===>  xz compatibility tests "
599
600LZMAMODE=1
601$ZSTD --format=xz -V || LZMAMODE=0
602if [ $LZMAMODE -eq 1 ]; then
603    $ECHO "xz support detected"
604    XZEXE=1
605    xz -Q -V && lzma -Q -V || XZEXE=0
606    if [ $XZEXE -eq 1 ]; then
607        $ECHO "Testing zstd xz and lzma support"
608        ./datagen > tmp
609        $ZSTD --format=lzma -f tmp
610        $ZSTD --format=xz -f tmp
611        xz -Q -t -v tmp.xz
612        xz -Q -t -v tmp.lzma
613        xz -Q -f -k tmp
614        lzma -Q -f -k --lzma1 tmp
615        $ZSTD -d -f -v tmp.xz
616        $ZSTD -d -f -v tmp.lzma
617        rm tmp*
618        $ECHO "Creating symlinks"
619        ln -s $ZSTD ./xz
620        ln -s $ZSTD ./unxz
621        ln -s $ZSTD ./lzma
622        ln -s $ZSTD ./unlzma
623        $ECHO "Testing xz and lzma symlinks"
624        ./datagen > tmp
625        ./xz tmp
626        xz -Q -d tmp.xz
627        ./lzma tmp
628        lzma -Q -d tmp.lzma
629        $ECHO "Testing unxz and unlzma symlinks"
630        xz -Q tmp
631        ./xz -d tmp.xz
632        lzma -Q tmp
633        ./lzma -d tmp.lzma
634        rm xz unxz lzma unlzma
635        rm tmp*
636    else
637        $ECHO "xz binary not detected"
638    fi
639else
640    $ECHO "xz mode not supported"
641fi
642
643
644$ECHO "\n===>  xz frame tests "
645
646if [ $LZMAMODE -eq 1 ]; then
647    ./datagen > tmp
648    $ZSTD -f --format=xz tmp
649    $ZSTD -f --format=lzma tmp
650    $ZSTD -f tmp
651    cat tmp.xz tmp.lzma tmp.zst tmp.lzma tmp.xz tmp.zst | $ZSTD -d -f -o tmp
652    truncateLastByte tmp.xz | $ZSTD -t > $INTOVOID && die "incomplete frame not detected !"
653    truncateLastByte tmp.lzma | $ZSTD -t > $INTOVOID && die "incomplete frame not detected !"
654    rm tmp*
655else
656    $ECHO "xz mode not supported"
657fi
658
659$ECHO "\n===>  lz4 compatibility tests "
660
661LZ4MODE=1
662$ZSTD --format=lz4 -V || LZ4MODE=0
663if [ $LZ4MODE -eq 1 ]; then
664    $ECHO "lz4 support detected"
665    LZ4EXE=1
666    lz4 -V || LZ4EXE=0
667    if [ $LZ4EXE -eq 1 ]; then
668        ./datagen > tmp
669        $ZSTD --format=lz4 -f tmp
670        lz4 -t -v tmp.lz4
671        lz4 -f tmp
672        $ZSTD -d -f -v tmp.lz4
673        rm tmp*
674    else
675        $ECHO "lz4 binary not detected"
676    fi
677else
678    $ECHO "lz4 mode not supported"
679fi
680
681
682$ECHO "\n===>  lz4 frame tests "
683
684if [ $LZ4MODE -eq 1 ]; then
685    ./datagen > tmp
686    $ZSTD -f --format=lz4 tmp
687    $ZSTD -f tmp
688    cat tmp.lz4 tmp.zst tmp.lz4 tmp.zst | $ZSTD -d -f -o tmp
689    truncateLastByte tmp.lz4 | $ZSTD -t > $INTOVOID && die "incomplete frame not detected !"
690    rm tmp*
691else
692    $ECHO "lz4 mode not supported"
693fi
694
695$ECHO "\n===> suffix list test"
696
697! $ZSTD -d tmp.abc 2> tmplg
698
699if [ $GZIPMODE -ne 1 ]; then
700    grep ".gz" tmplg > $INTOVOID && die "Unsupported suffix listed"
701fi
702
703if [ $LZMAMODE -ne 1 ]; then
704    grep ".lzma" tmplg > $INTOVOID && die "Unsupported suffix listed"
705    grep ".xz" tmplg > $INTOVOID && die "Unsupported suffix listed"
706fi
707
708if [ $LZ4MODE -ne 1 ]; then
709    grep ".lz4" tmplg > $INTOVOID && die "Unsupported suffix listed"
710fi
711
712$ECHO "\n===>  zstd round-trip tests "
713
714roundTripTest
715roundTripTest -g15K       # TableID==3
716roundTripTest -g127K      # TableID==2
717roundTripTest -g255K      # TableID==1
718roundTripTest -g522K      # TableID==0
719roundTripTest -g519K 6    # greedy, hash chain
720roundTripTest -g517K 16   # btlazy2
721roundTripTest -g516K 19   # btopt
722
723fileRoundTripTest -g500K
724
725$ECHO "\n===>  zstd long distance matching round-trip tests "
726roundTripTest -g0 "2 --single-thread --long"
727roundTripTest -g1000K "1 --single-thread --long"
728roundTripTest -g517K "6 --single-thread --long"
729roundTripTest -g516K "16 --single-thread --long"
730roundTripTest -g518K "19 --single-thread --long"
731fileRoundTripTest -g5M "3 --single-thread --long"
732
733
734roundTripTest -g96K "5 --single-thread"
735if [ -n "$hasMT" ]
736then
737    $ECHO "\n===>  zstdmt round-trip tests "
738    roundTripTest -g4M "1 -T0"
739    roundTripTest -g8M "3 -T2"
740    roundTripTest -g8000K "2 --threads=2"
741    fileRoundTripTest -g4M "19 -T2 -B1M"
742
743    $ECHO "\n===>  zstdmt long distance matching round-trip tests "
744    roundTripTest -g8M "3 --long=24 -T2"
745
746    $ECHO "\n===>  ovLog tests "
747    ./datagen -g2MB > tmp
748    refSize=$($ZSTD tmp -6 -c --zstd=wlog=18         | wc -c)
749    ov9Size=$($ZSTD tmp -6 -c --zstd=wlog=18,ovlog=9 | wc -c)
750    ov0Size=$($ZSTD tmp -6 -c --zstd=wlog=18,ovlog=0 | wc -c)
751    if [ $refSize -eq $ov9Size ]; then
752        echo ov9Size should be different from refSize
753        exit 1
754    fi
755    if [ $refSize -eq $ov0Size ]; then
756        echo ov0Size should be different from refSize
757        exit 1
758    fi
759    if [ $ov9Size -ge $ov0Size ]; then
760        echo ov9Size=$ov9Size should be smaller than ov0Size=$ov0Size
761        exit 1
762    fi
763
764else
765    $ECHO "\n===>  no multithreading, skipping zstdmt tests "
766fi
767
768rm tmp*
769
770$ECHO "\n===>  zstd --list/-l single frame tests "
771./datagen > tmp1
772./datagen > tmp2
773./datagen > tmp3
774$ZSTD tmp*
775$ZSTD -l *.zst
776$ZSTD -lv *.zst | grep "Decompressed Size:"  # check that decompressed size is present in header
777$ZSTD --list *.zst
778$ZSTD --list -v *.zst
779
780$ECHO "\n===>  zstd --list/-l multiple frame tests "
781cat tmp1.zst tmp2.zst > tmp12.zst
782cat tmp12.zst tmp3.zst > tmp123.zst
783$ZSTD -l *.zst
784$ZSTD -lv *.zst
785
786$ECHO "\n===>  zstd --list/-l error detection tests "
787$ZSTD -l tmp1 tmp1.zst && die "-l must fail on non-zstd file"
788$ZSTD --list tmp* && die "-l must fail on non-zstd file"
789$ZSTD -lv tmp1* && die "-l must fail on non-zstd file"
790$ZSTD --list -v tmp2 tmp12.zst && die "-l must fail on non-zstd file"
791
792$ECHO "\n===>  zstd --list/-l errors when presented with stdin / no files"
793$ZSTD -l && die "-l must fail on empty list of files"
794$ZSTD -l - && die "-l does not work on stdin"
795$ZSTD -l < tmp1.zst && die "-l does not work on stdin"
796$ZSTD -l - < tmp1.zst && die "-l does not work on stdin"
797$ZSTD -l - tmp1.zst && die "-l does not work on stdin"
798$ZSTD -l - tmp1.zst < tmp1.zst && die "-l does not work on stdin"
799$ZSTD -l tmp1.zst < tmp2.zst # this will check tmp1.zst, but not tmp2.zst, which is not an error : zstd simply doesn't read stdin in this case. It must not error just because stdin is not a tty
800
801$ECHO "\n===>  zstd --list/-l test with null files "
802./datagen -g0 > tmp5
803$ZSTD tmp5
804$ZSTD -l tmp5.zst
805$ZSTD -l tmp5* && die "-l must fail on non-zstd file"
806$ZSTD -lv tmp5.zst | grep "Decompressed Size: 0.00 KB (0 B)"  # check that 0 size is present in header
807$ZSTD -lv tmp5* && die "-l must fail on non-zstd file"
808
809$ECHO "\n===>  zstd --list/-l test with no content size field "
810./datagen -g513K | $ZSTD > tmp6.zst
811$ZSTD -l tmp6.zst
812$ZSTD -lv tmp6.zst | grep "Decompressed Size:"  && die "Field :Decompressed Size: should not be available in this compressed file"
813
814$ECHO "\n===>   zstd --list/-l test with no checksum "
815$ZSTD -f --no-check tmp1
816$ZSTD -l tmp1.zst
817$ZSTD -lv tmp1.zst
818
819rm tmp*
820
821
822$ECHO "\n===>   zstd long distance matching tests "
823roundTripTest -g0 " --single-thread --long"
824roundTripTest -g9M "2 --single-thread --long"
825# Test parameter parsing
826roundTripTest -g1M -P50 "1 --single-thread --long=29" " --memory=512MB"
827roundTripTest -g1M -P50 "1 --single-thread --long=29 --zstd=wlog=28" " --memory=256MB"
828roundTripTest -g1M -P50 "1 --single-thread --long=29" " --long=28 --memory=512MB"
829roundTripTest -g1M -P50 "1 --single-thread --long=29" " --zstd=wlog=28 --memory=512MB"
830
831
832$ECHO "\n===>   adaptive mode "
833roundTripTest -g270000000 " --adapt"
834roundTripTest -g27000000 " --adapt=min=1,max=4"
835$ECHO "===>   test: --adapt must fail on incoherent bounds "
836./datagen > tmp
837$ZSTD -f -vv --adapt=min=10,max=9 tmp && die "--adapt must fail on incoherent bounds"
838
839$ECHO "\n===>   rsyncable mode "
840roundTripTest -g10M " --rsyncable"
841roundTripTest -g10M " --rsyncable -B100K"
842$ECHO "===>   test: --rsyncable must fail with --single-thread"
843$ZSTD -f -vv --rsyncable --single-thread tmp && die "--rsyncable must fail with --single-thread"
844
845
846if [ "$1" != "--test-large-data" ]; then
847    $ECHO "Skipping large data tests"
848    exit 0
849fi
850
851
852#############################################################################
853
854$ECHO "\n===>   large files tests "
855
856roundTripTest -g270000000 1
857roundTripTest -g250000000 2
858roundTripTest -g230000000 3
859
860roundTripTest -g140000000 -P60 4
861roundTripTest -g130000000 -P62 5
862roundTripTest -g120000000 -P65 6
863
864roundTripTest -g70000000 -P70 7
865roundTripTest -g60000000 -P71 8
866roundTripTest -g50000000 -P73 9
867
868roundTripTest -g35000000 -P75 10
869roundTripTest -g30000000 -P76 11
870roundTripTest -g25000000 -P78 12
871
872roundTripTest -g18000013 -P80 13
873roundTripTest -g18000014 -P80 14
874roundTripTest -g18000015 -P81 15
875roundTripTest -g18000016 -P84 16
876roundTripTest -g18000017 -P88 17
877roundTripTest -g18000018 -P94 18
878roundTripTest -g18000019 -P96 19
879
880roundTripTest -g5000000000 -P99 1
881roundTripTest -g1700000000 -P0 "1 --zstd=strategy=6"   # ensure btlazy2 can survive an overflow rescale
882
883fileRoundTripTest -g4193M -P99 1
884
885
886$ECHO "\n===>   zstd long, long distance matching round-trip tests "
887roundTripTest -g270000000 "1 --single-thread --long"
888roundTripTest -g130000000 -P60 "5 --single-thread --long"
889roundTripTest -g35000000 -P70 "8 --single-thread --long"
890roundTripTest -g18000001 -P80  "18 --single-thread --long"
891# Test large window logs
892roundTripTest -g700M -P50 "1 --single-thread --long=29"
893roundTripTest -g600M -P50 "1 --single-thread --long --zstd=wlog=29,clog=28"
894
895
896if [ -n "$hasMT" ]
897then
898    $ECHO "\n===>   zstdmt long round-trip tests "
899    roundTripTest -g80000000 -P99 "19 -T2" " "
900    roundTripTest -g5000000000 -P99 "1 -T2" " "
901    roundTripTest -g500000000 -P97 "1 -T999" " "
902    fileRoundTripTest -g4103M -P98 " -T0" " "
903    roundTripTest -g400000000 -P97 "1 --long=24 -T2" " "
904else
905    $ECHO "\n**** no multithreading, skipping zstdmt tests **** "
906fi
907
908
909$ECHO "\n===>  cover dictionary builder : advanced options "
910
911TESTFILE=../programs/zstdcli.c
912./datagen > tmpDict
913$ECHO "- Create first dictionary"
914$ZSTD --train-cover=k=46,d=8,split=80 *.c ../programs/*.c -o tmpDict
915cp $TESTFILE tmp
916$ZSTD -f tmp -D tmpDict
917$ZSTD -d tmp.zst -D tmpDict -fo result
918$DIFF $TESTFILE result
919$ECHO "- Create second (different) dictionary"
920$ZSTD --train-cover=k=56,d=8 *.c ../programs/*.c ../programs/*.h -o tmpDictC
921$ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!"
922$ECHO "- Create dictionary with short dictID"
923$ZSTD --train-cover=k=46,d=8,split=80 *.c ../programs/*.c --dictID=1 -o tmpDict1
924cmp tmpDict tmpDict1 && die "dictionaries should have different ID !"
925$ECHO "- Create dictionary with size limit"
926$ZSTD --train-cover=steps=8 *.c ../programs/*.c -o tmpDict2 --maxdict=4K
927$ECHO "- Compare size of dictionary from 90% training samples with 80% training samples"
928$ZSTD --train-cover=split=90 -r *.c ../programs/*.c
929$ZSTD --train-cover=split=80 -r *.c ../programs/*.c
930$ECHO "- Create dictionary using all samples for both training and testing"
931$ZSTD --train-cover=split=100 -r *.c ../programs/*.c
932$ECHO "- Test -o before --train-cover"
933rm -f tmpDict dictionary
934$ZSTD -o tmpDict --train-cover *.c ../programs/*.c
935test -f tmpDict
936$ZSTD --train-cover *.c ../programs/*.c
937test -f dictionary
938rm -f tmp* dictionary
939
940
941rm -f tmp*
942