@@ -28,9 +28,11 @@ from autopilot.platform import model
28from autopilot.testcase import AutopilotTestCase
28from autopilot.testcase import AutopilotTestCase
29from autopilot.matchers import Eventually
29from autopilot.matchers import Eventually
30from autopilot.input import Touch
30from autopilot.input import Touch
31+from autopilot.introspection import get_proxy_object_for_existing_process
31from autopilot.display import Display
32from autopilot.display import Display
32import logging
33import logging
33import os.path
34import os.path
34from testtools.matchers import Equals, NotEquals
36from testtools.matchers import Equals, NotEquals
36from unity8 import (
38from unity8 import (
@@ -90,6 +92,10 @@ class UnityTestCase(AutopilotTestCase):
90 self.touch = Touch.create()
92 self.touch = Touch.create()
91 self._setup_display_details()
93 self._setup_display_details()
95+ self._using_upstart = False
96+ if model() != "Desktop": # or check env
97+ self._using_upstart = True
93 def _reset_launcher(self):
99 def _reset_launcher(self):
94 """Reset Unity launcher hide mode"""
100 """Reset Unity launcher hide mode"""
95 self._unityshell_schema.set_int(UNITYSHELL_LAUNCHER_KEY, self._launcher_hide_mode)
101 self._unityshell_schema.set_int(UNITYSHELL_LAUNCHER_KEY, self._launcher_hide_mode)
@@ -129,7 +135,7 @@ class UnityTestCase(AutopilotTestCase):
129 self.grid_size = int(os.getenv('GRID_UNIT_PX'))
135 self.grid_size = int(os.getenv('GRID_UNIT_PX'))
131 self.grid_size = int(self.grid_unit_px / scale_divisor)
137 self.grid_size = int(self.grid_unit_px / scale_divisor)
132− self.patch_environment("GRID_UNIT_PX", str(self.grid_size))
138+ self._patch_environment("GRID_UNIT_PX", str(self.grid_size))
134 def _geo_larger_than_display(self, width, height):
140 def _geo_larger_than_display(self, width, height):
135 should_scale = getattr(self, 'scale_geo', True)
141 should_scale = getattr(self, 'scale_geo', True)
@@ -147,6 +153,41 @@ class UnityTestCase(AutopilotTestCase):
147 divisor = divisor * 2
153 divisor = divisor * 2
148 return divisor
154 return divisor
156+ def _patch_environment(self, key, value):
157+ """Wrapper for patching env for either upstart or non-upstart
161+ if self._using_upstart:
163+ current_value = subprocess.check_output([
168+ except subprocess.CalledProcessError:
169+ current_value = None
174+ "%s=%s" % (key, value)
176+ self.addCleanup(self._upstart_reset_env, key, current_value)
178+ self.patch_environment(key, value)
180+ def _upstart_reset_env(self, key, value):
181+ logger.info("Resetting upstart env %s to %s", key, value)
183+ subprocess.call(["/sbin/initctl", "unset-env", key])
188+ "%s=%s" % (key, value)
150 def launch_unity(self, **kwargs):
191 def launch_unity(self, **kwargs):
151 """Launch the unity shell, return a proxy object for it."""
192 """Launch the unity shell, return a proxy object for it."""
152 binary_path = get_binary_path()
193 binary_path = get_binary_path()
@@ -175,13 +216,17 @@ class UnityTestCase(AutopilotTestCase):
175 except OSError:
216 except OSError:
219+ if self._using_upstart:
220+ app_proxy = self._launch_unity_with_upstart()
178− app_proxy = self.launch_test_application(
222+ app_proxy = self.launch_test_application(
179− binary_path,
223+ binary_path,
180− *self.unity_geometry_args,
224+ *self.unity_geometry_args,
181− app_type='qt',
225+ app_type='qt',
182− emulator_base=UnityEmulatorBase,
226+ emulator_base=UnityEmulatorBase,
183− **kwargs
227+ **kwargs
185 self._set_proxy(app_proxy)
230 self._set_proxy(app_proxy)
187 # Ensure that the dash is visible before we return:
232 # Ensure that the dash is visible before we return:
@@ -191,6 +236,54 @@ class UnityTestCase(AutopilotTestCase):
192 return app_proxy
237 return app_proxy
239+ def _launch_unity_with_upstart(self):
240+ subprocess.call(["/sbin/initctl", "set-env", "QT_LOAD_TESTABILITY=1"])
242+ output = subprocess.check_output([
248+ unity_already_started = False
249+ if "start/" in output:
250+ unity_already_started = True
252+ subprocess.check_call(["/sbin/initctl", "stop", "unity8"])
253+ except subprocess.CalledProcessError as e:
254+ logger.warning("Unable to stop unity8")
255+ e.args += ("Failed to stop existing unity8 process", )
258+ output = subprocess.check_output(["/sbin/initctl", "start", "unity8"])
261+ self._cleanup_launching_upstart_unity,
262+ unity_already_started
265+ pid = int(output.split()[-1])
267+ return get_proxy_object_for_existing_process(
269+ emulator_base=UnityEmulatorBase,
272+ def _cleanup_launching_upstart_unity(self, restart_unity):
273+ logger.info("Cleaning up launching unity, unsetting env")
274+ subprocess.call(["/sbin/initctl", "unset-env", "QT_LOAD_TESTABILITY"])
277+ logger.info("Stopping existing unity")
278+ subprocess.check_call(["/sbin/initctl", "stop", "unity8"])
279+ except subprocess.CalledProcessError:
280+ logger.warning("Appears unity was already stopped")
282+ # Actually, the previous env stuff will be still here right?
284+ logger.info("Starting unity again with original env")
285+ subprocess.check_call(["/sbin/initctl", "start", "unity8"])
194 def patch_lightdm_mock(self, mock_type='single'):
287 def patch_lightdm_mock(self, mock_type='single'):
195 self._lightdm_mock_type = mock_type
288 self._lightdm_mock_type = mock_type
196 logger.info("Setting up LightDM mock type '%s'", mock_type)
289 logger.info("Setting up LightDM mock type '%s'", mock_type)
@@ -204,7 +297,7 @@ class UnityTestCase(AutopilotTestCase):
204 new_ld_library_path = ':'.join(new_ld_library_path)
297 new_ld_library_path = ':'.join(new_ld_library_path)
205 logger.info("New library path: %s", new_ld_library_path)
298 logger.info("New library path: %s", new_ld_library_path)
207− self.patch_environment('LD_LIBRARY_PATH', new_ld_library_path)
300+ self._patch_environment('LD_LIBRARY_PATH', new_ld_library_path)
209 def _get_lightdm_mock_path(self, mock_type):
302 def _get_lightdm_mock_path(self, mock_type):
210 lib_path = get_mocks_library_path()
303 lib_path = get_mocks_library_path()
@@ -226,7 +319,7 @@ class UnityTestCase(AutopilotTestCase):
227 qml_import_path = ':'.join(qml_import_path)
320 qml_import_path = ':'.join(qml_import_path)
228 logger.info("New QML2 import path: %s", qml_import_path)
321 logger.info("New QML2 import path: %s", qml_import_path)
229− self.patch_environment('QML2_IMPORT_PATH', qml_import_path)
322+ self._patch_environment('QML2_IMPORT_PATH', qml_import_path)
231 def _set_proxy(self, proxy):
324 def _set_proxy(self, proxy):
232 """Keep a copy of the proxy object, so we can use it to get common
325 """Keep a copy of the proxy object, so we can use it to get common