Merge lp:~canonical-platform-qa/ubuntu-system-tests/systemd_support into lp:ubuntu-system-tests

Proposed by Sergio Cazzolato
Status: Merged
Approved by: Sergio Cazzolato
Approved revision: 503
Merged at revision: 482
Proposed branch: lp:~canonical-platform-qa/ubuntu-system-tests/systemd_support
Merge into: lp:ubuntu-system-tests
Diff against target: 1455 lines (+524/-463)
26 files modified
ubuntu_system_tests/helpers/addressbook/fixture_setup.py (+3/-3)
ubuntu_system_tests/helpers/addressbook/job.py (+24/-0)
ubuntu_system_tests/helpers/fixture_setup.py (+16/-8)
ubuntu_system_tests/helpers/indicators/network/job.py (+24/-0)
ubuntu_system_tests/helpers/init_systems.py (+176/-0)
ubuntu_system_tests/helpers/job.py (+0/-118)
ubuntu_system_tests/helpers/job_fixtures.py (+39/-0)
ubuntu_system_tests/helpers/jobs.py (+33/-0)
ubuntu_system_tests/helpers/location/fixture_setup.py (+4/-2)
ubuntu_system_tests/helpers/location/job.py (+1/-2)
ubuntu_system_tests/helpers/mediascanner/job.py (+1/-2)
ubuntu_system_tests/helpers/network/fixture_setup.py (+41/-1)
ubuntu_system_tests/helpers/power/fixture_setup.py (+1/-1)
ubuntu_system_tests/helpers/power/job.py (+3/-32)
ubuntu_system_tests/helpers/processes.py (+0/-6)
ubuntu_system_tests/helpers/testbed.py (+19/-38)
ubuntu_system_tests/helpers/ubuntuuitoolkit/environment.py (+0/-68)
ubuntu_system_tests/helpers/ubuntuuitoolkit/fixture_setup.py (+0/-61)
ubuntu_system_tests/helpers/ubuntuuitoolkit/units.py (+4/-7)
ubuntu_system_tests/helpers/unity8/fixture_setup.py (+41/-19)
ubuntu_system_tests/helpers/unity8/job.py (+8/-56)
ubuntu_system_tests/helpers/webbrowser/fixture_setup.py (+2/-5)
ubuntu_system_tests/host/commands.py (+55/-15)
ubuntu_system_tests/tests/base.py (+14/-9)
ubuntu_system_tests/tests/test_brightness.py (+13/-7)
ubuntu_system_tests/tests/test_settings_wizard.py (+2/-3)
To merge this branch: bzr merge lp:~canonical-platform-qa/ubuntu-system-tests/systemd_support
Reviewer Review Type Date Requested Status
Sergio Cazzolato Approve
Richard Huddie (community) Approve
platform-qa-bot continuous-integration Approve
Heber Parrucci (community) Approve
Omer Akram (community) Needs Fixing
Review via email: mp+307239@code.launchpad.net

Commit message

Adding changes to support systemd in the target device

Description of the change

This change aims to support systemd at the same time it is supported upstart. This is a temporal change until convergence is ready, then upstart support will be removed.

To test this branch, it is required to run the tests in a device and in yakkety test at least manually the helpers.job.py file. I removed the external dependencies in this file and tested all the job interface manually.

To test the apt-cacher-ng, run the setup in the device and to test that in yakkety it is possible to run manually the setup script for the apt-cacher-ng and check the cacher is installed and autostart is set.

@run_tests: ubuntu_system_tests.tests.test_rotation ubuntu_system_tests.tests.test_calculator ubuntu_system_tests.tests.test_brightness

To post a comment you must log in.
Revision history for this message
Richard Huddie (rhuddie) wrote :

I think there are a couple of issues here with the way the apt-cacher systemd service is being setup.

The apt-cacher-ng.service file should be copied into /lib/systemd/system/apt-cacher-ng.service and then you need to run following command to enable it:

systemctl enable apt-cacher-ng.service

Also you can run following command to check format and permissions for the service file:

systemd-analyze verify /lib/systemd/system/apt-cacher-ng.service

I think permissions 644 are required for that. Also I think the spaces in "WantedBy=multi - user.target" need to be removed.

Hopefully that should get to the point where the apt-cacher service is started on boot for systemd.

review: Needs Fixing
Revision history for this message
Sergio Cazzolato (sergio-j-cazzolato) wrote :

I added the enable, tx, I am still testing the changes after the merge with the trunk

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
480. By Santiago Baldassin

Refacoring jobs

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Heber Parrucci (heber013) wrote :

Review the comments

review: Needs Fixing
481. By Santiago Baldassin

Addressing comments from the reviews

Revision history for this message
Santiago Baldassin (sbaldassin) wrote :

All comments addressed

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
482. By Santiago Baldassin

fixing flake8 errors

483. By Santiago Baldassin

Merge from trunk

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
484. By Santiago Baldassin

Flake 8 issues

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
485. By Santiago Baldassin

minor fixes

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
486. By Santiago Baldassin

Fixing tests

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
487. By Santiago Baldassin

fixing flake8 issues

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
488. By Santiago Baldassin

Using the correct command lines

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
489. By Santiago Baldassin

Merge from trunk

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
490. By Santiago Baldassin

Fixing flake8 errors

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
491. By Santiago Baldassin

Fixing flake8 errors

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Heber Parrucci (heber013) wrote :

Looks better. Just a few details inline.

review: Needs Fixing
492. By Santiago Baldassin

adding the apt-get update

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Richard Huddie (rhuddie) wrote :

Comment below. I need to do some more checking.

review: Needs Fixing
Revision history for this message
Santiago Baldassin (sbaldassin) wrote :

Thanks Richard. Code Updated

Revision history for this message
Santiago Baldassin (sbaldassin) wrote :

All comments addressed

493. By Santiago Baldassin

Addressing comments from the reviews

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
494. By Santiago Baldassin

Merge from trunk

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Heber Parrucci (heber013) wrote :

I would run the stable suite against this branch because it changes base functionality that is used in several tests.

Revision history for this message
Omer Akram (om26er) wrote :

I am getting some errors while running tests from this branch: http://paste.ubuntu.com/23442024/

  $ systemctl set-environment XDG_DATA_HOME=/tmp/tmpqmqvjvxp
  > Failed to set environment: Access denied

review: Needs Fixing
495. By Santiago Baldassin

Fixing brightness test cases

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
496. By Santiago Baldassin

Fixing flake8 errors

497. By Santiago Baldassin

Executing set-environment with sudo for systemd

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Richard Huddie (rhuddie) wrote :

I saw this failure trying to run the brightness tests on arale, which is not happening in trunk: http://pastebin.ubuntu.com/23474902/

Couple of minor comments below.

review: Needs Fixing
498. By Santiago Baldassin

fixing brightness test cases

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Richard Huddie (rhuddie) wrote :

I saw this failure relating to introspecting maliit server on the first test run after boot for both krillin and arale: http://pastebin.ubuntu.com/23489848/

After the first test run it was ok for both devices, but if the device was rebooted it happened again. I confirmed that this problem doesn't happen on trunk.

Other minor comments below.

review: Needs Fixing
499. By Santiago Baldassin

fixing the test cases

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Richard Huddie (rhuddie) wrote :

Just need to remove the 'vegetahd' change for DEVICE_KRILLIN then it should be ready to land.

Revision history for this message
Heber Parrucci (heber013) wrote :

looks good. Just a minor suggestion

Revision history for this message
Heber Parrucci (heber013) wrote :
review: Needs Fixing
500. By Santiago Baldassin

Merge from trunk

501. By Santiago Baldassin

Fixing test cases after merge from trunk

502. By Santiago Baldassin

fixing flake8 errors

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Heber Parrucci (heber013) wrote :

Code looks good to me. Approved.

review: Approve
Revision history for this message
Richard Huddie (rhuddie) wrote :

Following the uitk removal landing, there are some helpers that will need fixing as they are currently using initctl directly: http://bazaar.launchpad.net/~canonical-platform-qa/ubuntu-system-tests/systemd_support/view/head:/ubuntu_system_tests/helpers/ubuntuuitoolkit/environment.py

review: Needs Fixing
503. By Heber Parrucci

Removing initctl-specific code and refactoring some functions accordingly.

Revision history for this message
Heber Parrucci (heber013) wrote :

> Following the uitk removal landing, there are some helpers that will need
> fixing as they are currently using initctl directly:
> http://bazaar.launchpad.net/~canonical-platform-qa/ubuntu-system-tests/systemd
> _support/view/head:/ubuntu_system_tests/helpers/ubuntuuitoolkit/environment.py

I've addressed this comment. Initctl-specific code was removed and some functions refactored accordingly. Thanks!

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Richard Huddie (rhuddie) wrote :

Question below

Revision history for this message
Heber Parrucci (heber013) wrote :

reply inline. Thanks!

Revision history for this message
Richard Huddie (rhuddie) wrote :

Tests seem to be working fine with latest updates.

