]> eyrie.org Git - kerberos/pam-webauth-otp.git/commitdiff
Add documentation tests
authorRuss Allbery <rra@stanford.edu>
Mon, 16 Sep 2013 18:32:50 +0000 (11:32 -0700)
committerRuss Allbery <rra@stanford.edu>
Mon, 16 Sep 2013 18:32:50 +0000 (11:32 -0700)
Fix the stopwords for the module documentation uncovered by adding
the tests.

docs/pam_webauth_otp.pod
tests/TESTS
tests/data/perl.conf [new file with mode: 0644]
tests/docs/pod-spelling-t [new file with mode: 0755]
tests/docs/pod-t [new file with mode: 0755]
tests/tap/perl/Test/RRA.pm [new file with mode: 0644]
tests/tap/perl/Test/RRA/Automake.pm [new file with mode: 0644]
tests/tap/perl/Test/RRA/Config.pm [new file with mode: 0644]

index 747c058477c40f776c223128459924fb8792cea0..a4ba68fb71bba79a3b1d0494cf1f3e1514f0f5b9 100644 (file)
@@ -1,3 +1,7 @@
+=for stopwords
+API Allbery OTP OTP-based SMS WebAuth WebKdcUserInfoURL appdefaults auth
+hostname keytab login middleware multifactor remctl remctl's
+
 =head1 NAME
 
 pam_webauth_otp - OTP PAM module for WebAuth user information service
index 400ba4b487d673941926684e58a0bae162423c64..3f3b0cd8161c18df42e0e8c6b79962beec6fe7b7 100644 (file)
@@ -1,3 +1,5 @@
+docs/pod
+docs/pod-spelling
 module/basic
 pam-util/args
 pam-util/fakepam
diff --git a/tests/data/perl.conf b/tests/data/perl.conf
new file mode 100644 (file)
index 0000000..a344a9a
--- /dev/null
@@ -0,0 +1,4 @@
+# Configuration for Perl tests.  -*- perl -*-
+
+# File must end with this line.
+1;
diff --git a/tests/docs/pod-spelling-t b/tests/docs/pod-spelling-t
new file mode 100755 (executable)
index 0000000..e1a95cd
--- /dev/null
@@ -0,0 +1,52 @@
+#!/usr/bin/perl
+#
+# Checks all POD files in the tree for spelling errors using Test::Spelling.
+# This test is disabled unless RRA_MAINTAINER_TESTS is set, since spelling
+# dictionaries vary too much between environments.
+#
+# The canonical version of this file is maintained in the rra-c-util package,
+# which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+#
+# Written by Russ Allbery <rra@stanford.edu>
+# Copyright 2012, 2013
+#     The Board of Trustees of the Leland Stanford Junior University
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+use 5.006;
+use strict;
+use warnings;
+
+use lib "$ENV{SOURCE}/tap/perl";
+
+use Test::More;
+use Test::RRA qw(skip_unless_maintainer use_prereq);
+use Test::RRA::Automake qw(automake_setup perl_dirs);
+
+# Only run this test for the maintainer.
+skip_unless_maintainer('Spelling tests');
+
+# Load prerequisite modules.
+use_prereq('Test::Spelling');
+
+# Set up Automake testing.
+automake_setup();
+
+# Run the tests.
+all_pod_files_spelling_ok(perl_dirs());
diff --git a/tests/docs/pod-t b/tests/docs/pod-t
new file mode 100755 (executable)
index 0000000..2743287
--- /dev/null
@@ -0,0 +1,48 @@
+#!/usr/bin/perl -w
+#
+# Check all POD documents in the tree, except for any embedded Perl module
+# distribution, for POD formatting errors.
+#
+# The canonical version of this file is maintained in the rra-c-util package,
+# which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+#
+# Written by Russ Allbery <rra@stanford.edu>
+# Copyright 2012, 2013
+#     The Board of Trustees of the Leland Stanford Junior University
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+use 5.006;
+use strict;
+use warnings;
+
+use lib "$ENV{SOURCE}/tap/perl";
+
+use Test::More;
+use Test::RRA qw(use_prereq);
+use Test::RRA::Automake qw(automake_setup perl_dirs);
+
+# Load prerequisite modules.
+use_prereq('Test::Pod');
+
+# Set up Automake testing.
+automake_setup();
+
+# Run the tests.
+all_pod_files_ok(perl_dirs());
diff --git a/tests/tap/perl/Test/RRA.pm b/tests/tap/perl/Test/RRA.pm
new file mode 100644 (file)
index 0000000..cc29583
--- /dev/null
@@ -0,0 +1,222 @@
+# Helper functions for test programs written in Perl.
+#
+# This module provides a collection of helper functions used by test programs
+# written in Perl.  This is a general collection of functions that can be used
+# by both C packages with Automake and by stand-alone Perl modules.  See
+# Test::RRA::Automake for additional functions specifically for C Automake
+# distributions.
+#
+# The canonical version of this file is maintained in the rra-c-util package,
+# which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+#
+# Written by Russ Allbery <rra@stanford.edu>
+# Copyright 2013
+#     The Board of Trustees of the Leland Stanford Junior University
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+package Test::RRA;
+
+use 5.006;
+use strict;
+use warnings;
+
+use Exporter;
+use Test::More;
+
+# For Perl 5.006 compatibility.
+## no critic (ClassHierarchies::ProhibitExplicitISA)
+
+# Declare variables that should be set in BEGIN for robustness.
+our (@EXPORT_OK, @ISA, $VERSION);
+
+# Set $VERSION and everything export-related in a BEGIN block for robustness
+# against circular module loading (not that we load any modules, but
+# consistency is good).
+BEGIN {
+    @ISA       = qw(Exporter);
+    @EXPORT_OK = qw(skip_unless_maintainer use_prereq);
+
+    # This version should match the corresponding rra-c-util release, but with
+    # two digits for the minor version, including a leading zero if necessary,
+    # so that it will sort properly.
+    $VERSION = '4.09';
+}
+
+# Skip this test unless maintainer tests are requested.  Takes a short
+# description of what tests this script would perform, which is used in the
+# skip message.  Calls plan skip_all, which will terminate the program.
+#
+# $description - Short description of the tests
+#
+# Returns: undef
+sub skip_unless_maintainer {
+    my ($description) = @_;
+    if (!$ENV{RRA_MAINTAINER_TESTS}) {
+        plan skip_all => "$description only run for maintainer";
+    }
+    return;
+}
+
+# Attempt to load a module and skip the test if the module could not be
+# loaded.  If the module could be loaded, call its import function manually.
+# If the module could not be loaded, calls plan skip_all, which will terminate
+# the program.
+#
+# The special logic here is based on Test::More and is required to get the
+# imports to happen in the caller's namespace.
+#
+# $module  - Name of the module to load
+# @imports - Any arguments to import, possibly including a version
+#
+# Returns: undef
+sub use_prereq {
+    my ($module, @imports) = @_;
+
+    # If the first import looks like a version, pass it as a bare string.
+    my $version = q{};
+    if (@imports >= 1 && $imports[0] =~ m{ \A \d+ (?: [.]\d+ )* \z }xms) {
+        $version = shift(@imports);
+    }
+
+    # Get caller information to put imports in the correct package.
+    my ($package) = caller;
+
+    # Do the import with eval, and try to isolate it from the surrounding
+    # context as much as possible.  Based heavily on Test::More::_eval.
+    ## no critic (BuiltinFunctions::ProhibitStringyEval)
+    ## no critic (ValuesAndExpressions::ProhibitImplicitNewlines)
+    my ($result, $error, $sigdie);
+    {
+        local $@            = undef;
+        local $!            = undef;
+        local $SIG{__DIE__} = undef;
+        $result = eval qq{
+            package $package;
+            use $module $version \@imports;
+            1;
+        };
+        $error = $@;
+        $sigdie = $SIG{__DIE__} || undef;
+    }
+
+    # If the use failed for any reason, skip the test.
+    if (!$result || $error) {
+        plan skip_all => "$module required for test";
+    }
+
+    # If the module set $SIG{__DIE__}, we cleared that via local.  Restore it.
+    ## no critic (Variables::RequireLocalizedPunctuationVars)
+    if (defined($sigdie)) {
+        $SIG{__DIE__} = $sigdie;
+    }
+    return;
+}
+
+1;
+__END__
+
+=for stopwords
+Allbery Allbery's DESC bareword sublicense MERCHANTABILITY NONINFRINGEMENT
+rra-c-util
+
+=head1 NAME
+
+Test::RRA - Support functions for Perl tests
+
+=head1 SYNOPSIS
+
+    use Test::RRA qw(skip_unless_maintainer use_prereq);
+
+    # Skip this test unless maintainer tests are requested.
+    skip_unless_maintainer('Coding style tests');
+
+    # Load modules, skipping the test if they're not available.
+    use_prereq('File::Slurp');
+    use_prereq('Test::Script::Run', '0.04');
+
+=head1 DESCRIPTION
+
+This module collects utility functions that are useful for Perl test
+scripts.  It assumes Russ Allbery's Perl module layout and test
+conventions and will only be useful for other people if they use the
+same conventions.
+
+=head1 FUNCTIONS
+
+None of these functions are imported by default.  The ones used by a
+script should be explicitly imported.
+
+=over 4
+
+=item skip_unless_maintainer(DESC)
+
+Checks whether RRA_MAINTAINER_TESTS is set in the environment and skips
+the whole test (by calling C<plan skip_all> from Test::More) if it is not.
+DESC is a description of the tests being skipped.  A space and C<only run
+for maintainer> will be appended to it and used as the skip reason.
+
+=item use_prereq(MODULE[, VERSION][, IMPORT ...])
+
+Attempts to load MODULE with the given VERSION and import arguments.  If
+this fails for any reason, the test will be skipped (by calling C<plan
+skip_all> from Test::More) with a skip reason saying that MODULE is
+required for the test.
+
+VERSION will be passed to C<use> as a version bareword if it looks like a
+version number.  The remaining IMPORT arguments will be passed as the
+value of an array.
+
+=back
+
+=head1 AUTHOR
+
+Russ Allbery <rra@stanford.edu>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2013 The Board of Trustees of the Leland Stanford Junior
+University
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+=head1 SEE ALSO
+
+Test::More(3), Test::RRA::Automake(3), Test::RRA::Config(3)
+
+This module is maintained in the rra-c-util package.  The current version
+is available from L<http://www.eyrie.org/~eagle/software/rra-c-util/>.
+
+=cut
diff --git a/tests/tap/perl/Test/RRA/Automake.pm b/tests/tap/perl/Test/RRA/Automake.pm
new file mode 100644 (file)
index 0000000..5a0f4e8
--- /dev/null
@@ -0,0 +1,362 @@
+# Helper functions for Perl test programs in Automake distributions.
+#
+# This module provides a collection of helper functions used by test programs
+# written in Perl and included in C source distributions that use Automake.
+# They embed knowledge of how I lay out my source trees and test suites with
+# Autoconf and Automake.  They may be usable by others, but doing so will
+# require closely following the conventions implemented by the rra-c-util
+# utility collection.
+#
+# All the functions here assume that BUILD and SOURCE are set in the
+# environment.  This is normally done via the C TAP Harness runtests wrapper.
+#
+# The canonical version of this file is maintained in the rra-c-util package,
+# which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+#
+# Written by Russ Allbery <rra@stanford.edu>
+# Copyright 2013
+#     The Board of Trustees of the Leland Stanford Junior University
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+package Test::RRA::Automake;
+
+use 5.006;
+use strict;
+use warnings;
+
+# For Perl 5.006 compatibility.
+## no critic (ClassHierarchies::ProhibitExplicitISA)
+
+use Exporter;
+use File::Spec;
+use Test::More;
+use Test::RRA::Config qw($LIBRARY_PATH);
+
+# Used below for use lib calls.
+my ($PERL_BLIB_ARCH, $PERL_BLIB_LIB);
+
+# Determine the path to the build tree of any embedded Perl module package in
+# this source package.  We do this in a BEGIN block because we're going to use
+# the results in a use lib command below.
+BEGIN {
+    $PERL_BLIB_ARCH = File::Spec->catdir(qw(perl blib arch));
+    $PERL_BLIB_LIB  = File::Spec->catdir(qw(perl blib lib));
+
+    # If BUILD is set, we can come up with better values.
+    if (defined($ENV{BUILD})) {
+        my ($vol, $dirs) = File::Spec->splitpath($ENV{BUILD}, 1);
+        my @dirs = File::Spec->splitdir($dirs);
+        pop(@dirs);
+        $PERL_BLIB_ARCH = File::Spec->catdir(@dirs, qw(perl blib arch));
+        $PERL_BLIB_LIB  = File::Spec->catdir(@dirs, qw(perl blib lib));
+    }
+}
+
+# Prefer the modules built as part of our source package.  Otherwise, we may
+# not find Perl modules while testing, or find the wrong versions.
+use lib $PERL_BLIB_ARCH;
+use lib $PERL_BLIB_LIB;
+
+# Declare variables that should be set in BEGIN for robustness.
+our (@EXPORT_OK, @ISA, $VERSION);
+
+# Set $VERSION and everything export-related in a BEGIN block for robustness
+# against circular module loading (not that we load any modules, but
+# consistency is good).
+BEGIN {
+    @ISA       = qw(Exporter);
+    @EXPORT_OK = qw(automake_setup perl_dirs test_file_path);
+
+    # This version should match the corresponding rra-c-util release, but with
+    # two digits for the minor version, including a leading zero if necessary,
+    # so that it will sort properly.
+    $VERSION = '4.09';
+}
+
+# Perl directories to skip globally for perl_dirs.  We ignore the perl
+# directory if it exists since, in my packages, it is treated as a Perl module
+# distribution and has its own standalone test suite.
+my @GLOBAL_SKIP = qw(.git perl);
+
+# Perform initial test setup for running a Perl test in an Automake package.
+# This verifies that BUILD and SOURCE are set and then changes directory to
+# the SOURCE directory by default.  Sets LD_LIBRARY_PATH if the $LIBRARY_PATH
+# configuration option is set.  Calls BAIL_OUT if BUILD or SOURCE are missing
+# or if anything else fails.
+#
+# $args_ref - Reference to a hash of arguments to configure behavior:
+#   chdir_build - If set to a true value, changes to BUILD instead of SOURCE
+#
+# Returns: undef
+sub automake_setup {
+    my ($args_ref) = @_;
+
+    # Bail if BUILD or SOURCE are not set.
+    if (!$ENV{BUILD}) {
+        BAIL_OUT('BUILD not defined (run under runtests)');
+    }
+    if (!$ENV{SOURCE}) {
+        BAIL_OUT('SOURCE not defined (run under runtests)');
+    }
+
+    # BUILD or SOURCE will be the test directory.  Change to the parent.
+    my $start = $args_ref->{chdir_build} ? $ENV{BUILD} : $ENV{SOURCE};
+    my ($vol, $dirs) = File::Spec->splitpath($start, 1);
+    my @dirs = File::Spec->splitdir($dirs);
+    pop(@dirs);
+    if ($dirs[-1] eq File::Spec->updir) {
+        pop(@dirs);
+        pop(@dirs);
+    }
+    my $root = File::Spec->catpath($vol, File::Spec->catdir(@dirs), q{});
+    chdir($root) or BAIL_OUT("cannot chdir to $root: $!");
+
+    # If BUILD is a subdirectory of SOURCE, add it to the global ignore list.
+    my ($buildvol, $builddirs) = File::Spec->splitpath($ENV{BUILD}, 1);
+    my @builddirs = File::Spec->splitdir($builddirs);
+    pop(@builddirs);
+    if ($buildvol eq $vol && @builddirs == @dirs + 1) {
+        while (@dirs && $builddirs[0] eq $dirs[0]) {
+            shift(@builddirs);
+            shift(@dirs);
+        }
+        if (@builddirs == 1) {
+            push(@GLOBAL_SKIP, $builddirs[0]);
+        }
+    }
+
+    # Set LD_LIBRARY_PATH if the $LIBRARY_PATH configuration option is set.
+    ## no critic (Variables::RequireLocalizedPunctuationVars)
+    if (defined($LIBRARY_PATH)) {
+        @builddirs = File::Spec->splitdir($builddirs);
+        pop(@builddirs);
+        my $libdir = File::Spec->catdir(@builddirs, $LIBRARY_PATH);
+        my $path = File::Spec->catpath($buildvol, $libdir, q{});
+        if (-d "$path/.libs") {
+            $path .= '/.libs';
+        }
+        if ($ENV{LD_LIBRARY_PATH}) {
+            $ENV{LD_LIBRARY_PATH} .= ":$path";
+        } else {
+            $ENV{LD_LIBRARY_PATH} = $path;
+        }
+    }
+    return;
+}
+
+# Returns a list of directories that may contain Perl scripts and that should
+# be passed to Perl test infrastructure that expects a list of directories to
+# recursively check.  The list will be all eligible top-level directories in
+# the package except for the tests directory, which is broken out to one
+# additional level.  Calls BAIL_OUT on any problems
+#
+# $args_ref - Reference to a hash of arguments to configure behavior:
+#   skip - A reference to an array of directories to skip
+#
+# Returns: List of directories possibly containing Perl scripts to test
+sub perl_dirs {
+    my ($args_ref) = @_;
+
+    # Add the global skip list.
+    my @skip = $args_ref->{skip} ? @{ $args_ref->{skip} } : ();
+    push(@skip, @GLOBAL_SKIP);
+
+    # Separate directories to skip under tests from top-level directories.
+    my @skip_tests = grep { m{ \A tests/ }xms } @skip;
+    @skip = grep { !m{ \A tests }xms } @skip;
+    for my $skip_dir (@skip_tests) {
+        $skip_dir =~ s{ \A tests/ }{}xms;
+    }
+
+    # Convert the skip lists into hashes for convenience.
+    my %skip = map { $_ => 1 } @skip, 'tests';
+    my %skip_tests = map { $_ => 1 } @skip_tests;
+
+    # Build the list of top-level directories to test.
+    opendir(my $rootdir, q{.}) or BAIL_OUT("cannot open .: $!");
+    my @dirs = grep { -d $_ && !$skip{$_} } readdir($rootdir);
+    closedir($rootdir);
+    @dirs = File::Spec->no_upwards(@dirs);
+
+    # Add the list of subdirectories of the tests directory.
+    if (-d 'tests') {
+        opendir(my $testsdir, q{tests}) or BAIL_OUT("cannot open tests: $!");
+
+        # Skip if found in %skip_tests or if not a directory.
+        my $is_skipped = sub {
+            my ($dir) = @_;
+            return 1 if $skip_tests{$dir};
+            $dir = File::Spec->catdir('tests', $dir);
+            return -d $dir ? 0 : 1;
+        };
+
+        # Build the filtered list of subdirectories of tests.
+        my @test_dirs = grep { !$is_skipped->($_) } readdir($testsdir);
+        closedir($testsdir);
+        @test_dirs = File::Spec->no_upwards(@test_dirs);
+
+        # Add the tests directory to the start of the directory name.
+        push(@dirs, map { File::Spec->catdir('tests', $_) } @test_dirs);
+    }
+    return @dirs;
+}
+
+# Find a configuration file for the test suite.  Searches relative to BUILD
+# first and then SOURCE and returns whichever is found first.  Calls BAIL_OUT
+# if the file could not be found.
+#
+# $file - Partial path to the file
+#
+# Returns: Full path to the file
+sub test_file_path {
+    my ($file) = @_;
+  BASE:
+    for my $base ($ENV{BUILD}, $ENV{SOURCE}) {
+        next if !defined($base);
+        if (-f "$base/$file") {
+            return "$base/$file";
+        }
+    }
+    BAIL_OUT("cannot find $file");
+    return;
+}
+
+1;
+__END__
+
+=for stopwords
+Allbery Automake Automake-aware Automake-based rra-c-util ARGS
+subdirectories sublicense MERCHANTABILITY NONINFRINGEMENT
+
+=head1 NAME
+
+Test::RRA::Automake - Automake-aware support functions for Perl tests
+
+=head1 SYNOPSIS
+
+    use Test::RRA::Automake qw(automake_setup perl_dirs test_file_path);
+    automake_setup({ chdir_build => 1 });
+
+    # Paths to directories that may contain Perl scripts.
+    my @dirs = perl_dirs({ skip => [qw(lib)] });
+
+    # Configuration for Kerberos tests.
+    my $keytab = test_file_path('config/keytab');
+
+=head1 DESCRIPTION
+
+This module collects utility functions that are useful for test scripts
+written in Perl and included in a C Automake-based package.  They assume
+the layout of a package that uses rra-c-util and C TAP Harness for the
+test structure.
+
+Loading this module will also add the directories C<perl/blib/arch> and
+C<perl/blib/lib> to the Perl library search path, relative to BUILD if
+that environment variable is set.  This is harmless for C Automake
+projects that don't contain an embedded Perl module, and for those
+projects that do, this will allow subsequent C<use> calls to find modules
+that are built as part of the package build process.
+
+The automake_setup() function should be called before calling any other
+functions provided by this module.
+
+=head1 FUNCTIONS
+
+None of these functions are imported by default.  The ones used by a
+script should be explicitly imported.  On failure, all of these functions
+call BAIL_OUT (from Test::More).
+
+=over 4
+
+=item automake_setup([ARGS])
+
+Verifies that the BUILD and SOURCE environment variables are set and
+then changes directory to the top of the source tree (which is one
+directory up from the SOURCE path, since SOURCE points to the top of
+the tests directory).
+
+If ARGS is given, it should be a reference to a hash of configuration
+options.  Only one option is supported: C<chdir_build>.  If it is set
+to a true value, automake_setup() changes directories to the top of
+the build tree instead.
+
+=item perl_dirs([ARGS])
+
+Returns a list of directories that may contain Perl scripts that should be
+tested by test scripts that test all Perl in the source tree (such as
+syntax or coding style checks).  The paths will be simple directory names
+relative to the current directory or two-part directory names under the
+F<tests> directory.  (Directories under F<tests> are broken out separately
+since it's common to want to apply different policies to different
+subdirectories of F<tests>.)
+
+If ARGS is given, it should be a reference to a hash of configuration
+options.  Only one option is supported: C<skip>, whose value should be a
+reference to an array of additional top-level directories or directories
+starting with C<tests/> that should be skipped.
+
+=item test_file_path(FILE)
+
+Given FILE, which should be a relative path, locates that file relative to
+the test directory in either the source or build tree.  FILE will be
+checked for relative to the environment variable BUILD first, and then
+relative to SOURCE.  test_file_path() returns the full path to FILE or
+calls BAIL_OUT if FILE could not be found.
+
+=back
+
+=head1 AUTHOR
+
+Russ Allbery <rra@stanford.edu>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2013 The Board of Trustees of the Leland Stanford Junior
+University
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+=head1 SEE ALSO
+
+Test::More(3), Test::RRA(3), Test::RRA::Config(3)
+
+The C TAP Harness test driver and libraries for TAP-based C testing are
+available from L<http://www.eyrie.org/~eagle/software/c-tap-harness/>.
+
+This module is maintained in the rra-c-util package.  The current version
+is available from L<http://www.eyrie.org/~eagle/software/rra-c-util/>.
+
+=cut
diff --git a/tests/tap/perl/Test/RRA/Config.pm b/tests/tap/perl/Test/RRA/Config.pm
new file mode 100644 (file)
index 0000000..f0f9018
--- /dev/null
@@ -0,0 +1,200 @@
+# Configuration for Perl test cases.
+#
+# In order to reuse the same Perl test cases in multiple packages, I use a
+# configuration file to store some package-specific data.  This module loads
+# that configuration and provides the namespace for the configuration
+# settings.
+#
+# The canonical version of this file is maintained in the rra-c-util package,
+# which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+
+package Test::RRA::Config;
+
+use 5.006;
+use strict;
+use warnings;
+
+# For Perl 5.006 compatibility.
+## no critic (ClassHierarchies::ProhibitExplicitISA)
+
+use Exporter;
+use Test::More;
+
+# Declare variables that should be set in BEGIN for robustness.
+our (@EXPORT_OK, @ISA, $VERSION);
+
+# Set $VERSION and everything export-related in a BEGIN block for robustness
+# against circular module loading (not that we load any modules, but
+# consistency is good).
+BEGIN {
+    @ISA       = qw(Exporter);
+    @EXPORT_OK = qw(
+      $COVERAGE_LEVEL @COVERAGE_SKIP_TESTS @CRITIC_IGNORE $LIBRARY_PATH
+      $MINIMUM_VERSION %MINIMUM_VERSION @POD_COVERAGE_EXCLUDE
+    );
+
+    # This version should match the corresponding rra-c-util release, but with
+    # two digits for the minor version, including a leading zero if necessary,
+    # so that it will sort properly.
+    $VERSION = '4.09';
+}
+
+# If BUILD or SOURCE are set in the environment, look for data/perl.conf under
+# those paths for a C Automake package.  Otherwise, look in t/data/perl.conf
+# for a standalone Perl module.  Don't use Test::RRA::Automake since it may
+# not exist.
+our $PATH;
+for my $base ($ENV{BUILD}, $ENV{SOURCE}, 't') {
+    next if !defined($base);
+    my $path = "$base/data/perl.conf";
+    if (-r $path) {
+        $PATH = $path;
+        last;
+    }
+}
+if (!defined($PATH)) {
+    BAIL_OUT('cannot find data/perl.conf');
+}
+
+# Pre-declare all of our variables and set any defaults.
+our $COVERAGE_LEVEL = 100;
+our @COVERAGE_SKIP_TESTS;
+our @CRITIC_IGNORE;
+our $LIBRARY_PATH;
+our $MINIMUM_VERSION = '5.008';
+our %MINIMUM_VERSION;
+our @POD_COVERAGE_EXCLUDE;
+
+# Load the configuration.
+if (!do($PATH)) {
+    my $error = $@ || $! || 'loading file did not return true';
+    BAIL_OUT("cannot load data/perl.conf: $error");
+}
+
+1;
+__END__
+
+=for stopwords
+Allbery rra-c-util Automake perlcritic .libs namespace subdirectory
+sublicense MERCHANTABILITY NONINFRINGEMENT
+
+=head1 NAME
+
+Test::RRA::Config - Perl test configuration
+
+=head1 SYNOPSIS
+
+    use Test::RRA::Config qw($MINIMUM_VERSION);
+    print "Required Perl version is $MINIMUM_VERSION\n";
+
+=head1 DESCRIPTION
+
+Test::RRA::Config encapsulates per-package configuration for generic Perl
+test programs that are shared between multiple packages using the
+rra-c-util infrastructure.  It handles locating and loading the test
+configuration file for both C Automake packages and stand-alone Perl
+modules.
+
+Test::RRA::Config looks for a file named F<data/perl.conf> relative to the
+root of the test directory.  That root is taken from the environment
+variables BUILD or SOURCE (in that order) if set, which will be the case
+for C Automake packages using C TAP Harness.  If neither is set, it
+expects the root of the test directory to be a directory named F<t>
+relative to the current directory, which will be the case for stand-alone
+Perl modules.
+
+The following variables are supported:
+
+=over 4
+
+=item $COVERAGE_LEVEL
+
+The coverage level achieved by the test suite for Perl test coverage
+testing using Test::Strict, as a percentage.  The test will fail if test
+coverage less than this percentage is achieved.  If not given, defaults
+to 100.
+
+=item @COVERAGE_SKIP_TESTS
+
+Directories under F<t> whose tests should be skipped when doing coverage
+testing.  This can be tests that won't contribute to coverage or tests
+that don't run properly under Devel::Cover for some reason (such as ones
+that use taint checking).  F<docs> and F<style> will always be skipped
+regardless of this setting.
+
+=item @CRITIC_IGNORE
+
+Additional directories to ignore when doing recursive perlcritic testing.
+The contents of this directory must be either top-level directory names or
+directory names starting with F<tests/>.
+
+=item $LIBRARY_PATH
+
+Add this directory (or a .libs subdirectory) relative to the top of the
+source tree to LD_LIBRARY_PATH when checking the syntax of Perl modules.
+This may be required to pick up libraries that are used by in-tree Perl
+modules so that Perl scripts can pass a syntax check.
+
+=item $MINIMUM_VERSION
+
+Default minimum version requirement for included Perl scripts.  If not
+given, defaults to 5.008.
+
+=item %MINIMUM_VERSION
+
+Minimum version exceptions for specific directories.  The keys should be
+minimum versions of Perl to enforce.  The value for each key should be a
+reference to an array of either top-level directory names or directory
+names starting with F<tests/>.  All files in those directories will have
+that minimum Perl version constraint imposed instead of $MINIMUM_VERSION.
+
+=item @POD_COVERAGE_EXCLUDE
+
+Regexes that match method names that should be excluded from POD coverage
+testing.  Normally, all methods have to be documented in the POD for a
+Perl module, but methods matching any of these regexes will be considered
+private and won't require documentation.
+
+=back
+
+No variables are exported by default, but the variables can be imported
+into the local namespace to avoid long variable names.
+
+=head1 AUTHOR
+
+Russ Allbery <rra@stanford.edu>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2013 The Board of Trustees of the Leland Stanford Junior
+University
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+=head1 SEE ALSO
+
+Test::RRA(3), Test::RRA::Automake(3)
+
+This module is maintained in the rra-c-util package.  The current version
+is available from L<http://www.eyrie.org/~eagle/software/rra-c-util/>.
+
+The C TAP Harness test driver and libraries for TAP-based C testing are
+available from L<http://www.eyrie.org/~eagle/software/c-tap-harness/>.
+
+=cut