tests: Add tests for the PGP trust model.
[gnupg.git] / tests / openpgp / README
1 #                                   Emacs, this is an -*- org -*- file.
2
3 * How to run the test suite
4 ** tldr: How to run all tests fast.
5
6  obj $ make check-all TESTFLAGS=--parallel
7
8 You can use --parallel=N to request N parallel jobs.  Hint: Tuck
9 TESTFLAGS=--parallel in your environment.
10
11 ** Running individual test suites or tests
12
13 From your build directory, run
14
15   obj $ make -C tests/openpgp check
16
17 to run all tests or
18
19   obj $ make -C tests/openpgp check TESTS=your-test.scm
20
21 to run a specific test (or any number of tests separated by spaces).
22
23 If you want to debug a test, add verbose=1 to see messages printed by
24 spawned programs to their standard error stream, verbose=2 to see what
25 programs are executed, or verbose=3 to see even more program output
26 and exit codes.
27
28 ** Inspecting the test environment
29
30 To inspect the environment in which tests are running, or to quickly
31 create keys for debugging or testing, you can start a shell.  There is
32 one test that doese just that:
33
34   obj $ make -C tests/openpgp check TESTS=shell.scm
35   PASS: tests/openpgp/setup.scm
36   Load legacy test environment? [Y/n] y
37   Drop 'batch' from gpg.conf? [Y/n] y
38
39   Enjoy your test environment.  Type 'exit' to exit it, it will be cleaned up after you.
40
41   ... $ gpg -k Alfa
42   gpg: NOTE: THIS IS A DEVELOPMENT VERSION!
43   gpg: It is only intended for test purposes and should NOT be
44   gpg: used in a production environment or with production keys!
45   gpg: /tmp/gpgscm-20170809T144032-run-tests-PFfybw/trustdb.gpg: trustdb created
46   pub   dsa1024 1999-03-08 [SCA]
47         A0FF4590BB6122EDEF6E3C542D727CC768697734
48   uid           [ unknown] Alfa Test (demo key) <alfa@example.net>
49   uid           [ unknown] Alpha Test (demo key) <alpha@example.net>
50   uid           [ unknown] Alice (demo key)
51   sub   elg1024 1999-03-08 [E]
52
53 PATH is adjusted so that you will use the tools from the build tree.
54 Note that the directory is removed when you exit the shell.
55
56 ** Passing options to the test driver
57
58 You can set TESTFLAGS to pass flags to 'run-tests.scm'.  For example,
59 to speed up the test suite when bisecting, do
60
61   obj $ make -C tests/openpgp check TESTFLAGS=--parallel
62
63 See below for the arguments supported by the driver.
64
65 ** Calling the test driver directly
66 This is a bit tricky because one needs to manually set some
67 environment variables.  We should make that easier.  See discussion
68 below.  From your build directory, do:
69
70   obj $ srcdir=<path to>/tests/openpgp \
71         GPGSCM_PATH=<path to>/tests/gpgscm:<path to>/tests/openpgp \
72         $(pwd)/tests/gpgscm/gpgscm [gpgscm args] \
73         run-tests.scm [test suite runner args]
74
75 *** Arguments supported by the test suite runner
76 The test suite runner supports two modes of operation, '--sequential'
77 and '--parallel'.  By default the tests are run in sequential order,
78 each one in a clean environment.
79
80 You can specify the tests to run as positional arguments relative to
81 srcdir (e.g. just 'version.scm').  Note that you do not have to
82 specify setup.scm and finish.scm, they are executed implicitly.
83
84 The test suite runner can be executed in any location that the current
85 user can write to.  It will create temporary files and directories,
86 but will in general clean up all of them.
87 *** Discussion of the various environment variables
88 **** srcdir
89 Must be set to the source of the openpgp test suite.  Used to locate
90 data files.
91 **** GPGSCM_PATH
92 Used to locate the Scheme library as well as code used by the test
93 suite.
94 **** BIN_PREFIX
95 The test suite does not hardcode any paths to tools.  If set it is
96 used to locate the tools to test, otherwise the test suite assumes to
97 be run from the build directory.
98 **** GPG_PRESET_PASSPHRASE
99 This tool is not installed by 'make install', hence we need to
100 explicitly override its position.  In fact, the location of any tool
101 used by the test suite can be overridden this way.  See defs.scm.
102 **** argv[0]
103 run-tests.scm depends on being able to re-exec gpgscm.  It uses
104 argv[0] for that.  Therefore you must use an absolute path to invoke
105 gpgscm.
106 * How to write tests
107 gpgscm provides a number of functions to aid you in writing tests, as
108 well as bindings to process management abstractions provided by GnuPG.
109 For the Scheme environment provided by TinySCHEME, see the TinySCHEME
110 manual that is included in tests/gpgscm/Manual.txt.
111
112 For a quick start, please have a look at various tests that are
113 already implemented, e.g. 'encrypt.scm'.
114 ** The test framework
115 The functions info, error, and skip display their first argument and
116 flush the output buffers.  error and skip will also terminate the
117 process, signaling that the test failed or should be skipped.
118
119 (for-each-p msg proc list) will display msg, and call proc with each
120 element of list while displaying the progress appropriately.
121 for-each-p' is similar, but accepts another callback before the 'list'
122 argument to format each item.  for-each-p can be safely nested, and
123 the inner progress indicator will be abbreviated using '.'.
124 ** Debugging tests
125
126 Say you are working on a new test called 'your-test.scm', you can run
127 it on its own using
128
129   obj $ make -C tests/openpgp check TESTS=your-test.scm
130
131 but something isn't working as expected.  There are several little
132 gadgets that might help.  The first one is 'trace', a function that
133 prints the value given to it and evaluates to it.  E.g.
134
135   (trace (+ 2 3))
136
137 prints '5' and evaluates to 5.  Also, there is an 'assert' macro that
138 aborts the execution if its argument does not evaluate to a trueish
139 value.  Feel free to express invariants with it.
140
141 You can also get an interactive repl by dropping
142
143   (interactive-repl (current-environment))
144
145 anywhere you like.  Or, if you want to examine the environment from an
146 operating system shell, use
147
148   (interactive-shell)
149
150 ** Interfacing with gpg
151
152 defs.scm defines several convenience functions.  Say you want to parse
153 the colon output from gpg, there is gpg-with-colons that splits the
154 result at newlines and colons, so you can use the result like this:
155
156  (define (fpr some-key)
157    (list-ref (assoc "fpr" (gpg-with-colons
158                            `(--with-fingerprint
159                              --list-secret-keys ,some-key)))
160              9))
161
162 Or if you want to count all non-revoked uids for a given key, do
163
164  (define (count-uids-of-secret-key some-key)
165    (length (filter (lambda (x) (and (string=? "uid" (car x))
166                                     (string=? "u" (cadr x))))
167                    (gpg-with-colons
168                     `(--with-fingerprint
169                       --list-secret-keys ,some-key)))))
170
171 ** Temporary files
172 (lettmp <bindings> <body>) will create and delete temporary files that
173 you can use in <body>.  (with-temporary-working-directory <body>) will
174 create a temporary director, change to that, and clean it up after
175 executing <body>).
176
177 make-temporary-file will create a temporary file.  You can optionally
178 provide an argument to that function that will serve as tag so you can
179 distinguish the files for debugging.  remove-temporary-file will
180 delete a file created using make-temporary-file.
181
182 ** Monadic transformer and pipe support
183 Tests often perform sequential transformations on files, or connect
184 processes using pipes.  To aid you in this, the test framework
185 provides two monadic data structures.
186
187 (Currently, the implementation mashes the 'bind' operation together
188 with the application of the monad.  Also, there is no 'return'
189 operation.  I guess all of that could be implemented on top of
190 call/cc, but it isn't at the moment.)
191 *** pipe
192 The pipe monad constructs pipe lines.  It consists of a function
193 pipe:do that binds the functions together and manages the execution of
194 the child processes, a family of functions that act as sources, a
195 function to spawn processes, and a family of functions acting as
196 sinks.
197
198 Sources are pipe:open, pipe:defer, pipe:echo.  To spawn a process use
199 pipe:spawn, or the convenience function pipe:gpg.  To sink the data
200 use pipe:splice, or pipe:write-to.
201
202 Example:
203
204   (pipe:do
205     (pipe:echo "3\n1\n2\n")
206     (pipe:spawn '("/usr/bin/sort"))
207     (pipe:write-to "sorted" (logior O_WRONLY O_CREAT) #o600))
208
209 Caveats: Due to the single-threaded nature of gpgscm you cannot use
210 both a source and sink that is implemented in Scheme.  pipe:defer and
211 pipe:echo are executing in gpgscm, and so does pipe:splice.
212 *** tr
213 The transformer monad describes sequential file transformations.
214
215 There is one source function, tr:open.  To describe a transformation
216 using some process, use tr:spawn, tr:gpg, or tr:pipe-do.  There are
217 several sinks, although sink is not quite the right term, because the
218 data is not consumed, and hence one can use them at any position.  The
219 "sinks" are tr:write-to, tr:call-with-content, tr:assert-identity, and
220 tr:assert-weak-identity.
221
222 A somewhat contrived example demonstrating many functions is:
223
224   (tr:do
225     (tr:pipe-do
226       (pipe:echo "3\n1\n2\n")
227       (pipe:spawn '("/usr/bin/sort")))
228     (tr:write-to "reference")
229     (tr:call-with-content
230      (lambda (c)
231        (echo "currently, c contains" (string-length c) "bytes")))
232     (tr:spawn "" '("/usr/bin/gcc" -x c "-E" -o **out** **in**))
233     (tr:pipe-do
234       (pipe:spawn '("/bin/grep" -v "#")))
235     (tr:assert-identity "reference"))
236
237 Caveats: As a convenience, gpgscm allows one to specify command line
238 arguments as Scheme symbols.  Scheme symbols, however, are
239 case-insensitive, and get converted to lower case.  Therefore, the -E
240 argument must be given as a string in the example above.  Similarly,
241 you need to quote numerical values.
242 ** Process management
243 If you just need to execute a single command, there is (call-with-fds
244 cmdline infd outfd errfd) which executes cmdline with the given file
245 descriptors bound to it, and waits for its completion returning the
246 status code.  There is (call cmdline) which is similar, but calls the
247 command with a closed stdin, connecting stdout and stderr to stderr if
248 gpgscm is executed with --verbose.  (call-check cmdline) raises an
249 exception if the command does not return 0.
250
251 (call-popen cmdline input) calls a command, writes input to its stdin,
252 and returns any output from stdout, or raises an exception containing
253 stderr on failure.
254 * Sample messages