20 """unity autopilot tests."""
23 from gi.repository
import Gio
27 from autopilot
import introspection
28 from autopilot.platform
import model
29 from autopilot.testcase
import AutopilotTestCase
30 from autopilot.matchers
import Eventually
31 from autopilot.input
import Touch
32 from autopilot.display
import Display
37 from testtools.matchers
import Equals
38 from ubuntuuitoolkit
import (
39 fixture_setup
as toolkit_fixtures,
46 get_mocks_library_path,
47 get_default_extra_mock_libraries,
57 main_window
as main_window_emulator,
61 logger = logging.getLogger(__name__)
63 UNITYSHELL_GSETTINGS_SCHEMA =
"org.compiz.unityshell"
64 UNITYSHELL_GSETTINGS_PATH =
"/org/compiz/profiles/unity/plugins/unityshell/"
65 UNITYSHELL_LAUNCHER_KEY =
"launcher-hide-mode"
66 UNITYSHELL_LAUNCHER_MODE = 1
69 def _get_device_emulation_scenarios(devices='All'):
70 nexus4 = (
'Desktop Nexus 4',
71 dict(app_width=768, app_height=1280, grid_unit_px=18))
72 nexus10 = (
'Desktop Nexus 10',
73 dict(app_width=2560, app_height=1600, grid_unit_px=20))
74 native = (
'Native Device',
75 dict(app_width=0, app_height=0, grid_unit_px=0))
77 if model() ==
'Desktop':
79 return [nexus4, nexus10]
80 elif devices ==
'Nexus4':
82 elif devices ==
'Nexus10':
86 'Unrecognized device-option "%s" passed.' % devices
92 def is_unity7_running():
93 """Return True if Unity7 is running. Otherwise, return False."""
96 UNITYSHELL_GSETTINGS_SCHEMA
in
97 Gio.Settings.list_relocatable_schemas()
101 def get_qml_import_path_with_mock():
102 """Return the QML2_IMPORT_PATH value with the mock path prepended."""
103 qml_import_path = [get_mocks_library_path()]
104 if os.getenv(
'QML2_IMPORT_PATH')
is not None:
105 qml_import_path.append(os.getenv(
'QML2_IMPORT_PATH'))
107 qml_import_path =
':'.join(qml_import_path)
108 logger.info(
"New QML2 import path: %s", qml_import_path)
109 return qml_import_path
114 """A test case base class for the Unity shell tests."""
119 output = subprocess.check_output(
120 [
"/sbin/initctl",
"status",
"unity8"],
121 stderr=subprocess.STDOUT,
122 universal_newlines=
True,
124 except subprocess.CalledProcessError
as e:
126 "Error: `initctl status unity8` failed, most probably the "
127 "unity8 session could not be found:\n\n"
129 "Please install unity8 or copy data/unity8.conf to "
132 os.path.join(os.getenv(
"XDG_CONFIG_HOME",
133 os.path.join(os.getenv(
"HOME"),
141 if "start/" in output:
143 "Error: Unity is currently running, these tests require it to "
145 "Please run this command before running these tests: \n"
146 "initctl stop unity8\n"
151 super(UnityTestCase, self).setUp()
152 if is_unity7_running():
153 self.useFixture(toolkit_fixtures.HideUnity7Launcher())
162 if model() !=
"Desktop":
163 from autopilot.input
import _uinput
164 _uinput._touch_device = _uinput.create_touch_device()
165 self.addCleanup(_uinput._touch_device.close)
167 self.
touch = Touch.create()
170 def _setup_display_details(self):
174 def _determine_geometry(self):
175 """Use the geometry that may be supplied or use the default."""
176 width = getattr(self,
'app_width', 0)
177 height = getattr(self,
'app_height', 0)
180 if width > 0
and height > 0:
183 width = width / scale_divisor
184 height = height / scale_divisor
186 "Geometry larger than display, scaled down to: %dx%d",
190 geo_string =
"%dx%d" % (width, height)
199 def _setup_grid_size(self, scale_divisor):
200 """Use the grid size that may be supplied or use the default."""
201 if getattr(self,
'grid_unit_px', 0) == 0:
202 self.
grid_size = int(os.getenv(
'GRID_UNIT_PX'))
204 self.
grid_size = int(self.grid_unit_px / scale_divisor)
207 def _geo_larger_than_display(self, width, height):
208 should_scale = getattr(self,
'scale_geo',
True)
210 screen = Display.create()
211 screen_width = screen.get_screen_width()
212 screen_height = screen.get_screen_height()
213 return (width > screen_width)
or (height > screen_height)
217 def _get_scaled_down_geo(self, width, height):
220 divisor = divisor * 2
223 def _patch_environment(self, key, value):
224 """Wrapper for patching env for upstart environment."""
226 current_value = subprocess.check_output(
227 [
"/sbin/initctl",
"get-env",
"--global", key],
228 stderr=subprocess.STDOUT,
229 universal_newlines=
True,
231 except subprocess.CalledProcessError:
238 "%s=%s" % (key, value)
239 ], stderr=subprocess.STDOUT)
242 def _upstart_reset_env(self, key, value):
243 logger.info(
"Resetting upstart env %s to %s", key, value)
246 [
"/sbin/initctl",
"unset-env", key],
247 stderr=subprocess.STDOUT,
254 "%s=%s" % (key, value)
255 ], stderr=subprocess.STDOUT)
258 """Launch the unity shell, return a proxy object for it."""
259 binary_path = get_binary_path()
260 lib_path = get_lib_path()
263 "Lib path is '%s', binary path is '%s'",
273 get_qml_import_path_with_mock()
284 os.getenv(
'MIR_SOCKET',
285 os.path.join(os.getenv(
'XDG_RUNTIME_DIR',
"/tmp"),
290 os.unlink(
"/tmp/mir_socket")
302 logger.debug(
"Unity started, waiting for it to be ready.")
304 logger.debug(
"Unity loaded and ready.")
306 if model() ==
'Desktop':
309 process_helpers.stop_job(
'unity8-dash')
313 def _launch_unity_with_upstart(self, binary_path, args):
314 logger.info(
"Starting unity")
317 binary_arg =
"BINARY=%s" % binary_path
318 extra_args =
"ARGS=%s" %
" ".join(args)
319 env_args = [
"%s=%s" % (k, v)
for k, v
in self._environment.items()]
320 all_args = [binary_arg, extra_args] + env_args
324 return process_helpers.restart_unity_with_testability(*all_args)
326 def _cleanup_launching_upstart_unity(self):
327 logger.info(
"Stopping unity")
329 subprocess.check_output(
330 [
"/sbin/initctl",
"stop",
"unity8"],
331 stderr=subprocess.STDOUT
333 except subprocess.CalledProcessError:
334 logger.warning(
"Appears unity was already stopped!")
336 def _patch_data_dirs(self):
338 if data_dirs
is not None:
341 def patch_lightdm_mock(self, mock_type='single'):
343 logger.info(
"Setting up LightDM mock type '%s'", mock_type)
344 new_ld_library_path = [
345 get_default_extra_mock_libraries(),
348 if os.getenv(
'LD_LIBRARY_PATH')
is not None:
349 new_ld_library_path.append(os.getenv(
'LD_LIBRARY_PATH'))
351 new_ld_library_path =
':'.join(new_ld_library_path)
352 logger.info(
"New library path: %s", new_ld_library_path)
354 self.
_environment[
'LD_LIBRARY_PATH'] = new_ld_library_path
356 def _get_lightdm_mock_path(self, mock_type):
357 lib_path = get_mocks_library_path()
358 lightdm_mock_path = os.path.abspath(
359 os.path.join(lib_path,
"LightDM", mock_type)
362 if not os.path.exists(lightdm_mock_path):
364 "LightDM mock '%s' does not exist at path '%s'."
365 % (mock_type, lightdm_mock_path)
367 return lightdm_mock_path
369 def _set_proxy(self, proxy):
370 """Keep a copy of the proxy object, so we can use it to get common
371 parts of the shell later on.
377 def _clear_proxy(self):
380 def wait_for_unity(self):
381 greeter_content_loader = self.main_window.wait_select_single(
382 objectName=
'greeterContentLoader')
383 greeter_content_loader.progress.wait_for(1)
386 pid = process_helpers.get_job_pid(
'unity8-dash')
387 dash_proxy = introspection.get_proxy_object_for_existing_process(
391 dash_app = dash_helpers.DashApp(dash_proxy)
395 def main_window(self):
396 return self._proxy.select_single(main_window_emulator.QQuickView)
399 class DashBaseTestCase(AutopilotTestCase):
401 scenarios = ubuntu_scenarios.get_device_simulation_scenarios()
402 qml_mock_enabled =
True
406 super(DashBaseTestCase, self).setUp()
408 if is_unity7_running():
409 self.useFixture(toolkit_fixtures.HideUnity7Launcher())
411 if model() !=
'Desktop':
413 self.addCleanup(process_helpers.stop_job,
'unity8')
414 process_helpers.restart_unity_with_testability()
415 process_helpers.unlock_unity()
417 self.ensure_dash_not_running()
419 if self.qml_mock_enabled:
420 self.environment[
'QML2_IMPORT_PATH'] = (
421 get_qml_import_path_with_mock()
424 if self.should_simulate_device():
427 self.simulate_device()
429 binary_path = get_binary_path(
'unity8-dash')
430 dash_proxy = self.launch_dash(binary_path, self.environment)
432 self.dash_app = dash_helpers.DashApp(dash_proxy)
433 self.dash = self.dash_app.dash
436 def ensure_dash_not_running(self):
437 if process_helpers.is_job_running(
'unity8-dash'):
438 process_helpers.stop_job(
'unity8-dash')
440 def launch_dash(self, binary_path, variables):
442 binary_path, variables)
443 self.useFixture(launch_dash_app_fixture)
444 return launch_dash_app_fixture.application_proxy
446 def wait_for_dash(self):
447 home_scope = self.dash.get_scope_by_index(0)
452 Eventually(Equals(
True), timeout=60)
454 self.assertThat(home_scope.isCurrent, Eventually(Equals(
True)))
456 def should_simulate_device(self):
457 return (hasattr(self,
'app_width')
and hasattr(self,
'app_height')
and
458 hasattr(self,
'grid_unit_px'))
460 def simulate_device(self):
461 simulate_device_fixture = self.useFixture(
462 toolkit_fixtures.SimulateDevice(
463 self.app_width, self.app_height, self.grid_unit_px))
464 self.environment[
'GRID_UNIT_PX'] = simulate_device_fixture.grid_unit_px
465 self.environment[
'ARGS'] =
'-windowgeometry {0}x{1}'\
466 .format(simulate_device_fixture.app_width,
467 simulate_device_fixture.app_height)
def _cleanup_launching_upstart_unity
def _get_lightdm_mock_path
def _launch_unity_with_upstart
def _setup_display_details
def _geo_larger_than_display