xref: /aosp_15_r20/external/zstd/tests/cli-tests/README.md (revision 01826a4963a0d8a59bc3812d29bdf0fb76416722)
1*01826a49SYabin Cui# CLI tests
2*01826a49SYabin Cui
3*01826a49SYabin CuiThe CLI tests are focused on testing the zstd CLI.
4*01826a49SYabin CuiThey are intended to be simple tests that the CLI and arguments work as advertised.
5*01826a49SYabin CuiThey are not intended to test the library, only the code in `programs/`.
6*01826a49SYabin CuiThe library will get incidental coverage, but if you find yourself trying to trigger a specific condition in the library, this is the wrong tool.
7*01826a49SYabin Cui
8*01826a49SYabin Cui## Test runner usage
9*01826a49SYabin Cui
10*01826a49SYabin CuiThe test runner `run.py` will run tests against the in-tree build of `zstd` and `datagen` by default. Which means that `zstd` and `datagen` must be built.
11*01826a49SYabin Cui
12*01826a49SYabin CuiThe `zstd` binary used can be passed with `--zstd /path/to/zstd`.
13*01826a49SYabin CuiAdditionally, to run `zstd` through a tool like `valgrind` or `qemu`, set the `--exec-prefix 'valgrind -q'` flag.
14*01826a49SYabin Cui
15*01826a49SYabin CuiSimilarly, the `--datagen`, and `--zstdgrep` flags can be set to specify
16*01826a49SYabin Cuithe paths to their respective binaries. However, these tools do not use
17*01826a49SYabin Cuithe `EXEC_PREFIX`.
18*01826a49SYabin Cui
19*01826a49SYabin CuiEach test executes in its own scratch directory under `scratch/test/name`. E.g. `scratch/basic/help.sh/`. Normally these directories are removed after the test executes. However, the `--preserve` flag will preserve these directories after execution, and save the tests exit code, stdout, and stderr in the scratch directory to `exit`, `stderr`, and `stdout` respectively. This can be useful for debugging/editing a test and updating the expected output.
20*01826a49SYabin Cui
21*01826a49SYabin Cui### Running all the tests
22*01826a49SYabin Cui
23*01826a49SYabin CuiBy default the test runner `run.py` will run all the tests, and report the results.
24*01826a49SYabin Cui
25*01826a49SYabin CuiExamples:
26*01826a49SYabin Cui
27*01826a49SYabin Cui```
28*01826a49SYabin Cui./run.py
29*01826a49SYabin Cui./run.py --preserve
30*01826a49SYabin Cui./run.py --zstd ../../build/programs/zstd --datagen ../../build/tests/datagen
31*01826a49SYabin Cui```
32*01826a49SYabin Cui
33*01826a49SYabin Cui### Running specific tests
34*01826a49SYabin Cui
35*01826a49SYabin CuiA set of test names can be passed to the test runner `run.py` to only execute those tests.
36*01826a49SYabin CuiThis can be useful for writing or debugging a test, especially with `--preserve`.
37*01826a49SYabin Cui
38*01826a49SYabin CuiThe test name can either be the path to the test file, or the test name, which is the path relative to the test directory.
39*01826a49SYabin Cui
40*01826a49SYabin CuiExamples:
41*01826a49SYabin Cui
42*01826a49SYabin Cui```
43*01826a49SYabin Cui./run.py basic/help.sh
44*01826a49SYabin Cui./run.py --preserve basic/help.sh basic/version.sh
45*01826a49SYabin Cui./run.py --preserve --verbose basic/help.sh
46*01826a49SYabin Cui```
47*01826a49SYabin Cui
48*01826a49SYabin Cui### Updating exact output
49*01826a49SYabin Cui
50*01826a49SYabin CuiIf a test is failing because a `.stderr.exact` or `.stdout.exact` no longer matches, you can re-run the tests with `--set-exact-output` and the correct output will be written.
51*01826a49SYabin Cui
52*01826a49SYabin CuiExample:
53*01826a49SYabin Cui```
54*01826a49SYabin Cui./run.py --set-exact-output
55*01826a49SYabin Cui./run.py basic/help.sh --set-exact-output
56*01826a49SYabin Cui```
57*01826a49SYabin Cui
58*01826a49SYabin Cui## Writing a test
59*01826a49SYabin Cui
60*01826a49SYabin CuiTest cases are arbitrary executables, and can be written in any language, but are generally shell scripts.
61*01826a49SYabin CuiAfter the script executes, the exit code, stderr, and stdout are compared against the expectations.
62*01826a49SYabin Cui
63*01826a49SYabin CuiEach test is run in a clean directory that the test can use for intermediate files. This directory will be cleaned up at the end of the test, unless `--preserve` is passed to the test runner. Additionally, the `setup` script can prepare the directory before the test runs.
64*01826a49SYabin Cui
65*01826a49SYabin Cui### Calling zstd, utilities, and environment variables
66*01826a49SYabin Cui
67*01826a49SYabin CuiThe `$PATH` for tests is prepended with the `bin/` sub-directory, which contains helper scripts for ease of testing.
68*01826a49SYabin CuiThe `zstd` binary will call the zstd binary specified by `run.py` with the correct `$EXEC_PREFIX`.
69*01826a49SYabin CuiSimilarly, `datagen`, `unzstd`, `zstdgrep`, `zstdcat`, etc, are provided.
70*01826a49SYabin Cui
71*01826a49SYabin CuiHelper utilities like `cmp_size`, `println`, and `die` are provided here too. See their scripts for details.
72*01826a49SYabin Cui
73*01826a49SYabin CuiCommon shell script libraries are provided under `common/`, with helper variables and functions. They can be sourced with `source "$COMMON/library.sh`.
74*01826a49SYabin Cui
75*01826a49SYabin CuiLastly, environment variables are provided for testing, which can be listed when calling `run.py` with `--verbose`.
76*01826a49SYabin CuiThey are generally used by the helper scripts in `bin/` to coordinate everything.
77*01826a49SYabin Cui
78*01826a49SYabin Cui### Basic test case
79*01826a49SYabin Cui
80*01826a49SYabin CuiWhen executing your `$TEST` executable, by default the exit code is expected to be `0`. However, you can provide an alternate expected exit code in a `$TEST.exit` file.
81*01826a49SYabin Cui
82*01826a49SYabin CuiWhen executing your `$TEST` executable, by default the expected stderr and stdout are empty. However, you can override the default by providing one of three files:
83*01826a49SYabin Cui
84*01826a49SYabin Cui* `$TEST.{stdout,stderr}.exact`
85*01826a49SYabin Cui* `$TEST.{stdout,stderr}.glob`
86*01826a49SYabin Cui* `$TEST.{stdout,stderr}.ignore`
87*01826a49SYabin Cui
88*01826a49SYabin CuiIf you provide a `.exact` file, the output is expected to exactly match, byte-for-byte.
89*01826a49SYabin Cui
90*01826a49SYabin CuiIf you provide a `.glob` file, the output is expected to match the expected file, where each line is interpreted as a glob syntax. Additionally, a line containing only `...` matches all lines until the next expected line matches.
91*01826a49SYabin Cui
92*01826a49SYabin CuiIf you provide a `.ignore` file, the output is ignored.
93*01826a49SYabin Cui
94*01826a49SYabin Cui#### Passing examples
95*01826a49SYabin Cui
96*01826a49SYabin CuiAll these examples pass.
97*01826a49SYabin Cui
98*01826a49SYabin CuiExit 1, and change the expectation to be 1.
99*01826a49SYabin Cui
100*01826a49SYabin Cui```
101*01826a49SYabin Cuiexit-1.sh
102*01826a49SYabin Cui---
103*01826a49SYabin Cui#!/bin/sh
104*01826a49SYabin Cuiexit 1
105*01826a49SYabin Cui---
106*01826a49SYabin Cui
107*01826a49SYabin Cuiexit-1.sh.exit
108*01826a49SYabin Cui---
109*01826a49SYabin Cui1
110*01826a49SYabin Cui---
111*01826a49SYabin Cui```
112*01826a49SYabin Cui
113*01826a49SYabin CuiCheck the stdout output exactly matches.
114*01826a49SYabin Cui
115*01826a49SYabin Cui```
116*01826a49SYabin Cuiecho.sh
117*01826a49SYabin Cui---
118*01826a49SYabin Cui#!/bin/sh
119*01826a49SYabin Cuiecho "hello world"
120*01826a49SYabin Cui---
121*01826a49SYabin Cui
122*01826a49SYabin Cuiecho.sh.stdout.exact
123*01826a49SYabin Cui---
124*01826a49SYabin Cuihello world
125*01826a49SYabin Cui---
126*01826a49SYabin Cui```
127*01826a49SYabin Cui
128*01826a49SYabin CuiCheck the stderr output using a glob.
129*01826a49SYabin Cui
130*01826a49SYabin Cui```
131*01826a49SYabin Cuirandom.sh
132*01826a49SYabin Cui---
133*01826a49SYabin Cui#!/bin/sh
134*01826a49SYabin Cuihead -c 10 < /dev/urandom | xxd >&2
135*01826a49SYabin Cui---
136*01826a49SYabin Cui
137*01826a49SYabin Cuirandom.sh.stderr.glob
138*01826a49SYabin Cui---
139*01826a49SYabin Cui00000000: * * * * *                 *
140*01826a49SYabin Cui```
141*01826a49SYabin Cui
142*01826a49SYabin CuiMultiple lines can be matched with ...
143*01826a49SYabin Cui
144*01826a49SYabin Cui```
145*01826a49SYabin Cuirandom-num-lines.sh
146*01826a49SYabin Cui---
147*01826a49SYabin Cui#!/bin/sh
148*01826a49SYabin Cuiecho hello
149*01826a49SYabin Cuiseq 0 $RANDOM
150*01826a49SYabin Cuiecho world
151*01826a49SYabin Cui---
152*01826a49SYabin Cui
153*01826a49SYabin Cuirandom-num-lines.sh.stdout.glob
154*01826a49SYabin Cui---
155*01826a49SYabin Cuihello
156*01826a49SYabin Cui0
157*01826a49SYabin Cui...
158*01826a49SYabin Cuiworld
159*01826a49SYabin Cui---
160*01826a49SYabin Cui```
161*01826a49SYabin Cui
162*01826a49SYabin Cui#### Failing examples
163*01826a49SYabin Cui
164*01826a49SYabin CuiExit code is expected to be 0, but is 1.
165*01826a49SYabin Cui
166*01826a49SYabin Cui```
167*01826a49SYabin Cuiexit-1.sh
168*01826a49SYabin Cui---
169*01826a49SYabin Cui#!/bin/sh
170*01826a49SYabin Cuiexit 1
171*01826a49SYabin Cui---
172*01826a49SYabin Cui```
173*01826a49SYabin Cui
174*01826a49SYabin CuiStdout is expected to be empty, but isn't.
175*01826a49SYabin Cui
176*01826a49SYabin Cui```
177*01826a49SYabin Cuiecho.sh
178*01826a49SYabin Cui---
179*01826a49SYabin Cui#!/bin/sh
180*01826a49SYabin Cuiecho hello world
181*01826a49SYabin Cui```
182*01826a49SYabin Cui
183*01826a49SYabin CuiStderr is expected to be hello but is world.
184*01826a49SYabin Cui
185*01826a49SYabin Cui```
186*01826a49SYabin Cuihello.sh
187*01826a49SYabin Cui---
188*01826a49SYabin Cui#!/bin/sh
189*01826a49SYabin Cuiecho world >&2
190*01826a49SYabin Cui---
191*01826a49SYabin Cui
192*01826a49SYabin Cuihello.sh.stderr.exact
193*01826a49SYabin Cui---
194*01826a49SYabin Cuihello
195*01826a49SYabin Cui---
196*01826a49SYabin Cui```
197*01826a49SYabin Cui
198*01826a49SYabin Cui### Setup & teardown scripts
199*01826a49SYabin Cui
200*01826a49SYabin CuiFinally, test writing can be eased with setup and teardown scripts.
201*01826a49SYabin CuiEach directory in the test directory is a test-suite consisting of all tests within that directory (but not sub-directories).
202*01826a49SYabin CuiThis test suite can come with 4 scripts to help test writing:
203*01826a49SYabin Cui
204*01826a49SYabin Cui* `setup_once`
205*01826a49SYabin Cui* `teardown_once`
206*01826a49SYabin Cui* `setup`
207*01826a49SYabin Cui* `teardown`
208*01826a49SYabin Cui
209*01826a49SYabin CuiThe `setup_once` and `teardown_once` are run once before and after all the tests in the suite respectively.
210*01826a49SYabin CuiThey operate in the scratch directory for the test suite, which is the parent directory of each scratch directory for each test case.
211*01826a49SYabin CuiThey can do work that is shared between tests to improve test efficiency.
212*01826a49SYabin CuiFor example, the `dictionaries/setup_once` script builds several dictionaries, for use in the `dictionaries` tests.
213*01826a49SYabin Cui
214*01826a49SYabin CuiThe `setup` and `teardown` scripts run before and after each test case respectively, in the test case's scratch directory.
215*01826a49SYabin CuiThese scripts can do work that is shared between test cases to make tests more succinct.
216*01826a49SYabin CuiFor example, the `dictionaries/setup` script copies the dictionaries built by the `dictionaries/setup_once` script into the test's scratch directory, to make them easier to use, and make sure they aren't accidentally modified.
217*01826a49SYabin Cui
218*01826a49SYabin Cui#### Examples
219*01826a49SYabin Cui
220*01826a49SYabin Cui```
221*01826a49SYabin Cuibasic/setup
222*01826a49SYabin Cui---
223*01826a49SYabin Cui#!/bin/sh
224*01826a49SYabin Cui# Create some files for testing with
225*01826a49SYabin Cuidatagen > file
226*01826a49SYabin Cuidatagen > file0
227*01826a49SYabin Cuidatagen > file1
228*01826a49SYabin Cui---
229*01826a49SYabin Cui
230*01826a49SYabin Cuibasic/test.sh
231*01826a49SYabin Cui---
232*01826a49SYabin Cui#!/bin/sh
233*01826a49SYabin Cuizstd file file0 file1
234*01826a49SYabin Cui---
235*01826a49SYabin Cui
236*01826a49SYabin Cuidictionaries/setup_once
237*01826a49SYabin Cui---
238*01826a49SYabin Cui#!/bin/sh
239*01826a49SYabin Cuiset -e
240*01826a49SYabin Cui
241*01826a49SYabin Cuimkdir files/ dicts/
242*01826a49SYabin Cuifor i in $(seq 10); do
243*01826a49SYabin Cui	datagen -g1000 > files/$i
244*01826a49SYabin Cuidone
245*01826a49SYabin Cui
246*01826a49SYabin Cuizstd --train -r files/ -o dicts/0
247*01826a49SYabin Cui---
248*01826a49SYabin Cui
249*01826a49SYabin Cuidictionaries/setup
250*01826a49SYabin Cui---
251*01826a49SYabin Cui#!/bin/sh
252*01826a49SYabin Cui
253*01826a49SYabin Cui# Runs in the test case's scratch directory.
254*01826a49SYabin Cui# The test suite's scratch directory that
255*01826a49SYabin Cui# `setup_once` operates in is the parent directory.
256*01826a49SYabin Cuicp -r ../files ../dicts .
257*01826a49SYabin Cui---
258*01826a49SYabin Cui```
259