mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
7e19786a5d
* tests/gpgscm/tests.scm (mkdtemp): Do not magically obey the environment variable 'TMP', make sure to always return an absolute path. * tests/gpgme/Makefile.am (TMP): Drop variable. (TESTS_ENVIRONMENT): Drop 'TMP'. * tests/gpgme/gpgme-defs.scm (create-gpgmehome): Start the agent. Do not create private key store, the agent does that for us. * tests/gpgsm/Makefile.am (TMP): Drop variable. (TESTS_ENVIRONMENT): Drop 'TMP'. * tests/gpgme/gpgme-defs.scm (create-gpgsmhome): Start the agent. Do not create private key store, the agent does that for us. * tests/migrations/Makefile.am (TMP): Drop variable. (TESTS_ENVIRONMENT): Drop 'TMP'. * tests/migrations/common.scm (gpgconf): New variable. (run-test): Create and remove socket directory. * tests/migrations/extended-pkf.scm (src-tarball): Remove variable. (setup): Remove function. (trigger-migration): Likewise. Use 'run-test' to execute the test. * tests/migrations/from-classic.scm (src-tarball): Remove variable. (setup): Remove function. Use 'run-test' to execute the tests. * tests/openpgp/Makefile.am (TMP): Drop variable. (TESTS_ENVIRONMENT): Drop 'TMP'. * tests/openpgp/README: Do not mention 'TMP'. * tests/openpgp/defs.scm (with-home-directory): New macro. (create-legacy-gpghome): Do not create private key store, the agent does that for us. (start-agent): Make sure to terminate the right agent with 'atexit'. -- Previously, the test suite relied upon creating home directories in '/tmp'. This has been problematic in some build environments, although POSIX mandates that '/tmp' must be available. We now rely on 'gpgconf --create-socketdir' to create a suitable socket directory for us. This allows us to get rid of some cruft. It also aligns the environment the tests are run in closer with the environment that we intend that GnuPG runs in. Signed-off-by: Justus Winter <justus@g10code.com>
218 lines
8.5 KiB
Org Mode
218 lines
8.5 KiB
Org Mode
# Emacs, this is an -*- org -*- file.
|
|
|
|
* How to run the test suite
|
|
From your build directory, run
|
|
|
|
obj $ make -C tests/openpgp check
|
|
|
|
to run all tests or
|
|
|
|
obj $ make -C tests/openpgp check XTESTS=your-test.scm
|
|
|
|
to run a specific test (or any number of tests separated by spaces).
|
|
|
|
If you want to debug a test, add verbose=1 to see messages printed by
|
|
spawned programs to their standard error stream, verbose=2 to see what
|
|
programs are executed, or verbose=3 to see even more program output
|
|
and exit codes.
|
|
|
|
** Passing options to the test driver
|
|
|
|
You can set TESTFLAGS to pass flags to 'run-tests.scm'. For example,
|
|
to speed up the test suite when bisecting, do
|
|
|
|
obj $ make -C tests/openpgp check TESTFLAGS=--parallel
|
|
|
|
See below for the arguments supported by the driver.
|
|
|
|
** Calling the test driver directly
|
|
This is a bit tricky because one needs to manually set some
|
|
environment variables. We should make that easier. See discussion
|
|
below. From your build directory, do:
|
|
|
|
obj $ srcdir=<path to>/tests/openpgp \
|
|
GPGSCM_PATH=<path to>/tests/gpgscm:<path to>/tests/openpgp \
|
|
$(pwd)/tests/gpgscm/gpgscm [gpgscm args] \
|
|
run-tests.scm [test suite runner args]
|
|
|
|
*** Arguments supported by the test suite runner
|
|
The test suite runner supports two modes of operation, '--sequential'
|
|
and '--parallel'. By default the tests are run in sequential order,
|
|
each one in a clean environment.
|
|
|
|
You can specify the tests to run as positional arguments relative to
|
|
srcdir (e.g. just 'version.scm'). Note that you do not have to
|
|
specify setup.scm and finish.scm, they are executed implicitly.
|
|
|
|
The test suite runner can be executed in any location that the current
|
|
user can write to. It will create temporary files and directories,
|
|
but will in general clean up all of them.
|
|
*** Discussion of the various environment variables
|
|
**** srcdir
|
|
Must be set to the source of the openpgp test suite. Used to locate
|
|
data files.
|
|
**** GPGSCM_PATH
|
|
Used to locate the Scheme library as well as code used by the test
|
|
suite.
|
|
**** BIN_PREFIX
|
|
The test suite does not hardcode any paths to tools. If set it is
|
|
used to locate the tools to test, otherwise the test suite assumes to
|
|
be run from the build directory.
|
|
**** MKTDATA and GPG_PRESET_PASSPHRASE
|
|
These two tools are not installed by 'make install', hence we need to
|
|
explicitly override their position. In fact, the location of any tool
|
|
used by the test suite can be overridden this way. See defs.scm.
|
|
**** argv[0]
|
|
run-tests.scm depends on being able to re-exec gpgscm. It uses
|
|
argv[0] for that. Therefore you must use an absolute path to invoke
|
|
gpgscm.
|
|
* How to write tests
|
|
gpgscm provides a number of functions to aid you in writing tests, as
|
|
well as bindings to process management abstractions provided by GnuPG.
|
|
For the Scheme environment provided by TinySCHEME, see the TinySCHEME
|
|
manual that is included in tests/gpgscm/Manual.txt.
|
|
|
|
For a quick start, please have a look at various tests that are
|
|
already implemented, e.g. 'encrypt.scm'.
|
|
** The test framework
|
|
The functions info, error, and skip display their first argument and
|
|
flush the output buffers. error and skip will also terminate the
|
|
process, signaling that the test failed or should be skipped.
|
|
|
|
(for-each-p msg proc list) will display msg, and call proc with each
|
|
element of list while displaying the progress appropriately.
|
|
for-each-p' is similar, but accepts another callback before the 'list'
|
|
argument to format each item. for-each-p can be safely nested, and
|
|
the inner progress indicator will be abbreviated using '.'.
|
|
** Debugging tests
|
|
|
|
Say you are working on a new test called 'your-test.scm', you can run
|
|
it on its own using
|
|
|
|
obj $ make -C tests/openpgp check XTESTS=your-test.scm
|
|
|
|
but something isn't working as expected. There are several little
|
|
gadgets that might help. The first one is 'trace', a function that
|
|
prints the value given to it and evaluates to it. E.g.
|
|
|
|
(trace (+ 2 3))
|
|
|
|
prints '5' and evaluates to 5. Also, there is an 'assert' macro that
|
|
aborts the execution if its argument does not evaluate to a trueish
|
|
value. Feel free to express invariants with it.
|
|
|
|
You can also get an interactive repl by dropping
|
|
|
|
(interactive-repl (current-environment))
|
|
|
|
anywhere you like. Or, if you want to examine the environment from an
|
|
operating system shell, use
|
|
|
|
(interactive-shell)
|
|
|
|
** Interfacing with gpg
|
|
|
|
defs.scm defines several convenience functions. Say you want to parse
|
|
the colon output from gpg, there is gpg-with-colons that splits the
|
|
result at newlines and colons, so you can use the result like this:
|
|
|
|
(define (fpr some-key)
|
|
(list-ref (assoc "fpr" (gpg-with-colons
|
|
`(--with-fingerprint
|
|
--list-secret-keys ,some-key)))
|
|
9))
|
|
|
|
Or if you want to count all non-revoked uids for a given key, do
|
|
|
|
(define (count-uids-of-secret-key some-key)
|
|
(length (filter (lambda (x) (and (string=? "uid" (car x))
|
|
(string=? "u" (cadr x))))
|
|
(gpg-with-colons
|
|
`(--with-fingerprint
|
|
--list-secret-keys ,some-key)))))
|
|
|
|
** Temporary files
|
|
(lettmp <bindings> <body>) will create and delete temporary files that
|
|
you can use in <body>. (with-temporary-working-directory <body>) will
|
|
create a temporary director, change to that, and clean it up after
|
|
executing <body>).
|
|
|
|
make-temporary-file will create a temporary file. You can optionally
|
|
provide an argument to that function that will serve as tag so you can
|
|
distinguish the files for debugging. remove-temporary-file will
|
|
delete a file created using make-temporary-file.
|
|
|
|
** Monadic transformer and pipe support
|
|
Tests often perform sequential transformations on files, or connect
|
|
processes using pipes. To aid you in this, the test framework
|
|
provides two monadic data structures.
|
|
|
|
(Currently, the implementation mashes the 'bind' operation together
|
|
with the application of the monad. Also, there is no 'return'
|
|
operation. I guess all of that could be implemented on top of
|
|
call/cc, but it isn't at the moment.)
|
|
*** pipe
|
|
The pipe monad constructs pipe lines. It consists of a function
|
|
pipe:do that binds the functions together and manages the execution of
|
|
the child processes, a family of functions that act as sources, a
|
|
function to spawn processes, and a family of functions acting as
|
|
sinks.
|
|
|
|
Sources are pipe:open, pipe:defer, pipe:echo. To spawn a process use
|
|
pipe:spawn, or the convenience function pipe:gpg. To sink the data
|
|
use pipe:splice, or pipe:write-to.
|
|
|
|
Example:
|
|
|
|
(pipe:do
|
|
(pipe:echo "3\n1\n2\n")
|
|
(pipe:spawn '("/usr/bin/sort"))
|
|
(pipe:write-to "sorted" (logior O_WRONLY O_CREAT) #o600))
|
|
|
|
Caveats: Due to the single-threaded nature of gpgscm you cannot use
|
|
both a source and sink that is implemented in Scheme. pipe:defer and
|
|
pipe:echo are executing in gpgscm, and so does pipe:splice.
|
|
*** tr
|
|
The transformer monad describes sequential file transformations.
|
|
|
|
There is one source function, tr:open. To describe a transformation
|
|
using some process, use tr:spawn, tr:gpg, or tr:pipe-do. There are
|
|
several sinks, although sink is not quite the right term, because the
|
|
data is not consumed, and hence one can use them at any position. The
|
|
"sinks" are tr:write-to, tr:call-with-content, tr:assert-identity, and
|
|
tr:assert-weak-identity.
|
|
|
|
A somewhat contrived example demonstrating many functions is:
|
|
|
|
(tr:do
|
|
(tr:pipe-do
|
|
(pipe:echo "3\n1\n2\n")
|
|
(pipe:spawn '("/usr/bin/sort")))
|
|
(tr:write-to "reference")
|
|
(tr:call-with-content
|
|
(lambda (c)
|
|
(echo "currently, c contains" (string-length c) "bytes")))
|
|
(tr:spawn "" '("/usr/bin/gcc" -x c "-E" -o **out** **in**))
|
|
(tr:pipe-do
|
|
(pipe:spawn '("/bin/grep" -v "#")))
|
|
(tr:assert-identity "reference"))
|
|
|
|
Caveats: As a convenience, gpgscm allows one to specify command line
|
|
arguments as Scheme symbols. Scheme symbols, however, are
|
|
case-insensitive, and get converted to lower case. Therefore, the -E
|
|
argument must be given as a string in the example above. Similarly,
|
|
you need to quote numerical values.
|
|
** Process management
|
|
If you just need to execute a single command, there is (call-with-fds
|
|
cmdline infd outfd errfd) which executes cmdline with the given file
|
|
descriptors bound to it, and waits for its completion returning the
|
|
status code. There is (call cmdline) which is similar, but calls the
|
|
command with a closed stdin, connecting stdout and stderr to stderr if
|
|
gpgscm is executed with --verbose. (call-check cmdline) raises an
|
|
exception if the command does not return 0.
|
|
|
|
(call-popen cmdline input) calls a command, writes input to its stdin,
|
|
and returns any output from stdout, or raises an exception containing
|
|
stderr on failure.
|
|
* Sample messages
|