Test::MTA::Exim4 - Test Anything interface for testing Exim4 configurations
version 0.06
Test::MTA::Exim4 allows the testing of an exim
installation and
configuration using the perl TAP (Test Anything Protocol) methodology.
This allows the writing of some simple test scripts which can check for
features of exim
and check that this configuration routes, accepts or
rejects mail as you would expect. As such it is an ideal system for creating a
test suite for your mail configuration allowing you to check that there are no
unexpected regressions when you make a change.
You need to be aware that an exim
installation depends on more than just a
config file - the exim binary, and the installation environment may effect the
behaviour and/or routing of messages. You really need to do final configuration
tests on the box that the system will be running on in production.
At present this module is experimental - both the API and implementation are subject to change. To this end I welcome discussion on how best to implement or expose functionality. There is other work proposed to produce similar test modules for other MTAs and so a common mechanism or compatibility layer between them is possible - this module has been produced to get something out as code is a better discussion point than vapourware ideas!
Having said all that, it has now been around for several years, without substantial changes, so it may be as well to accept the API to be as stable as that of exim itself...
The sample
directory contains an example used for testing the <exim.org>
installation, and should hopefully act as a reasonable example configuration.
my $exim = Test::MTA::Exim4->new( \%fields );
Create a new exim configuration testing object. You may pass configuration information in as a hash reference - this is the only point at which the locations of the exim binary and configuration file may be set.
The options that can be passed in are:-
-
exim_path
This is the path to the exim binary. If this is not set, the default is taken as the first of the following:-
DEFAULT_EXIM_PATH
- environment variableexim4
in the current pathexim
in the current path/usr/sbin/exim
-
config_file
The configuration file used. If this is not set the value of the environment variable
DEFAULT_EXIM_CONFIG_FILE
is used and if that is not set no config file is passed to the exim binary (meaning the default compiled into that is used). -
test
A test object - defaults to a new instance of Test::Builder
-
timeout
The timeout enforced on commands, in seconds. Defaults to 5 seconds.
Resets the internal state. Not sure when this might be useful!
Checks that exim
considers the configuration file as syntactically valid.
The config file must be specified when new
is called, otherwise the default
is used.
Returns the version of exim
seen when the configuration was checked. This is
intended for use within your own tests for appropriate versions, for example:-
# ensure we are running exim 4.69 or later
ok(($exim->exim_version gt '4.69'), 'Exim version check');
Returns the build number of exim
seen when the configuration was checked.
This is intended for use within your own tests for appropriate versions/builds.
$exim->has_option($option, $optional_msg)
Checks whether the named exim
option exists. This is taken from the list of
options listed by exim -bP
$exim->has_not_option($option, $optional_msg)
Precisely the opposite of has_option with an opposite test - so fails if the option does exist.
$exim->option_is($option, $value, $optional_msg)
Checks the named exim
option has the appropriate value. This is taken from
the list of options listed by exim -bP
$exim->option_is_true($option, $optional_msg)
Checks the named exim
option has a true value. This is taken from the list
of options listed by exim -bP
$exim->option_is_false($option, $optional_msg)
Checks the named exim
option has a false value. This is taken from the list
of options listed by exim -bP
$exim->expansion_is($string, $value, $optional_msg)
Checks the given exim
expansion string ends up with the appropriate value.
$exim->has_capability($type, $what, $optional_msg)
$exim->has_capability('lookup', 'lsearch', 'Has lsearch capability')
Checks that exim
has the appropriate capability. This is taken from the
lists of capabilities listed by exim -bV
The types of capability are:-
- support_for
- lookup
- authenticator
- router
- transport
The items within a capability are processed to be lowercase alphanumeric only -
so iconv
rather than iconv()
as output by exim. The subitems (for example
maildir
is a subitem of appendfile
) are treated as separately checkable
items.
If the version of exim
being used has both built-in and dynamic lookups (or
potentially in later versions multiple types of other capabilities), then these
are merged into a single capability list.
Precisely the opposite of has_capability with an opposite test - so fails if this does exist.
$exim->routes_ok($address, $optional_msg);
$exim->routes_ok('[email protected]', 'Checking routing');
Checks that exim
with this configuration can route to the address given.
Accepts any working address which may route to any number of final targets as
long as there are no undeliverable addresses in the set.
$exim->routes_as_ok($address, $target, $optional_msg);
$exim->routes_as_ok('[email protected]',
{transport => 'local_smtp}, 'Checking routing');
Checks that exim
with this configuration routes to the address given with
the appropriate target results.
The target is an arrayref of hashes (or as a special case a single hash), which matches against the addresses section of the result from _run_exim_bt. Each address matches if all the elements given in the target hash match (so an empty hash will match anything).
See _run_exim_bt for hash elements.
$exim->discards_ok($address, $optional_msg);
$exim->discards_ok('[email protected]', 'Checking discarding');
Checks that exim
with this configuration will discard the given address.
$exim->undeliverable_ok($address, $optional_msg);
$exim->undeliverable_ok('[email protected]', 'Checking discarding');
Checks that exim
with this configuration will consider the given address to
be undeliverable.
These methods are not intended to be run by end users, but are exposed.
Runs an exim instance with the appropriate configuration file and arguments. The configuration file is taken from the test object, the arguments are passed as arguments to this function.
Runs exim -bV
with the appropriate configuration file, to check that the
configuration file is valid. The output of the command is parsed and stashed
and used to provide the functions to check versions numbers and capabilities.
Runs exim -bP
with the appropriate configuration file, to cause Exim to
display the value of all the main configuration options. The output of the
command is parsed and stashed and used to provide the functions to check
individual option values.
Runs exim -be
, with the appropriate configuration file, in expansion testing
mode, to cause Exim to expand the specified string.
Runs exim -bt
(address test mode) with the appropriate configuration file,
to check how the single address passed routes. The output of the command is
parsed and passed back in the results.
The results structure is a hash that looks like:-
{
all_ok => # no invocation errors
deliverable => # number of deliverable addresses
undeliverable => # number of undeliverable addresses
total => # total number of addresses
addresses => {}
}
The addresses
part of the structure has one key for each resultant address,
the value of which is another hash, which may contain the following items:-
-
ok
True if the address routed OK, False otherwise.
-
discarded
True if the address was discarded by the router, false or missing if not.
-
data
Scalar of lines picked out of exim output related to this address and not otherwise recognised.
-
router
The router name used to handle this address.
-
transport
The transport name used to handle this address.
-
address
The final destination address.
-
original
The original address that was used within this transformation. This is actually an arrayref each containing an address as several transformations may take place.
-
target
For a local transport, the delivery target.
Spits out some Test::Builder diagnostics for the last run command. Used internally by some tests on failure. The output data is the last error seen by IPC::Cmd and the complete output of the command.
The module draws very strongly on the Test::Exim4::Routing module by Max Maischein. It is structured differently, and is currently very experimental (meaning the API may change in a big way), so these changes were made as a new module in a name space that is intended for use by similar modules for other MTAs.
Nigel Metheringham [email protected]
This software is copyright (c) 2019 by Nigel Metheringham.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.