#!perl # vim:ts=4:sw=4:et use strict; use warnings; use Test::More; use File::Temp qw(tempfile tempdir); # in core since perl 5.6.1 use File::Path qw(make_path); # in core since Perl 5.001 use File::Basename; # in core since Perl 5 use FindBin; # in core since Perl 5.00307 use lib "$FindBin::Bin/."; use helpers; test_setup(); my $dpkg_root = $ENV{DPKG_ROOT} // ''; # # "is-enabled" is not true for a random, non-existing unit file # my ($fh, $random_unit) = tempfile('unit\x2dXXXXX', SUFFIX => '.service', TMPDIR => 1, UNLINK => 1); close($fh); $random_unit = basename($random_unit); isnt_enabled($random_unit); isnt_enabled($random_unit, user => 1); isnt_debian_installed($random_unit); isnt_debian_installed($random_unit, user => 1); # # "is-enabled" is not true for a random, existing user unit file # my $servicefile_path = "$dpkg_root/usr/lib/systemd/user/$random_unit"; make_path("$dpkg_root/usr/lib/systemd/user"); open($fh, '>', $servicefile_path); print $fh <<'EOT'; [Unit] Description=test unit [Service] ExecStart=/bin/sleep 1 [Install] WantedBy=default.target EOT close($fh); isnt_enabled($random_unit); isnt_enabled($random_unit, user => 1); isnt_debian_installed($random_unit); isnt_debian_installed($random_unit, user => 1); # # "enable" creates the requested symlinks # unless ($ENV{'TEST_ON_REAL_SYSTEM'}) { # This might exist if we don't start from a fresh directory ok(! -d "$dpkg_root/etc/systemd/user/default.target.wants", 'default.target.wants does not exist yet'); } my $retval = dsh('--user', 'enable', $random_unit); is($retval, 0, "enable command succeeded"); my $symlink_path = "$dpkg_root/etc/systemd/user/default.target.wants/$random_unit"; ok(-l $symlink_path, "$random_unit was enabled"); is($dpkg_root . readlink($symlink_path), $servicefile_path, "symlink points to $servicefile_path"); # # "is-enabled" now returns true for the user instance # isnt_enabled($random_unit); isnt_debian_installed($random_unit); is_enabled($random_unit, user => 1); is_debian_installed($random_unit, user => 1); # # deleting the symlinks and running "enable" again does not re-create them # unlink($symlink_path); ok(! -l $symlink_path, 'symlink deleted'); isnt_enabled($random_unit); isnt_enabled($random_unit, user => 1); isnt_debian_installed($random_unit); is_debian_installed($random_unit, user => 1); $retval = dsh('--user', 'enable', $random_unit); is($retval, 0, "enable command succeeded"); isnt_enabled($random_unit, user => 1); # # "disable" deletes the statefile when purging # my $statefile = "$dpkg_root/var/lib/systemd/deb-systemd-user-helper-enabled/$random_unit.dsh-also"; ok(-f $statefile, 'state file exists'); $ENV{'_DEB_SYSTEMD_HELPER_PURGE'} = '1'; $retval = dsh('--user', 'disable', $random_unit); delete $ENV{'_DEB_SYSTEMD_HELPER_PURGE'}; is($retval, 0, "disable command succeeded"); ok(! -f $statefile, 'state file does not exist anymore after purging'); isnt_debian_installed($random_unit); isnt_debian_installed($random_unit, user => 1); # # "enable" re-creates the symlinks after purging # ok(! -l $symlink_path, 'symlink does not exist yet'); isnt_enabled($random_unit); isnt_enabled($random_unit, user => 1); $retval = dsh('--user', 'enable', $random_unit); is($retval, 0, "enable command succeeded"); isnt_enabled($random_unit); isnt_debian_installed($random_unit); is_enabled($random_unit, user => 1); is_debian_installed($random_unit, user => 1); # # "disable" removes the symlinks # $ENV{'_DEB_SYSTEMD_HELPER_PURGE'} = '1'; $retval = dsh('--user', 'disable', $random_unit); delete $ENV{'_DEB_SYSTEMD_HELPER_PURGE'}; is($retval, 0, "disable command succeeded"); isnt_enabled($random_unit); isnt_enabled($random_unit, user => 1); # # "enable" re-creates the symlinks # ok(! -l $symlink_path, 'symlink does not exist yet'); isnt_enabled($random_unit); isnt_enabled($random_unit, user => 1); $retval = dsh('--user', 'enable', $random_unit); is($retval, 0, "enable command succeeded"); isnt_enabled($random_unit); isnt_debian_installed($random_unit); is_enabled($random_unit, user => 1); is_debian_installed($random_unit, user => 1); # # "purge" works # $retval = dsh('--user', 'purge', $random_unit); is($retval, 0, "purge command succeeded"); isnt_enabled($random_unit, user => 1); isnt_debian_installed($random_unit, user => 1); # # "enable" re-creates the symlinks after purging # ok(! -l $symlink_path, 'symlink does not exist yet'); isnt_enabled($random_unit, user => 1); $retval = dsh('--user', 'enable', $random_unit); is($retval, 0, "enable command succeeded"); is_enabled($random_unit, user => 1); is_debian_installed($random_unit, user => 1); # # "mask" (when enabled) results in the symlink pointing to /dev/null # my $mask_path = "$dpkg_root/etc/systemd/user/$random_unit"; ok(! -l $mask_path, 'mask link does not exist yet'); $retval = dsh('--user', 'mask', $random_unit); is($retval, 0, "mask command succeeded"); ok(-l $mask_path, 'mask link exists'); is(readlink($mask_path), '/dev/null', 'service masked'); $retval = dsh('--user', 'unmask', $random_unit); is($retval, 0, "unmask command succeeded"); ok(! -e $mask_path, 'mask link does not exist anymore'); # # "mask" (when disabled) works the same way # $retval = dsh('--user', 'disable', $random_unit); is($retval, 0, "disable command succeeded"); ok(! -e $symlink_path, 'symlink no longer exists'); $retval = dsh('--user', 'mask', $random_unit); is($retval, 0, "mask command succeeded"); ok(-l $mask_path, 'mask link exists'); is(readlink($mask_path), '/dev/null', 'service masked'); $retval = dsh('--user', 'unmask', $random_unit); is($retval, 0, "unmask command succeeded"); ok(! -e $mask_path, 'symlink no longer exists'); # # "mask" / "unmask" don't do anything when the unit is already masked # ok(! -l $mask_path, 'mask link does not exist yet'); symlink('/dev/null', $mask_path); ok(-l $mask_path, 'mask link exists'); is(readlink($mask_path), '/dev/null', 'service masked'); $retval = dsh('--user', 'mask', $random_unit); is($retval, 0, "mask command succeeded"); ok(-l $mask_path, 'mask link exists'); is(readlink($mask_path), '/dev/null', 'service still masked'); $retval = dsh('--user', 'unmask', $random_unit); is($retval, 0, "unmask command succeeded"); ok(-l $mask_path, 'mask link exists'); is(readlink($mask_path), '/dev/null', 'service still masked'); # # "mask" / "unmask" don't do anything when the user copied the .service. # unlink($mask_path); open($fh, '>', $mask_path); print $fh <<'EOT'; [Unit] Description=test unit [Service] ExecStart=/bin/sleep 1 [Install] WantedBy=default.target EOT close($fh); ok(-e $mask_path, 'local service file exists'); ok(! -l $mask_path, 'local service file is not a symlink'); $retval = dsh('--user', 'mask', $random_unit); isnt($retval, -1, 'deb-systemd-helper could be executed'); ok(!($retval & 127), 'deb-systemd-helper did not exit due to a signal'); is($retval >> 8, 0, 'deb-systemd-helper exited with exit code 0'); ok(-e $mask_path, 'local service file still exists'); ok(! -l $mask_path, 'local service file is still not a symlink'); $retval = dsh('--user', 'unmask', $random_unit); isnt($retval, -1, 'deb-systemd-helper could be executed'); ok(!($retval & 127), 'deb-systemd-helper did not exit due to a signal'); is($retval >> 8, 0, 'deb-systemd-helper exited with exit code 0'); ok(-e $mask_path, 'local service file still exists'); ok(! -l $mask_path, 'local service file is still not a symlink'); unlink($mask_path); # # "Alias=" handling # $retval = dsh('--user', 'purge', $random_unit); is($retval, 0, "purge command succeeded"); open($fh, '>', $servicefile_path); print $fh <<'EOT'; [Unit] Description=test unit [Service] ExecStart=/bin/sleep 1 [Install] WantedBy=default.target Alias=foo\x2dtest.service EOT close($fh); isnt_enabled($random_unit, user => 1); isnt_enabled('foo\x2dtest.service', user => 1); my $alias_path = $dpkg_root . '/etc/systemd/user/foo\x2dtest.service'; ok(! -l $alias_path, 'alias link does not exist yet'); $retval = dsh('--user', 'enable', $random_unit); is($retval, 0, "enable command succeeded"); is($dpkg_root . readlink($alias_path), $servicefile_path, 'correct alias link'); is_enabled($random_unit, user => 1); ok(! -l $mask_path, 'mask link does not exist yet'); $retval = dsh('--user', 'mask', $random_unit); is($retval, 0, "mask command succeeded"); is($dpkg_root . readlink($alias_path), $servicefile_path, 'correct alias link'); is(readlink($mask_path), '/dev/null', 'service masked'); $retval = dsh('--user', 'unmask', $random_unit); is($retval, 0, "unmask command succeeded"); is($dpkg_root . readlink($alias_path), $servicefile_path, 'correct alias link'); ok(! -l $mask_path, 'mask link does not exist any more'); $retval = dsh('--user', 'disable', $random_unit); isnt_enabled($random_unit, user => 1); ok(! -l $alias_path, 'alias link does not exist any more'); # # "Alias=" / "mask" with removed package (as in postrm) # $retval = dsh('--user', 'purge', $random_unit); is($retval, 0, "purge command succeeded"); $retval = dsh('--user', 'enable', $random_unit); is($retval, 0, "enable command succeeded"); is($dpkg_root . readlink($alias_path), $servicefile_path, 'correct alias link'); unlink($servicefile_path); $retval = dsh('--user', 'mask', $random_unit); is($retval, 0, "mask command succeeded with uninstalled unit"); is($dpkg_root . readlink($alias_path), $servicefile_path, 'correct alias link'); is(readlink($mask_path), '/dev/null', 'service masked'); $retval = dsh('--user', 'purge', $random_unit); is($retval, 0, "purge command succeeded with uninstalled unit"); ok(! -l $alias_path, 'alias link does not exist any more'); is(readlink($mask_path), '/dev/null', 'service masked'); $retval = dsh('--user', 'unmask', $random_unit); is($retval, 0, "unmask command succeeded with uninstalled unit"); ok(! -l $mask_path, 'mask link does not exist any more'); # # "Alias=" to the same unit name # open($fh, '>', $servicefile_path); print $fh <<"EOT"; [Unit] Description=test unit [Service] ExecStart=/bin/sleep 1 [Install] WantedBy=default.target Alias=$random_unit EOT close($fh); isnt_enabled($random_unit, user => 1); isnt_enabled('foo\x2dtest.service', user => 1); # note that in this case $alias_path and $mask_path are identical $retval = dsh('--user', 'enable', $random_unit); is($retval, 0, "enable command succeeded"); is_enabled($random_unit, user => 1); # systemctl enable does create the alias link even if it's not needed #ok(! -l $mask_path, 'mask link does not exist yet'); unlink($servicefile_path); $retval = dsh('--user', 'mask', $random_unit); is($retval, 0, "mask command succeeded"); is(readlink($mask_path), '/dev/null', 'service masked'); $retval = dsh('--user', 'unmask', $random_unit); is($retval, 0, "unmask command succeeded"); ok(! -l $mask_path, 'mask link does not exist any more'); $retval = dsh('--user', 'purge', $random_unit); isnt_enabled($random_unit, user => 1); ok(! -l $mask_path, 'mask link does not exist any more'); # # "Alias=" without "WantedBy=" # open($fh, '>', $servicefile_path); print $fh <<'EOT'; [Unit] Description=test unit [Service] ExecStart=/bin/sleep 1 [Install] Alias=baz\x2dtest.service EOT close($fh); isnt_enabled($random_unit, user => 1); isnt_enabled('baz\x2dtest.service', user => 1); $alias_path = $dpkg_root . '/etc/systemd/user/baz\x2dtest.service'; ok(! -l $alias_path, 'alias link does not exist yet'); $retval = dsh('--user', 'enable', $random_unit); is($retval, 0, "enable command succeeded"); is_enabled($random_unit, user => 1); ok(-l $alias_path, 'alias link does exist'); is($dpkg_root . readlink($alias_path), $servicefile_path, 'correct alias link'); done_testing;