20 """unity autopilot tests."""
23 from gi.repository
import Gio
27 from autopilot.platform
import model
28 from autopilot.testcase
import AutopilotTestCase
29 from autopilot.matchers
import Eventually
30 from autopilot.input
import Touch
31 from autopilot.display
import Display
36 from testtools.matchers
import Equals
41 get_mocks_library_path,
42 get_default_extra_mock_libraries,
50 logger = logging.getLogger(__name__)
52 UNITYSHELL_GSETTINGS_SCHEMA =
"org.compiz.unityshell"
53 UNITYSHELL_GSETTINGS_PATH =
"/org/compiz/profiles/unity/plugins/unityshell/"
54 UNITYSHELL_LAUNCHER_KEY =
"launcher-hide-mode"
55 UNITYSHELL_LAUNCHER_MODE = 1
58 def _get_device_emulation_scenarios(devices='All'):
59 nexus4 = (
'Desktop Nexus 4',
60 dict(app_width=768, app_height=1280, grid_unit_px=18))
61 nexus10 = (
'Desktop Nexus 10',
62 dict(app_width=2560, app_height=1600, grid_unit_px=20))
63 native = (
'Native Device',
64 dict(app_width=0, app_height=0, grid_unit_px=0))
66 if model() ==
'Desktop':
68 return [nexus4, nexus10]
69 elif devices ==
'Nexus4':
71 elif devices ==
'Nexus10':
75 'Unrecognized device-option "%s" passed.' % devices
83 """A test case base class for the Unity shell tests."""
88 output = subprocess.check_output(
89 [
"/sbin/initctl",
"status",
"unity8"],
90 stderr=subprocess.STDOUT,
91 universal_newlines=
True,
93 except subprocess.CalledProcessError
as e:
95 "Error: `initctl status unity8` failed, most probably the "
96 "unity8 session could not be found:\n\n"
98 "Please install unity8 or copy data/unity8.conf to "
101 os.path.join(os.getenv(
"XDG_CONFIG_HOME",
102 os.path.join(os.getenv(
"HOME"),
110 if "start/" in output:
112 "Error: Unity is currently running, these tests require it to "
114 "Please run this command before running these tests: \n"
115 "initctl stop unity8\n"
120 super(UnityTestCase, self).setUp()
121 if (Gio
is not None and
122 UNITYSHELL_GSETTINGS_SCHEMA
in
123 Gio.Settings.list_relocatable_schemas()):
127 UNITYSHELL_GSETTINGS_SCHEMA,
128 UNITYSHELL_GSETTINGS_PATH,
131 UNITYSHELL_LAUNCHER_KEY,
133 self._unityshell_schema.set_int(
134 UNITYSHELL_LAUNCHER_KEY,
135 UNITYSHELL_LAUNCHER_MODE,
146 if model() !=
"Desktop":
147 from autopilot.input
import _uinput
148 _uinput._touch_device = _uinput.create_touch_device()
149 self.addCleanup(_uinput._touch_device.close)
152 self.
touch = Touch.create()
155 def _reset_launcher(self):
156 """Reset Unity launcher hide mode"""
157 self._unityshell_schema.set_int(
158 UNITYSHELL_LAUNCHER_KEY,
162 def _setup_display_details(self):
166 def _determine_geometry(self):
167 """Use the geometry that may be supplied or use the default."""
168 width = getattr(self,
'app_width', 0)
169 height = getattr(self,
'app_height', 0)
172 if width > 0
and height > 0:
175 width = width / scale_divisor
176 height = height / scale_divisor
178 "Geometry larger than display, scaled down to: %dx%d",
182 geo_string =
"%dx%d" % (width, height)
191 def _setup_grid_size(self, scale_divisor):
192 """Use the grid size that may be supplied or use the default."""
193 if getattr(self,
'grid_unit_px', 0) == 0:
194 self.
grid_size = int(os.getenv(
'GRID_UNIT_PX'))
196 self.
grid_size = int(self.grid_unit_px / scale_divisor)
200 self.patch_environment(
"GRID_UNIT_PX", str(self.
grid_size))
202 def _geo_larger_than_display(self, width, height):
203 should_scale = getattr(self,
'scale_geo',
True)
205 screen = Display.create()
206 screen_width = screen.get_screen_width()
207 screen_height = screen.get_screen_height()
208 return (width > screen_width)
or (height > screen_height)
212 def _get_scaled_down_geo(self, width, height):
215 divisor = divisor * 2
218 def _patch_environment(self, key, value):
219 """Wrapper for patching env for upstart environment."""
221 current_value = subprocess.check_output(
222 [
"/sbin/initctl",
"get-env",
"--global", key],
223 stderr=subprocess.STDOUT,
224 universal_newlines=
True,
226 except subprocess.CalledProcessError:
233 "%s=%s" % (key, value)
234 ], stderr=subprocess.STDOUT)
237 def _upstart_reset_env(self, key, value):
238 logger.info(
"Resetting upstart env %s to %s", key, value)
241 [
"/sbin/initctl",
"unset-env", key],
242 stderr=subprocess.STDOUT,
249 "%s=%s" % (key, value)
250 ], stderr=subprocess.STDOUT)
253 """Launch the unity shell, return a proxy object for it."""
254 binary_path = get_binary_path()
255 lib_path = get_lib_path()
258 "Lib path is '%s', binary path is '%s'",
277 os.getenv(
'MIR_SOCKET',
278 os.path.join(os.getenv(
'XDG_RUNTIME_DIR',
"/tmp"),
283 os.unlink(
"/tmp/mir_socket")
295 logger.debug(
"Unity started, waiting for it to be ready.")
297 logger.debug(
"Unity loaded and ready.")
301 def _launch_unity_with_upstart(self, binary_path, args):
302 logger.info(
"Starting unity")
305 binary_arg =
"BINARY=%s" % binary_path
306 extra_args =
"ARGS=%s" %
" ".join(args)
307 env_args = [
"%s=%s" % (k, v)
for k, v
in self._environment.items()]
308 all_args = [binary_arg, extra_args] + env_args
312 return restart_unity_with_testability(*all_args)
314 def _cleanup_launching_upstart_unity(self):
315 logger.info(
"Stopping unity")
317 subprocess.check_output(
318 [
"/sbin/initctl",
"stop",
"unity8"],
319 stderr=subprocess.STDOUT
321 except subprocess.CalledProcessError:
322 logger.warning(
"Appears unity was already stopped!")
324 def _patch_data_dirs(self):
326 if data_dirs
is not None:
329 def patch_lightdm_mock(self, mock_type='single'):
331 logger.info(
"Setting up LightDM mock type '%s'", mock_type)
332 new_ld_library_path = [
333 get_default_extra_mock_libraries(),
336 if os.getenv(
'LD_LIBRARY_PATH')
is not None:
337 new_ld_library_path.append(os.getenv(
'LD_LIBRARY_PATH'))
339 new_ld_library_path =
':'.join(new_ld_library_path)
340 logger.info(
"New library path: %s", new_ld_library_path)
342 self.
_environment[
'LD_LIBRARY_PATH'] = new_ld_library_path
344 def _get_lightdm_mock_path(self, mock_type):
345 lib_path = get_mocks_library_path()
346 lightdm_mock_path = os.path.abspath(
347 os.path.join(lib_path,
"LightDM", mock_type)
350 if not os.path.exists(lightdm_mock_path):
352 "LightDM mock '%s' does not exist at path '%s'."
353 % (mock_type, lightdm_mock_path)
355 return lightdm_mock_path
357 def _setup_extra_mock_environment_patch(self):
358 qml_import_path = [get_mocks_library_path()]
359 if os.getenv(
'QML2_IMPORT_PATH')
is not None:
360 qml_import_path.append(os.getenv(
'QML2_IMPORT_PATH'))
362 qml_import_path =
':'.join(qml_import_path)
363 logger.info(
"New QML2 import path: %s", qml_import_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 assertUnityReady(self):
379 home_scope = dash.get_scope(
'clickscope')
385 Eventually(Equals(
True), timeout=60)
387 self.assertThat(home_scope.isCurrent, Eventually(Equals(
True)))
390 dash = self._proxy.wait_select_single(Dash)
394 def main_window(self):
395 return self._proxy.select_single(main_window_emulator.QQuickView)
def _cleanup_launching_upstart_unity
def _get_lightdm_mock_path
def _launch_unity_with_upstart
def _setup_extra_mock_environment_patch
def _setup_display_details
def _geo_larger_than_display