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())
161 if model() !=
"Desktop":
162 from autopilot.input
import _uinput
163 _uinput._touch_device = _uinput.create_touch_device()
164 self.addCleanup(_uinput._touch_device.close)
166 self.
touch = Touch.create()
169 def _setup_display_details(self):
173 def _determine_geometry(self):
174 """Use the geometry that may be supplied or use the default."""
175 width = getattr(self,
'app_width', 0)
176 height = getattr(self,
'app_height', 0)
179 if width > 0
and height > 0:
182 width = width / scale_divisor
183 height = height / scale_divisor
185 "Geometry larger than display, scaled down to: %dx%d",
189 geo_string =
"%dx%d" % (width, height)
198 def _setup_grid_size(self, scale_divisor):
199 """Use the grid size that may be supplied or use the default."""
200 if getattr(self,
'grid_unit_px', 0) == 0:
201 self.
grid_size = int(os.getenv(
'GRID_UNIT_PX'))
203 self.
grid_size = int(self.grid_unit_px / scale_divisor)
206 def _geo_larger_than_display(self, width, height):
207 should_scale = getattr(self,
'scale_geo',
True)
209 screen = Display.create()
210 screen_width = screen.get_screen_width()
211 screen_height = screen.get_screen_height()
212 return (width > screen_width)
or (height > screen_height)
216 def _get_scaled_down_geo(self, width, height):
219 divisor = divisor * 2
222 def _patch_environment(self, key, value):
223 """Wrapper for patching env for upstart environment."""
225 current_value = subprocess.check_output(
226 [
"/sbin/initctl",
"get-env",
"--global", key],
227 stderr=subprocess.STDOUT,
228 universal_newlines=
True,
230 except subprocess.CalledProcessError:
237 "%s=%s" % (key, value)
238 ], stderr=subprocess.STDOUT)
241 def _upstart_reset_env(self, key, value):
242 logger.info(
"Resetting upstart env %s to %s", key, value)
245 [
"/sbin/initctl",
"unset-env", key],
246 stderr=subprocess.STDOUT,
253 "%s=%s" % (key, value)
254 ], stderr=subprocess.STDOUT)
257 """Launch the unity shell, return a proxy object for it."""
258 binary_path = get_binary_path()
259 lib_path = get_lib_path()
262 "Lib path is '%s', binary path is '%s'",
271 get_qml_import_path_with_mock()
282 os.getenv(
'MIR_SOCKET',
283 os.path.join(os.getenv(
'XDG_RUNTIME_DIR',
"/tmp"),
288 os.unlink(
"/tmp/mir_socket")
300 logger.debug(
"Unity started, waiting for it to be ready.")
302 logger.debug(
"Unity loaded and ready.")
304 if model() ==
'Desktop':
307 process_helpers.stop_job(
'unity8-dash')
311 def _launch_unity_with_upstart(self, binary_path, args):
312 logger.info(
"Starting unity")
315 binary_arg =
"BINARY=%s" % binary_path
316 extra_args =
"ARGS=%s" %
" ".join(args)
317 env_args = [
"%s=%s" % (k, v)
for k, v
in self._environment.items()]
318 all_args = [binary_arg, extra_args] + env_args
322 return process_helpers.restart_unity_with_testability(*all_args)
324 def _cleanup_launching_upstart_unity(self):
325 logger.info(
"Stopping unity")
327 subprocess.check_output(
328 [
"/sbin/initctl",
"stop",
"unity8"],
329 stderr=subprocess.STDOUT
331 except subprocess.CalledProcessError:
332 logger.warning(
"Appears unity was already stopped!")
334 def _patch_data_dirs(self):
336 if data_dirs
is not None:
339 def patch_lightdm_mock(self):
340 logger.info(
"Setting up LightDM mock lib")
341 new_ld_library_path = [
342 get_default_extra_mock_libraries(),
345 if os.getenv(
'LD_LIBRARY_PATH')
is not None:
346 new_ld_library_path.append(os.getenv(
'LD_LIBRARY_PATH'))
348 new_ld_library_path =
':'.join(new_ld_library_path)
349 logger.info(
"New library path: %s", new_ld_library_path)
351 self.
_environment[
'LD_LIBRARY_PATH'] = new_ld_library_path
353 def _get_lightdm_mock_path(self):
354 lib_path = get_mocks_library_path()
355 lightdm_mock_path = os.path.abspath(
356 os.path.join(lib_path,
"LightDM",
"liblightdm")
359 if not os.path.exists(lightdm_mock_path):
361 "LightDM mock does not exist at path '%s'."
362 % (lightdm_mock_path)
364 return lightdm_mock_path
366 def _set_proxy(self, proxy):
367 """Keep a copy of the proxy object, so we can use it to get common
368 parts of the shell later on.
374 def _clear_proxy(self):
377 def wait_for_unity(self):
378 greeter_content_loader = self.main_window.wait_select_single(
379 objectName=
'greeterContentLoader')
380 greeter_content_loader.progress.wait_for(1)
383 pid = process_helpers.get_job_pid(
'unity8-dash')
384 dash_proxy = introspection.get_proxy_object_for_existing_process(
388 dash_app = dash_helpers.DashApp(dash_proxy)
392 def main_window(self):
393 return self._proxy.select_single(main_window_emulator.QQuickView)
396 class DashBaseTestCase(AutopilotTestCase):
398 scenarios = ubuntu_scenarios.get_device_simulation_scenarios()
399 qml_mock_enabled =
True
403 super(DashBaseTestCase, self).setUp()
405 if is_unity7_running():
406 self.useFixture(toolkit_fixtures.HideUnity7Launcher())
408 if model() !=
'Desktop':
410 self.addCleanup(process_helpers.stop_job,
'unity8')
411 process_helpers.restart_unity_with_testability()
412 process_helpers.unlock_unity()
414 self.ensure_dash_not_running()
416 if self.qml_mock_enabled:
417 self.environment[
'QML2_IMPORT_PATH'] = (
418 get_qml_import_path_with_mock()
421 if self.should_simulate_device():
424 self.simulate_device()
426 binary_path = get_binary_path(
'unity8-dash')
427 dash_proxy = self.launch_dash(binary_path, self.environment)
429 self.dash_app = dash_helpers.DashApp(dash_proxy)
430 self.dash = self.dash_app.dash
433 def ensure_dash_not_running(self):
434 if process_helpers.is_job_running(
'unity8-dash'):
435 process_helpers.stop_job(
'unity8-dash')
437 def launch_dash(self, binary_path, variables):
439 binary_path, variables)
440 self.useFixture(launch_dash_app_fixture)
441 return launch_dash_app_fixture.application_proxy
443 def wait_for_dash(self):
444 home_scope = self.dash.get_scope_by_index(0)
449 Eventually(Equals(
True), timeout=60)
451 self.assertThat(home_scope.isCurrent, Eventually(Equals(
True)))
453 def should_simulate_device(self):
454 return (hasattr(self,
'app_width')
and hasattr(self,
'app_height')
and
455 hasattr(self,
'grid_unit_px'))
457 def simulate_device(self):
458 simulate_device_fixture = self.useFixture(
459 toolkit_fixtures.SimulateDevice(
460 self.app_width, self.app_height, self.grid_unit_px))
461 self.environment[
'GRID_UNIT_PX'] = simulate_device_fixture.grid_unit_px
462 self.environment[
'ARGS'] =
'-windowgeometry {0}x{1}'\
463 .format(simulate_device_fixture.app_width,
464 simulate_device_fixture.app_height)
def launch_unity(self, kwargs)
def _patch_data_dirs(self)
def _set_proxy(self, proxy)
def _geo_larger_than_display(self, width, height)
def _cleanup_launching_upstart_unity(self)
def patch_lightdm_mock(self)
def _setup_grid_size(self, scale_divisor)
def _get_lightdm_mock_path(self)
def _setup_display_details(self)
def _patch_environment(self, key, value)
def _upstart_reset_env(self, key, value)
def _determine_geometry(self)
def _launch_unity_with_upstart(self, binary_path, args)
def _get_scaled_down_geo(self, width, height)