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"
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 = self.main_window.wait_select_single(objectName=
'greeter')
379 greeter.waiting.wait_for(
False)
382 pid = process_helpers.get_job_pid(
'unity8-dash')
383 dash_proxy = introspection.get_proxy_object_for_existing_process(
387 dash_app = dash_helpers.DashApp(dash_proxy)
391 def main_window(self):
392 return self._proxy.select_single(main_window_emulator.QQuickView)
395 class DashBaseTestCase(AutopilotTestCase):
397 scenarios = ubuntu_scenarios.get_device_simulation_scenarios()
398 qml_mock_enabled =
True
404 if is_unity7_running():
405 self.useFixture(toolkit_fixtures.HideUnity7Launcher())
407 if model() !=
'Desktop':
409 self.addCleanup(process_helpers.stop_job,
'unity8')
410 process_helpers.restart_unity_with_testability()
411 process_helpers.unlock_unity()
413 self.ensure_dash_not_running()
415 if self.qml_mock_enabled:
416 self.environment[
'QML2_IMPORT_PATH'] = (
417 get_qml_import_path_with_mock()
420 if self.should_simulate_device():
423 self.simulate_device()
425 binary_path = get_binary_path(
'unity8-dash')
426 dash_proxy = self.launch_dash(binary_path, self.environment)
428 self.dash_app = dash_helpers.DashApp(dash_proxy)
429 self.dash = self.dash_app.dash
432 def ensure_dash_not_running(self):
433 if process_helpers.is_job_running(
'unity8-dash'):
434 process_helpers.stop_job(
'unity8-dash')
436 def launch_dash(self, binary_path, variables):
438 binary_path, variables)
439 self.useFixture(launch_dash_app_fixture)
440 return launch_dash_app_fixture.application_proxy
442 def wait_for_dash(self):
443 home_scope = self.dash.get_scope_by_index(0)
448 Eventually(Equals(
True), timeout=60)
450 self.assertThat(home_scope.isCurrent, Eventually(Equals(
True)))
452 def should_simulate_device(self):
453 return (hasattr(self,
'app_width')
and hasattr(self,
'app_height')
and
454 hasattr(self,
'grid_unit_px'))
456 def simulate_device(self):
457 simulate_device_fixture = self.useFixture(
458 toolkit_fixtures.SimulateDevice(
459 self.app_width, self.app_height, self.grid_unit_px))
460 self.environment[
'GRID_UNIT_PX'] = simulate_device_fixture.grid_unit_px
461 self.environment[
'ARGS'] =
'-windowgeometry {0}x{1}'\
462 .format(simulate_device_fixture.app_width,
463 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)