The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.


Test::Config::System - System configuration related unit tests


Version 0.63


    use Test::Config::System tests => 3;
    check_package('less', 'package less');
    check_package('emacs21', 'emacs uninstalled', 1);
    check_link('/etc/alternatives/www-browser', '/usr/bin/w3m');
    check_file_contents('Test/Config/', qr/do {local \$\//);


Test::Config::System provides functions to help test system configuration, such as installed packages or config files. It was built for use in a cfengine staging environment. ( cfengine is used for automating and managing system configuration at large sites).

Test::Config::System does not depend on, or interact with cfengine in any way, however, and can be used on its own or with another configuration management tool (such as puppet or bcfg2).

This module is a subclass of Test::Builder::Module, and is used like any other Test::* module. Instead of directly providing an ok() function, the functions exported (described below), call ok() themselves, based on the outcome of the check they preform.


    use Test::Config::System tests => 3;
    # check something we already know:  :)
    check_package('perl', 'perl is installed');
    check_file_contents('/etc/apt/sources.list', qr/apt-proxy/,
        'apt-proxy is not being used', 1); # the apt-proxy is not
                                           # anywhere in sources.list
    check_package('vim');      # Make sure we have the one true editor


check_package check_any_package check_file_contents check_link check_dir check_file

From Test::Builder::Module:

plan diag ok skip


Each of the functions below use Test::Builder::Module's ok() function to report test success or failure. They return the result of ok() upon normal completion, or a false value (undef in scalar context, an empty list in list context) on error (eg a required parameter not provided, or FS doesn't support symlinks).


NOTE: check_package currently only supports dpkg and rpm.

check_package tests whether or not a package is installed. If the package is not installed or if the given package manager does not exist, the test fails. Otherwise, the test will pass. (If the test is inverted, the outcome is the opposite).

  - NAME: package name
  - DESC: test name (optional, defaults to package name)
  - INVERT: invert test (optional.  Possible values are 0 (default) and 1.)
  - PACKAGE_MANAGER: package manager (optional.  Defaults to 'dpkg'.
                                      Supported values are 'dpkg' and 'rpm'.
                                      If the given package manager is not
                                      supported, returns false)


    # Will fail if nethack is not installed
    # This will fail if x11-common is installed:
    check_package('x11-common', 'x11-common is not installed', 1);

check_any_package( LIST, [DESC, INVERT, PACKAGE_MANAGER] )

NOTE: check_any_package currently only supports dpkg and rpm.

check_any_package tests if any one in a list of packages is installed. Much like Perl's "||" operator, check_any_package will short-circuit (if the first package is installed, the test will immediately pass without checking the others).

  - LIST: a list of packages to check
  - DESC: see C<check_package>
  - INVERT: inverts test (A value of 1 will cause the test to fail
                          unless I<none> of the given packages are installed)
  - PACKAGE_MANAGER: see C<check_package>


    # Will pass if either of the given packages are installed
        'Test::Config::System is installed');
    # Will fail if either xserver-xorg or xserver-xfree86 is installed
    check_any_package(['xserver-xorg', 'xserver-xfree86',
        'No X11 server installed', 1);

check_file_contents( FILENAME, REGEX, [DESC, INVERT] )

check_file_contents tests that a file's contents match a given regex. It slurps the contents of the given filename, then matches it against the given regex. If the regex matches the contents of the file, ok() is called with a true value, causing the test to pass. If the regex does not match, the test will fail (as in check_package, if the test is inverted, the results are inverted as well).

If the given file cannot be opened for reading, ok() will be called with a false value (unless, as always, invert is true).

Note that the entire file is slurped into memory at once. This has two concequences. First, large files will eat up RAM. Second, ^ and $ do not work line-by-line, as one might expect. "\n" (or your system's line-end sequence) can be used in place of ^ or $ to match the start and end of a line.

  - FILENAME: file to test
  - REGEX: regex to match (qr//-style regex)
  - DESC: test name (optional, defaults to filename)
  - INVERT: invert test (optional.  Possible values are 0 (default) and 1.)


    check_file_contents('/etc/fstab', qr|proc\s+/proc\s+proc\s+defaults\s+0\s+0|,
        'proc is in fstab');
    check_file_contents('/etc/passwd', qr|evilbob:x:\d+:\d+:|,
        'evilbob is not in passwd', 1);


check_link verifies that a symlink exists and, optionally, points to the correct target.

If no filename is passed, it will return a false value, otherwise a test will be run and the result of ok() will be returned.

If the filesystem does not support symlinks, the test will be skipped, and check_link will return false.

  - FILENAME: filename (path to a symlink)
  - TARGET:   path the link should point to.  optional.  If not specified,
              check_link will ignore the target, and just verify that the
              link exists.
  - DESC: test name (optional, defaults to filename)
  - INVERT: invert test (optional.  Possible values are 0 (default) and 1.)    


    check_link('/etc/alternatives/rsh', '/usr/bin/ssh');
    check_link('/etc/sudoers', '', 'sudoers is not a symlink', 1);

check_file( PATH, [STAT, DESC, INVERT] )

check_file verifies that a directory exists. Optionally, it can check various attributes such as owner, group, or permissions.

  - PATH: path of the file to check
  - STAT: a hashref of attributes and their desired values.  Valid keys:
        -uid    owner uid
        -gid    owner gid
        -mode   file permissions
    Each key is optional, as is the entire hash.  Note that the type need
    not be specified in -mode; it is added automatically (ie use 0700
    instead of 010700).

  - DESC: test name (optional, defaults to PATH)
  - INVERT: invert test (optional.  Possible values are 0 (default) and 1.)


    check_file('/etc/sudoers', { '-uid' => 0, '-gid' => 0, '-mode' => 0440);

check_dir( PATH, [STAT, DESC, INVERT] )

check_dir is check_file for directories (they both call the same internal sub). Arguments and calling are exactly the same, the only significant difference is that check_dir verifies that PATH is a directory rather than a file.


    check_dir('/home/ian', { '-uid' => scalar getpwnam('ian') } );
    check_dir('/root/', { '-uid' => 0, '-gid' => 0, '-mode' => 0700 },
        '/root/ has sane permissions');
    check_dir('/home/evilbob', { }, 'Evilbobs homedir does not exist',1);


Ian Kilgore, <iank at>


  • Never call check_file_contents with untrusted input.

    check_file_contents runs a given regexp, which can contain arbitrary perl code.

  • check_package currently only supports dpkg and rpm

Please report any bugs or feature requests to bug-test-config-system at, or through the web interface at I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.


You can find documentation for this module with the perldoc command.

    perldoc Test::Config::System

You can also look for information at:


Many thanks to [naikonta] at perlmonks, for reviewing the module before the release of 0.01.


Copyright 2007 Ian Kilgore, all rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.