review: Approve
Revision history for this message
Sergio Cazzolato (sergio-j-cazzolato) wrote :

Minor comment inline

review: Needs Fixing
Revision history for this message
Sergio Cazzolato (sergio-j-cazzolato) wrote :

> Minor comment inline

The comment should not block the change and it could be fixed later

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ubuntu_system_tests/helpers/addressbook/fixture_setup.py'
2--- ubuntu_system_tests/helpers/addressbook/fixture_setup.py 2015-11-05 17:48:13 +0000
3+++ ubuntu_system_tests/helpers/addressbook/fixture_setup.py 2016-11-23 13:22:18 +0000
4@@ -25,10 +25,10 @@
5 import fixtures
6
7 from dbus.exceptions import DBusException
8-from subprocess import check_call
9
10 from ubuntu_system_tests.helpers import wait_until
11-from ubuntu_system_tests.helpers.addressbook import dbus_service
12+from ubuntu_system_tests.helpers.addressbook import dbus_service, job
13+from ubuntu_system_tests.helpers.init_systems import get_init_system
14
15 CONTACTS_DB_DIR = '~/.local/share/evolution/addressbook/system/'
16
17@@ -68,7 +68,7 @@
18 self._restart_service()
19
20 def _restart_service(self):
21- check_call(['initctl', 'restart', 'address-book-service'])
22+ get_init_system().restart(job.AddressBookJob())
23 wait_until(self._is_address_book_service_running)
24
25 def _is_address_book_service_running(self):
26
27=== added file 'ubuntu_system_tests/helpers/addressbook/job.py'
28--- ubuntu_system_tests/helpers/addressbook/job.py 1970-01-01 00:00:00 +0000
29+++ ubuntu_system_tests/helpers/addressbook/job.py 2016-11-23 13:22:18 +0000
30@@ -0,0 +1,24 @@
31+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
32+
33+# Ubuntu System Tests
34+# Copyright (C) 2016 Canonical
35+#
36+# This program is free software: you can redistribute it and/or modify
37+# it under the terms of the GNU General Public License as published by
38+# the Free Software Foundation, either version 3 of the License, or
39+# (at your option) any later version.
40+#
41+# This program is distributed in the hope that it will be useful,
42+# but WITHOUT ANY WARRANTY; without even the implied warranty of
43+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44+# GNU General Public License for more details.
45+#
46+# You should have received a copy of the GNU General Public License
47+# along with this program. If not, see <http://www.gnu.org/licenses/>.
48+from ubuntu_system_tests.helpers.jobs import JobBase
49+
50+
51+class AddressBookJob(JobBase):
52+
53+ def __init__(self):
54+ super().__init__('address-book-service')
55
56=== modified file 'ubuntu_system_tests/helpers/fixture_setup.py'
57--- ubuntu_system_tests/helpers/fixture_setup.py 2016-09-23 17:34:14 +0000
58+++ ubuntu_system_tests/helpers/fixture_setup.py 2016-11-23 13:22:18 +0000
59@@ -1,32 +1,40 @@
60 import fixtures
61
62+from ubuntu_system_tests.helpers import wait_until
63+from ubuntu_system_tests.helpers.init_systems import get_init_system
64+
65+UBUNTU_PLATFORM_API_TEST_OVERRIDE = 'UBUNTU_PLATFORM_API_TEST_OVERRIDE'
66+
67
68 class EnableFakeSensors(fixtures.Fixture):
69 """Fixture to enable fake sensors."""
70
71- def __init__(self, job, sensors, clean_up=True):
72+ def __init__(self, job, sensors):
73 super().__init__()
74- self.job = job()
75- self.sensors = sensors()
76- self.clean_up = clean_up
77+ self.job = job
78+ self.init_system = get_init_system()
79+ self.sensors = sensors
80
81 def setUp(self):
82 super().setUp()
83 if not self.are_fake_sensors_enabled():
84 self.enable_fake_sensors()
85- if self.clean_up:
86- self.addCleanup(self.job.restart)
87+
88+ self.addCleanup(self.init_system.restart, self.job)
89
90 def enable_fake_sensors(self):
91 """Enable fake sensors on the job process."""
92- self.job.restart(fake_sensors=True)
93+ self.init_system.ensure_stopped(self.job)
94+ args = ['UBUNTU_PLATFORM_API_TEST_OVERRIDE=sensors']
95+ self.init_system.start(self.job, *args)
96 self.sensors.validate_fifo_ready(self.job.name)
97 self.sensors.setup_sensors(self.job.name)
98+ wait_until(self.init_system.is_running, self.job)
99
100 def are_fake_sensors_enabled(self):
101 """Return True if fake sensors enabled."""
102 try:
103- pid = self.job.get_pid()
104+ pid = self.init_system.get_pid(self.job)
105 except ValueError:
106 return False
107 return self.sensors.are_fake_sensors_enabled_for_process(pid)
108
109=== added file 'ubuntu_system_tests/helpers/indicators/network/job.py'
110--- ubuntu_system_tests/helpers/indicators/network/job.py 1970-01-01 00:00:00 +0000
111+++ ubuntu_system_tests/helpers/indicators/network/job.py 2016-11-23 13:22:18 +0000
112@@ -0,0 +1,24 @@
113+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
114+
115+# Ubuntu System Tests
116+# Copyright (C) 2016 Canonical
117+#
118+# This program is free software: you can redistribute it and/or modify
119+# it under the terms of the GNU General Public License as published by
120+# the Free Software Foundation, either version 3 of the License, or
121+# (at your option) any later version.
122+#
123+# This program is distributed in the hope that it will be useful,
124+# but WITHOUT ANY WARRANTY; without even the implied warranty of
125+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
126+# GNU General Public License for more details.
127+#
128+# You should have received a copy of the GNU General Public License
129+# along with this program. If not, see <http://www.gnu.org/licenses/>.
130+from ubuntu_system_tests.helpers.jobs import JobBase
131+
132+
133+class IndicatorNetworkInitSystem(JobBase):
134+
135+ def __init__(self):
136+ super().__init__('indicator-network')
137
138=== added file 'ubuntu_system_tests/helpers/init_systems.py'
139--- ubuntu_system_tests/helpers/init_systems.py 1970-01-01 00:00:00 +0000
140+++ ubuntu_system_tests/helpers/init_systems.py 2016-11-23 13:22:18 +0000
141@@ -0,0 +1,176 @@
142+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
143+
144+# Ubuntu System Tests
145+# Copyright (C) 2016 Canonical
146+#
147+# This program is free software: you can redistribute it and/or modify
148+# it under the terms of the GNU General Public License as published by
149+# the Free Software Foundation, either version 3 of the License, or
150+# (at your option) any later version.
151+#
152+# This program is distributed in the hope that it will be useful,
153+# but WITHOUT ANY WARRANTY; without even the implied warranty of
154+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
155+# GNU General Public License for more details.
156+#
157+# You should have received a copy of the GNU General Public License
158+# along with this program. If not, see <http://www.gnu.org/licenses/>.
159+import os
160+import subprocess
161+import time
162+
163+from ubuntu_system_tests.helpers.processes import is_process_running
164+from ubuntu_system_tests.helpers.testbed import run_command
165+from ubuntu_system_tests.helpers.utils import wait_until
166+
167+
168+def get_init_system():
169+ init_sim_link = os.readlink('/sbin/init')
170+ return Upstart() if 'upstart' in init_sim_link else SystemD()
171+
172+
173+class InitSystem:
174+ """This contains a base implementation for an Init System, which now can
175+ either be systemd or upstart. The init system is the one responsible for
176+ start, stop, restart jobs.
177+ """
178+
179+ def __init__(self, start_command, stop_command,
180+ restart_command, status_command,
181+ set_env_command, unset_env_command,
182+ get_env_command):
183+
184+ self.start_command = start_command
185+ self.stop_command = stop_command
186+ self.status_command = status_command
187+ self.restart_command = restart_command
188+ self.set_env_command = set_env_command
189+ self.unset_env_command = unset_env_command
190+ self.get_env_command = get_env_command
191+
192+ def start(self, job, *args, **kwargs):
193+ """Start the job """
194+ command = self.start_command.format(job.name)
195+ run_command(command, job.sudo, *args, **kwargs)
196+
197+ def stop(self, job, *args, **kwargs):
198+ """Stop the job"""
199+ command = self.stop_command.format(job.name)
200+ run_command(command, job.sudo, *args, **kwargs)
201+
202+ def restart(self, job, *args, **kwargs):
203+ """Restart the job"""
204+ command = self.restart_command.format(job.name)
205+ run_command(command, job.sudo, *args, **kwargs)
206+
207+ def get_status(self, job, *args, **kwargs):
208+ """Restart the job"""
209+ command = self.status_command.format(job.name)
210+ return run_command(command, job.sudo, *args, **kwargs).strip()
211+
212+ def get_pid(self, job):
213+ return int(self.get_status(job).split()[-1])
214+
215+ def is_running(self, job):
216+ return 'running' in self.get_status(job)
217+
218+ def ensure_stopped(self, job, *args, **kwargs):
219+ """Stops the job if it is running and then checks
220+ that it effectively was stopped
221+ """
222+ self.stop(job, *args, **kwargs)
223+ count = 0
224+ while is_process_running(job.name) and count < 5:
225+ time.sleep(1)
226+ count += 1
227+ if is_process_running(job.name):
228+ raise RuntimeError("Process could not be stopped")
229+
230+ def set_environment_variable(self, key, value, global_scope=True,
231+ sudo=False):
232+ set_command = self.set_env_command.format(key, value)
233+ self._manage_environment_variable(set_command, global_scope, sudo)
234+
235+ def unset_environment_variable(self, key, global_scope=True, sudo=False):
236+ unset_command = self.unset_env_command.format(key)
237+ self._manage_environment_variable(unset_command, global_scope, sudo)
238+
239+ def get_environment_variable(self, key, global_scope=False, sudo=False):
240+ show_command = self.get_env_command.format(key)
241+ return self._manage_environment_variable(show_command, global_scope,
242+ sudo)
243+
244+ def _manage_environment_variable(self, command, global_scope, sudo):
245+ if global_scope:
246+ command += ' --global'
247+ return run_command(command, sudo)
248+
249+
250+class Upstart(InitSystem):
251+ """This class contains the implementation for upstart managed jobs """
252+
253+ def __init__(self):
254+ super().__init__(start_command='/sbin/initctl start {}',
255+ stop_command='/sbin/initctl stop {}',
256+ status_command='/sbin/initctl status {}',
257+ restart_command='/sbin/initctl restart {}',
258+ set_env_command='/sbin/initctl set-env {}={}',
259+ unset_env_command='/sbin/initctl unset-env {}',
260+ get_env_command='/sbin/initctl get-env {}={}')
261+
262+ def wait_for_job_spawned(self, job_name, timeout=10):
263+ """Wait until the named job is in spawned state."""
264+ spawned = wait_until(
265+ lambda: 'start/spawned' in self.get_status(job_name),
266+ timeout=timeout)
267+ if not spawned:
268+ raise RuntimeError(
269+ 'Job {} not in start/spawned state within timeout {}'.format(
270+ job_name, timeout))
271+
272+ def get_env_variable(self, key, global_scope=False):
273+ try:
274+ vars = super().get_environment_variable(key=key,
275+ global_scope=global_scope)
276+ except subprocess.CalledProcessError:
277+ return None
278+ else:
279+ return vars.rstrip()
280+
281+
282+class SystemD(InitSystem):
283+ """This class contains the implementation for systemd managed jobs """
284+
285+ def __init__(self):
286+ super().__init__(start_command='systemctl start {}',
287+ stop_command='systemctl stop {}',
288+ status_command='systemctl status {}',
289+ restart_command='systemctl restart {}',
290+ set_env_command='systemctl set-environment {}={}',
291+ unset_env_command='systemctl unset-environment {}',
292+ get_env_command='systemctl show-environment')
293+
294+ def is_running(self, *args, **kwargs):
295+ """Return True if the job is running. Otherwise, False."""
296+ line = run_command(self.status_command, *args, **kwargs)
297+ return 'active' in line
298+
299+ def wait_for_job_spawned(self, job_name, timeout=10):
300+ spawned = wait_until(self.is_running, job_name, timeout=timeout)
301+ if not spawned:
302+ raise RuntimeError(
303+ 'Job {} not in start/spwaned state within timeout {}'.format(
304+ job_name, timeout))
305+
306+ def get_env_variable(self, key, global_scope=False, sudo=True):
307+ vars = self._manage_environment_variable(self.get_env_command,
308+ global_scope, sudo)
309+ for var in vars.split('\n'):
310+ keyval = var.split('=')
311+ if len(keyval) == 2 and keyval[0] == key:
312+ return keyval[1]
313+ return None
314+
315+ def _manage_environment_variable(self, command, global_scope, sudo=True):
316+ return super()._manage_environment_variable(command, global_scope,
317+ True)
318
319=== removed file 'ubuntu_system_tests/helpers/job.py'
320--- ubuntu_system_tests/helpers/job.py 2016-11-01 13:05:25 +0000
321+++ ubuntu_system_tests/helpers/job.py 1970-01-01 00:00:00 +0000
322@@ -1,118 +0,0 @@
323-# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
324-
325-# Ubuntu System Tests
326-# Copyright (C) 2016 Canonical
327-#
328-# This program is free software: you can redistribute it and/or modify
329-# it under the terms of the GNU General Public License as published by
330-# the Free Software Foundation, either version 3 of the License, or
331-# (at your option) any later version.
332-#
333-# This program is distributed in the hope that it will be useful,
334-# but WITHOUT ANY WARRANTY; without even the implied warranty of
335-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
336-# GNU General Public License for more details.
337-#
338-# You should have received a copy of the GNU General Public License
339-# along with this program. If not, see <http://www.gnu.org/licenses/>.
340-import subprocess
341-
342-from ubuntu_system_tests.helpers.testbed import run_command_with_sudo
343-from ubuntu_system_tests.helpers.utils import wait_until
344-
345-
346-class JobBase:
347- """This contains a base implementation for a Job entity and its
348- common functions like:
349- start, stop, get_status, etc.
350- """
351-
352- def __init__(self, name, sudo=False):
353- self.name = name
354- self.start_command = '/sbin/initctl start {name}'.format(name=name)
355- self.stop_command = '/sbin/initctl stop {name}'.format(name=name)
356- self.status_command = '/sbin/initctl status {name}'.format(name=name)
357- self.sudo = sudo
358-
359- def start(self, *args, **kwargs):
360- """Start the job
361- :param args: The arguments to be used when starting the job.
362- """
363- JobBase._run_command(self.start_command, self.sudo, *args, **kwargs)
364-
365- def stop(self, *args, **kwargs):
366- """Stop the job"""
367- JobBase._run_command(self.stop_command, self.sudo, *args, **kwargs)
368-
369- def restart(self, *args, **kwargs):
370- """Restart the job"""
371- self.ensure_stopped(*args, **kwargs)
372- self.start(*args, **kwargs)
373-
374- def get_status(self, *args, **kwargs):
375- """Gets the current status of the job"""
376- return JobBase._run_command(self.status_command, self.sudo, *args,
377- **kwargs)
378-
379- def get_pid(self, *args, **kwargs):
380- """Gets the current pid of the running job"""
381- status = self.get_status(*args, **kwargs)
382- if "start/" not in status:
383- raise ValueError(
384- '{} is not in the running state.'.format(self.name))
385- pid = status.split()[-1]
386- if not pid.isdigit():
387- raise ValueError(
388- '{} does not have valid process id: {}'.format(self.name, pid))
389- return int(pid)
390-
391- def is_running(self, *args, **kwargs):
392- """Return True if the job is running. Otherwise, False."""
393- return 'start/' in self.get_status(*args, **kwargs)
394-
395- def is_supported(self, *args, **kwargs):
396- """Check if job is supported
397- :return True if job is supported, False otherwise
398- """
399- try:
400- output = self.get_status(*args, **kwargs)
401- except (subprocess.CalledProcessError, ValueError):
402- return False
403- else:
404- return 'Unknown job' not in output
405-
406- def wait_for_job_spawned(self, timeout=10):
407- """Wait until the named job is in spawned state."""
408- spawned = wait_until(
409- lambda: 'start/spawned' in self.get_status(), timeout=timeout)
410- if not spawned:
411- raise RuntimeError(
412- 'Job {} not in start/spwaned state within timeout {}'.format(
413- self.name, timeout))
414-
415- def ensure_stopped(self, timeout=300, *args, **kwargs):
416- """Stops the job if it is running and then checks
417- that it effectively was stopped
418- """
419- if self.is_running(*args, **kwargs):
420- self.stop()
421- if not wait_until(lambda: not self.is_running(), timeout=timeout):
422- raise RuntimeError(
423- 'Job {} not stopped within timeout {}'.format(
424- self.name, timeout))
425-
426- @staticmethod
427- def _run_command(command, sudo=False, *args, **kwargs):
428- """Run the provided command
429- :param command: The command to run
430- :param sudo: True if you want to run the command with sudo privileges
431- :param args: List with the arguments for the command
432- :return: Output of command.
433- """
434- kwargs['universal_newlines'] = kwargs.get('universal_newlines', True)
435- if sudo:
436- return run_command_with_sudo(command, *args, **kwargs)
437- else:
438- command = '{c} {a}'.format(c=command, a=' '.join(args)).strip()
439- return subprocess.check_output(command, shell=True,
440- stderr=subprocess.STDOUT, **kwargs)
441
442=== added file 'ubuntu_system_tests/helpers/job_fixtures.py'
443--- ubuntu_system_tests/helpers/job_fixtures.py 1970-01-01 00:00:00 +0000
444+++ ubuntu_system_tests/helpers/job_fixtures.py 2016-11-23 13:22:18 +0000
445@@ -0,0 +1,39 @@
446+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
447+
448+# Ubuntu System Tests
449+# Copyright (C) 2016 Canonical
450+#
451+# This program is free software: you can redistribute it and/or modify
452+# it under the terms of the GNU General Public License as published by
453+# the Free Software Foundation, either version 3 of the License, or
454+# (at your option) any later version.
455+#
456+# This program is distributed in the hope that it will be useful,
457+# but WITHOUT ANY WARRANTY; without even the implied warranty of
458+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
459+# GNU General Public License for more details.
460+#
461+# You should have received a copy of the GNU General Public License
462+# along with this program. If not, see <http://www.gnu.org/licenses/>.
463+import fixtures
464+from ubuntu_system_tests.helpers.init_systems import get_init_system
465+
466+
467+class JobEnvironmentVariable(fixtures.Fixture):
468+ """ Class used to set an environment variable for a job during the
469+ test execution. This Fixture could use either upstart or systemd
470+ depending the machine/device where it is executed.
471+ """
472+
473+ def __init__(self, global_=False, **kwargs):
474+ super().__init__()
475+ self.variables = kwargs
476+ self.global_ = global_
477+
478+ def setUp(self):
479+ super().setUp()
480+ init_system = get_init_system()
481+ for key, value in self.variables.items():
482+ init_system.set_environment_variable(key, value, self.global_)
483+ self.addCleanup(init_system.unset_environment_variable,
484+ key, value, self.global_)
485
486=== added file 'ubuntu_system_tests/helpers/jobs.py'
487--- ubuntu_system_tests/helpers/jobs.py 1970-01-01 00:00:00 +0000
488+++ ubuntu_system_tests/helpers/jobs.py 2016-11-23 13:22:18 +0000
489@@ -0,0 +1,33 @@
490+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
491+
492+# Ubuntu System Tests
493+# Copyright (C) 2016 Canonical
494+#
495+# This program is free software: you can redistribute it and/or modify
496+# it under the terms of the GNU General Public License as published by
497+# the Free Software Foundation, either version 3 of the License, or
498+# (at your option) any later version.
499+#
500+# This program is distributed in the hope that it will be useful,
501+# but WITHOUT ANY WARRANTY; without even the implied warranty of
502+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
503+# GNU General Public License for more details.
504+#
505+# You should have received a copy of the GNU General Public License
506+# along with this program. If not, see <http://www.gnu.org/licenses/>.
507+from ubuntu_system_tests.helpers.init_systems import get_init_system
508+
509+
510+class JobBase:
511+ """ This contains a base implementation for a Job entity """
512+
513+ def __init__(self, name, sudo=False):
514+ self.name = name
515+ self.sudo = sudo
516+
517+ def is_supported(self, *args, **kwargs):
518+ """Check if job is supported
519+ :return True if job is supported, False otherwise
520+ """
521+ return 'Unknown job' not in get_init_system().get_status(
522+ self, *args, **kwargs)
523
524=== modified file 'ubuntu_system_tests/helpers/location/fixture_setup.py'
525--- ubuntu_system_tests/helpers/location/fixture_setup.py 2016-09-22 13:35:43 +0000
526+++ ubuntu_system_tests/helpers/location/fixture_setup.py 2016-11-23 13:22:18 +0000
527@@ -25,6 +25,7 @@
528 from ubuntu_system_tests.helpers import testbed as tb
529 from ubuntu_system_tests.helpers.backup_restore_fixture import (
530 BackupRestoreRequestAccessFixture)
531+from ubuntu_system_tests.helpers.init_systems import get_init_system
532 from ubuntu_system_tests.helpers.location.job import LocationServiceJob
533
534 UPSTART_OVERRIDE_FILE = '/etc/init/ubuntu-location-service.override'
535@@ -60,6 +61,7 @@
536 self.latitude = latitude
537 self.longitude = longitude
538 self.job = LocationServiceJob()
539+ self.init_system = get_init_system()
540
541 def setUp(self):
542 super().setUp()
543@@ -70,13 +72,13 @@
544 """
545 Stop the already running location service
546 """
547- self.job.stop()
548+ self.init_system.stop(self.job)
549
550 def start_location_service(self):
551 """
552 Start the location service
553 """
554- self.job.start()
555+ self.init_system.start(self.job)
556
557 def start_location_service_with_dummy_fix(self):
558 """
559
560=== modified file 'ubuntu_system_tests/helpers/location/job.py'
561--- ubuntu_system_tests/helpers/location/job.py 2016-09-21 19:04:49 +0000
562+++ ubuntu_system_tests/helpers/location/job.py 2016-11-23 13:22:18 +0000
563@@ -15,8 +15,7 @@
564 #
565 # You should have received a copy of the GNU General Public License
566 # along with this program. If not, see <http://www.gnu.org/licenses/>.
567-
568-from ubuntu_system_tests.helpers.job import JobBase
569+from ubuntu_system_tests.helpers.jobs import JobBase
570
571
572 class LocationServiceJob(JobBase):
573
574=== modified file 'ubuntu_system_tests/helpers/mediascanner/job.py'
575--- ubuntu_system_tests/helpers/mediascanner/job.py 2016-08-24 19:55:06 +0000
576+++ ubuntu_system_tests/helpers/mediascanner/job.py 2016-11-23 13:22:18 +0000
577@@ -15,8 +15,7 @@
578 #
579 # You should have received a copy of the GNU General Public License
580 # along with this program. If not, see <http://www.gnu.org/licenses/>.
581-
582-from ubuntu_system_tests.helpers.job import JobBase
583+from ubuntu_system_tests.helpers.jobs import JobBase
584
585
586 class MediaScannerJob(JobBase):
587
588=== modified file 'ubuntu_system_tests/helpers/network/fixture_setup.py'
589--- ubuntu_system_tests/helpers/network/fixture_setup.py 2015-08-13 00:13:21 +0000
590+++ ubuntu_system_tests/helpers/network/fixture_setup.py 2016-11-23 13:22:18 +0000
591@@ -17,10 +17,13 @@
592 # You should have received a copy of the GNU General Public License
593 # along with this program. If not, see <http://www.gnu.org/licenses/>.
594 #
595-
596 import fixtures
597+import os
598
599+from ubuntu_system_tests.helpers.indicators.network.job import (
600+ IndicatorNetworkInitSystem)
601 from ubuntu_system_tests.helpers import network
602+from ubuntu_system_tests.helpers.testbed import run_command_with_sudo, NM_PATH
603
604
605 class TurnOffInternet(fixtures.Fixture):
606@@ -48,3 +51,40 @@
607 super().setUp()
608 network.turn_off_data_connection()
609 self.addCleanup(network.turn_on_data_connection)
610+
611+
612+class RemoveNetworks(fixtures.Fixture):
613+ """Removes all networks from the device
614+
615+ Removes all networks from the device and restarts
616+ network services to action that change and on cleanup
617+ restores the previous state
618+ """
619+
620+ def __init__(self):
621+ super().__init__()
622+ self.indicator_job = IndicatorNetworkInitSystem()
623+
624+ def setUp(self):
625+ super().setUp()
626+ # only backup networks if one already exists
627+ if self.is_network_present():
628+ self.tmpdir_fixture = fixtures.TempDir()
629+ self.useFixture(self.tmpdir_fixture)
630+ run_command_with_sudo('mv {}/* {}/'.format(
631+ NM_PATH, self.tmpdir_fixture.path))
632+ # If we succesfully move the connection files
633+ # then we need to make sure to reinstate them
634+ self.addCleanup(self._restore_networks)
635+ run_command_with_sudo('service network-manager restart')
636+ self.indicator_job.restart()
637+
638+ def _restore_networks(self):
639+ run_command_with_sudo('mv {}/* {}'.format(
640+ self.tmpdir_fixture.path, NM_PATH))
641+ run_command_with_sudo('service network-manager restart')
642+ self.indicator_job.restart()
643+
644+ def is_network_present(self):
645+ """Return True if a network is currently present."""
646+ return len(os.listdir(NM_PATH)) > 0
647
648=== modified file 'ubuntu_system_tests/helpers/power/fixture_setup.py'
649--- ubuntu_system_tests/helpers/power/fixture_setup.py 2016-09-23 18:47:23 +0000
650+++ ubuntu_system_tests/helpers/power/fixture_setup.py 2016-11-23 13:22:18 +0000
651@@ -73,4 +73,4 @@
652 class EnableRepowerdFakeSensors(EnableFakeSensors):
653 """Fixture to enable fake sensors for repowerd."""
654 def __init__(self):
655- super().__init__(RepowerdJob, RepowerdSensors)
656+ super().__init__(RepowerdJob(), RepowerdSensors())
657
658=== modified file 'ubuntu_system_tests/helpers/power/job.py'
659--- ubuntu_system_tests/helpers/power/job.py 2016-08-24 21:27:41 +0000
660+++ ubuntu_system_tests/helpers/power/job.py 2016-11-23 13:22:18 +0000
661@@ -16,10 +16,7 @@
662 # You should have received a copy of the GNU General Public License
663 # along with this program. If not, see <http://www.gnu.org/licenses/>.
664
665-from subprocess import CalledProcessError
666-
667-from ubuntu_system_tests.helpers import wait_until
668-from ubuntu_system_tests.helpers.job import JobBase
669+from ubuntu_system_tests.helpers.jobs import JobBase
670
671
672 class RepowerdJob(JobBase):
673@@ -27,31 +24,5 @@
674 is a system daemon that helps manage power states
675 """
676
677- def __init__(self, sudo=True):
678- super().__init__('repowerd', sudo)
679-
680- def start(self, fake_sensors=False, **kwargs):
681- """Start a new repowerd process.
682- :param fake_sensors: If True then enable fake sensors,
683- otherwise use real sensors.
684- """
685- cmd = self.start_command
686- if fake_sensors:
687- cmd += ' UBUNTU_PLATFORM_API_TEST_OVERRIDE=sensors'
688- JobBase._run_command(cmd, self.sudo, **kwargs)
689-
690- def restart(self, fake_sensors=False):
691- """Restart repowerd process, stopping existing process if running.
692- :param fake_sensors: If True then enable fake sensors, otherwise use
693- real sensors.
694- """
695- try:
696- pid = self.get_pid()
697- except CalledProcessError:
698- pass
699- else:
700- self.stop()
701- JobBase._run_command('rm -f /tmp/sensor-fifo-{}'.format(pid),
702- self.sudo)
703- self.start(fake_sensors=fake_sensors)
704- wait_until(self.is_running)
705+ def __init__(self):
706+ super().__init__('repowerd', sudo=True)
707
708=== modified file 'ubuntu_system_tests/helpers/processes.py'
709--- ubuntu_system_tests/helpers/processes.py 2016-11-04 13:55:30 +0000
710+++ ubuntu_system_tests/helpers/processes.py 2016-11-23 13:22:18 +0000
711@@ -26,12 +26,6 @@
712 import psutil
713 from retrying import retry
714
715-from ubuntu_system_tests.helpers import (
716- try_import
717-)
718-
719-process_helpers = try_import('unity8.process_helpers')
720-
721 logger = logging.getLogger(__name__)
722
723
724
725=== modified file 'ubuntu_system_tests/helpers/testbed.py'
726--- ubuntu_system_tests/helpers/testbed.py 2016-11-01 13:05:25 +0000
727+++ ubuntu_system_tests/helpers/testbed.py 2016-11-23 13:22:18 +0000
728@@ -19,7 +19,6 @@
729 #
730 import os
731 import subprocess
732-from subprocess import check_call
733
734 import fixtures
735 import pexpect
736@@ -56,42 +55,6 @@
737 os.fchmod(askpass.fileno(), 0o0744)
738
739
740-class RemoveNetworks(fixtures.Fixture):
741- """Removes all networks from the device
742-
743- Removes all networks from the device and restarts
744- network services to action that change and on cleanup
745- restores the previous state
746- """
747-
748- def __init__(self):
749- super().__init__()
750-
751- def setUp(self):
752- super().setUp()
753- # only backup networks if one already exists
754- if self.is_network_present():
755- self.tmpdir_fixture = fixtures.TempDir()
756- self.useFixture(self.tmpdir_fixture)
757- run_command_with_sudo('mv {}/* {}/'.format(
758- NM_PATH, self.tmpdir_fixture.path))
759- # If we succesfully move the connection files
760- # then we need to make sure to reinstate them
761- self.addCleanup(self._restore_networks)
762- run_command_with_sudo('service network-manager restart')
763- check_call(['initctl', 'restart', 'indicator-network'])
764-
765- def _restore_networks(self):
766- run_command_with_sudo('mv {}/* {}'.format(
767- self.tmpdir_fixture.path, NM_PATH))
768- run_command_with_sudo('service network-manager restart')
769- check_call(['initctl', 'restart', 'indicator-network'])
770-
771- def is_network_present(self):
772- """Return True if a network is currently present."""
773- return len(os.listdir(NM_PATH)) > 0
774-
775-
776 def run_command_with_sudo(command, *args, **kwargs):
777 """Run the provided command with sudo.
778 :param command: Command to execute with sudo privileges.
779@@ -99,11 +62,29 @@
780 password = _get_device_password()
781 if not password:
782 raise ValueError('Password required to execute command: %s' % command)
783- root_command = ['sudo -A {}'.format(command)] + list(args)
784+ root_command = 'sudo -A {} '.format(command)
785+ if args:
786+ root_command += ' '.join(args)
787 with AskPass(password):
788 return subprocess.check_output(root_command, shell=True, **kwargs)
789
790
791+def run_command(command, sudo=False, *args, **kwargs):
792+ """Run the provided command
793+ :param command: The command to run
794+ :param sudo: True if you want to run the command with sudo privileges
795+ :param args: List with the arguments for the command
796+ :return: Output of command.
797+ """
798+ kwargs['universal_newlines'] = kwargs.get('universal_newlines', True)
799+ if sudo:
800+ return run_command_with_sudo(command, *args, **kwargs)
801+ else:
802+ command = '{c} {a}'.format(c=command, a=' '.join(args)).strip()
803+ return subprocess.check_output(command, shell=True,
804+ stderr=subprocess.STDOUT, **kwargs)
805+
806+
807 def run_command_with_password_prompt(command, args=[],
808 password_pattern='password',
809 timeout=30):
810
811=== removed file 'ubuntu_system_tests/helpers/ubuntuuitoolkit/environment.py'
812--- ubuntu_system_tests/helpers/ubuntuuitoolkit/environment.py 2016-11-11 18:00:12 +0000
813+++ ubuntu_system_tests/helpers/ubuntuuitoolkit/environment.py 1970-01-01 00:00:00 +0000
814@@ -1,68 +0,0 @@
815-# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
816-#
817-# Copyright (C) 2016 Canonical Ltd.
818-#
819-# This program is free software; you can redistribute it and/or modify
820-# it under the terms of the GNU Lesser General Public License as published by
821-# the Free Software Foundation; version 3.
822-#
823-# This program is distributed in the hope that it will be useful,
824-# but WITHOUT ANY WARRANTY; without even the implied warranty of
825-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
826-# GNU Lesser General Public License for more details.
827-#
828-# You should have received a copy of the GNU Lesser General Public License
829-# along with this program. If not, see <http://www.gnu.org/licenses/>.
830-
831-import logging
832-import subprocess
833-
834-from autopilot import logging as autopilot_logging
835-
836-
837-logger = logging.getLogger(__name__)
838-
839-
840-def is_initctl_env_var_set(variable, global_=False):
841- """Check True if an initctl environment variable is set.
842-
843- :param variable: The name of the variable to check.
844- :param global: if True, the method will operate on the global environment
845- table. Default is False.
846- :return: True if the variable is set. False otherwise.
847-
848- """
849- try:
850- get_initctl_env_var(variable, global_)
851- return True
852- except subprocess.CalledProcessError:
853- return False
854-
855-
856-def get_initctl_env_var(variable, global_=False):
857- """Return the value of an initctl environment variable."""
858- command = ['/sbin/initctl', 'get-env', variable]
859- if global_:
860- command += ['--global']
861- output = subprocess.check_output(
862- command, stderr=subprocess.STDOUT, universal_newlines=True)
863- return output.rstrip()
864-
865-
866-@autopilot_logging.log_action(logger.info)
867-def set_initctl_env_var(variable, value, global_=False):
868- """Set the value of an initctl environment variable."""
869- command = ['/sbin/initctl', 'set-env', '%s=%s' % (variable, value)]
870- if global_:
871- command += ['--global']
872- subprocess.call(command, stderr=subprocess.STDOUT, universal_newlines=True)
873-
874-
875-@autopilot_logging.log_action(logger.info)
876-def unset_initctl_env_var(variable, global_=False):
877- """Remove an initctl environment variable."""
878- command = ['/sbin/initctl', 'unset-env', variable]
879- if global_:
880- command += ['--global']
881- subprocess.call(
882- command, stderr=subprocess.STDOUT, universal_newlines=True)
883
884=== removed file 'ubuntu_system_tests/helpers/ubuntuuitoolkit/fixture_setup.py'
885--- ubuntu_system_tests/helpers/ubuntuuitoolkit/fixture_setup.py 2016-11-16 12:51:50 +0000
886+++ ubuntu_system_tests/helpers/ubuntuuitoolkit/fixture_setup.py 1970-01-01 00:00:00 +0000
887@@ -1,61 +0,0 @@
888-# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
889-#
890-# Copyright (C) 2016 Canonical Ltd.
891-#
892-# This program is free software; you can redistribute it and/or modify
893-# it under the terms of the GNU Lesser General Public License as published by
894-# the Free Software Foundation; version 3.
895-#
896-# This program is distributed in the hope that it will be useful,
897-# but WITHOUT ANY WARRANTY; without even the implied warranty of
898-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
899-# GNU Lesser General Public License for more details.
900-#
901-# You should have received a copy of the GNU Lesser General Public License
902-# along with this program. If not, see <http://www.gnu.org/licenses/>.
903-
904-import logging
905-
906-import fixtures
907-from ubuntu_system_tests.helpers.ubuntuuitoolkit import environment
908-
909-logger = logging.getLogger(__name__)
910-
911-
912-class InitctlEnvironmentVariable(fixtures.Fixture):
913- """Set the value of initctl environment variables."""
914-
915- def __init__(self, global_=False, **kwargs):
916- super().__init__()
917- # Added one level of indirection to be able to spy the calls to
918- # environment during tests.
919- self.environment = environment
920- self.variables = kwargs
921- self.global_ = global_
922-
923- def setUp(self):
924- super().setUp()
925- for variable, value in self.variables.items():
926- self._add_variable_cleanup(variable)
927- if value is None:
928- self.environment.unset_initctl_env_var(
929- variable, global_=self.global_)
930- else:
931- self.environment.set_initctl_env_var(
932- variable, value, global_=self.global_)
933-
934- def _add_variable_cleanup(self, variable):
935- if self.environment.is_initctl_env_var_set(
936- variable, global_=self.global_):
937- original_value = self.environment.get_initctl_env_var(
938- variable, global_=self.global_)
939- self.addCleanup(
940- self.environment.set_initctl_env_var,
941- variable,
942- original_value,
943- global_=self.global_)
944- else:
945- self.addCleanup(
946- self.environment.unset_initctl_env_var,
947- variable,
948- global_=self.global_)
949
950=== modified file 'ubuntu_system_tests/helpers/ubuntuuitoolkit/units.py'
951--- ubuntu_system_tests/helpers/ubuntuuitoolkit/units.py 2016-11-11 18:00:12 +0000
952+++ ubuntu_system_tests/helpers/ubuntuuitoolkit/units.py 2016-11-23 13:22:18 +0000
953@@ -18,19 +18,16 @@
954
955 import os
956
957-from ubuntu_system_tests.helpers.ubuntuuitoolkit import environment
958-
959+from ubuntu_system_tests.helpers.init_systems import get_init_system
960
961 ENV_GRID_UNIT_PX = 'GRID_UNIT_PX'
962 DEFAULT_GRID_UNIT_PX = 8
963
964
965 def get_grid_unit():
966- grid_unit_px = os.environ.get(ENV_GRID_UNIT_PX, None)
967- if not grid_unit_px and environment.is_initctl_env_var_set(
968- ENV_GRID_UNIT_PX):
969- grid_unit_px = environment.get_initctl_env_var(ENV_GRID_UNIT_PX)
970- return float(grid_unit_px or DEFAULT_GRID_UNIT_PX)
971+ return float(os.environ.get(ENV_GRID_UNIT_PX) or
972+ get_init_system().get_env_variable(ENV_GRID_UNIT_PX) or
973+ DEFAULT_GRID_UNIT_PX)
974
975
976 def gu(value):
977
978=== modified file 'ubuntu_system_tests/helpers/unity8/fixture_setup.py'
979--- ubuntu_system_tests/helpers/unity8/fixture_setup.py 2016-10-27 12:54:00 +0000
980+++ ubuntu_system_tests/helpers/unity8/fixture_setup.py 2016-11-23 13:22:18 +0000
981@@ -26,17 +26,25 @@
982 from dbus import DBusException
983 from retrying import retry
984
985+from ubuntu_system_tests.helpers import context
986+from ubuntu_system_tests.helpers import wait_until
987+from ubuntu_system_tests.helpers.autopilot import get_proxy_object
988+from ubuntu_system_tests.helpers.init_systems import get_init_system
989 from ubuntu_system_tests.helpers.processes import (
990 PidNotFoundError,
991- ensure_all_apps_closed,
992- is_testability_enabled_for_process)
993+ ensure_all_apps_closed)
994+
995 from ubuntu_system_tests.helpers.unity8 import Unity8Job
996 from autopilot import (
997 exceptions
998 )
999
1000+from ubuntu_system_tests.helpers.unity8 import get_dash
1001+
1002 logger = logging.getLogger(__name__)
1003
1004+UBUNTU_PLATFORM_API_TEST_OVERRIDE = 'UBUNTU_PLATFORM_API_TEST_OVERRIDE'
1005+
1006
1007 class SettingsWizard(fixtures.Fixture):
1008
1009@@ -71,14 +79,16 @@
1010 open(self.WIZARD_FILE, 'a').close()
1011
1012
1013-class StartUnity8(fixtures.Fixture):
1014+class SetupUnity8(fixtures.Fixture):
1015
1016- def __init__(self):
1017+ def __init__(self, restart=True):
1018 self.unity8 = Unity8Job()
1019+ self.init_system = get_init_system()
1020+ self.restart = restart
1021
1022- def setUp(self, restart_unity=True):
1023+ def setUp(self):
1024 super().setUp()
1025- self.setup_unity(restart_unity=restart_unity)
1026+ self.setup_unity(restart=self.restart)
1027
1028 # Retry added until fix for bug 1427946 in QtMir is landed
1029 @retry(stop_max_attempt_number=5,
1030@@ -91,20 +101,21 @@
1031 isinstance(exception, PidNotFoundError) or
1032 isinstance(exception, exceptions.ProcessSearchError) or
1033 isinstance(exception, exceptions.BackendException)))
1034- def setup_unity(self, restart_unity=True):
1035+ def setup_unity(self, restart=True):
1036 """Setup unity8 environment, restarting if any error is observed.
1037- :param restart_unity: Whether unity8 should be restarted.
1038+ :param restart: Whether unity8 should be restarted.
1039 """
1040- if restart_unity:
1041- self.unity8.restart()
1042- else:
1043- # If unity8 is not restarted, we need to make sure
1044- # that testability is enabled for the unity8 instance
1045- # which is already running, if it's not, then we have
1046- # no chance other than to restart unity8
1047- if not is_testability_enabled_for_process(
1048- self.unity8.get_pid()):
1049- self.unity8.restart()
1050+ from ubuntu_system_tests.helpers.unity8.shell import Unity8 # NOQA
1051+ if restart:
1052+ self.init_system.ensure_stopped(self.unity8)
1053+ self.init_system.start(self.unity8)
1054+ wait_until(self.init_system.is_running, self.unity8)
1055+ context.shared.unity_pid = self.init_system.get_pid(self.unity8)
1056+ context.shared.unity = get_proxy_object(pid=context.shared.unity_pid)
1057+ self.unity8.wait_for_unity_ready()
1058+ context.shared.unity.wait_for_greeter_content()
1059+ context.shared.unity.unlock()
1060+ context.shared.dash = get_dash()
1061 self.addCleanup(ensure_all_apps_closed)
1062
1063
1064@@ -112,7 +123,18 @@
1065 """Fixture to enable fake sensors for unity8."""
1066 def __init__(self):
1067 self.unity8 = Unity8Job()
1068+ self.init_system = get_init_system()
1069
1070 def setUp(self):
1071 super().setUp()
1072- self.unity8.restart(fake_sensors=True)
1073+ self.init_system.ensure_stopped(self.unity8)
1074+ self.init_system.set_environment_variable(
1075+ UBUNTU_PLATFORM_API_TEST_OVERRIDE, 'sensors',
1076+ global_scope=False)
1077+ self.addCleanup(self.init_system.unset_environment_variable,
1078+ UBUNTU_PLATFORM_API_TEST_OVERRIDE)
1079+ args = ['QT_LOAD_TESTABILITY=1', '--no-wait']
1080+ self.init_system.start(self.unity8, *args)
1081+ self.unity8.sensors.validate_fifo_ready(self.unity8.name)
1082+ self.unity8.sensors.setup_sensors(self.unity8.name)
1083+ self.useFixture(SetupUnity8(restart=False))
1084
1085=== modified file 'ubuntu_system_tests/helpers/unity8/job.py'
1086--- ubuntu_system_tests/helpers/unity8/job.py 2016-10-28 14:53:08 +0000
1087+++ ubuntu_system_tests/helpers/unity8/job.py 2016-11-23 13:22:18 +0000
1088@@ -15,22 +15,17 @@
1089 #
1090 # You should have received a copy of the GNU General Public License
1091 # along with this program. If not, see <http://www.gnu.org/licenses/>.
1092-
1093-from subprocess import CalledProcessError
1094 from threading import Event
1095
1096 from ubuntu_system_tests.helpers import ofono
1097+from ubuntu_system_tests.helpers.jobs import JobBase
1098 from ubuntu_system_tests.helpers.notifications import sim_pin_observer
1099+from ubuntu_system_tests.helpers.processes import is_process_running
1100 from ubuntu_system_tests.helpers.unity8.sensors_utils import Unity8Sensors
1101 from ubuntu_system_tests.helpers import context
1102-from ubuntu_system_tests.helpers import wait_until
1103-from ubuntu_system_tests.helpers.autopilot import get_proxy_object
1104-from ubuntu_system_tests.helpers.job import JobBase
1105-from ubuntu_system_tests.helpers.unity8 import get_dash
1106+
1107 from ubuntu_system_tests.helpers.unity8 import greeter
1108
1109-from ubuntu_system_tests.helpers.ubuntuuitoolkit import environment
1110-
1111
1112 class Unity8Job(JobBase):
1113
1114@@ -39,53 +34,14 @@
1115 self.sensors = Unity8Sensors()
1116
1117 def ensure_unity_running_and_greeter_hidden(self):
1118- if not self.is_running():
1119- self.start()
1120+ if not is_process_running(self.name):
1121+ self.init_system.start()
1122 greeter.wait_for_greeter()
1123 greeter.hide_greeter_with_dbus()
1124
1125- def start(self, fake_sensors=False, *args, **kwargs):
1126- """Start a new unity8 process.
1127- :param fake_sensors: If True then enable fake sensors,
1128- otherwise use real sensors.
1129- """
1130- api_test_override = 'UBUNTU_PLATFORM_API_TEST_OVERRIDE'
1131- try:
1132- environment.get_initctl_env_var(api_test_override)
1133- except CalledProcessError:
1134- pass
1135- else:
1136- environment.unset_initctl_env_var(api_test_override)
1137- if fake_sensors:
1138- environment.set_initctl_env_var(api_test_override, 'sensors')
1139- args = ['QT_LOAD_TESTABILITY=1', '--no-wait']
1140- JobBase._run_command(self.start_command, self.sudo, *args, **kwargs)
1141- if fake_sensors:
1142- self.sensors.validate_fifo_ready(self.name)
1143- self.sensors.setup_sensors(self.name)
1144- wait_until(self.is_running, timeout=60)
1145- context.shared.unity_pid = self.get_pid()
1146- unity = self.get_unity8_proxy_object()
1147- context.shared.unity = unity
1148- self.wait_for_unity_ready()
1149- unity.wait_for_greeter_content()
1150- unity.unlock()
1151- context.shared.dash = get_dash()
1152-
1153- def restart(self, fake_sensors=False):
1154- """Restart unity8 process, stopping existing process if running.
1155- :param fake_sensors: If True then enable fake sensors, otherwise use
1156- real sensors.
1157- """
1158- try:
1159- pid = self.get_pid()
1160- except CalledProcessError:
1161- pass
1162- else:
1163- JobBase._run_command('rm -f /tmp/sensor-fifo-{}'.format(pid),
1164- self.sudo)
1165- self.ensure_stopped()
1166- self.start(fake_sensors=fake_sensors)
1167+ def setup_fake_sensors(self):
1168+ self.sensors.validate_fifo_ready(self.name)
1169+ self.sensors.setup_sensors(self.name)
1170
1171 @staticmethod
1172 def wait_for_unity_ready(dismiss_sim_unlock=True):
1173@@ -114,7 +70,3 @@
1174 pin_observer.stop()
1175 else:
1176 context.shared.unity.wait_for_greeter_content()
1177-
1178- def get_unity8_proxy_object(self):
1179- from ubuntu_system_tests.helpers.unity8.shell import Unity8 # NOQA
1180- return get_proxy_object(self.get_pid())
1181
1182=== modified file 'ubuntu_system_tests/helpers/webbrowser/fixture_setup.py'
1183--- ubuntu_system_tests/helpers/webbrowser/fixture_setup.py 2016-11-01 14:23:52 +0000
1184+++ ubuntu_system_tests/helpers/webbrowser/fixture_setup.py 2016-11-23 13:22:18 +0000
1185@@ -22,7 +22,6 @@
1186 import random
1187 import shutil
1188 import time
1189-
1190 import fixtures
1191
1192 from ubuntu_system_tests.helpers import (
1193@@ -35,11 +34,10 @@
1194 from ubuntu_system_tests.helpers import file_system as fs
1195 from ubuntu_system_tests.helpers.gallery.fixture_setup import (
1196 BackupRestoreGalleryData)
1197+from ubuntu_system_tests.helpers.job_fixtures import JobEnvironmentVariable
1198 from ubuntu_system_tests.helpers.media import BackupRestoreLocalMediaFixture
1199 from ubuntu_system_tests.helpers.webbrowser import WebBrowser
1200
1201-from ubuntu_system_tests.helpers.ubuntuuitoolkit import fixture_setup
1202-
1203
1204 class WebbrowserTestEnvironment(fixtures.Fixture):
1205 """Fixture to prepare webbrowser test environment."""
1206@@ -89,8 +87,7 @@
1207 super().setUp()
1208 tempdir = self.useFixture(fixtures.TempDir())
1209 self.path = tempdir.path
1210- self.useFixture(fixture_setup.InitctlEnvironmentVariable(
1211- XDG_DATA_HOME=self.path))
1212+ self.useFixture(JobEnvironmentVariable(XDG_DATA_HOME=self.path))
1213
1214
1215 class UrlDatabaseFixture(fixtures.Fixture):
1216
1217=== modified file 'ubuntu_system_tests/host/commands.py'
1218--- ubuntu_system_tests/host/commands.py 2016-11-08 12:12:29 +0000
1219+++ ubuntu_system_tests/host/commands.py 2016-11-23 13:22:18 +0000
1220@@ -41,7 +41,8 @@
1221 APT_CACHER = 'apt-cacher-ng'
1222 APT_CACHER_CACHE_DIR = '/var/cache/apt-cacher-ng'
1223 APT_CACHER_LOG_DIR = '/var/log/apt-cacher-ng/'
1224-APT_CACHER_INIT_FILE = '/etc/init/apt-cacher-ng.conf'
1225+APT_CACHER_UPSTART_INIT_FILE = '/etc/init/apt-cacher-ng.conf'
1226+APT_CACHER_SYSTEMD_INIT_FILE = '/etc/systemd/system/apt-cacher-ng.service'
1227 APT_PROXY = 'Acquire::http { Proxy \\"http://127.0.0.1:3142\\"; };'
1228 APT_PROXY_FILE = '/etc/apt/apt.conf.d/01proxy'
1229 EXT_CACHE_DIR = '/userdata/apt-cacher-ng/cache'
1230@@ -421,19 +422,58 @@
1231
1232
1233 def _get_apt_cacher_autostart_command():
1234- """Write the apt-cacher-ng conf file into /etc/init/apt-cacher-ng.conf
1235- to re-launch apt-cacher-ng on each subsequent reboot.
1236-
1237- This method assumes that upstart is used as the init system. If this
1238- changes in future then this method will need updating to accomodate that.
1239- """
1240- script = ('start on runlevel [2345]\n'
1241- 'script\n' +
1242- _get_mount_dir_command(EXT_LOG_DIR, APT_CACHER_LOG_DIR) +
1243- _get_mount_dir_command(EXT_CACHE_DIR, APT_CACHER_CACHE_DIR) +
1244- _get_apt_cacher_start_command() +
1245- '\nend script')
1246- return _get_create_file_command(content=script, path=APT_CACHER_INIT_FILE)
1247+ return 'if [ -z "$(pidof systemd)" ]; then {} else {} fi;'.format(
1248+ _get_apt_cacher_upstart_autostart_command(),
1249+ _get_apt_cacher_systemd_autostart_command())
1250+
1251+
1252+def _array_to_script(*lines):
1253+ """ Retrieve a string with \n characters based on a string list
1254+ :param lines: A list with the lines
1255+ :return: the string with the array elements and \n characters
1256+ """
1257+ return '\n'.join(lines)
1258+
1259+
1260+def _get_apt_cacher_upstart_autostart_command():
1261+ """Write the apt-cacher-ng conf file into /etc/init/apt-cacher-ng.conf
1262+ to re-launch apt-cacher-ng on each subsequent reboot.
1263+
1264+ This method assumes that upstart is used as the init system. If this
1265+ changes in future then this method will need updating to accomodate that.
1266+ """
1267+ script = _array_to_script(
1268+ 'start on runlevel [2345]',
1269+ 'script',
1270+ _get_mount_dir_command(EXT_LOG_DIR, APT_CACHER_LOG_DIR) +
1271+ _get_mount_dir_command(EXT_CACHE_DIR, APT_CACHER_CACHE_DIR) +
1272+ _get_apt_cacher_start_command(),
1273+ 'end script')
1274+ return _get_create_file_command(content=script,
1275+ path=APT_CACHER_UPSTART_INIT_FILE)
1276+
1277+
1278+def _get_apt_cacher_systemd_autostart_command():
1279+ """Write the apt-cacher-ng conf file into /etc/init/apt-cacher-ng.conf
1280+ to re-launch apt-cacher-ng on each subsequent reboot.
1281+
1282+ This method assumes that upstart is used as the init system. If this
1283+ changes in future then this method will need updating to accomodate that.
1284+ """
1285+ script = _array_to_script(
1286+ '[Unit]',
1287+ 'Description=Autostart Apt Cacher NG',
1288+ '',
1289+ '[Service]',
1290+ 'Type=simple',
1291+ 'ExecStart={}',
1292+ '',
1293+ '[Install]',
1294+ 'WantedBy=multi-user.target').format(_get_apt_cacher_start_command())
1295+ file_cmd = _get_create_file_command(content=script,
1296+ path=APT_CACHER_SYSTEMD_INIT_FILE)
1297+ enable_cmd = 'systemctl enable apt-cacher-ng.service;'
1298+ return file_cmd + enable_cmd
1299
1300
1301 def _get_apt_cacher_install_setup_command(apt_cacher_required):
1302@@ -624,7 +664,7 @@
1303
1304 def _get_install_packages_command(packages):
1305 """Return command to install packages on device."""
1306- return ('apt-get -y --no-install-recommends install {packages}; ').format(
1307+ return 'apt-get -y --no-install-recommends install {packages}; '.format(
1308 packages=packages)
1309
1310
1311
1312=== modified file 'ubuntu_system_tests/tests/base.py'
1313--- ubuntu_system_tests/tests/base.py 2016-11-01 14:23:52 +0000
1314+++ ubuntu_system_tests/tests/base.py 2016-11-23 13:22:18 +0000
1315@@ -34,16 +34,18 @@
1316 from ubuntu_system_tests.helpers import (
1317 context,
1318 images,
1319- mir,
1320+ mir
1321 )
1322 from ubuntu_system_tests.helpers import screen
1323-from ubuntu_system_tests.helpers.ubuntuuitoolkit import fixture_setup
1324 from ubuntu_system_tests.helpers import wait_until
1325-from ubuntu_system_tests.helpers.location.fixture_setup import \
1326- SetLocationAccessRequests
1327+from ubuntu_system_tests.helpers.autopilot import get_proxy_object
1328+from ubuntu_system_tests.helpers.init_systems import get_init_system
1329+from ubuntu_system_tests.helpers.job_fixtures import JobEnvironmentVariable
1330+from ubuntu_system_tests.helpers.location.fixture_setup import (
1331+ SetLocationAccessRequests)
1332 from ubuntu_system_tests.helpers.unity8 import Unity8Job
1333 from ubuntu_system_tests.helpers.timeout import timeout
1334-from ubuntu_system_tests.helpers.unity8.fixture_setup import StartUnity8
1335+from ubuntu_system_tests.helpers.unity8.fixture_setup import SetupUnity8
1336 from ubuntu_system_tests.helpers.webapp import (
1337 DEFAULT_WEBVIEW_INSPECTOR_IP,
1338 DEFAULT_WEBVIEW_INSPECTOR_PORT,
1339@@ -61,8 +63,7 @@
1340
1341 PLATFORMS_DEFAULT_SETUP = [DESKTOP_PLATFORM_NAME]
1342 DEFAULT_FIXTURES = [SetLocationAccessRequests('unity8-dash', True),
1343- fixture_setup.InitctlEnvironmentVariable(
1344- QT_LOAD_TESTABILITY='1')]
1345+ JobEnvironmentVariable(QT_LOAD_TESTABILITY='1')]
1346
1347
1348 class BaseUbuntuSystemTestCase(testcase.AutopilotTestCase):
1349@@ -72,7 +73,7 @@
1350 super().tearDownClass()
1351 unity8.ensure_unity_running_and_greeter_hidden()
1352
1353- def setUp(self, custom_fixtures=[StartUnity8()]):
1354+ def setUp(self, custom_fixtures=[SetupUnity8()]):
1355 super().setUp()
1356 self._reset_autopilot_registry()
1357 self._init_shared_context()
1358@@ -84,6 +85,10 @@
1359 # This stops the OSK from being displayed, so must remove it.
1360 self._setup_keyboard()
1361 if self.device_unlock_required():
1362+ from ubuntu_system_tests.helpers.unity8.shell import Unity8 # NOQA
1363+ context.shared.unity_pid = get_init_system().get_pid(Unity8Job())
1364+ context.shared.unity = get_proxy_object(
1365+ pid=context.shared.unity_pid)
1366 context.shared.unity.unlock()
1367
1368 def _setup_keyboard(self):
1369@@ -182,7 +187,7 @@
1370 """ Setup the environment for the webapps. This method has to be
1371 called before launch the first web app in the test.
1372 """
1373- self.useFixture(fixture_setup.InitctlEnvironmentVariable(
1374+ self.useFixture(JobEnvironmentVariable(
1375 global_=True,
1376 UBUNTU_WEBVIEW_DEVTOOLS_HOST=DEFAULT_WEBVIEW_INSPECTOR_IP,
1377 UBUNTU_WEBVIEW_DEVTOOLS_PORT=str(DEFAULT_WEBVIEW_INSPECTOR_PORT)))
1378
1379=== modified file 'ubuntu_system_tests/tests/test_brightness.py'
1380--- ubuntu_system_tests/tests/test_brightness.py 2016-11-16 12:42:25 +0000
1381+++ ubuntu_system_tests/tests/test_brightness.py 2016-11-23 13:22:18 +0000
1382@@ -23,14 +23,18 @@
1383 from autopilot.matchers import Eventually
1384 from testtools.matchers import Equals, LessThan, GreaterThan
1385
1386-from ubuntu_system_tests.helpers.brightness.sensors_utils import \
1387- RepowerdSensors
1388-from ubuntu_system_tests.helpers.indicators.battery import BatteryIndicatorPage
1389+from ubuntu_system_tests.helpers.brightness.sensors_utils import (
1390+ RepowerdSensors)
1391+from ubuntu_system_tests.helpers.indicators.battery import (
1392+ BatteryIndicatorPage)
1393
1394 from ubuntu_system_tests.helpers import system_settings
1395 from ubuntu_system_tests.helpers.indicators.indicators import IndicatorsFactory
1396 from ubuntu_system_tests.helpers import display
1397 from ubuntu_system_tests.helpers.power import fixture_setup as power_fixture
1398+from ubuntu_system_tests.helpers.power.fixture_setup import (
1399+ EnableRepowerdFakeSensors)
1400+from ubuntu_system_tests.helpers.unity8.fixture_setup import SetupUnity8
1401 from ubuntu_system_tests.tests import base
1402
1403 DEVICE_ARALE = 'arale'
1404@@ -41,8 +45,10 @@
1405
1406 class BrightnessTestCase(base.BaseUbuntuSystemTestCase):
1407
1408- def setUp(self):
1409- super().setUp()
1410+ def setUp(self, custom_fixtures=[]):
1411+ if not custom_fixtures:
1412+ custom_fixtures.append(SetupUnity8())
1413+ super().setUp(custom_fixtures=custom_fixtures)
1414 max_brightness = display.get_max_brightness_level()
1415
1416 self.useFixture(
1417@@ -72,8 +78,8 @@
1418 @skipUnless(sensors.is_brightness_sensor_present(),
1419 'Brightness sensor support required.')
1420 def setUp(self):
1421- self.useFixture(power_fixture.EnableRepowerdFakeSensors())
1422- super().setUp()
1423+ super().setUp(custom_fixtures=[EnableRepowerdFakeSensors(),
1424+ SetupUnity8()])
1425
1426 def _test_automatic_screen_brightness(self, settings_page):
1427 """
1428
1429=== modified file 'ubuntu_system_tests/tests/test_settings_wizard.py'
1430--- ubuntu_system_tests/tests/test_settings_wizard.py 2016-07-07 09:03:17 +0000
1431+++ ubuntu_system_tests/tests/test_settings_wizard.py 2016-11-23 13:22:18 +0000
1432@@ -15,13 +15,12 @@
1433 #
1434 # You should have received a copy of the GNU General Public License
1435 # along with this program. If not, see <http://www.gnu.org/licenses/>
1436-
1437 from ubuntu_system_tests.common.config import get_device_config_stack
1438+from ubuntu_system_tests.helpers.network.fixture_setup import RemoveNetworks
1439 from ubuntu_system_tests.helpers import ofono
1440 from ubuntu_system_tests.helpers.platform import (
1441 is_agps_supported, is_wifi_supported
1442 )
1443-from ubuntu_system_tests.helpers import testbed
1444 from ubuntu_system_tests.helpers.system_settings import (
1445 is_reporting_enabled,
1446 )
1447@@ -53,7 +52,7 @@
1448 self.unity = self.launch_unity()
1449 self.wizard = self._get_settings_wizard()
1450 self.is_sim_inserted = ofono.is_sim_inserted(ignore_phonesim=False)
1451- self.useFixture(testbed.RemoveNetworks())
1452+ self.useFixture(RemoveNetworks())
1453
1454 def _apply_default_config(self):
1455 """Create config for the test based on supplied and default values"""

Subscribers

People subscribed via source and target branches

to all changes: