summaryrefslogtreecommitdiffstats
path: root/t/dh_install
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 21:06:40 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 21:06:40 +0000
commitd827c6cf1631209f5042a9d1d8a7ecc24223c8a0 (patch)
tree91a431d301efd0e524bdfb0c46e97d591a9d7b03 /t/dh_install
parentInitial commit. (diff)
downloaddebhelper-d827c6cf1631209f5042a9d1d8a7ecc24223c8a0.tar.xz
debhelper-d827c6cf1631209f5042a9d1d8a7ecc24223c8a0.zip
Adding upstream version 13.11.4.upstream/13.11.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rwxr-xr-xt/dh_install/01-basics.t33
-rwxr-xr-xt/dh_install/02-bugs-53XXXX.t65
-rwxr-xr-xt/dh_install/03-866570-dont-install-from-host.t24
-rwxr-xr-xt/dh_install/04-sourcedir.t47
-rw-r--r--t/dh_installchangelogs/debian/control10
-rwxr-xr-xt/dh_installchangelogs/dh_installchangelogs.t252
-rwxr-xr-xt/dh_installdocs/01-868204-ignore-broken-symlinks.t30
-rw-r--r--t/dh_installdocs/debian/changelog5
-rw-r--r--t/dh_installdocs/debian/control21
-rw-r--r--t/dh_installdocs/debian/copyright1
-rw-r--r--t/dh_installdocs/debian/docfile1
-rwxr-xr-xt/dh_installdocs/dh_installdocs.t75
-rw-r--r--t/dh_installgsettings/debian/changelog5
-rw-r--r--t/dh_installgsettings/debian/control17
-rwxr-xr-xt/dh_installgsettings/dh_installgsettings.t49
-rw-r--r--t/dh_installinit/debian/bar.other.init4
-rw-r--r--t/dh_installinit/debian/changelog5
-rw-r--r--t/dh_installinit/debian/control20
-rw-r--r--t/dh_installinit/debian/foo.service5
-rwxr-xr-xt/dh_installinit/dh_installinit.t44
-rwxr-xr-xt/dh_installman/01-basics.t94
-rw-r--r--t/dh_installman/libmanpage.so.1.2.3.pod17
-rw-r--r--t/dh_installman/libmanpage.so.9.2.31
-rw-r--r--t/dh_installman/manpage-compressed.pod17
-rw-r--r--t/dh_installman/manpage-perl.pod17
-rw-r--r--t/dh_installman/manpage-uncompressed.pod17
-rw-r--r--t/dh_installpam/debian/changelog5
-rw-r--r--t/dh_installpam/debian/control10
-rw-r--r--t/dh_installpam/debian/foo.pam1
-rwxr-xr-xt/dh_installpam/dh_installpam.t38
-rw-r--r--t/dh_installsystemd/debian/changelog5
-rw-r--r--t/dh_installsystemd/debian/control20
-rw-r--r--t/dh_installsystemd/debian/foo.init4
-rw-r--r--t/dh_installsystemd/debian/foo.service8
-rw-r--r--t/dh_installsystemd/debian/foo2.service8
-rwxr-xr-xt/dh_installsystemd/dh_installsystemd.t255
-rwxr-xr-xt/dh_installsystemd/dh_installsystemd_tmpfiles.t87
-rwxr-xr-xt/dh_installsystemd/dh_systemd.t123
-rw-r--r--t/dh_installsystemd/simple/debian/changelog5
-rw-r--r--t/dh_installsystemd/simple/debian/control10
-rw-r--r--t/dh_installsystemd/simple/debian/foo.service8
-rw-r--r--t/dh_installsystemduser/debian/baz.user.service8
-rw-r--r--t/dh_installsystemduser/debian/changelog5
-rw-r--r--t/dh_installsystemduser/debian/control10
-rw-r--r--t/dh_installsystemduser/debian/foo.user.service8
-rwxr-xr-xt/dh_installsystemduser/dh_installsystemduser.t112
46 files changed, 1606 insertions, 0 deletions
diff --git a/t/dh_install/01-basics.t b/t/dh_install/01-basics.t
new file mode 100755
index 0000000..b266196
--- /dev/null
+++ b/t/dh_install/01-basics.t
@@ -0,0 +1,33 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use Test::More;
+
+use File::Basename qw(dirname);
+use lib dirname(dirname(__FILE__));
+use Test::DH;
+use File::Path qw(remove_tree make_path);
+use Debian::Debhelper::Dh_Lib qw(!dirname);
+
+plan(tests => 2);
+
+
+each_compat_subtest {
+ my ($compat) = @_;
+ # regular specification of file not in debian/tmp
+ create_empty_file('dh_install');
+ ok(run_dh_tool('dh_install', 'dh_install', 'usr/bin'));
+ ok(-e "debian/debhelper/usr/bin/dh_install");
+ remove_tree('debian/debhelper', 'debian/tmp');
+};
+
+each_compat_subtest {
+ my ($compat) = @_;
+ # specification of file in subdir, not in debian/tmp
+ make_path('bar/usr/bin');
+ create_empty_file('bar/usr/bin/foo');
+ ok(run_dh_tool('dh_install', 'bar/usr/bin/foo'));
+ ok(-e "debian/debhelper/bar/usr/bin/foo");
+ remove_tree('debian/debhelper', 'debian/tmp');
+};
+
diff --git a/t/dh_install/02-bugs-53XXXX.t b/t/dh_install/02-bugs-53XXXX.t
new file mode 100755
index 0000000..1c42489
--- /dev/null
+++ b/t/dh_install/02-bugs-53XXXX.t
@@ -0,0 +1,65 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use Test::More;
+
+use File::Basename qw(dirname);
+use lib dirname(dirname(__FILE__));
+use Test::DH;
+use File::Path qw(remove_tree make_path);
+use Debian::Debhelper::Dh_Lib qw(!dirname);
+
+plan(tests => 4);
+
+each_compat_from_and_above_subtest(7, sub {
+ my ($compat) = @_;
+ # #537140: debian/tmp is explcitly specified despite being searched by
+ # default in v7+
+
+ make_path('debian/tmp/usr/bin');
+ create_empty_file('debian/tmp/usr/bin/foo');
+ create_empty_file('debian/tmp/usr/bin/bar');
+ ok(run_dh_tool('dh_install', 'debian/tmp/usr/bin/foo'));
+ ok(-e "debian/debhelper/usr/bin/foo", "#537140 [${compat}]");
+ ok(! -e "debian/debhelper/usr/bin/bar", "#537140 [${compat}]");
+ remove_tree('debian/debhelper', 'debian/tmp');
+});
+
+each_compat_from_and_above_subtest(7, sub {
+ my ($compat) = @_;
+ # #534565: glob expands to dangling symlink -> should install the dangling link
+ make_path('debian/tmp/usr/bin');
+ make_symlink_raw_target('broken', 'debian/tmp/usr/bin/foo');
+ create_empty_file('debian/tmp/usr/bin/bar');
+ ok(run_dh_tool('dh_install', 'usr/bin/*'));
+ ok(-l "debian/debhelper/usr/bin/foo", "#534565 [${compat}]");
+ ok(!-e "debian/debhelper/usr/bin/foo", "#534565 [${compat}]");
+ ok(-e "debian/debhelper/usr/bin/bar", "#534565 [${compat}]");
+ ok(!-l "debian/debhelper/usr/bin/bar", "#534565 [${compat}]");
+ remove_tree('debian/debhelper', 'debian/tmp');
+});
+
+each_compat_subtest {
+ my ($compat) = @_;
+ # #537017: --sourcedir=debian/tmp/foo is used
+ make_path('debian/tmp/foo/usr/bin');
+ create_empty_file('debian/tmp/foo/usr/bin/foo');
+ create_empty_file('debian/tmp/foo/usr/bin/bar');
+ ok(run_dh_tool('dh_install', '--sourcedir=debian/tmp/foo', 'usr/bin/bar'));
+ ok(-e "debian/debhelper/usr/bin/bar", "#537017 [${compat}]");
+ ok(!-e "debian/debhelper/usr/bin/foo", "#537017 [${compat}]");
+ remove_tree('debian/debhelper', 'debian/tmp');
+};
+
+each_compat_from_and_above_subtest(7, sub {
+ my ($compat) = @_;
+ # #535367: installation of entire top-level directory from debian/tmp
+ make_path('debian/tmp/usr/bin');
+ create_empty_file('debian/tmp/usr/bin/foo');
+ create_empty_file('debian/tmp/usr/bin/bar');
+ ok(run_dh_tool('dh_install', 'usr'));
+ ok(-e "debian/debhelper/usr/bin/foo", "#535367 [${compat}]");
+ ok(-e "debian/debhelper/usr/bin/bar", "#535367 [${compat}]");
+ remove_tree('debian/debhelper', 'debian/tmp');
+});
+
diff --git a/t/dh_install/03-866570-dont-install-from-host.t b/t/dh_install/03-866570-dont-install-from-host.t
new file mode 100755
index 0000000..92345d1
--- /dev/null
+++ b/t/dh_install/03-866570-dont-install-from-host.t
@@ -0,0 +1,24 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use Test::More;
+
+use File::Basename qw(dirname);
+use lib dirname(dirname(__FILE__));
+use Test::DH;
+use File::Path qw(remove_tree make_path);
+use Debian::Debhelper::Dh_Lib qw(!dirname);
+
+plan(tests => 1);
+
+each_compat_subtest {
+ my ($compat) = @_;
+ # #866570 - leading slashes must *not* pull things from the root FS.
+ make_path('bin');
+ create_empty_file('bin/grep-i-licious');
+ ok(run_dh_tool('dh_install', '/bin/grep*'));
+ ok(-e "debian/debhelper/bin/grep-i-licious", "#866570 [${compat}]");
+ ok(!-e "debian/debhelper/bin/grep", "#866570 [${compat}]");
+ remove_tree('debian/debhelper', 'debian/tmp');
+};
+
diff --git a/t/dh_install/04-sourcedir.t b/t/dh_install/04-sourcedir.t
new file mode 100755
index 0000000..83bd006
--- /dev/null
+++ b/t/dh_install/04-sourcedir.t
@@ -0,0 +1,47 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use Test::More;
+
+use File::Basename qw(dirname);
+use lib dirname(dirname(__FILE__));
+use Test::DH;
+use File::Path qw(remove_tree make_path);
+use Debian::Debhelper::Dh_Lib qw(!dirname);
+
+plan(tests => 3);
+
+
+each_compat_subtest {
+ my ($compat) = @_;
+ # redundant --sourcedir=debian/tmp in v7+
+ make_path('debian/tmp/usr/bin');
+ create_empty_file('debian/tmp/usr/bin/foo');
+ create_empty_file('debian/tmp/usr/bin/bar');
+ ok(run_dh_tool('dh_install', '--sourcedir=debian/tmp', 'usr/bin/foo'));
+ ok(-e "debian/debhelper/usr/bin/foo");
+ ok(! -e "debian/debhelper/usr/bin/bar");
+ remove_tree('debian/debhelper', 'debian/tmp');
+};
+
+each_compat_subtest {
+ my ($compat) = @_;
+ # #534565: fallback use of debian/tmp in v7+
+ make_path('debian/tmp/usr/bin');
+ create_empty_file('debian/tmp/usr/bin/foo');
+ create_empty_file('debian/tmp/usr/bin/bar');
+ ok(run_dh_tool('dh_install', 'usr'));
+ ok(-e "debian/debhelper/usr/bin/foo", "#534565 [${compat}]");
+ ok(-e "debian/debhelper/usr/bin/bar", "#534565 [${compat}]");
+ remove_tree('debian/debhelper', 'debian/tmp');
+};
+
+each_compat_subtest {
+ my ($compat) = @_;
+ # specification of file in source directory not in debian/tmp
+ make_path('bar/usr/bin');
+ create_empty_file('bar/usr/bin/foo');
+ ok(run_dh_tool('dh_install', '--sourcedir=bar', 'usr/bin/foo'));
+ ok(-e "debian/debhelper/usr/bin/foo");
+ remove_tree('debian/debhelper', 'debian/tmp');
+};
diff --git a/t/dh_installchangelogs/debian/control b/t/dh_installchangelogs/debian/control
new file mode 100644
index 0000000..4f4238e
--- /dev/null
+++ b/t/dh_installchangelogs/debian/control
@@ -0,0 +1,10 @@
+Source: foo
+Section: misc
+Priority: optional
+Maintainer: Test <testing@nowhere>
+Standards-Version: 3.9.8
+
+Package: foo
+Architecture: all
+Description: package foo
+ Package foo
diff --git a/t/dh_installchangelogs/dh_installchangelogs.t b/t/dh_installchangelogs/dh_installchangelogs.t
new file mode 100755
index 0000000..989a552
--- /dev/null
+++ b/t/dh_installchangelogs/dh_installchangelogs.t
@@ -0,0 +1,252 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use POSIX qw(locale_h);
+use Test::More;
+use Time::Piece;
+use Time::Seconds qw(ONE_MONTH ONE_YEAR);
+
+use File::Basename qw(dirname);
+use lib dirname(dirname(__FILE__));
+use Test::DH;
+
+use constant TEST_DIR => dirname($0);
+our @TEST_DH_EXTRA_TEMPLATE_FILES = (qw(
+ debian/changelog
+ debian/control
+));
+
+# Force Time::Piece to generate dch-compliant timestamps (i.e. in English).
+setlocale(LC_ALL, "C.UTF-8");
+
+use constant CUTOFF_DATE_STR => "2019-07-06"; # oldstable = Debian 10 Buster
+use constant CUTOFF_DATE => Time::Piece->strptime(CUTOFF_DATE_STR, "%Y-%m-%d");
+use constant MIN_NUM_ENTRIES => 4;
+
+sub install_changelog {
+ my ($latest_offset_years, $num_years, $is_binnmu) = @_;
+ $is_binnmu //= 0;
+
+ my $entry_date_first = CUTOFF_DATE->add_years($latest_offset_years);
+ my $entry_date_stop = $entry_date_first->add_years(-$num_years);
+
+ my $changelog = "${\TEST_DIR}/debian/changelog";
+
+ open(my $fd, ">", $changelog) or error("open($changelog): $!");
+
+ if ($is_binnmu) {
+ my $nmu_date = $entry_date_first->add_months(-1);
+ my $nmu_entry = entry_text($nmu_date, 1);
+ print($fd $nmu_entry);
+ }
+
+ # Add one entry every three months ~= four per year.
+ my $entry_date = $entry_date_first;
+ while ($entry_date > $entry_date_stop) {
+ my $entry = entry_text($entry_date, 0);
+ print($fd $entry);
+
+ $entry_date = $entry_date->add_months(-3);
+ }
+ close($fd);
+}
+
+sub entry_text {
+ my ($entry_date, $is_binnmu) = @_;
+ my $entry_date_str = $entry_date->strftime("%a, %d %b %Y %T %z");
+ my $ver = $entry_date->year . "." . $entry_date->mon . "-1";
+ my $binnmu_text = "";
+
+ if ($is_binnmu) {
+ $binnmu_text = " binary-only=yes";
+ $ver .= "+b1";
+ }
+
+ my $entry = "";
+ $entry .= "foo ($ver) unstable; urgency=low$binnmu_text\n\n";
+ $entry .= " * New release.\n\n";
+ $entry .= " -- Test <testing\@nowhere> $entry_date_str\n\n";
+
+ return $entry;
+}
+
+sub changelog_lines_pkg {
+ return changelog_lines("debian/changelog");
+}
+sub changelog_lines_installed {
+ return changelog_lines("debian/foo/usr/share/doc/foo/changelog.Debian");
+}
+sub changelog_lines_binnmu {
+ return changelog_lines("debian/foo/usr/share/doc/foo/changelog.Debian.all");
+}
+sub changelog_lines {
+ my ($changelog) = @_;
+ open(my $fd, $changelog) or error("open($changelog): $!");
+ my @lines = @{readlines($fd)};
+ @lines = grep(!/^$/, @lines);
+ return @lines;
+}
+
+sub dates_in_lines {
+ my @lines = @_;
+ my @lines_dates = grep(/^ -- /, @lines);
+ @lines_dates = map { (my $l = $_) =~ s/^\s*--\s+.*?\s+<[^>]*>\s+[A-Za-z]+, +//; $l } @lines_dates;
+ @lines_dates = map { Time::Piece->strptime($_, "%d %b %Y %T %z") } @lines_dates;
+ return @lines_dates;
+}
+
+plan(tests => 8);
+
+# Test changelog with only recent entries (< oldstable)
+my $years_after_cutoff = 2;
+my $years_of_changelog = 2;
+install_changelog($years_after_cutoff, $years_of_changelog);
+each_compat_subtest {
+ my @lines_orig = changelog_lines_pkg();
+ ok(run_dh_tool("dh_installchangelogs"));
+ my @lines = changelog_lines_installed();
+ my @comments = grep(/^#/, @lines);
+
+ is(@lines, @lines_orig);
+ is(@comments, 0);
+};
+
+# Test changelog with both recent and old entries
+$years_after_cutoff = 1;
+$years_of_changelog = 4;
+install_changelog($years_after_cutoff, $years_of_changelog);
+each_compat_subtest {
+ my @lines_orig = changelog_lines_pkg();
+ ok(run_dh_tool("dh_installchangelogs"));
+ my @lines = changelog_lines_installed();
+ my @entries = dates_in_lines(@lines);
+ my @entries_old = grep { $_ < CUTOFF_DATE } @entries;
+ my @comments = grep(/^#/, @lines);
+
+ cmp_ok(@lines, "<", @lines_orig);
+ cmp_ok(@entries, ">", 1);
+ is(@entries_old, 0);
+ cmp_ok(@comments, ">=", 1);
+};
+
+# Test changelog with only old entries
+$years_after_cutoff = -1;
+$years_of_changelog = 2;
+install_changelog($years_after_cutoff, $years_of_changelog);
+each_compat_subtest {
+ my @lines_orig = changelog_lines_pkg();
+ ok(run_dh_tool("dh_installchangelogs"));
+ my @lines = changelog_lines_installed();
+ my @entries = dates_in_lines(@lines);
+ my @entries_old = grep { $_ < CUTOFF_DATE } @entries;
+ my @comments = grep(/^#/, @lines);
+
+ cmp_ok(@lines, "<", @lines_orig);
+ is(@entries, MIN_NUM_ENTRIES);
+ is(@entries_old, MIN_NUM_ENTRIES);
+ cmp_ok(@comments, ">=", 1);
+};
+
+# Test changelog with only recent entries (< oldstable) + binNUM
+$years_after_cutoff = 2;
+$years_of_changelog = 2;
+install_changelog($years_after_cutoff, $years_of_changelog, 1);
+each_compat_subtest {
+ my @lines_orig = changelog_lines_pkg();
+ my @entries_orig = dates_in_lines(@lines_orig);
+ ok(run_dh_tool("dh_installchangelogs"));
+ my @lines = changelog_lines_installed();
+ my @entries = dates_in_lines(@lines);
+ my @entries_nmu = dates_in_lines(changelog_lines_binnmu());
+ my @comments = grep(/^#/, @lines);
+
+ is(@entries, @entries_orig-1);
+ is($entries[0], $entries_orig[1]);
+ is(@comments, 0);
+
+ is(@entries_nmu, 1);
+};
+
+# Test changelog with both recent and old entries + binNMU
+$years_after_cutoff = 1;
+$years_of_changelog = 4;
+install_changelog($years_after_cutoff, $years_of_changelog, 1);
+each_compat_subtest {
+ my @lines_orig = changelog_lines_pkg();
+ my @entries_orig = dates_in_lines(@lines_orig);
+ ok(run_dh_tool("dh_installchangelogs"));
+ my @lines = changelog_lines_installed();
+ my @entries = dates_in_lines(@lines);
+ my @entries_old = grep { $_ < CUTOFF_DATE } @entries;
+ my @entries_nmu = dates_in_lines(changelog_lines_binnmu());
+ my @comments = grep(/^#/, @lines);
+
+ cmp_ok(@entries, "<", @entries_orig-1);
+ is($entries[0], $entries_orig[1]);
+ is(@entries_old, 0);
+ cmp_ok(@comments, ">=", 1);
+
+ is(@entries_nmu, 1);
+};
+
+# Test changelog with only old entries + binNMU
+$years_after_cutoff = -1;
+$years_of_changelog = 2;
+install_changelog($years_after_cutoff, $years_of_changelog, 1);
+each_compat_subtest {
+ my @lines_orig = changelog_lines_pkg();
+ my @entries_orig = dates_in_lines(@lines_orig);
+ ok(run_dh_tool("dh_installchangelogs"));
+ my @lines = changelog_lines_installed();
+ my @entries = dates_in_lines(@lines);
+ my @entries_old = grep { $_ < CUTOFF_DATE } @entries;
+ my @entries_nmu = dates_in_lines(changelog_lines_binnmu());
+ my @comments = grep(/^#/, @lines);
+
+ is(@entries, MIN_NUM_ENTRIES);
+ is($entries[0], $entries_orig[1]);
+ is(@entries_old, MIN_NUM_ENTRIES);
+ cmp_ok(@comments, ">=", 1);
+
+ is(@entries_nmu, 1);
+};
+
+# Test changelog with both recent and old entries + --no-trim
+$years_after_cutoff = 1;
+$years_of_changelog = 4;
+install_changelog($years_after_cutoff, $years_of_changelog);
+each_compat_subtest {
+ my @lines_orig = changelog_lines_pkg();
+ ok(run_dh_tool("dh_installchangelogs", "--no-trim"));
+ my @lines = changelog_lines_installed();
+ my @entries = dates_in_lines(@lines);
+ my @entries_old = grep { $_ < CUTOFF_DATE } @entries;
+ my @comments = grep(/^#/, @lines);
+
+ is(@lines, @lines_orig);
+ cmp_ok(@entries, ">", 1);
+ cmp_ok(@entries_old, ">", 1);
+ is(@comments, 0);
+};
+
+# Test changelog with both recent and old entries + notrimdch
+$years_after_cutoff = 1;
+$years_of_changelog = 4;
+install_changelog($years_after_cutoff, $years_of_changelog);
+each_compat_subtest {
+ my @lines_orig = changelog_lines_pkg();
+ $ENV{DEB_BUILD_OPTIONS} = "notrimdch";
+ ok(run_dh_tool("dh_installchangelogs"));
+ my @lines = changelog_lines_installed();
+ my @entries = dates_in_lines(@lines);
+ my @entries_old = grep { $_ < CUTOFF_DATE } @entries;
+ my @comments = grep(/^#/, @lines);
+
+ is(@lines, @lines_orig);
+ cmp_ok(@entries, ">", 1);
+ cmp_ok(@entries_old, ">", 1);
+ is(@comments, 0);
+};
+
+unlink("${\TEST_DIR}/debian/changelog");
diff --git a/t/dh_installdocs/01-868204-ignore-broken-symlinks.t b/t/dh_installdocs/01-868204-ignore-broken-symlinks.t
new file mode 100755
index 0000000..b9801d2
--- /dev/null
+++ b/t/dh_installdocs/01-868204-ignore-broken-symlinks.t
@@ -0,0 +1,30 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use Test::More;
+
+use File::Basename qw(dirname);
+use lib dirname(dirname(__FILE__));
+use Test::DH;
+use File::Path qw(remove_tree make_path);
+use Debian::Debhelper::Dh_Lib qw(!dirname);
+
+plan(tests => 1);
+
+each_compat_subtest {
+ my ($compat) = @_;
+ # #868204 - dh_installdocs did not replace dangling symlink
+ make_path('debian/debhelper/usr/share/doc/debhelper');
+ make_symlink_raw_target('../to/nowhere/bar',
+ 'debian/debhelper/usr/share/doc/debhelper/README.Debian');
+ create_empty_file('debian/README.Debian');
+
+ ok(-l 'debian/debhelper/usr/share/doc/debhelper/README.Debian');
+ ok(!-e 'debian/debhelper/usr/share/doc/debhelper/README.Debian');
+
+ ok(run_dh_tool('dh_installdocs'));
+ ok(!-l 'debian/debhelper/usr/share/doc/debhelper/README.Debian', "#868204 [${compat}]");
+ ok(-f 'debian/debhelper/usr/share/doc/debhelper/README.Debian', "#868204 [${compat}]");
+ remove_tree('debian/debhelper', 'debian/tmp');
+};
+
diff --git a/t/dh_installdocs/debian/changelog b/t/dh_installdocs/debian/changelog
new file mode 100644
index 0000000..5850f0e
--- /dev/null
+++ b/t/dh_installdocs/debian/changelog
@@ -0,0 +1,5 @@
+foo (1.0-1) unstable; urgency=low
+
+ * Initial release. (Closes: #XXXXXX)
+
+ -- Test <testing@nowhere> Mon, 11 Jul 2016 18:10:59 +0200
diff --git a/t/dh_installdocs/debian/control b/t/dh_installdocs/debian/control
new file mode 100644
index 0000000..7e9a228
--- /dev/null
+++ b/t/dh_installdocs/debian/control
@@ -0,0 +1,21 @@
+Source: foo
+Section: misc
+Priority: optional
+Maintainer: Test <testing@nowhere>
+Rules-Requires-Root: no
+Standards-Version: 3.9.8
+
+Package: foo
+Architecture: all
+Description: package foo
+ Package foo
+
+Package: bar
+Architecture: all
+Description: package bar
+ Package bar
+
+Package: baz
+Architecture: all
+Description: package baz
+ Package baz
diff --git a/t/dh_installdocs/debian/copyright b/t/dh_installdocs/debian/copyright
new file mode 100644
index 0000000..7e6ffb0
--- /dev/null
+++ b/t/dh_installdocs/debian/copyright
@@ -0,0 +1 @@
+Some test copyright file
diff --git a/t/dh_installdocs/debian/docfile b/t/dh_installdocs/debian/docfile
new file mode 100644
index 0000000..2719eec
--- /dev/null
+++ b/t/dh_installdocs/debian/docfile
@@ -0,0 +1 @@
+This file must not be empty, or dh_installdocs won't install it.
diff --git a/t/dh_installdocs/dh_installdocs.t b/t/dh_installdocs/dh_installdocs.t
new file mode 100755
index 0000000..64f1254
--- /dev/null
+++ b/t/dh_installdocs/dh_installdocs.t
@@ -0,0 +1,75 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use Test::More;
+
+
+use File::Path qw(remove_tree);
+use File::Basename qw(dirname);
+use lib dirname(dirname(__FILE__));
+use Test::DH;
+
+our @TEST_DH_EXTRA_TEMPLATE_FILES = (qw(
+ debian/changelog
+ debian/control
+ debian/docfile
+ debian/copyright
+));
+
+plan(tests => 5);
+
+
+my $NODOC_PROFILE = {
+ 'env' => {
+ 'DEB_BUILD_PROFILES' => 'nodoc',
+ },
+};
+
+my $doc = "debian/docfile";
+
+each_compat_subtest {
+ ok(run_dh_tool('dh_installdocs', '-pbar', $doc));
+ ok(-e "debian/bar/usr/share/doc/bar/docfile");
+ remove_tree(qw(debian/foo debian/bar debian/baz));
+};
+
+each_compat_subtest {
+ #regression in debhelper 9.20160702 (#830309)
+ ok(run_dh_tool('dh_installdocs', '-pbaz', '--link-doc=foo', $doc));
+
+ ok(-l "debian/baz/usr/share/doc/baz");
+ ok(readlink("debian/baz/usr/share/doc/baz") eq 'foo');
+ ok(-e "debian/baz/usr/share/doc/foo/docfile");
+ remove_tree(qw(debian/foo debian/bar debian/baz));
+};
+
+each_compat_subtest {
+ ok(run_dh_tool('dh_installdocs', '-pfoo', '--link-doc=bar', $doc));
+
+ ok(-l "debian/foo/usr/share/doc/foo");
+ ok(readlink("debian/foo/usr/share/doc/foo") eq 'bar');
+ ok(-e "debian/foo/usr/share/doc/bar/docfile");
+ remove_tree(qw(debian/foo debian/bar debian/baz));
+};
+
+# ... and with nodoc
+
+each_compat_subtest {
+ # docs are ignored, but copyright file is still there
+ ok(run_dh_tool($NODOC_PROFILE, 'dh_installdocs', $doc));
+ for my $pkg (qw(foo bar baz)) {
+ ok(! -e "debian/$pkg/usr/share/doc/$pkg/docfile");
+ ok(-e "debian/$pkg/usr/share/doc/$pkg/copyright");
+ }
+ remove_tree(qw(debian/foo debian/bar debian/baz));
+};
+
+each_compat_subtest {
+ # docs are ignored, but symlinked doc dir is still there
+ ok(run_dh_tool($NODOC_PROFILE, 'dh_installdocs', '-pfoo', '--link-doc=bar', $doc));
+ ok(-l "debian/foo/usr/share/doc/foo");
+ ok(readlink("debian/foo/usr/share/doc/foo") eq 'bar');
+ ok(! -e "debian/foo/usr/share/doc/bar/docfile");
+ remove_tree(qw(debian/foo debian/bar debian/baz));
+};
+
diff --git a/t/dh_installgsettings/debian/changelog b/t/dh_installgsettings/debian/changelog
new file mode 100644
index 0000000..5850f0e
--- /dev/null
+++ b/t/dh_installgsettings/debian/changelog
@@ -0,0 +1,5 @@
+foo (1.0-1) unstable; urgency=low
+
+ * Initial release. (Closes: #XXXXXX)
+
+ -- Test <testing@nowhere> Mon, 11 Jul 2016 18:10:59 +0200
diff --git a/t/dh_installgsettings/debian/control b/t/dh_installgsettings/debian/control
new file mode 100644
index 0000000..c3cb827
--- /dev/null
+++ b/t/dh_installgsettings/debian/control
@@ -0,0 +1,17 @@
+Source: foo
+Section: misc
+Priority: optional
+Maintainer: Test <testing@nowhere>
+Standards-Version: 3.9.8
+
+Package: has-settings
+Architecture: all
+Depends: ${misc:Depends}
+Description: package has-settings
+ This package has a GSettings schema.
+
+Package: no-settings
+Architecture: all
+Depends: ${misc:Depends}
+Description: package no-settings
+ This package doesn't have a GSettings schema.
diff --git a/t/dh_installgsettings/dh_installgsettings.t b/t/dh_installgsettings/dh_installgsettings.t
new file mode 100755
index 0000000..fe76e8d
--- /dev/null
+++ b/t/dh_installgsettings/dh_installgsettings.t
@@ -0,0 +1,49 @@
+#!/usr/bin/perl
+use strict;
+use Test::More tests => 1;
+
+use autodie;
+use File::Basename qw(dirname);
+use lib dirname(dirname(__FILE__));
+use Test::DH;
+use File::Path qw(remove_tree make_path);
+use Debian::Debhelper::Dh_Lib qw(!dirname);
+
+our @TEST_DH_EXTRA_TEMPLATE_FILES = (qw(
+ debian/changelog
+ debian/control
+));
+
+my $SCHEMAS = 'usr/share/glib-2.0/schemas';
+
+sub touch {
+ my $path = shift;
+ open(my $fh, '>>', $path);
+ close $fh;
+}
+
+sub slurp {
+ my $path = shift;
+ local $/ = undef;
+ open(my $fh, '<', $path);
+ my $contents = <$fh>;
+ close $fh;
+ return $contents;
+}
+
+each_compat_subtest {
+ make_path("debian/has-settings/$SCHEMAS");
+ touch("debian/has-settings/$SCHEMAS/com.example.HasSettings.xml");
+ make_path("debian/has-unimportant-settings/$SCHEMAS");
+ touch("debian/no-settings.substvars");
+ ok(run_dh_tool('dh_installgsettings', '-phas-settings'), 'run for has-settings');
+ ok(run_dh_tool('dh_installgsettings', '-pno-settings'), 'run for no-settings');
+ remove_tree(qw(debian/has-settings debian/has-unimportant-settings));
+ like(slurp('debian/has-settings.substvars'),
+ qr{^misc:Depends=dconf-gsettings-backend \| gsettings-backend$}m,
+ 'has-settings should depend on a backend');
+ unlike(slurp('debian/no-settings.substvars'),
+ qr{^misc:Depends=dconf-gsettings-backend \| gsettings-backend$}m,
+ 'no-settings should not depend on a backend');
+};
+
diff --git a/t/dh_installinit/debian/bar.other.init b/t/dh_installinit/debian/bar.other.init
new file mode 100644
index 0000000..ea948c5
--- /dev/null
+++ b/t/dh_installinit/debian/bar.other.init
@@ -0,0 +1,4 @@
+#!/bin/sh
+cat << 'EOF'
+I am init script to be installed into package "bar" into /etc/init.d/other path.
+EOF \ No newline at end of file
diff --git a/t/dh_installinit/debian/changelog b/t/dh_installinit/debian/changelog
new file mode 100644
index 0000000..5850f0e
--- /dev/null
+++ b/t/dh_installinit/debian/changelog
@@ -0,0 +1,5 @@
+foo (1.0-1) unstable; urgency=low
+
+ * Initial release. (Closes: #XXXXXX)
+
+ -- Test <testing@nowhere> Mon, 11 Jul 2016 18:10:59 +0200
diff --git a/t/dh_installinit/debian/control b/t/dh_installinit/debian/control
new file mode 100644
index 0000000..48d4de2
--- /dev/null
+++ b/t/dh_installinit/debian/control
@@ -0,0 +1,20 @@
+Source: foo
+Section: misc
+Priority: optional
+Maintainer: Test <testing@nowhere>
+Standards-Version: 3.9.8
+
+Package: foo
+Architecture: all
+Description: package foo
+ Package foo
+
+Package: bar
+Architecture: all
+Description: package bar
+ Package bar
+
+Package: baz
+Architecture: all
+Description: package baz
+ Package baz
diff --git a/t/dh_installinit/debian/foo.service b/t/dh_installinit/debian/foo.service
new file mode 100644
index 0000000..aa21636
--- /dev/null
+++ b/t/dh_installinit/debian/foo.service
@@ -0,0 +1,5 @@
+[Unit]
+Description=A unit
+
+[Service]
+ExecStart=/bin/true
diff --git a/t/dh_installinit/dh_installinit.t b/t/dh_installinit/dh_installinit.t
new file mode 100755
index 0000000..7a7817c
--- /dev/null
+++ b/t/dh_installinit/dh_installinit.t
@@ -0,0 +1,44 @@
+#!/usr/bin/perl
+use strict;
+use Test::More;
+
+use File::Basename qw(dirname);
+use lib dirname(dirname(__FILE__));
+use Test::DH;
+use File::Path qw(remove_tree make_path);
+use Debian::Debhelper::Dh_Lib qw(!dirname);
+
+our @TEST_DH_EXTRA_TEMPLATE_FILES = (qw(
+ debian/changelog
+ debian/control
+ debian/foo.service
+ debian/bar.other.init
+));
+
+plan(tests => 2);
+
+each_compat_up_to_and_incl_subtest(10, sub {
+ make_path(qw(debian/foo debian/bar debian/baz));
+ ok(run_dh_tool('dh_installinit'));
+ ok(-e "debian/foo/lib/systemd/system/foo.service");
+ ok(find_script('foo', 'postinst'));
+ ok(run_dh_tool('dh_clean'));
+
+});
+
+each_compat_from_and_above_subtest(11, sub {
+ make_path(qw(debian/foo debian/bar debian/baz));
+
+ ok(run_dh_tool('dh_installinit'));
+ ok(run_dh_tool({'quiet' => 1}, 'dh_installinit', '--name=other'));
+ ok(! -e "debian/foo/lib/systemd/system/foo.service");
+ ok(!find_script('foo', 'postinst'));
+ ok(run_dh_tool('dh_clean'));
+
+ make_path(qw(debian/foo/lib/systemd/system/ debian/bar debian/baz));
+ copy_file('debian/foo.service', 'debian/foo/lib/systemd/system/foo.service');
+ ok(run_dh_tool('dh_installinit'));
+ ok(!find_script('foo', 'postinst'));
+ ok(run_dh_tool('dh_clean'));
+});
+
diff --git a/t/dh_installman/01-basics.t b/t/dh_installman/01-basics.t
new file mode 100755
index 0000000..141059a
--- /dev/null
+++ b/t/dh_installman/01-basics.t
@@ -0,0 +1,94 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use Test::More;
+
+use File::Basename qw(dirname);
+use lib dirname(dirname(__FILE__));
+use Test::DH;
+use File::Path qw(remove_tree make_path);
+use Debian::Debhelper::Dh_Lib qw(!dirname);
+
+sub has_man_db_tool {
+ my ($tool) = @_;
+ open(my $old_stderr, '>&', *STDERR) or error("dup(STDERR, tmp_fd): $!");
+ open(*STDERR, '>', '/dev/null') or error("re-open stderr as /dev/null: $!");
+
+ my $res = defined(`$tool --version`);
+ open(*STDERR, '>&', $old_stderr) or error("dup(tmp_fd, STDERR): $!");
+ close($old_stderr);
+ return $res;
+}
+
+if (has_man_db_tool('man') || has_man_db_tool('man-recode')) {
+ plan(tests => 2);
+} else {
+ plan(skip_all => 'Test requires man or man-recode');
+}
+
+our @TEST_DH_EXTRA_TEMPLATE_FILES = (qw(
+ manpage-uncompressed.pod
+ manpage-compressed.pod
+ manpage-perl.pod
+ libmanpage.so.1.2.3.pod
+ libmanpage.so.9.2.3
+));
+
+each_compat_subtest {
+ my ($compat) = @_;
+ if (! -d 'generated-manpages') {
+ # Static data that can be reused. Generate only in the first test
+ make_path('generated-manpages');
+ for my $basename (qw(manpage-uncompressed manpage-compressed manpage-perl libmanpage.so.1.2.3)) {
+ doit('pod2man', '--utf8', '-c', 'Debhelper', '-r', '1.0', "${basename}.pod",
+ "generated-manpages/${basename}.1");
+ }
+ doit('pod2man', '--utf8', '-c', 'Debhelper', '-r', '1.0', '-s', '3', 'manpage-perl.pod',
+ 'generated-manpages/manpage-perl.3perl');
+ doit('gzip', '-9n', 'generated-manpages/manpage-compressed.1');
+ }
+ ok(run_dh_tool('dh_installman', 'generated-manpages/manpage-uncompressed.1',
+ 'generated-manpages/manpage-compressed.1.gz',
+ 'generated-manpages/manpage-perl.3perl',
+ 'generated-manpages/libmanpage.so.1.2.3.1',
+ 'libmanpage.so.9.2.3'));
+
+ ok(-e 'debian/debhelper/usr/share/man/man1/manpage-uncompressed.1');
+ ok(-e 'debian/debhelper/usr/share/man/man1/manpage-compressed.1');
+ ok(-e 'debian/debhelper/usr/share/man/man3/manpage-perl.3');
+ ok(-e 'debian/debhelper/usr/share/man/man1/libmanpage.so.1.2.3.1');
+ ok(! -e 'debian/debhelper/usr/share/man/man9/libmanpage.so.9.2.9.2.3');
+ ok(-l 'debian/debhelper/usr/share/man/man3/libmanpage.so.9.2.3');
+ remove_tree('debian/debhelper', 'debian/tmp', 'debian/.debhelper');
+};
+
+each_compat_subtest {
+ my ($compat) = @_;
+ if (! -d 'generated-manpages') {
+ # Static data that can be reused. Generate only in the first test
+ make_path('generated-manpages');
+ for my $basename (qw(manpage-uncompressed manpage-compressed libmanpage.so.1.2.3)) {
+ doit('pod2man', '--utf8', '-c', 'Debhelper', '-r', '1.0', "${basename}.pod",
+ "generated-manpages/${basename}.1");
+ }
+ doit('pod2man', '--utf8', '-c', 'Debhelper', '-r', '1.0', '-s', '3', 'manpage-perl.pod',
+ 'generated-manpages/manpage-perl.3perl');
+ doit('gzip', '-9n', 'generated-manpages/manpage-compressed.1');
+ }
+ mkdirs('debian/debhelper/usr/share/man/man1');
+ mkdirs('debian/debhelper/usr/share/man/man3');
+ copy_file('generated-manpages/manpage-uncompressed.1', 'debian/debhelper/usr/share/man/man1/manpage-uncompressed.1');
+ copy_file('generated-manpages/manpage-compressed.1.gz', 'debian/debhelper/usr/share/man/man1/manpage-compressed.1.gz');
+ copy_file('generated-manpages/manpage-perl.3perl', 'debian/debhelper/usr/share/man/man3/manpage-perl.3perl');
+ copy_file('generated-manpages/libmanpage.so.1.2.3.1', 'debian/debhelper/usr/share/man/man1/libmanpage.so.1.2.3.1');
+ copy_file('libmanpage.so.9.2.3', 'debian/debhelper/usr/share/man/man3/libmanpage.so.9.2.3');
+ ok(run_dh_tool('dh_installman'));
+ ok(-e 'debian/debhelper/usr/share/man/man1/manpage-uncompressed.1');
+ ok(-e 'debian/debhelper/usr/share/man/man1/manpage-compressed.1');
+ ok(-e 'debian/debhelper/usr/share/man/man3/manpage-perl.3perl');
+ ok(-e 'debian/debhelper/usr/share/man/man1/libmanpage.so.1.2.3.1');
+ ok(! -e 'debian/debhelper/usr/share/man/man9/libmanpage.so.9.2.9.2.3');
+ ok(-l 'debian/debhelper/usr/share/man/man3/libmanpage.so.9.2.3');
+ remove_tree('debian/debhelper', 'debian/tmp', 'debian/.debhelper');
+};
+
diff --git a/t/dh_installman/libmanpage.so.1.2.3.pod b/t/dh_installman/libmanpage.so.1.2.3.pod
new file mode 100644
index 0000000..0b68dec
--- /dev/null
+++ b/t/dh_installman/libmanpage.so.1.2.3.pod
@@ -0,0 +1,17 @@
+=head1 NAME
+
+libmanpage.so.1.2.3 - Something very exciting
+
+=head1 SYNOPSIS
+
+This tool does not exist but would be awesome.
+
+=head1 SEE ALSO
+
+L<debhelper(7)>
+
+=head1 AUTHORS
+
+Niels Thykier <niels@thykier.net>
+
+=cut
diff --git a/t/dh_installman/libmanpage.so.9.2.3 b/t/dh_installman/libmanpage.so.9.2.3
new file mode 100644
index 0000000..07658f3
--- /dev/null
+++ b/t/dh_installman/libmanpage.so.9.2.3
@@ -0,0 +1 @@
+.so man1/manpage-uncompressed.1
diff --git a/t/dh_installman/manpage-compressed.pod b/t/dh_installman/manpage-compressed.pod
new file mode 100644
index 0000000..d2c0596
--- /dev/null
+++ b/t/dh_installman/manpage-compressed.pod
@@ -0,0 +1,17 @@
+=head1 NAME
+
+manpage - Something very exciting
+
+=head1 SYNOPSIS
+
+This tool does not exist but would be awesome.
+
+=head1 SEE ALSO
+
+L<debhelper(7)>
+
+=head1 AUTHORS
+
+Niels Thykier <niels@thykier.net>
+
+=cut
diff --git a/t/dh_installman/manpage-perl.pod b/t/dh_installman/manpage-perl.pod
new file mode 100644
index 0000000..9b66d9d
--- /dev/null
+++ b/t/dh_installman/manpage-perl.pod
@@ -0,0 +1,17 @@
+=head3 NAME
+
+manpage-uncompressed - Something very exciting
+
+=head3 SYNOPSIS
+
+This tool does not exist but would be awesome.
+
+=head3 SEE ALSO
+
+L<debhelper(7)>
+
+=head3 AUTHORS
+
+Niels Thykier <niels@thykier.net>
+
+=cut
diff --git a/t/dh_installman/manpage-uncompressed.pod b/t/dh_installman/manpage-uncompressed.pod
new file mode 100644
index 0000000..c95037c
--- /dev/null
+++ b/t/dh_installman/manpage-uncompressed.pod
@@ -0,0 +1,17 @@
+=head1 NAME
+
+manpage-uncompressed - Something very exciting
+
+=head1 SYNOPSIS
+
+This tool does not exist but would be awesome.
+
+=head1 SEE ALSO
+
+L<debhelper(7)>
+
+=head1 AUTHORS
+
+Niels Thykier <niels@thykier.net>
+
+=cut
diff --git a/t/dh_installpam/debian/changelog b/t/dh_installpam/debian/changelog
new file mode 100644
index 0000000..5850f0e
--- /dev/null
+++ b/t/dh_installpam/debian/changelog
@@ -0,0 +1,5 @@
+foo (1.0-1) unstable; urgency=low
+
+ * Initial release. (Closes: #XXXXXX)
+
+ -- Test <testing@nowhere> Mon, 11 Jul 2016 18:10:59 +0200
diff --git a/t/dh_installpam/debian/control b/t/dh_installpam/debian/control
new file mode 100644
index 0000000..c266f51
--- /dev/null
+++ b/t/dh_installpam/debian/control
@@ -0,0 +1,10 @@
+Source: foo
+Section: misc
+Priority: optional
+Maintainer: Test <testing@example.org>
+Standards-Version: 3.9.8
+
+Package: foo
+Architecture: all
+Description: package foo
+ Package foo
diff --git a/t/dh_installpam/debian/foo.pam b/t/dh_installpam/debian/foo.pam
new file mode 100644
index 0000000..fab1c8c
--- /dev/null
+++ b/t/dh_installpam/debian/foo.pam
@@ -0,0 +1 @@
+@include common-auth
diff --git a/t/dh_installpam/dh_installpam.t b/t/dh_installpam/dh_installpam.t
new file mode 100755
index 0000000..4e76799
--- /dev/null
+++ b/t/dh_installpam/dh_installpam.t
@@ -0,0 +1,38 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Test::More;
+use File::Basename qw(dirname);
+use lib dirname(dirname(__FILE__));
+use Test::DH;
+use File::Path qw(make_path);
+use Debian::Debhelper::Dh_Lib qw(!dirname);
+
+plan(tests => 2);
+
+our @TEST_DH_EXTRA_TEMPLATE_FILES = (qw(
+ debian/changelog
+ debian/control
+ debian/foo.pam
+));
+
+each_compat_up_to_and_incl_subtest(13, sub {
+ make_path(qw(debian/foo));
+ ok(run_dh_tool('dh_installpam'));
+
+ ok(-f 'debian/foo/etc/pam.d/foo');
+ ok(! -f 'debian/foo/usr/lib/pam.d/foo');
+
+ ok(run_dh_tool('dh_clean'));
+});
+
+each_compat_from_and_above_subtest(14, sub {
+ make_path(qw(debian/foo));
+ ok(run_dh_tool('dh_installpam'));
+
+ ok(! -f 'debian/foo/etc/pam.d/foo');
+ ok(-f 'debian/foo/usr/lib/pam.d/foo');
+
+ ok(run_dh_tool('dh_clean'));
+});
diff --git a/t/dh_installsystemd/debian/changelog b/t/dh_installsystemd/debian/changelog
new file mode 100644
index 0000000..5850f0e
--- /dev/null
+++ b/t/dh_installsystemd/debian/changelog
@@ -0,0 +1,5 @@
+foo (1.0-1) unstable; urgency=low
+
+ * Initial release. (Closes: #XXXXXX)
+
+ -- Test <testing@nowhere> Mon, 11 Jul 2016 18:10:59 +0200
diff --git a/t/dh_installsystemd/debian/control b/t/dh_installsystemd/debian/control
new file mode 100644
index 0000000..48d4de2
--- /dev/null
+++ b/t/dh_installsystemd/debian/control
@@ -0,0 +1,20 @@
+Source: foo
+Section: misc
+Priority: optional
+Maintainer: Test <testing@nowhere>
+Standards-Version: 3.9.8
+
+Package: foo
+Architecture: all
+Description: package foo
+ Package foo
+
+Package: bar
+Architecture: all
+Description: package bar
+ Package bar
+
+Package: baz
+Architecture: all
+Description: package baz
+ Package baz
diff --git a/t/dh_installsystemd/debian/foo.init b/t/dh_installsystemd/debian/foo.init
new file mode 100644
index 0000000..2b77921
--- /dev/null
+++ b/t/dh_installsystemd/debian/foo.init
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+some script
+
diff --git a/t/dh_installsystemd/debian/foo.service b/t/dh_installsystemd/debian/foo.service
new file mode 100644
index 0000000..2b48a78
--- /dev/null
+++ b/t/dh_installsystemd/debian/foo.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=A unit
+
+[Service]
+ExecStart=/bin/true
+
+[Install]
+WantedBy=multi-user.target
diff --git a/t/dh_installsystemd/debian/foo2.service b/t/dh_installsystemd/debian/foo2.service
new file mode 100644
index 0000000..42b9445
--- /dev/null
+++ b/t/dh_installsystemd/debian/foo2.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Another unit
+
+[Service]
+ExecStart=/bin/true
+
+[Install]
+WantedBy=multi-user.target
diff --git a/t/dh_installsystemd/dh_installsystemd.t b/t/dh_installsystemd/dh_installsystemd.t
new file mode 100755
index 0000000..bbb4eb0
--- /dev/null
+++ b/t/dh_installsystemd/dh_installsystemd.t
@@ -0,0 +1,255 @@
+#!/usr/bin/perl
+use strict;
+use Test::More;
+
+use File::Basename qw(dirname);
+use lib dirname(dirname(__FILE__));
+use Test::DH;
+use File::Path qw(remove_tree make_path);
+use Debian::Debhelper::Dh_Lib qw(!dirname);
+
+plan(tests => 4);
+
+sub write_file {
+ my ($path, $content) = @_;
+
+ my $dir = dirname($path);
+ mkdirs($dir);
+
+ open(my $fd, '>>', $path) or error("open($path) failed: $!");
+ print {$fd} $content . '\n';
+ close($fd) or error("close($path) failed: $!");
+}
+
+sub unit_is_enabled {
+ my ($package, $unit, $num_enables) = @_;
+ my @output;
+ my $matches;
+ my @postinst_snippets = find_script($package, 'postinst');
+ @output=`cat @postinst_snippets` if @postinst_snippets;
+ # Match exactly one tab; the "dont-enable" script has an "enable"
+ # line for re-enabling the service if the admin had it enabled.
+ # But we do not want to include that in our count.
+ $matches = grep { m{^\tif deb-systemd-helper .* was-enabled .*'\Q$unit\E\.service'} } @output;
+ ok($matches == $num_enables) or diag("$unit appears to have been enabled $matches times (expected $num_enables)");
+}
+
+sub unit_is_started {
+ my ($package, $unit, $num_starts, $num_stops) = @_;
+ my @output;
+ my $matches;
+ $num_stops = $num_stops // $num_starts;
+ my @postinst_snippets = find_script($package, 'postinst');
+ @output=`cat @postinst_snippets` if @postinst_snippets;
+ $matches = grep { m{deb-systemd-invoke \$_dh_action .*'\Q$unit\E.service'} } @output;
+ ok($matches == $num_starts) or diag("$unit appears to have been started $matches times (expected $num_starts)");
+ my @prerm_snippets = find_script($package, 'prerm');
+ @output=`cat @prerm_snippets` if @prerm_snippets;
+ $matches = grep { m{deb-systemd-invoke stop .*'\Q$unit\E.service'} } @output;
+ ok($matches == $num_stops) or diag("$unit appears to have been stopped $matches times (expected $num_stops)");
+}
+
+
+#
+# Test a simple source package defining a single binary package
+#
+our $TEST_DH_FIXTURE_DIR = 'simple';
+our @TEST_DH_EXTRA_TEMPLATE_FILES = (qw(
+ debian/changelog
+ debian/control
+ debian/foo.service
+));
+
+each_compat_subtest {
+ ok(run_dh_tool('dh_installsystemd'));
+ ok(-e 'debian/foo/lib/systemd/system/foo.service');
+ ok(find_script('foo', 'postinst'));
+ unit_is_enabled('foo', 'foo', 1);
+ unit_is_started('foo', 'foo', 1);
+ ok(run_dh_tool('dh_clean'));
+
+ ok(run_dh_tool('dh_installsystemd', '--no-start'));
+ ok(-e 'debian/foo/lib/systemd/system/foo.service');
+ ok(find_script('foo', 'postinst'));
+ unit_is_enabled('foo', 'foo', 1);
+ unit_is_started('foo', 'foo', 0, 0);
+ ok(run_dh_tool('dh_clean'));
+
+ ok(run_dh_tool('dh_installsystemd', '--no-start', 'foo.service'));
+ ok(-e 'debian/foo/lib/systemd/system/foo.service');
+ ok(find_script('foo', 'postinst'));
+ unit_is_enabled('foo', 'foo', 1);
+ unit_is_started('foo', 'foo', 0, 0);
+ ok(run_dh_tool('dh_clean'));
+};
+
+
+#
+# Test a more complex source package defining three binary packages
+#
+$TEST_DH_FIXTURE_DIR = '.';
+@TEST_DH_EXTRA_TEMPLATE_FILES = (qw(
+ debian/changelog
+ debian/control
+ debian/foo.service
+ debian/foo2.service
+));
+
+each_compat_subtest {
+ ok(run_dh_tool( 'dh_installsystemd'));
+ ok(-e 'debian/foo/lib/systemd/system/foo.service');
+ ok(find_script('foo', 'postinst'));
+ unit_is_enabled('foo', 'foo', 1);
+ unit_is_started('foo', 'foo', 1);
+ unit_is_enabled('foo', 'foo2', 0);
+ unit_is_started('foo', 'foo2', 0);
+ ok(run_dh_tool('dh_clean'));
+
+ make_path('debian/foo/lib/systemd/system/');
+ copy_file('debian/foo2.service', 'debian/foo/lib/systemd/system/foo2.service');
+ ok(run_dh_tool('dh_installsystemd'));
+ ok(-e 'debian/foo/lib/systemd/system/foo.service');
+ ok(find_script('foo', 'postinst'));
+ unit_is_enabled('foo', 'foo', 1);
+ unit_is_started('foo', 'foo', 1);
+ unit_is_enabled('foo', 'foo2', 1);
+ unit_is_started('foo', 'foo2', 1);
+ ok(run_dh_tool('dh_clean'));
+
+
+ # lib -> usr/lib (if we ever support that)
+ make_path('debian/foo/lib/systemd/system/');
+ copy_file('debian/foo2.service', 'debian/foo/lib/systemd/system/foo2.service');
+ ok(run_dh_tool('dh_installsystemd'));
+ ok(-e 'debian/foo/lib/systemd/system/foo2.service');
+ ok(find_script('foo', 'postinst'));
+ unit_is_enabled('foo', 'foo', 1);
+ unit_is_started('foo', 'foo', 1);
+ unit_is_enabled('foo', 'foo2', 1);
+ unit_is_started('foo', 'foo2', 1);
+ ok(run_dh_tool('dh_clean'));
+
+ # lib -> usr/lib with both no-empty (if we ever suport that)
+ make_path('debian/foo/lib/systemd/system/');
+ make_path('debian/foo/lib/systemd/system/');
+ copy_file('debian/foo2.service', 'debian/foo/lib/systemd/system/foo2.service');
+ copy_file('debian/foo2.service', 'debian/foo/lib/systemd/system/bar.service');
+ ok(run_dh_tool('dh_installsystemd'));
+ ok(-e 'debian/foo/lib/systemd/system/bar.service');
+ ok(-e 'debian/foo/lib/systemd/system/foo2.service');
+ ok(find_script('foo', 'postinst'));
+ unit_is_enabled('foo', 'foo', 1);
+ unit_is_started('foo', 'foo', 1);
+ unit_is_enabled('foo', 'foo2', 1);
+ unit_is_started('foo', 'foo2', 1);
+ ok(run_dh_tool('dh_clean'));
+
+ make_path('debian/foo/lib/systemd/system/');
+ copy_file('debian/foo2.service', 'debian/foo/lib/systemd/system/foo2.service');
+ ok(run_dh_tool('dh_installsystemd', '--no-start'));
+ ok(-e 'debian/foo/lib/systemd/system/foo.service');
+ ok(find_script('foo', 'postinst'));
+ unit_is_enabled('foo', 'foo', 1);
+ unit_is_started('foo', 'foo', 0, 0);
+ unit_is_enabled('foo', 'foo2', 1);
+ unit_is_started('foo', 'foo2', 0, 0);
+ ok(run_dh_tool('dh_clean'));
+
+ make_path('debian/foo/lib/systemd/system/');
+ copy_file('debian/foo2.service', 'debian/foo/lib/systemd/system/foo2.service');
+ ok(run_dh_tool('dh_installsystemd', '-p', 'foo', '--no-start', 'foo.service'));
+ ok(run_dh_tool('dh_installsystemd', '-p', 'foo', 'foo2.service'));
+ ok(-e 'debian/foo/lib/systemd/system/foo.service');
+ ok(find_script('foo', 'postinst'));
+ unit_is_enabled('foo', 'foo', 1);
+ unit_is_started('foo', 'foo', 0, 0);
+ unit_is_enabled('foo', 'foo2', 1);
+ unit_is_started('foo', 'foo2', 1);
+ ok(run_dh_tool('dh_clean'));
+
+ make_path('debian/foo/lib/systemd/system/');
+ copy_file('debian/foo2.service', 'debian/foo/lib/systemd/system/foo2.service');
+ ok(run_dh_tool('dh_installsystemd', '-p', 'foo', '--no-enable', 'foo.service'));
+ ok(run_dh_tool('dh_installsystemd', '-p', 'foo', 'foo2.service'));
+ ok(-e 'debian/foo/lib/systemd/system/foo.service');
+ ok(find_script('foo', 'postinst'));
+ unit_is_enabled('foo', 'foo', 0);
+ unit_is_started('foo', 'foo', 1, 1);
+ unit_is_enabled('foo', 'foo2', 1);
+ unit_is_started('foo', 'foo2', 1);
+ ok(run_dh_tool('dh_clean'));
+
+ make_path('debian/foo/lib/systemd/system/');
+ ok(run_dh_tool('dh_installsystemd', '--no-restart-after-upgrade'));
+ my @foo_postinst = find_script('foo', 'postinst');
+ ok(@foo_postinst);
+ my $matches = @foo_postinst ? grep { m{deb-systemd-invoke start .*foo.service} } `cat @foo_postinst` : -1;
+ ok($matches == 1);
+ ok(run_dh_tool('dh_clean'));
+
+ # Quoting #764730
+ make_path('debian/foo/lib/systemd/system/');
+ copy_file('debian/foo.service', 'debian/foo/lib/systemd/system/foo\x2dfuse.service');
+ ok(run_dh_tool('dh_installsystemd'));
+ unit_is_enabled('foo', 'foo\x2dfuse', 1);
+ unit_is_started('foo', 'foo\x2dfuse', 1);
+ ok(run_dh_tool('dh_clean'));
+
+ # --name flag #870768
+ make_path('debian/foo/lib/systemd/system/');
+ copy_file('debian/foo2.service', 'debian/foo/lib/systemd/system/foo2.service');
+ ok(run_dh_tool('dh_installsystemd', '--name=foo'));
+ unit_is_enabled('foo', 'foo', 1);
+ unit_is_started('foo', 'foo', 1);
+ unit_is_enabled('foo', 'foo2', 0);
+ unit_is_started('foo', 'foo2', 0);
+ ok(run_dh_tool('dh_installsystemd', '--name=foo2'));
+ unit_is_enabled('foo', 'foo', 1);
+ unit_is_started('foo', 'foo', 1);
+ unit_is_enabled('foo', 'foo2', 1);
+ unit_is_started('foo', 'foo2', 1);
+ ok(run_dh_tool('dh_clean'));
+
+ make_path('debian/foo/lib/systemd/system/');
+ copy_file('debian/foo.service', 'debian/foo/lib/systemd/system/target.service');
+ make_symlink_raw_target('target.service', 'debian/foo/lib/systemd/system/source.service');
+ ok(run_dh_tool('dh_installsystemd'));
+ unit_is_enabled('foo', 'foo', 1);
+ # Alias= realized by symlinks are not enabled in maintaner scripts
+ unit_is_enabled('foo', 'source', 0);
+ unit_is_enabled('foo', 'target', 1);
+ ok(run_dh_tool('dh_clean'));
+};
+
+each_compat_up_to_and_incl_subtest(11, sub {
+ make_path('debian/foo/lib/systemd/system/');
+ make_path('debian/foo/etc/init.d/');
+ copy_file('debian/foo.service', 'debian/foo/lib/systemd/system/target.service');
+ make_symlink_raw_target('target.service', 'debian/foo/lib/systemd/system/source.service');
+ write_file('debian/foo/etc/init.d/source', '# something');
+ ok(run_dh_tool('dh_installsystemd'));
+ unit_is_enabled('foo', 'foo', 1);
+ # Alias= realized by symlinks are not enabled in maintaner scripts
+ unit_is_enabled('foo', 'source', 0);
+ unit_is_enabled('foo', 'target', 1);
+ # The presence of a sysvinit script for the alias unit inhibits start of both
+ unit_is_started('foo', 'source', 0);
+ unit_is_started('foo', 'target', 0);
+ ok(run_dh_tool('dh_clean'));
+});
+
+each_compat_from_and_above_subtest(12, sub {
+ make_path('debian/foo/lib/systemd/system/');
+ make_path('debian/foo/etc/init.d/');
+ copy_file('debian/foo.service', 'debian/foo/lib/systemd/system/target.service');
+ make_symlink_raw_target('target.service', 'debian/foo/lib/systemd/system/source.service');
+ write_file('debian/foo/etc/init.d/source', '# something');
+ ok(run_dh_tool('dh_installsystemd'));
+ unit_is_enabled('foo', 'foo', 1);
+ # Alias= realized by symlinks are not enabled in maintaner scripts
+ unit_is_enabled('foo', 'source', 0);
+ unit_is_enabled('foo', 'target', 1);
+ unit_is_started('foo', 'source', 0);
+ unit_is_started('foo', 'target', 1);
+ ok(run_dh_tool('dh_clean'));
+});
diff --git a/t/dh_installsystemd/dh_installsystemd_tmpfiles.t b/t/dh_installsystemd/dh_installsystemd_tmpfiles.t
new file mode 100755
index 0000000..0fffe57
--- /dev/null
+++ b/t/dh_installsystemd/dh_installsystemd_tmpfiles.t
@@ -0,0 +1,87 @@
+#!/usr/bin/perl
+use strict;
+use Test::More;
+
+use File::Basename qw(dirname);
+use lib dirname(dirname(__FILE__));
+use Test::DH;
+use File::Path qw(remove_tree make_path);
+use Debian::Debhelper::Dh_Lib qw(!dirname);
+
+our @TEST_DH_EXTRA_TEMPLATE_FILES = (qw(
+ debian/changelog
+ debian/control
+ debian/foo.service
+ debian/foo.init
+));
+
+plan(tests => 3);
+
+
+# Units are installed and enabled
+each_compat_from_x_to_and_incl_y_subtest(11, 12, sub {
+ make_path('debian/foo/usr/lib/tmpfiles.d');
+ create_empty_file('debian/foo/usr/lib/tmpfiles.d/foo.conf');
+ ok(run_dh_tool('dh_installinit'));
+ ok(run_dh_tool('dh_installsystemd'));
+ ok(-e "debian/foo/etc/init.d/foo");
+ ok(-e "debian/foo/lib/systemd/system/foo.service");
+ my @postinst = find_script('foo', 'postinst');
+ # We should have two snippets (one for the tmpfiles and one for the services).
+ is(scalar(@postinst), 2);
+ if (scalar(@postinst) == 2) {
+ open(my $fd, '<', $postinst[0]) or error("open($postinst[0]) failed: $!");
+ my $early_snippet = readlines($fd);
+ close($fd);
+ open($fd, '<', $postinst[1]) or error("open($postinst[1]) failed: $!");
+ my $late_snippet = readlines($fd);
+ close($fd);
+ ok(! grep { m/(?:invoke|update)-rc.d|deb-systemd-invoke/ } @{$early_snippet});
+ ok(grep { m/(?:invoke|update)-rc.d|deb-systemd-invoke/ } @{$late_snippet});
+ ok(grep { m/systemd-tmpfiles/ } @{$early_snippet});
+ ok(! grep { m/systemd-tmpfiles/ } @{$late_snippet});
+ }
+ ok(run_dh_tool('dh_clean'));
+
+});
+
+each_compat_from_and_above_subtest(13, sub {
+ make_path('debian/foo/usr/lib/tmpfiles.d');
+ create_empty_file('debian/foo/usr/lib/tmpfiles.d/foo.conf');
+ ok(run_dh_tool('dh_installinit'));
+ ok(run_dh_tool('dh_installsystemd'));
+ ok(-e "debian/foo/etc/init.d/foo");
+ ok(-e "debian/foo/lib/systemd/system/foo.service");
+ my @postinst = find_script('foo', 'postinst');
+ # We should have one snippet (one for the services).
+ is(scalar(@postinst), 1);
+ if (scalar(@postinst) == 1) {
+ open(my $fd, '<', $postinst[0]) or error("open($postinst[0]) failed: $!");
+ my $snippet = readlines($fd);
+ close($fd);
+ ok(grep { m/(?:invoke|update)-rc.d|deb-systemd-invoke/ } @{$snippet});
+ ok(! grep { m/systemd-tmpfiles/ } @{$snippet});
+ }
+ ok(run_dh_tool('dh_clean'));
+});
+
+
+each_compat_from_and_above_subtest(13, sub {
+ make_path('debian/foo/usr/lib/tmpfiles.d');
+ create_empty_file('debian/foo/usr/lib/tmpfiles.d/foo.conf');
+ ok(run_dh_tool('dh_installtmpfiles'));
+ # dh_installtmpfiles do not install services
+ ok(!-e "debian/foo/etc/init.d/foo");
+ ok(!-e "debian/foo/lib/systemd/system/foo.service");
+ my @postinst = find_script('foo', 'postinst');
+ # We should have too snippets (one for the tmpfiles and one for the services).
+ is(scalar(@postinst), 1);
+ if (scalar(@postinst) == 1) {
+ open(my $fd, '<', $postinst[0]) or error("open($postinst[0]) failed: $!");
+ my $snippet = readlines($fd);
+ close($fd);
+ ok(! grep { m/(?:invoke|update)-rc.d|deb-systemd-invoke/ } @{$snippet});
+ ok(grep { m/systemd-tmpfiles/ } @{$snippet});
+ }
+ ok(run_dh_tool('dh_clean'));
+});
diff --git a/t/dh_installsystemd/dh_systemd.t b/t/dh_installsystemd/dh_systemd.t
new file mode 100755
index 0000000..c3c9401
--- /dev/null
+++ b/t/dh_installsystemd/dh_systemd.t
@@ -0,0 +1,123 @@
+#!/usr/bin/perl
+use strict;
+use Test::More;
+
+use File::Basename qw(dirname);
+use lib dirname(dirname(__FILE__));
+use Test::DH;
+use File::Path qw(remove_tree make_path);
+use Debian::Debhelper::Dh_Lib qw(!dirname);
+
+our @TEST_DH_EXTRA_TEMPLATE_FILES = (qw(
+ debian/changelog
+ debian/control
+ debian/foo.service
+ debian/foo2.service
+));
+
+plan(tests => 1);
+
+sub unit_is_enabled {
+ my ($package, $unit, $num_enables) = @_;
+ my @output;
+ my $matches;
+ @output=`cat debian/$package.postinst.debhelper`;
+ # Match exactly one tab; the "dont-enable" script has an "enable"
+ # line for re-enabling the service if the admin had it enabled.
+ # But we do not want to include that in our count.
+ $matches = grep { m{^\tif deb-systemd-helper .* was-enabled .*'\Q$unit\E\.service'} } @output;
+ ok($matches == $num_enables) or diag("$unit appears to have been enabled $matches times (expected $num_enables)");
+}
+sub unit_is_started {
+ my ($package, $unit, $num_starts, $num_stops) = @_;
+ my @output;
+ my $matches;
+ $num_stops = $num_stops // $num_starts;
+ @output=`cat debian/$package.postinst.debhelper`;
+ $matches = grep { m{deb-systemd-invoke \$_dh_action .*'\Q$unit\E.service'} } @output;
+ ok($matches == $num_starts) or diag("$unit appears to have been started $matches times (expected $num_starts)");
+ @output=`cat debian/$package.prerm.debhelper`;
+ $matches = grep { m{deb-systemd-invoke stop .*'\Q$unit\E.service'} } @output;
+ ok($matches == $num_stops) or diag("$unit appears to have been stopped $matches times (expected $num_stops)");
+}
+
+# Units are installed and enabled
+each_compat_from_x_to_and_incl_y_subtest(10, 10, sub {
+ ok(run_dh_tool('dh_systemd_enable'));
+ ok(run_dh_tool('dh_systemd_start'));
+ ok(-e "debian/foo/lib/systemd/system/foo.service");
+ ok(-e "debian/foo.postinst.debhelper");
+ unit_is_enabled('foo', 'foo', 1);
+ unit_is_started('foo', 'foo', 1);
+ unit_is_enabled('foo', 'foo2', 0);
+ unit_is_started('foo', 'foo2', 0);
+ ok(run_dh_tool('dh_clean'));
+
+ make_path('debian/foo/lib/systemd/system/');
+ copy_file('debian/foo2.service', 'debian/foo/lib/systemd/system/foo2.service');
+ ok(run_dh_tool('dh_systemd_enable'));
+ ok(run_dh_tool('dh_systemd_start'));
+ ok(-e "debian/foo/lib/systemd/system/foo.service");
+ ok(-e "debian/foo.postinst.debhelper");
+ unit_is_enabled('foo', 'foo', 1);
+ unit_is_started('foo', 'foo', 1);
+ unit_is_enabled('foo', 'foo2', 1);
+ unit_is_started('foo', 'foo2', 1);
+ ok(run_dh_tool('dh_clean'));
+
+ make_path('debian/foo/lib/systemd/system/');
+ copy_file('debian/foo2.service', 'debian/foo/lib/systemd/system/foo2.service');
+ ok(run_dh_tool('dh_systemd_enable'));
+ ok(run_dh_tool('dh_systemd_start', '--no-start'));
+ ok(-e "debian/foo/lib/systemd/system/foo.service");
+ ok(-e "debian/foo.postinst.debhelper");
+ unit_is_enabled('foo', 'foo', 1);
+ unit_is_started('foo', 'foo', 0, 1); # present units are stopped on remove even if no start
+ unit_is_enabled('foo', 'foo2', 1);
+ unit_is_started('foo', 'foo2', 0, 1);
+ ok(run_dh_tool('dh_clean'));
+
+ make_path('debian/foo/lib/systemd/system/');
+ copy_file('debian/foo2.service', 'debian/foo/lib/systemd/system/foo2.service');
+ ok(run_dh_tool('dh_systemd_enable'));
+ ok(run_dh_tool('dh_systemd_start', '--no-start', 'debian/foo.service'));
+ ok(run_dh_tool('dh_systemd_start', '-p', 'foo', 'foo2.service'));
+ ok(-e "debian/foo/lib/systemd/system/foo.service");
+ ok(-e "debian/foo.postinst.debhelper");
+ unit_is_enabled('foo', 'foo', 1);
+ unit_is_started('foo', 'foo', 0, 1);
+ unit_is_enabled('foo', 'foo2', 1);
+ unit_is_started('foo', 'foo2', 1);
+ ok(run_dh_tool('dh_clean'));
+
+ make_path('debian/foo/lib/systemd/system/');
+ copy_file('debian/foo2.service', 'debian/foo/lib/systemd/system/foo2.service');
+ ok(run_dh_tool('dh_systemd_enable', '--no-enable', 'debian/foo.service'));
+ ok(run_dh_tool('dh_systemd_enable', '-p', 'foo', 'foo2.service'));
+ ok(run_dh_tool('dh_systemd_start'));
+ ok(-e "debian/foo/lib/systemd/system/foo.service");
+ ok(-e "debian/foo.postinst.debhelper");
+ unit_is_enabled('foo', 'foo', 0);
+ unit_is_started('foo', 'foo', 1, 1);
+ unit_is_enabled('foo', 'foo2', 1);
+ unit_is_started('foo', 'foo2', 1);
+ ok(run_dh_tool('dh_clean'));
+
+ make_path('debian/foo/lib/systemd/system/');
+ copy_file('debian/foo.service', 'debian/foo/lib/systemd/system/foo.service');
+ ok(run_dh_tool('dh_systemd_start', '--no-restart-after-upgrade'));
+ my $matches = grep { m{deb-systemd-invoke start .*foo.service} } `cat debian/foo.postinst.debhelper`;
+ ok($matches == 1);
+ ok(run_dh_tool('dh_clean'));
+
+ # Quoting #764730
+ make_path('debian/foo/lib/systemd/system/');
+ copy_file('debian/foo.service', 'debian/foo/lib/systemd/system/foo\x2dfuse.service');
+ ok(run_dh_tool('dh_systemd_enable'));
+ ok(run_dh_tool('dh_systemd_start'));
+ unit_is_enabled('foo', 'foo\x2dfuse', 1);
+ unit_is_started('foo', 'foo\x2dfuse', 1);
+ ok(run_dh_tool('dh_clean'));
+});
+
+
diff --git a/t/dh_installsystemd/simple/debian/changelog b/t/dh_installsystemd/simple/debian/changelog
new file mode 100644
index 0000000..5b1a8fe
--- /dev/null
+++ b/t/dh_installsystemd/simple/debian/changelog
@@ -0,0 +1,5 @@
+foo (1.0-1) unstable; urgency=low
+
+ * Initial release. (Closes: #XXXXXX)
+
+ -- Test <test@example.org> Mon, 11 Jul 2016 18:10:59 +0200
diff --git a/t/dh_installsystemd/simple/debian/control b/t/dh_installsystemd/simple/debian/control
new file mode 100644
index 0000000..4f4238e
--- /dev/null
+++ b/t/dh_installsystemd/simple/debian/control
@@ -0,0 +1,10 @@
+Source: foo
+Section: misc
+Priority: optional
+Maintainer: Test <testing@nowhere>
+Standards-Version: 3.9.8
+
+Package: foo
+Architecture: all
+Description: package foo
+ Package foo
diff --git a/t/dh_installsystemd/simple/debian/foo.service b/t/dh_installsystemd/simple/debian/foo.service
new file mode 100644
index 0000000..2b48a78
--- /dev/null
+++ b/t/dh_installsystemd/simple/debian/foo.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=A unit
+
+[Service]
+ExecStart=/bin/true
+
+[Install]
+WantedBy=multi-user.target
diff --git a/t/dh_installsystemduser/debian/baz.user.service b/t/dh_installsystemduser/debian/baz.user.service
new file mode 100644
index 0000000..3af041d
--- /dev/null
+++ b/t/dh_installsystemduser/debian/baz.user.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Baz User Unit
+
+[Service]
+ExecStart=/bin/true
+
+[Install]
+WantedBy=default.target
diff --git a/t/dh_installsystemduser/debian/changelog b/t/dh_installsystemduser/debian/changelog
new file mode 100644
index 0000000..5850f0e
--- /dev/null
+++ b/t/dh_installsystemduser/debian/changelog
@@ -0,0 +1,5 @@
+foo (1.0-1) unstable; urgency=low
+
+ * Initial release. (Closes: #XXXXXX)
+
+ -- Test <testing@nowhere> Mon, 11 Jul 2016 18:10:59 +0200
diff --git a/t/dh_installsystemduser/debian/control b/t/dh_installsystemduser/debian/control
new file mode 100644
index 0000000..adccbc6
--- /dev/null
+++ b/t/dh_installsystemduser/debian/control
@@ -0,0 +1,10 @@
+Source: foo
+Section: misc
+Priority: optional
+Maintainer: Test <testing@exampe.org>
+Standards-Version: 3.9.8
+
+Package: foo
+Architecture: all
+Description: package foo
+ Package foo
diff --git a/t/dh_installsystemduser/debian/foo.user.service b/t/dh_installsystemduser/debian/foo.user.service
new file mode 100644
index 0000000..7ef597d
--- /dev/null
+++ b/t/dh_installsystemduser/debian/foo.user.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Foo User Unit
+
+[Service]
+ExecStart=/bin/true
+
+[Install]
+WantedBy=default.target
diff --git a/t/dh_installsystemduser/dh_installsystemduser.t b/t/dh_installsystemduser/dh_installsystemduser.t
new file mode 100755
index 0000000..5171728
--- /dev/null
+++ b/t/dh_installsystemduser/dh_installsystemduser.t
@@ -0,0 +1,112 @@
+#!/usr/bin/perl
+use strict;
+use Test::More;
+use File::Path qw(make_path);
+use File::Basename qw(dirname);
+use lib dirname(dirname(__FILE__));
+use Test::DH;
+use Debian::Debhelper::Dh_Lib qw(!dirname);
+
+plan(tests => 1);
+
+our @TEST_DH_EXTRA_TEMPLATE_FILES = (qw(
+ debian/changelog
+ debian/control
+ debian/foo.user.service
+ debian/baz.user.service
+));
+
+
+sub read_script {
+ my ($package, $name) = @_;
+ my @lines;
+
+ foreach my $script (find_script($package, $name)) {
+ open(my $fh, '<', $script) or die("open($script): $!");
+ push @lines, $_ for <$fh>;
+ close($fh);
+ }
+
+ return @lines;
+}
+
+sub _unit_check_user_enabled {
+ my ($package, $unit, $enabled) = @_;
+ my $verb = $enabled ? "is" : "isnt";
+ my $matches;
+
+ my @postinst = read_script($package, 'postinst');
+ # Match exactly two tab character. The "dont-enable" script has
+ # an "enable" line for re-enabling the service if the admin had it
+ # enabled, but we do not want to include that in our count.
+ $matches = grep { m{^\t\tif deb-systemd-helper( --\w+)* --user was-enabled.*'\Q$unit'} } @postinst;
+ is($matches, $enabled, "$unit $verb enabled");
+}
+
+sub _unit_check_user_started {
+ my ($package, $unit, $started) = @_;
+ my $verb = $started ? "is" : "isnt";
+ my $matches;
+
+ my @postinst = read_script($package, 'postinst');
+ # Match exactly two tab character. The "dont-enable" script has
+ # an "enable" line for re-enabling the service if the admin had it
+ # enabled, but we do not want to include that in our count.
+ $matches = grep { m{deb-systemd-invoke --user restart.*'\Q$unit'} } @postinst;
+ is($matches, $started, "$unit $verb started");
+
+ my @prerm = read_script($package, 'prerm');
+ $matches = grep { m{deb-systemd-invoke --user stop.*'\Q$unit'} } @prerm;
+ is($matches, $started, "$unit $verb stopped");
+}
+
+sub is_enabled { _unit_check_user_enabled(@_, 1); }
+sub isnt_enabled { _unit_check_user_enabled(@_, 0); }
+sub is_started { _unit_check_user_started(@_, 1); }
+sub isnt_started { _unit_check_user_started(@_, 0); }
+
+each_compat_subtest {
+ my ($compat) = @_;
+ make_path('debian/foo/usr/lib/systemd/user/');
+ copy_file('debian/foo.user.service', 'debian/foo/usr/lib/systemd/user/bar.service');
+ ok(run_dh_tool('dh_installsystemduser'));
+ ok(-e 'debian/foo/usr/lib/systemd/user/foo.service');
+ is_enabled('foo', 'foo.service');
+ is_enabled('foo', 'bar.service');
+ if ($compat > 13) {
+ is_started('foo', 'foo.service');
+ is_started('foo', 'bar.service');
+ } else {
+ isnt_started('foo', 'foo.service');
+ isnt_started('foo', 'bar.service');
+ }
+ ok(run_dh_tool('dh_clean'));
+
+ ok(run_dh_tool('dh_installsystemduser'));
+ ok(-e 'debian/foo/usr/lib/systemd/user/foo.service');
+ ok(! -e 'debian/foo/usr/lib/systemd/user/baz.service');
+ is_enabled('foo', 'foo.service');
+ isnt_enabled('foo', 'baz.service');
+ if ($compat > 13) {
+ is_started('foo', 'foo.service');
+ isnt_started('foo', 'baz.service');
+ } else {
+ isnt_started('foo', 'bar.service');
+ isnt_started('foo', 'baz.service');
+ }
+ ok(run_dh_tool('dh_clean'));
+
+ ok(run_dh_tool('dh_installsystemduser', '--name', 'baz'));
+ ok(! -e 'debian/foo/usr/lib/systemd/user/foo.service');
+ ok(-e 'debian/foo/usr/lib/systemd/user/baz.service');
+ isnt_enabled('foo', 'foo.service');
+ is_enabled('foo', 'baz.service');
+ if ($compat > 13) {
+ isnt_started('foo', 'foo.service');
+ is_started('foo', 'baz.service');
+ } else {
+ isnt_started('foo', 'foo.service');
+ isnt_started('foo', 'baz.service');
+ }
+ ok(run_dh_tool('dh_clean'));
+};