Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Replace tesh.pl by pesh.py a much better version of tesh in python.
[simgrid.git] / tools / tesh / tesh.pod
1 =encoding UTF-8
2
3 =head1 NAME
4
5 tesh -- testing shell
6
7 =head1 SYNOPSIS
8
9 B<tesh> [I<options>]... I<testsuite>
10
11 =head1 DESCRIPTION
12
13 Tesh is the testing shell, a specialized shell for running tests. It
14 provides the specified input to the tested commands, and check that
15 they produce the expected output and return the expected value.
16
17 =head1 OPTIONS
18
19   --help              : display help
20   --cd some/directory : ask tesh to switch the working directory before
21                         launching the tests
22   --setenv var=value  : set a specific environment variable
23   --cfg arg           : add parameter --cfg=arg to each command line
24   --log arg           : add parameter --log=arg to each command line
25   --enable-coverage   : ignore output lines starting with "profiling:"
26
27
28 =head1 TEST SUITE FILE SYTAX
29
30 A test suite is composed of one or several I<command blocks> separated
31 by empty lines, each of them being composed of a command to run, its
32 input text and the expected output.
33
34 The first char of each line specifies the type of line according to
35 the following list. The second char of each line is ignored.
36
37  `$' command to run in foreground
38  `&' command to run in background
39
40  `<' input to pass to the command
41  `>' output expected from the command
42
43  `!' metacommand, which can be one of:
44      `timeout' <integer>|no
45      `expect signal' <signal name>
46      `expect return' <integer>
47      `output' <ignore|display>
48      `output sort' [integer]
49      `setenv <key>=<val>'
50      `ignore' <regexp>
51
52  `p' an informative message to print
53  `#' a comment
54
55 If the expected output do not match the produced output, or if the
56 command did not end as expected, Tesh provides an error message (see
57 the OUTPUT section below) and stops.
58
59 =head2 Command blocks examples
60
61 In a given command block, you can declare the command, its input and
62 its expected output in the order that you see fit.
63
64     $ cat
65     < TOTO
66     > TOTO
67
68     > TOTO
69     $ cat
70     < TOTO
71
72     > TOTO
73     < TOTO
74     $ cat
75
76 You can group several commands together, provided that they don't have
77 any input nor output.
78
79     $ mkdir testdir
80     $ cd testdir
81
82 =head2 Enforcing the command return code
83
84 By default, Tesh enforces that the tested command returns 0. If not,
85 it fails with an appropriate message and returns I<code+40> itself.
86
87 You specify that a given command block is expected to return another
88 code as follows:
89
90     # This command MUST return 42
91     ! expect return 42
92     $ sh -e "exit 42"
93
94 The I<expect return> construct applies only to the next command block.
95
96 =head2 Commands that are expected to raise signals
97
98 By default, Tesh detects when the command is killed by a signal (such
99 as SEGV on segfaults). This is usually unexpected and unfortunate. But
100 if not, you can specify that a given command block is expected to fail
101 with a signal as follows:
102
103     # This command MUST raise a segfault
104     ! expect signal SIGSEGV
105     $ ./some_failing_code
106
107 The I<expect signal> construct applies only to the next command block.
108
109 =head2 Timeouts
110
111 By default, no command is allowed to run more than 5 seconds. You can
112 change this value as follows:
113
114     # Allow some more time to the command
115     ! timeout 60
116     $ ./some_longer_command
117
118 You can also disable the timeout completely by passing "no" as a value:
119
120     # This command will never timeout
121     ! timeout no
122     $ ./some_very_long_but_safe_command
123
124 =head2 Setting environment variables
125
126 You can modify the environment of the tested commands as follows:
127
128     ! setenv PATH=/bin
129     $ my_command
130
131 You can also set an envirmnent variable from the command line:
132
133     tesh --setenv bindir=/opt/bin/
134
135 And then use it within the tesh file:
136
137     $ ${bindir}/myprogram
138
139 Tesh also supports perl default value for undefined variables:
140
141     $ ${bindir:=/usr/bin}/myprogram
142
143 =head2 Not enforcing the expected output 
144
145 By default, the commands output is matched against the one expected,
146 and an error is raised on discrepancy. Metacommands to change this:
147
148 =over 4
149
150 =item output ignore
151
152 The output is completely discarded.
153
154 =item output display
155
156 The output is displayed, but no error is issued if it differs from the
157 expected output.
158
159 =item output sort
160
161 The output is sorted before comparison (see next section).
162
163 =back
164
165 =head2 Sorting output
166
167 If the order of the command output changes between runs, you want to
168 sort it before enforcing that it is exactly what you expect. In
169 SimGrid for example, this happens when parallel execution is
170 activated: User processes are run in parallel at each timestamp, and
171 the output is not reproducible anymore. Until you sort the lines.
172
173 You can sort the command output as follows:
174
175     ! output sort
176     $ ./some_multithreaded_command
177
178 Sorting lines this ways often makes the tesh output very intricate,
179 complicating the error analysis: the process logical order is defeated
180 by the lexicographical sort.
181
182 The solution is to prefix each line of your output with temporal
183 information so that lines can be grouped by timestamps. The
184 lexicographical sort then only applies to lines that occured at the
185 same timestamp. Here is a SimGrid example:
186
187     # Sort only lines depending on the first 19 chars
188     ! output sort 19
189     $ ./some_simgrid_simulator --log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n
190
191 This approach may seem surprizing at the first glance but it does its job:
192
193 =over 4
194
195 =item Every timestamps remain separated, as it should; 
196
197 =item In each timestamp, the output order of processes become
198    reproducible: that's the lexicographical order of their name;
199
200 =item For each process, the order of its execution is preserved: its
201    messages within a given timestamp are not reordered.
202
203 =back
204
205 That way, tesh can do its job (no false positive, no false negative)
206 despite the unpredictable order of executions of processes within a
207 timestamp, and reported errors remain easy to analyze (execution of a
208 given process preserved).
209
210 This example is very SimGrid oriented, but the feature could even be
211 usable by others, who knows?
212
213 =head2 Ignoring some output
214
215 Some outputed lines can be ignored by setting the ignore command followed
216 by a regular expression:
217
218     ! ignore .*0x[0-9A-F]+\.
219     $  printf 'word\nMemory address: 0x42AA42.\nanotherword\n'
220     > word
221     > anotherword
222
223
224 =head2 Colored and formatted text
225
226 Tesh removes ANSI/VT100 control sequences from outputed text to make easier the writing of tests.
227
228     $ printf "I \033[0;31mlove\033[0m tesh\n"
229     > I love tesh
230
231
232
233 =head1 BUILTIN COMMANDS
234
235 =head2 mkfile: creating a file
236
237 This command creates a file of the name provided as argument, and adds
238 the content it gets as input.
239
240   $ mkfile myFile
241   > some content
242   > to the file
243
244 It is not possible to use the cat command, as one would expect,
245 because stream redirections are currently not implemented in Tesh.
246
247 =head1 BUGS, LIMITATIONS AND POSSIBLE IMPROVEMENTS
248
249 The main limitation is the lack of stream redirections in the commands
250 (">", "<" and "|" shell constructs and friends). The B<mkfile> builtin
251 command makes this situation bearable.
252
253 It would be nice if we could replace the tesh file completely with
254 command line flags when the output is not to be verified.
255
256
257 =cut