sysv-generator-test.py revision e28aa588f04ace17ca94e9e0667819bea265fbd9
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# systemd-sysv-generator integration test
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# (C) 2015 Canonical Ltd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# Author: Martin Pitt <martin.pitt@ubuntu.com>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# along with systemd; If not, see <http://www.gnu.org/licenses/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringimport unittest
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringimport sys
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringimport os
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poetteringimport subprocess
96aad8d15a324d0e956a4e5653a11a67b209b41aLennart Poetteringimport tempfile
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringimport shutil
4ad7f2761da661853dcc29d542efb4727abb1101Nick Owensfrom glob import glob
39d8db043b599a7382f94bfc904d5e108af438bdLennart Poettering
51323288fc628a5cac50914df915545d685b793eLennart Poetteringtry:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering from configparser import RawConfigParser
ad867662936a4c7ab2c7116d804c272338801231Lennart Poetteringexcept ImportError:
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering # python 2
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering from ConfigParser import RawConfigParser
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poetteringsysv_generator = os.path.join(os.environ.get('builddir', '.'), 'systemd-sysv-generator')
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poetteringclass SysvGeneratorTest(unittest.TestCase):
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering def setUp(self):
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering self.workdir = tempfile.mkdtemp(prefix='sysv-gen-test.')
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering self.init_d_dir = os.path.join(self.workdir, 'init.d')
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering os.mkdir(self.init_d_dir)
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering self.rcnd_dir = self.workdir
818f766b12e025683cf4fed12b3da2a025bb0b31Lennart Poettering self.unit_dir = os.path.join(self.workdir, 'systemd')
818f766b12e025683cf4fed12b3da2a025bb0b31Lennart Poettering os.mkdir(self.unit_dir)
818f766b12e025683cf4fed12b3da2a025bb0b31Lennart Poettering self.out_dir = os.path.join(self.workdir, 'output')
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering os.mkdir(self.out_dir)
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering def tearDown(self):
818f766b12e025683cf4fed12b3da2a025bb0b31Lennart Poettering shutil.rmtree(self.workdir)
818f766b12e025683cf4fed12b3da2a025bb0b31Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering #
547973dea7abd6c124ff6c79fe2bbe322a7314aeLennart Poettering # Helper methods
a761c1ca851a9397b5a207ef600e077d0f7f4534Lennart Poettering #
019036a47fcd10fcf0286800d144c706f3773e2fLennart Poettering
547973dea7abd6c124ff6c79fe2bbe322a7314aeLennart Poettering def run_generator(self, expect_error=False):
b2b796b8ab5565fbe60b544d2579e2bfca31bf6aLennart Poettering '''Run sysv-generator.
b2b796b8ab5565fbe60b544d2579e2bfca31bf6aLennart Poettering
b2b796b8ab5565fbe60b544d2579e2bfca31bf6aLennart Poettering Fail if stderr contains any "Fail", unless expect_error is True.
91adc4db33f69606aabd332813a5d7d5751c859fLennart Poettering Return (stderr, filename -> ConfigParser) pair with ouput to stderr and
91adc4db33f69606aabd332813a5d7d5751c859fLennart Poettering parsed generated units.
91adc4db33f69606aabd332813a5d7d5751c859fLennart Poettering '''
3bbdc31df37a23b5134a115c01d15e7ff870b3ccLennart Poettering env = os.environ.copy()
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering env['SYSTEMD_LOG_LEVEL'] = 'debug'
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering env['SYSTEMD_SYSVINIT_PATH'] = self.init_d_dir
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering env['SYSTEMD_SYSVRCND_PATH'] = self.rcnd_dir
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering env['SYSTEMD_UNIT_PATH'] = self.unit_dir
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering gen = subprocess.Popen(
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering [sysv_generator, 'ignored', 'ignored', self.out_dir],
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering stdout=subprocess.PIPE, stderr=subprocess.PIPE,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering universal_newlines=True, env=env)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering (out, err) = gen.communicate()
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if not expect_error:
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering self.assertFalse('Fail' in err, err)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering self.assertEqual(gen.returncode, 0, err)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering results = {}
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering for service in glob(self.out_dir + '/*.service'):
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering cp = RawConfigParser()
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering cp.optionxform = lambda o: o # don't lower-case option names
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering with open(service) as f:
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering cp.readfp(f)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering results[os.path.basename(service)] = cp
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return (err, results)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ef9fb66c0b292d3543c16bfce99ad677bef0f401Lennart Poettering def add_sysv(self, fname, keys, enable=False, prio=1):
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering '''Create a SysV init script with the given keys in the LSB header
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering There are sensible default values for all fields.
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering If enable is True, links will be created in the rcN.d dirs. In that
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering case, the priority can be given with "prio" (default to 1).
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering Return path of generated script.
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering '''
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering name_without_sh = fname.endswith('.sh') and fname[:-3] or fname
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering keys.setdefault('Provides', name_without_sh)
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering keys.setdefault('Required-Start', '$local_fs')
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering keys.setdefault('Required-Stop', keys['Required-Start'])
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering keys.setdefault('Default-Start', '2 3 4 5')
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering keys.setdefault('Default-Stop', '0 1 6')
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering keys.setdefault('Short-Description', 'test %s service' %
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering name_without_sh)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering keys.setdefault('Description', 'long description for test %s service' %
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering name_without_sh)
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering script = os.path.join(self.init_d_dir, fname)
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering with open(script, 'w') as f:
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering f.write('#!/bin/init-d-interpreter\n### BEGIN INIT INFO\n')
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering for k, v in keys.items():
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering if v is not None:
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering f.write('#%20s %s\n' % (k + ':', v))
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering f.write('### END INIT INFO\ncode --goes here\n')
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering os.chmod(script, 0o755)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if enable:
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering def make_link(prefix, runlevel):
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering d = os.path.join(self.rcnd_dir, 'rc%s.d' % runlevel)
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering if not os.path.isdir(d):
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering os.mkdir(d)
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering os.symlink('../init.d/' + fname, os.path.join(d, prefix + fname))
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering for rl in keys['Default-Start'].split():
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering make_link('S%02i' % prio, rl)
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering for rl in keys['Default-Stop'].split():
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering make_link('K%02i' % (99 - prio), rl)
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering return script
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering def assert_enabled(self, unit, runlevels):
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering '''assert that a unit is enabled in precisely the given runlevels'''
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering all_runlevels = [2, 3, 4, 5]
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering # should be enabled
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering for runlevel in all_runlevels:
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering link = os.path.join(self.out_dir, 'runlevel%i.target.wants' % runlevel, 'foo.service')
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if runlevel in runlevels:
51323288fc628a5cac50914df915545d685b793eLennart Poettering target = os.readlink(link)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering self.assertTrue(os.path.exists(target))
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering self.assertEqual(os.path.basename(target), 'foo.service')
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else:
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering self.assertFalse(os.path.exists(link),
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering '%s unexpectedly exists' % link)
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering #
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering # test cases
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering #
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering def test_nothing(self):
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering '''no input files'''
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering results = self.run_generator()[1]
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering self.assertEqual(results, {})
7588460aaf6bd33f6c9bd5645916cfd8a862e9c4Tom Gundersen self.assertEqual(os.listdir(self.out_dir), [])
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering def test_simple_disabled(self):
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering '''simple service without dependencies, disabled'''
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering self.add_sysv('foo', {}, enable=False)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering err, results = self.run_generator()
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering self.assertEqual(len(results), 1)
51323288fc628a5cac50914df915545d685b793eLennart Poettering
51323288fc628a5cac50914df915545d685b793eLennart Poettering # no enablement links or other stuff
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering self.assertEqual(os.listdir(self.out_dir), ['foo.service'])
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering s = results['foo.service']
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering self.assertEqual(s.sections(), ['Unit', 'Service'])
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering self.assertEqual(s.get('Unit', 'Description'), 'LSB: test foo service')
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering # $local_fs does not need translation, don't expect any dependency
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering # fields here
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering self.assertEqual(set(s.options('Unit')),
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering set(['Documentation', 'SourcePath', 'Description']))
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering self.assertEqual(s.get('Service', 'Type'), 'forking')
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering init_script = os.path.join(self.init_d_dir, 'foo')
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering self.assertEqual(s.get('Service', 'ExecStart'),
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering '%s start' % init_script)
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering self.assertEqual(s.get('Service', 'ExecStop'),
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering '%s stop' % init_script)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering def test_simple_enabled_all(self):
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering '''simple service without dependencies, enabled in all runlevels'''
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering self.add_sysv('foo', {}, enable=True)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering err, results = self.run_generator()
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering self.assertEqual(list(results), ['foo.service'])
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering self.assert_enabled('foo.service', [2, 3, 4, 5])
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering def test_simple_enabled_some(self):
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering '''simple service without dependencies, enabled in some runlevels'''
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering self.add_sysv('foo', {'Default-Start': '2 4'}, enable=True)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering err, results = self.run_generator()
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering self.assertEqual(list(results), ['foo.service'])
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering self.assert_enabled('foo.service', [2, 4])
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering def test_lsb_macro_dep_single(self):
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering '''single LSB macro dependency: $network'''
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering self.add_sysv('foo', {'Required-Start': '$network'})
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering s = self.run_generator()[1]['foo.service']
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering self.assertEqual(set(s.options('Unit')),
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering set(['Documentation', 'SourcePath', 'Description', 'After', 'Wants']))
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering self.assertEqual(s.get('Unit', 'After'), 'network-online.target')
931851e8e492a4d2715e22dcde50a5e7ccef4b49Lennart Poettering self.assertEqual(s.get('Unit', 'Wants'), 'network-online.target')
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering def test_lsb_macro_dep_multi(self):
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering '''multiple LSB macro dependencies'''
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering self.add_sysv('foo', {'Required-Start': '$named $portmap'})
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s = self.run_generator()[1]['foo.service']
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering self.assertEqual(set(s.options('Unit')),
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt set(['Documentation', 'SourcePath', 'Description', 'After']))
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering self.assertEqual(s.get('Unit', 'After'), 'nss-lookup.target rpcbind.target')
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering def test_lsb_deps(self):
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering '''LSB header dependencies to other services'''
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering # also give symlink priorities here; they should be ignored
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering self.add_sysv('foo', {'Required-Start': 'must1 must2',
51323288fc628a5cac50914df915545d685b793eLennart Poettering 'Should-Start': 'may1 ne_may2'},
51323288fc628a5cac50914df915545d685b793eLennart Poettering enable=True, prio=40)
51323288fc628a5cac50914df915545d685b793eLennart Poettering self.add_sysv('must1', {}, enable=True, prio=10)
51323288fc628a5cac50914df915545d685b793eLennart Poettering self.add_sysv('must2', {}, enable=True, prio=15)
51323288fc628a5cac50914df915545d685b793eLennart Poettering self.add_sysv('may1', {}, enable=True, prio=20)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering # do not create ne_may2
51323288fc628a5cac50914df915545d685b793eLennart Poettering err, results = self.run_generator()
51323288fc628a5cac50914df915545d685b793eLennart Poettering self.assertEqual(sorted(results),
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering ['foo.service', 'may1.service', 'must1.service', 'must2.service'])
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
51323288fc628a5cac50914df915545d685b793eLennart Poettering # foo should depend on all of them
51323288fc628a5cac50914df915545d685b793eLennart Poettering self.assertEqual(sorted(results['foo.service'].get('Unit', 'After').split()),
51323288fc628a5cac50914df915545d685b793eLennart Poettering ['may1.service', 'must1.service', 'must2.service', 'ne_may2.service'])
51323288fc628a5cac50914df915545d685b793eLennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering # other services should not depend on each other
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering self.assertFalse(results['must1.service'].has_option('Unit', 'After'))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering self.assertFalse(results['must2.service'].has_option('Unit', 'After'))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering self.assertFalse(results['may1.service'].has_option('Unit', 'After'))
51323288fc628a5cac50914df915545d685b793eLennart Poettering
51323288fc628a5cac50914df915545d685b793eLennart Poettering def test_symlink_prio_deps(self):
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering '''script without LSB headers use rcN.d priority'''
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering # create two init.d scripts without LSB header and enable them with
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering # startup priorities
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for prio, name in [(10, 'provider'), (15, 'consumer')]:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering with open(os.path.join(self.init_d_dir, name), 'w') as f:
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering f.write('#!/bin/init-d-interpreter\ncode --goes here\n')
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering os.fchmod(f.fileno(), 0o755)
51323288fc628a5cac50914df915545d685b793eLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering d = os.path.join(self.rcnd_dir, 'rc2.d')
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if not os.path.isdir(d):
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering os.mkdir(d)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering os.symlink('../init.d/' + name, os.path.join(d, 'S%02i%s' % (prio, name)))
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering err, results = self.run_generator()
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering self.assertEqual(sorted(results), ['consumer.service', 'provider.service'])
7b9f7afcc04e80b77a2567b0750aa2cd03c1a1cdLennart Poettering self.assertFalse(results['provider.service'].has_option('Unit', 'After'))
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering self.assertEqual(results['consumer.service'].get('Unit', 'After'),
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering 'provider.service')
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering def test_multiple_provides(self):
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poettering '''multiple Provides: names'''
51323288fc628a5cac50914df915545d685b793eLennart Poettering
51323288fc628a5cac50914df915545d685b793eLennart Poettering self.add_sysv('foo', {'Provides': 'foo bar baz'})
51323288fc628a5cac50914df915545d685b793eLennart Poettering s = self.run_generator()[1]['foo.service']
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering self.assertEqual(set(s.options('Unit')),
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering set(['Documentation', 'SourcePath', 'Description']))
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering # should create symlinks for the alternative names
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering for f in ['bar.service', 'baz.service']:
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering self.assertEqual(os.readlink(os.path.join(self.out_dir, f)),
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering 'foo.service')
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering def test_nonexecutable_script(self):
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering '''ignores non-executable init.d script'''
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering os.chmod(self.add_sysv('foo', {}), 0o644)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering err, results = self.run_generator()
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering self.assertEqual(results, {})
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringif __name__ == '__main__':
966c66e34940001a40806142ecebaae61b478444Lennart Poettering unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2))
82bd6dddc4a363a9c3c6f41eb46eb171a80dca27Lennart Poettering