summaryrefslogtreecommitdiff
path: root/dh_elpa_test
diff options
context:
space:
mode:
Diffstat (limited to 'dh_elpa_test')
-rwxr-xr-xdh_elpa_test364
1 files changed, 364 insertions, 0 deletions
diff --git a/dh_elpa_test b/dh_elpa_test
new file mode 100755
index 0000000..09fe39d
--- /dev/null
+++ b/dh_elpa_test
@@ -0,0 +1,364 @@
+#!/usr/bin/perl
+
+=head1 NAME
+
+dh_elpa_test - run ELPA package testsuites
+
+=cut
+
+use strict;
+use warnings;
+no warnings "experimental::smartmatch";
+
+=head1 SYNOPSIS
+
+B<dh_elpa_test> [S<I<debhelper options>>] [S<I<--autopkgtest>>] [S<I<pkg-file>>]
+
+=head1 DESCRIPTION
+
+B<dh_elpa_test> is a debhelper program that is responsible for running
+the testsuites of ELPA packages, when those test suites use ERT or
+buttercup(1). dh_auto_test(1) is rarely suitable.
+
+Testing with buttercup(1) will be activated if the package
+build-depends on elpa-buttercup. Testing with ERT will be activated
+if ERT test files can be found. Neither kind of test will be
+activated unless the debhelper compat level is 10 or higher.
+
+=head1 FILES
+
+=over 4
+
+=item debian/elpa-test
+
+Configuration for running the package's test suite. Each line is of
+the form I<key> = I<value>, with I<key> drawn from the list of
+configuration options below.
+
+Note that you should not surround values with double quotation marks.
+This is convenient for including lisp. Configuration values cannot
+cover more than one line. Lines preceded with a # are ignored as
+comments.
+
+This configuration file is optional; in many cases, B<dh_elpa_test>
+can figure out how to run the test suite itself.
+
+=back
+
+=head1 CONFIGURATION KEYS
+
+=over 4
+
+=item B<disable>
+
+If this key is set to any value, dh_elpa(1) will not invoke
+B<dh_elpa_test>.
+
+=item B<buttercup_load_path>
+
+A comma-separated list of directories to add to the load-path when
+buttercup(1) invokes Emacs. Will be passed to buttercup(1) with its
+B<-L> command line argument.
+
+=item B<buttercup_patterns>
+
+A comma-separated list of Emacs regular expressions jointly matching
+all and only the files containing Buttercup tests that you wish to
+run. If this key is not defined, all tests that can be found
+will be run. Will be passed to buttercup(1) with its B<-p> command
+line argument.
+
+=item B<ert_exclude>
+
+A comma-separated list of file globs matching files containing ERT
+tests that should not be run.
+
+The '*' character in globs in this configuration key does NOT match
+'/' directory separators.
+
+=item B<ert_helper>
+
+The name of a *.el file containing Emacs Lisp code that will run the
+ERT test suite. When this key is not defined, B<dh_elpa_test>
+calls the function B<(ert-run-tests-batch-and-exit)>.
+
+Note that this is not the way to load test helpers that do needed work
+but don't actually run the tests. For that, you can use something like
+
+=over 4
+
+ ert_eval = (load-file "test-helper.el")
+
+=back
+
+=item B<ert_eval>
+
+Emacs Lisp code to be run prior to running ERT tests by the Emacs
+instance spawned by B<dh_elpa_test> to run those tests.
+
+=item B<ert_load_path>
+
+A comma-separated list of directories to add to the load-path when
+B<dh_elpa_test> invokes Emacs to run ERT tests.
+
+=item B<autopkgtest_keep>
+
+A comma-separated list of file globs matching files that should not be
+moved out of the source tree before running DEP8 tests (see the
+B<--autopkgtest> option below).
+
+The '*' character in globs in this configuration key matches '/'
+directory separators.
+
+=back
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--autopkgtest>
+
+Operate in autopkgtest mode. B<dh_elpa_test> will rename non-test *.el
+files so that Emacs will not load them. This ensures that the test
+test the installed binary package rather than the unpacked source
+package.
+
+To exclude files from this removal, specify them in the
+B<autopkgtest_keep> configuration option (see above).
+
+=back
+
+=head1 ENVIRONMENT VARIABLES
+
+Older versions of B<dh_elpa_test> were configured using environment
+variables corresponding to some of the above configuration keys. For
+example, the B<ert_eval> configuration key replaced environment
+variable B<DH_ELPA_TEST_ERT_EVAL>. Their use is now deprecated. If
+the debian/elpa-test file exists, they will be ignored.
+
+=cut
+
+use File::Find::Rule;
+use Array::Utils qw{ array_minus };
+use Text::Glob qw{ glob_to_regex };
+use Config::Tiny;
+
+use Debian::Debhelper::Dh_Lib;
+use Debian::Control;
+
+# ---- Subroutines
+
+# like Find::File::Rule::name, but matches the whole path of the file
+# (relative to cwd when search was started) against the glob, rather
+# than just the basename (also, unlike Find::File::Rule::name, accepts
+# a single glob and no regexps since that's all we need here)
+sub long_name {
+ my $glob = shift;
+
+ return sub {
+ ( undef, undef, my $fullname ) = @_;
+
+ if ( $fullname =~ glob_to_regex($glob) ) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+}
+
+# ---- Script setup
+
+# check command line opts for autopkgtest mode
+my $autopkgtest = ( "--autopkgtest" ~~ @ARGV );
+
+# This checks whether the debhelper compat is 10 or above. With
+# debhelper compat below 9, dh_elpa_test will get run more in more
+# than one sequence, including inside fakeroot, which can cause tests
+# to fail
+if ( get_buildoption("nocheck") || compat(9) ) {
+ exit 0;
+}
+
+# note that we don't need package.elpa-test since we are testing all
+# lisp we can find in the *source* package
+my $options = Config::Tiny->new;
+if ( -f "debian/elpa-test") {
+ verbose_print("I: Ignoring DH_ELPA_TEST_* envvars since debian/elpa-test exists");
+ $options = Config::Tiny->read( "debian/elpa-test" );
+} else {
+ my @envvars = ("DH_ELPA_TEST_DISABLE",
+ "DH_ELPA_TEST_BUTTERCUP_LOAD_PATH",
+ "DH_ELPA_TEST_BUTTERCUP_PATTERNS",
+ "DH_ELPA_TEST_ERT_EXCLUDE",
+ "DH_ELPA_TEST_ERT_HELPER",
+ "DH_ELPA_TEST_ERT_EVAL",
+ "DH_ELPA_TEST_ERT_LOAD_PATH"
+ );
+ foreach my $envvar ( @envvars ) {
+ if (defined $ENV{$envvar}) {
+ my $short = lc(substr($envvar, 13));
+ print "W: environment variable $envvar is deprecated; see dh_elpa_test(1)\n";
+ $options->{_}->{$short} = $ENV{$envvar};
+ }
+ }
+}
+
+my @non_test_files;
+if ($autopkgtest) {
+ # Since we were not invoked by the dh sequencer, we need to check
+ # here whether tests have been disabled. Note that we can't
+ # replace the test in elpa.pm with this one because we can't
+ # (cleanly) disable dh_auto_test from within dh_elpa_test
+ if ( defined $options->{_}->{ "disable" } ) {
+ exit 0;
+ }
+
+ my $rule = File::Find::Rule->new;
+ $rule
+ ->or(File::Find::Rule
+ ->name('.pc', 'debian')
+ ->directory->prune->discard,
+ File::Find::Rule->new);
+ $rule
+ ->file()
+ ->name( '*.el' )
+ ->none(File::Find::Rule->grep( "ert-deftest" ), # ERT
+ File::Find::Rule->grep( "\\(describe \"" ) # Buttercup
+ );
+
+ if ( defined $options->{_}->{'autopkgtest_keep'} ) {
+ foreach my $glob (split(',', $options->{_}->{'autopkgtest_keep'} )) {
+ # We want the user to be able to say
+ # autopkgtest_keep = test/resources/*
+ # and have that affect all subdirs of resources
+ $Text::Glob::strict_wildcard_slash = 0;
+ # TODO should we do this for ert_exclude too?
+ $rule->not_exec( long_name($glob) );
+ }
+ }
+
+ @non_test_files = $rule->in('.');
+
+ foreach my $old ( @non_test_files ) {
+ my $new = $old =~ s|\.el$|.disabled|r;
+ rename $old, $new or die "Failed to rename: $!\n";
+ }
+}
+
+# these are from dh_elpa
+# TODO have dh_elpa export them so we can import them, instead of copy/paste
+my $dhelpadir="/usr/share/emacs/site-lisp/elpa";
+my $elpadir="/usr/share/emacs/site-lisp/elpa-src";
+
+my $control = Debian::Control->new();
+$control->read("debian/control");
+
+if ($autopkgtest) {
+ # save stderr handle for restoration
+ {
+ no warnings 'once';
+ open(OLDERR, ">&", \*STDERR);
+ }
+ # redirect stderr to stdout while we run our tests
+ # emacs --batch and ERT itself both produce a lot of output on
+ # stderr even when there has been no error, and adt-run interprets
+ # this as a test failure
+ open(STDERR, ">&STDOUT");
+ # unbuffer them to ensure lines appear in the right order
+ select STDERR; $| = 1;
+ select STDOUT; $| = 1;
+}
+
+# ---- Buttercup
+
+if ($control->source->Build_Depends->has( "elpa-buttercup" )) {
+ my @args = qw{ buttercup -L . };
+ if (defined $options->{_}->{'buttercup_load_path'}) {
+ foreach my $dir (split(',', $options->{_}->{'buttercup_load_path'})) {
+ push @args, ('-L', "$dir");
+ }
+ }
+ if (defined $options->{_}->{'buttercup_patterns'}) {
+ foreach my $pattern (split(',', $options->{_}->{'buttercup_patterns'})) {
+ push @args, ('-p', "$pattern");
+ }
+ }
+ print_and_doit(@args);
+}
+
+# ---- ERT
+
+my $rule = File::Find::Rule->new;
+$rule
+ ->or(File::Find::Rule
+ ->name('.pc', 'debian')
+ ->directory->prune->discard,
+ File::Find::Rule->new);
+$rule
+ ->file()
+ ->name( '*.el' )
+ ->grep( "ert-deftest" );
+if (defined $options->{_}->{'ert_exclude'}) {
+ foreach my $glob (split(',', $options->{_}->{'ert_exclude'})) {
+ $rule->not_exec( long_name($glob) );
+ }
+}
+my @ert_files = $rule->in('.');
+
+if (@ert_files) {
+ my @args = qw{ emacs -batch -Q -l package };
+ push @args, ("--eval", "(add-to-list 'package-directory-list \"$dhelpadir\")");
+ push @args, ("--eval", "(add-to-list 'package-directory-list \"$elpadir\")");
+ push @args, ("-f", "package-initialize");
+
+ # work around the fact that s-el and dash-el are not packaged with
+ # dh_elpa so aren't in $dhelpadir
+ push @args, ("-L", "/usr/share/emacs/site-lisp/s-el")
+ if ($control->source->Build_Depends->has( "s-el" ));
+ push @args, ("-L", "/usr/share/emacs/site-lisp/dash-el")
+ if ($control->source->Build_Depends->has( "dash-el" ));
+
+ # add the user's load-path entries
+ if (defined $options->{_}->{'ert_load_path'}) {
+ foreach my $dir (split(',', $options->{_}->{'ert_load_path'})) {
+ push @args, ('-L', "$dir");
+ }
+ }
+
+ # make some guesses about where stuff that needs to be in
+ # load-path will be
+ push @args, ("-L", ".");
+ push @args, ("-L", "test") if ( -d "test" );
+ push @args, ("-L", "tests") if ( -d "tests" );
+ # TODO maybe we should just add all dirs containing files in @ert_files?
+
+ # now finish adding the user's stuff
+ push @args, ("--eval", $options->{_}->{'ert_eval'})
+ if (defined $options->{_}->{'ert_eval'});
+ foreach my $ert_file (@ert_files) {
+ push @args, ("-l", "$ert_file");
+ }
+ if (defined $options->{_}->{'ert_helper'}) {
+ push @args, ("-l", $options->{_}->{'ert_helper'});
+ } else {
+ push @args, ("--eval", "(ert-run-tests-batch-and-exit)");
+ }
+
+ print_and_doit(@args);
+}
+
+# ---- Cleanup
+
+END {
+ if ($autopkgtest) {
+ # restore stderr now we've finished running tests
+ open(STDERR, ">&OLDERR");
+
+ # Restore files that we renamed so that we comply with DEP8
+ # rw-build-tree
+ foreach my $new ( @non_test_files ) {
+ my $old = $new =~ s|\.el$|.disabled|r;
+ rename $old, $new or die "Failed to rename: $!\n";
+ }
+ }
+}