Commit f7242964 authored by Didier Roche's avatar Didier Roche Committed by Martin Pitt
Browse files

Add display managers autopkg tests

parent 87952c2f
systemd (215-9) UNRELEASED; urgency=medium
* Add display managers autopkgtests.
-- Didier Roche <didrocks@ubuntu.com> Wed, 10 Dec 2014 13:57:17 +0100
systemd (215-8) unstable; urgency=medium
[ Didier Roche ]
......
......@@ -11,3 +11,7 @@ Depends: python3-systemd
Tests: boot-and-services
Depends: lightdm, cron, network-manager, busybox-static
Restrictions: needs-root, isolation-machine, needs-recommends, breaks-testbed
Tests: display-managers
Depends: systemd, lightdm
Restrictions: needs-root, isolation-machine, needs-recommends, breaks-testbed
#!/usr/bin/python3
# autopkgtest check: Boot with systemd and check different dm configurations
# (C) 2014 Canonical Ltd.
# Author: Didier Roche <didrocks@ubuntu.com>
from contextlib import suppress
import fileinput
import os
import subprocess
import shutil
import sys
import unittest
from time import sleep
DDM_CONFIG_PATH = "/etc/X11/default-display-manager"
SYSTEMD_DEFAULT_DM_PATH = "/etc/systemd/system/display-manager.service"
SYSTEMD_SYSTEM_UNIT_DIR = "/lib/systemd/system"
LIGHTDM_SYSTEMD_UNIT_PATH = os.path.join(SYSTEMD_SYSTEM_UNIT_DIR, 'lightdm.service')
class DisplayManagersTest(unittest.TestCase):
'''Check that multiple dm configurations are handled'''
def setUp(self):
super().setUp()
with suppress(FileNotFoundError):
os.remove(SYSTEMD_DEFAULT_DM_PATH)
with suppress(FileNotFoundError):
os.remove(DDM_CONFIG_PATH)
subprocess.check_call('apt-get install -y --reinstall lightdm 2>&1', shell=True)
# Remove all Conditional ExecStartPre= as we want to check systemd logic, not unit
for line in fileinput.input([LIGHTDM_SYSTEMD_UNIT_PATH], inplace=True):
if not line.startswith('ExecStartPre='):
print(line)
self.files_to_clean = []
def tearDown(self):
for f in self.files_to_clean:
os.remove(f)
super().tearDown()
def test_one_systemd(self):
'''one systemd dm is started'''
self.reload_state()
self.assertTrue(self.is_active_unit('lightdm'))
def test_multiple_systemd(self):
'''only default systemd dm is started'''
self.create_systemd_dm_unit("systemddm")
self.reload_state()
self.assertTrue(self.is_active_unit('lightdm'))
self.assertFalse(self.is_active_unit('systemddm'))
def test_multiple_systemd_ddmconfig_match(self):
'''display-manager symlink respect ddm config and starts right unit'''
# lightdm was the default
self.create_systemd_dm_unit("systemddm", make_ddm_default="systemddm")
self.reload_state()
self.assertFalse(self.is_active_unit('lightdm'))
self.assertTrue(self.is_active_unit('systemddm'))
# FIXME: generator doesn't retarget in that case where it should
@unittest.expectedFailure
def test_multiple_systemd_ddmconfig_match_no_symlink(self):
'''create a display-manager symlink to matching systemd unit ddm config'''
# lightdm was the default
self.create_systemd_dm_unit("systemddm", make_ddm_default="systemddm")
os.remove(SYSTEMD_DEFAULT_DM_PATH)
self.reload_state()
self.assertFalse(self.is_active_unit('lightdm'))
self.assertTrue(self.is_active_unit('systemddm'))
def test_one_systemd_no_ddmconfig(self):
'''without any ddm config, the default systemd unit via symlink is still the default'''
os.remove(DDM_CONFIG_PATH)
self.reload_state()
self.assertTrue(self.is_active_unit('lightdm'))
def test_one_systemd_masked_symlink_with_ddmconfig(self):
'''a masked symlink will be updated to match systemd ddmconfig unit'''
os.remove(SYSTEMD_DEFAULT_DM_PATH)
os.symlink("/dev/null", SYSTEMD_DEFAULT_DM_PATH)
self.reload_state()
self.assertTrue(self.is_active_unit('lightdm'))
def test_one_systemd_masked_symlink_no_ddmconfig(self):
'''without any ddm config, a masked symlinked will stayed masked'''
os.remove(DDM_CONFIG_PATH)
os.remove(SYSTEMD_DEFAULT_DM_PATH)
os.symlink("/dev/null", SYSTEMD_DEFAULT_DM_PATH)
self.reload_state()
self.assertFalse(self.is_active_unit('lightdm'))
def test_multiple_systemd_wrong_ddmconfig(self):
'''ddm config matches no systemd unit, don't start any of them'''
self.create_systemd_dm_unit("systemddm", make_ddm_default="systemddm_doesnt_match")
self.reload_state()
self.assertFalse(self.is_active_unit('lightdm'))
self.assertFalse(self.is_active_unit('systemddm'))
def test_one_init(self):
'''one init dm is started'''
# fake removing lightdm (or we shoud remove all processes under lightdm)
os.remove(DDM_CONFIG_PATH)
os.remove(SYSTEMD_DEFAULT_DM_PATH)
os.remove(LIGHTDM_SYSTEMD_UNIT_PATH)
self.create_init_dm("initdm", make_ddm_default="initdm")
self.reload_state()
self.assertTrue(self.is_active_unit('initdm'))
def test_multiple_init(self):
'''all init dms are enabled, regardless of ddm'''
# this enable to keep previous init behavior,
# especially when they don't support ddm config like nodm
os.remove(DDM_CONFIG_PATH)
os.remove(SYSTEMD_DEFAULT_DM_PATH)
os.remove(LIGHTDM_SYSTEMD_UNIT_PATH)
self.create_init_dm("initdm", make_ddm_default="initdm")
self.create_init_dm("otherinitdm")
self.reload_state()
self.assertTrue(self.is_active_unit('initdm'))
self.assertTrue(self.is_active_unit('otherinitdm'))
def test_multiple_init_no_ddm(self):
'''all init dms are enabled, without any ddm file'''
os.remove(DDM_CONFIG_PATH)
os.remove(SYSTEMD_DEFAULT_DM_PATH)
os.remove(LIGHTDM_SYSTEMD_UNIT_PATH)
self.create_init_dm("initdm")
self.create_init_dm("otherinitdm")
self.reload_state()
self.assertTrue(self.is_active_unit('initdm'))
self.assertTrue(self.is_active_unit('otherinitdm'))
def test_systemd_matches_ddm_and_init(self):
'''default ddm config systemd is enabled as well as all inits'''
# lightdm is the default
self.create_init_dm("initdm")
self.reload_state()
self.assertTrue(self.is_active_unit('lightdm'))
self.assertTrue(self.is_active_unit('initdm'))
def test_systemd_and_init_matches_ddm(self):
'''default ddm init prevents systemd units to start'''
self.create_init_dm("initdm", make_ddm_default="initdm")
self.reload_state()
self.assertFalse(self.is_active_unit('lightdm'))
self.assertTrue(self.is_active_unit('initdm'))
def test_no_ddmconfig_multiple_systemd_and_init(self):
'''no ddm config let default systemd and all init dms enabled'''
os.remove(DDM_CONFIG_PATH)
self.create_systemd_dm_unit("systemddm")
self.create_init_dm("initdm")
self.reload_state()
self.assertTrue(self.is_active_unit('lightdm'))
self.assertTrue(self.is_active_unit('initdm'))
self.assertFalse(self.is_active_unit('systemddm'))
def test_no_ddmconfig_no_default_systemd_and_init(self):
'''no ddm config default systemd unit will only have init dms enabled'''
os.remove(DDM_CONFIG_PATH)
os.remove(SYSTEMD_DEFAULT_DM_PATH)
self.create_systemd_dm_unit("systemddm")
self.create_init_dm("initdm")
self.reload_state()
self.assertFalse(self.is_active_unit('lightdm'))
self.assertTrue(self.is_active_unit('initdm'))
self.assertFalse(self.is_active_unit('systemddm'))
# NOTE: I think init shouldn't start in that case
def test_one_systemd_one_init_masked_symlink_with_ddmconfig(self):
'''a masked symlink will be updated to match systemd ddmconfig systemd unit and init is started'''
os.remove(SYSTEMD_DEFAULT_DM_PATH)
os.symlink("/dev/null", SYSTEMD_DEFAULT_DM_PATH)
self.create_init_dm("initdm")
self.reload_state()
self.assertTrue(self.is_active_unit('lightdm'))
self.assertTrue(self.is_active_unit('initdm'))
# NOTE: I think init shouldn't start in that case
def test_one_systemd_one_init_masked_symlink_no_ddmconfig(self):
'''without any ddm config, a masked symlinked will stayed masked, but init will be started'''
os.remove(DDM_CONFIG_PATH)
os.remove(SYSTEMD_DEFAULT_DM_PATH)
os.symlink("/dev/null", SYSTEMD_DEFAULT_DM_PATH)
self.create_init_dm("initdm")
self.reload_state()
self.assertFalse(self.is_active_unit('lightdm'))
self.assertTrue(self.is_active_unit('initdm'))
# Helper methods
def create_systemd_dm_unit(self, name, make_ddm_default=None):
dest_unit = "{}.service".format(os.path.join(SYSTEMD_SYSTEM_UNIT_DIR, name))
shutil.copy(LIGHTDM_SYSTEMD_UNIT_PATH, dest_unit)
# remove BusName to avoid conflicts
for line in fileinput.input([LIGHTDM_SYSTEMD_UNIT_PATH], inplace=True):
if not line.startswith('BusName='):
print(line)
self.files_to_clean.append(dest_unit)
if make_ddm_default:
self.make_ddm_default(make_ddm_default)
def create_init_dm(self, name, make_ddm_default=None):
init_script = "/etc/init.d/{}".format(name)
with open(init_script, 'w') as f:
f.write('''#!/bin/sh
### BEGIN INIT INFO
# Provides: {service}
# Required-Start: $local_fs $remote_fs dbus
# Required-Stop: $local_fs $remote_fs dbus
# Should-Start: $named
# Should-Stop: $named
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start {service}
### END INIT INFO
exit 0'''.format(service=name))
os.fchmod(f.fileno(), 0o755)
self.files_to_clean.append(init_script)
rc2_link = "/etc/rc2.d/S05{}".format(name)
os.symlink("../init.d/{}".format(name), rc2_link)
self.files_to_clean.append(rc2_link)
insserv_script = "/etc/insserv.conf.d/{}".format(name)
with open(insserv_script, 'w') as f:
f.write("$x-display-manager {}".format(name))
self.files_to_clean.append(insserv_script)
if make_ddm_default:
self.make_ddm_default(make_ddm_default)
def make_ddm_default(self, binary_name):
with open(DDM_CONFIG_PATH, 'w') as f:
f.write("/usr/bin/{}".format(binary_name))
def is_active_unit(self, unit):
'''Check that given unit is active'''
if subprocess.call(['systemctl', '-q', 'is-active', unit]) != 0:
return False
return True
def reload_state(self):
subprocess.check_call(['systemctl', 'daemon-reload'])
subprocess.check_call(['systemctl', 'default'])
sleep(2) # a more robust way would be to loop over remaining jobs to process
def boot_with_systemd():
'''Reboot with systemd as init
In case something else is currently running in the testbed
'''
if subprocess.call(['systemctl', 'status'], stdout=subprocess.PIPE,
stderr=subprocess.PIPE) != 0:
print('Installing systemd-sysv and rebooting...')
subprocess.check_call('apt-get -y install systemd-sysv 2>&1',
shell=True)
subprocess.check_call(['autopkgtest-reboot', 'boot-systemd'])
if __name__ == '__main__':
if not os.getenv('ADT_REBOOT_MARK'):
boot_with_systemd()
unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
verbosity=2))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment