Status: | Merged |
---|---|
Approved by: | Santiago Baldassin |
Approved revision: | 592 |
Merged at revision: | 584 |
Proposed branch: | lp:autopilot |
Merge into: | lp:autopilot/1.6 |
Diff against target: |
745 lines (+125/-263) 17 files modified
README (+6/-0) autopilot/application/_launcher.py (+20/-14) autopilot/display/__init__.py (+6/-45) autopilot/display/_upa.py (+45/-27) autopilot/input/__init__.py (+7/-13) autopilot/introspection/types.py (+1/-0) autopilot/introspection/utilities.py (+1/-0) autopilot/platform.py (+2/-21) autopilot/process/__init__.py (+0/-4) autopilot/run.py (+1/-0) autopilot/testcase.py (+8/-7) autopilot/tests/unit/introspection_base.py (+1/-0) autopilot/tests/unit/test_application_launcher.py (+18/-21) autopilot/tests/unit/test_platform.py (+0/-22) autopilot/tests/unit/test_query_resolution.py (+0/-82) autopilot/utilities.py (+2/-0) debian/control (+7/-7) |
To merge this branch: | bzr merge lp:autopilot |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Autopilot Hackers | Pending | ||
Review via email: mp+318824@code.launchpad.net |
Commit message
New upstream release.
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'README' |
2 | --- README 2016-08-04 05:32:39 +0000 |
3 | +++ README 2017-03-02 18:46:50 +0000 |
4 | @@ -72,6 +72,12 @@ |
5 | If you are in the root of the autopilot source tree this will run/list the tests from |
6 | within that local module. Otherwise autopilot will look in the system python path. |
7 | |
8 | +Release Autopilot |
9 | +================= |
10 | +1. Open a new request on bileto: https://bileto.ubuntu.com/ with the lp:autopilot -> lp:autopilot/1.5 merge proposal |
11 | +2. Add the relevant details (i.e. bug fix details in the landing description and a link to the testplan: https://wiki.ubuntu.com/Process/Merges/TestPlan/autopilot) |
12 | +3. Build the silo and run the tests |
13 | +4. Once happy with all tests approve and publish the result |
14 | |
15 | Release Manual Tests |
16 | ==================== |
17 | |
18 | === modified file 'autopilot/application/_launcher.py' |
19 | --- autopilot/application/_launcher.py 2015-12-08 21:42:14 +0000 |
20 | +++ autopilot/application/_launcher.py 2017-03-02 18:46:50 +0000 |
21 | @@ -1,7 +1,7 @@ |
22 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
23 | # |
24 | # Autopilot Functional Test Tool |
25 | -# Copyright (C) 2013 Canonical |
26 | +# Copyright (C) 2013,2017 Canonical |
27 | # |
28 | # This program is free software: you can redistribute it and/or modify |
29 | # it under the terms of the GNU General Public License as published by |
30 | @@ -20,21 +20,20 @@ |
31 | """Base module for application launchers.""" |
32 | |
33 | import fixtures |
34 | -from gi.repository import GLib |
35 | +from gi import require_version |
36 | try: |
37 | - from gi import require_version |
38 | + require_version('UbuntuAppLaunch', '3') |
39 | +except ValueError: |
40 | require_version('UbuntuAppLaunch', '2') |
41 | - from gi.repository import UbuntuAppLaunch |
42 | -except ImportError: |
43 | - # Note: the renamed package is not in Trusty. |
44 | - from gi.repository import UpstartAppLaunch as UbuntuAppLaunch |
45 | +from gi.repository import GLib, UbuntuAppLaunch |
46 | + |
47 | import json |
48 | import logging |
49 | import os |
50 | import psutil |
51 | import subprocess |
52 | import signal |
53 | -from testtools.content import content_from_file |
54 | +from systemd import journal |
55 | from autopilot.utilities import safe_text_content |
56 | |
57 | from autopilot._timeout import Timeout |
58 | @@ -186,13 +185,20 @@ |
59 | self.addCleanup(self._stop_application, app_id) |
60 | self.addCleanup(self._attach_application_log, app_id) |
61 | |
62 | + @staticmethod |
63 | + def _get_user_unit_match(app_id): |
64 | + return 'ubuntu-app-launch-*-%s-*.service' % app_id |
65 | + |
66 | def _attach_application_log(self, app_id): |
67 | - log_path = UbuntuAppLaunch.application_log_path(app_id) |
68 | - if log_path and os.path.exists(log_path): |
69 | - self.caseAddDetail( |
70 | - "Application Log (%s)" % app_id, |
71 | - content_from_file(log_path) |
72 | - ) |
73 | + j = journal.Reader() |
74 | + j.log_level(journal.LOG_INFO) |
75 | + j.add_match(_SYSTEMD_USER_UNIT=self._get_user_unit_match(app_id)) |
76 | + log_data = '' |
77 | + for i in j: |
78 | + log_data += str(i) + '\n' |
79 | + if len(log_data) > 0: |
80 | + self.caseAddDetail('Application Log (%s)' % app_id, |
81 | + safe_text_content(log_data)) |
82 | |
83 | def _stop_application(self, app_id): |
84 | state = {} |
85 | |
86 | === modified file 'autopilot/display/__init__.py' |
87 | --- autopilot/display/__init__.py 2014-07-09 00:21:04 +0000 |
88 | +++ autopilot/display/__init__.py 2017-03-02 18:46:50 +0000 |
89 | @@ -40,9 +40,9 @@ |
90 | def is_rect_on_screen(screen_number, rect): |
91 | """Return True if *rect* is **entirely** on the specified screen, with no |
92 | overlap.""" |
93 | - (x, y, w, h) = rect |
94 | - (mx, my, mw, mh) = Display.create().get_screen_geometry(screen_number) |
95 | - return (x >= mx and x + w <= mx + mw and y >= my and y + h <= my + mh) |
96 | + x, y, w, h = rect |
97 | + mx, my, mw, mh = Display.create().get_screen_geometry(screen_number) |
98 | + return x >= mx and x + w <= mx + mw and y >= my and y + h <= my + mh |
99 | |
100 | |
101 | def is_point_on_screen(screen_number, point): |
102 | @@ -52,8 +52,8 @@ |
103 | |
104 | """ |
105 | x, y = point |
106 | - (mx, my, mw, mh) = Display.create().get_screen_geometry(screen_number) |
107 | - return (x >= mx and x < mx + mw and y >= my and y < my + mh) |
108 | + mx, my, mw, mh = Display.create().get_screen_geometry(screen_number) |
109 | + return mx <= x < mx + mw and my <= y < my + mh |
110 | |
111 | |
112 | def is_point_on_any_screen(point): |
113 | @@ -71,45 +71,6 @@ |
114 | Mouse.create().move(x, y, False) |
115 | |
116 | |
117 | -# veebers TODO: Write this so it's usable. |
118 | -# def drag_window_to_screen(self, window, screen): |
119 | -# """Drags *window* to *screen* |
120 | - |
121 | -# :param BamfWindow window: The window to drag |
122 | -# :param integer screen: The screen to drag the *window* to |
123 | -# :raises: **TypeError** if *window* is not a BamfWindow |
124 | - |
125 | -# """ |
126 | -# if not isinstance(window, BamfWindow): |
127 | -# raise TypeError("Window must be a BamfWindow") |
128 | - |
129 | -# if window.monitor == screen: |
130 | -# logger.debug( |
131 | -# "Window %r is already on screen %d." % (window.x_id, screen)) |
132 | -# return |
133 | - |
134 | -# assert(not window.is_maximized) |
135 | -# (win_x, win_y, win_w, win_h) = window.geometry |
136 | -# (mx, my, mw, mh) = self.get_screen_geometry(screen) |
137 | - |
138 | -# logger.debug("Dragging window %r to screen %d." % (window.x_id, screen)) |
139 | - |
140 | -# mouse = Mouse() |
141 | -# keyboard = Keyboard() |
142 | -# mouse.move(win_x + win_w/2, win_y + win_h/2) |
143 | -# keyboard.press("Alt") |
144 | -# mouse.press() |
145 | -# keyboard.release("Alt") |
146 | - |
147 | -# # We do the movements in two steps, to reduce the risk of being |
148 | -# # blocked by the pointer barrier |
149 | -# target_x = mx + mw/2 |
150 | -# target_y = my + mh/2 |
151 | -# mouse.move(win_x, target_y, rate=20, time_between_events=0.005) |
152 | -# mouse.move(target_x, target_y, rate=20, time_between_events=0.005) |
153 | -# mouse.release() |
154 | - |
155 | - |
156 | class Display(object): |
157 | |
158 | """The base class/inteface for the display devices.""" |
159 | @@ -146,8 +107,8 @@ |
160 | return Display() |
161 | |
162 | backends = OrderedDict() |
163 | + backends['UPA'] = get_upa_display |
164 | backends['X11'] = get_x11_display |
165 | - backends['UPA'] = get_upa_display |
166 | return _pick_backend(backends, preferred_backend) |
167 | |
168 | class BlacklistedDriverError(RuntimeError): |
169 | |
170 | === modified file 'autopilot/display/_upa.py' |
171 | --- autopilot/display/_upa.py 2014-03-25 14:42:25 +0000 |
172 | +++ autopilot/display/_upa.py 2017-03-02 18:46:50 +0000 |
173 | @@ -17,44 +17,33 @@ |
174 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
175 | # |
176 | |
177 | +import os |
178 | +import subprocess |
179 | |
180 | from autopilot.display import Display as DisplayBase |
181 | -from autopilot.platform import image_codename |
182 | -import subprocess |
183 | +from autopilot.platform import get_display_server, image_codename |
184 | + |
185 | +DISPLAY_SERVER_X11 = 'X11' |
186 | +DISPLAY_SERVER_MIR = 'MIR' |
187 | +ENV_MIR_SOCKET = 'MIR_SERVER_HOST_SOCKET' |
188 | |
189 | |
190 | def query_resolution(): |
191 | - try: |
192 | - return _get_fbset_resolution() |
193 | - except Exception: |
194 | + display_server = get_display_server() |
195 | + if display_server == DISPLAY_SERVER_X11: |
196 | + return _get_resolution_from_xrandr() |
197 | + elif display_server == DISPLAY_SERVER_MIR: |
198 | + return _get_resolution_from_mirout() |
199 | + else: |
200 | return _get_hardcoded_resolution() |
201 | |
202 | |
203 | -def _get_fbset_resolution(): |
204 | - """Return the resolution, as determined by fbset, or None.""" |
205 | - fbset_output = _get_fbset_output() |
206 | - for line in fbset_output.split('\n'): |
207 | - line = line.strip() |
208 | - if line.startswith('Mode'): |
209 | - quoted_resolution = line.split()[1] |
210 | - resolution_string = quoted_resolution.strip('"') |
211 | - return tuple(int(piece) for piece in resolution_string.split('x')) |
212 | - raise RuntimeError("No modes found from fbset output") |
213 | - |
214 | - |
215 | -def _get_fbset_output(): |
216 | - return subprocess.check_output(["fbset", "-s", "-x"]).decode().strip() |
217 | - |
218 | - |
219 | def _get_hardcoded_resolution(): |
220 | name = image_codename() |
221 | |
222 | resolutions = { |
223 | - "generic": (480, 800), |
224 | - "mako": (768, 1280), |
225 | - "maguro": (720, 1280), |
226 | - "manta": (2560, 1600), |
227 | - "grouper": (800, 1280), |
228 | + "Aquaris_M10_HD": (800, 1280), |
229 | + "Desktop": (1920, 1080) |
230 | } |
231 | |
232 | if name not in resolutions: |
233 | @@ -64,6 +53,35 @@ |
234 | return resolutions[name] |
235 | |
236 | |
237 | +def _get_stdout_for_command(command, *args): |
238 | + full_command = [command] |
239 | + full_command.extend(args) |
240 | + return subprocess.check_output( |
241 | + full_command, |
242 | + universal_newlines=True, |
243 | + stderr=subprocess.DEVNULL, |
244 | + ).split('\n') |
245 | + |
246 | + |
247 | +def _get_resolution(server_output): |
248 | + relevant_line = list(filter(lambda line: '*' in line, server_output))[0] |
249 | + if relevant_line: |
250 | + return tuple([int(i) for i in relevant_line.split()[0].split('x')]) |
251 | + raise ValueError( |
252 | + 'Failed to get display resolution, is a display connected?' |
253 | + ) |
254 | + |
255 | + |
256 | +def _get_resolution_from_xrandr(): |
257 | + return _get_resolution(_get_stdout_for_command('xrandr', '--current')) |
258 | + |
259 | + |
260 | +def _get_resolution_from_mirout(): |
261 | + return _get_resolution( |
262 | + _get_stdout_for_command('mirout', os.environ.get(ENV_MIR_SOCKET)) |
263 | + ) |
264 | + |
265 | + |
266 | class Display(DisplayBase): |
267 | """The base class/inteface for the display devices""" |
268 | |
269 | @@ -91,4 +109,4 @@ |
270 | :return: Tuple containing (x, y, width, height). |
271 | |
272 | """ |
273 | - return (0, 0, self._X, self._Y) |
274 | + return 0, 0, self._X, self._Y |
275 | |
276 | === modified file 'autopilot/input/__init__.py' |
277 | --- autopilot/input/__init__.py 2016-01-08 09:35:07 +0000 |
278 | +++ autopilot/input/__init__.py 2017-03-02 18:46:50 +0000 |
279 | @@ -126,9 +126,9 @@ |
280 | raise |
281 | |
282 | backends = OrderedDict() |
283 | - backends['X11'] = get_x11_kb |
284 | backends['UInput'] = get_uinput_kb |
285 | backends['OSK'] = get_osk_kb |
286 | + backends['X11'] = get_x11_kb |
287 | return _pick_backend(backends, preferred_backend) |
288 | |
289 | @contextmanager |
290 | @@ -283,21 +283,15 @@ |
291 | from autopilot.input._X11 import Mouse |
292 | return Mouse() |
293 | |
294 | - from autopilot.platform import model |
295 | - if model() != 'Desktop': |
296 | - _logger.info( |
297 | - "You cannot create a Mouse on the devices where X11 is not " |
298 | - "available. consider using a Touch or Pointer device. " |
299 | - "For more information, see: " |
300 | - "http://unity.ubuntu.com/autopilot/api/input.html" |
301 | - "#autopilot-unified-input-system" |
302 | - ) |
303 | - raise RuntimeError( |
304 | - "Cannot create a Mouse on devices where X11 is not available." |
305 | - ) |
306 | + def get_uinput_mouse(): |
307 | + # Return the Touch device for now as Mouse under a Mir desktop |
308 | + # is a challenge for now. |
309 | + from autopilot.input._uinput import Touch |
310 | + return Touch() |
311 | |
312 | backends = OrderedDict() |
313 | backends['X11'] = get_x11_mouse |
314 | + backends['UInput'] = get_uinput_mouse |
315 | return _pick_backend(backends, preferred_backend) |
316 | |
317 | @property |
318 | |
319 | === modified file 'autopilot/introspection/types.py' |
320 | --- autopilot/introspection/types.py 2015-12-08 01:07:10 +0000 |
321 | +++ autopilot/introspection/types.py 2017-03-02 18:46:50 +0000 |
322 | @@ -255,6 +255,7 @@ |
323 | def _create_generic_repr(target_type): |
324 | return compatible_repr(lambda self: repr(target_type(self))) |
325 | |
326 | + |
327 | _bytes_repr = _create_generic_repr(bytes) |
328 | _text_repr = _create_generic_repr(str) |
329 | _dict_repr = _create_generic_repr(dict) |
330 | |
331 | === modified file 'autopilot/introspection/utilities.py' |
332 | --- autopilot/introspection/utilities.py 2016-07-14 08:18:20 +0000 |
333 | +++ autopilot/introspection/utilities.py 2017-03-02 18:46:50 +0000 |
334 | @@ -138,4 +138,5 @@ |
335 | """ |
336 | return self._query_pids_for_process(process_name) |
337 | |
338 | + |
339 | process_util = ProcessUtil() |
340 | |
341 | === modified file 'autopilot/platform.py' |
342 | --- autopilot/platform.py 2014-07-23 01:59:47 +0000 |
343 | +++ autopilot/platform.py 2017-03-02 18:46:50 +0000 |
344 | @@ -19,8 +19,6 @@ |
345 | |
346 | |
347 | import os |
348 | -import psutil |
349 | -from functools import lru_cache |
350 | |
351 | """ |
352 | Platform identification utilities for Autopilot. |
353 | @@ -143,27 +141,10 @@ |
354 | def get_display_server(): |
355 | """Returns display server type. |
356 | |
357 | - :returns: string indicating display server type. Either "X11", "MIR" or |
358 | - "UNKNOWN" |
359 | + :returns: string indicating display server type. |
360 | |
361 | """ |
362 | - if _display_is_x11(): |
363 | - return "X11" |
364 | - elif _display_is_mir(): |
365 | - return "MIR" |
366 | - else: |
367 | - return "UNKNOWN" |
368 | - |
369 | - |
370 | -def _display_is_x11(): |
371 | - return 'DISPLAY' in os.environ |
372 | - |
373 | - |
374 | -@lru_cache() |
375 | -def _display_is_mir(): |
376 | - return "unity-system-compositor" in [ |
377 | - _get_process_name(p.name) for p in psutil.process_iter() |
378 | - ] |
379 | + return os.environ.get('XDG_SESSION_TYPE', 'UNKNOWN').upper() |
380 | |
381 | |
382 | # Different vers. of psutil across Trusty and Utopic have name as either a |
383 | |
384 | === modified file 'autopilot/process/__init__.py' |
385 | --- autopilot/process/__init__.py 2015-05-04 06:28:37 +0000 |
386 | +++ autopilot/process/__init__.py 2017-03-02 18:46:50 +0000 |
387 | @@ -89,10 +89,6 @@ |
388 | from autopilot.process._bamf import ProcessManager |
389 | return ProcessManager() |
390 | |
391 | - def get_upa_pm(): |
392 | - from autopilot.process._upa import ProcessManager |
393 | - return ProcessManager() |
394 | - |
395 | backends = OrderedDict() |
396 | backends['BAMF'] = get_bamf_pm |
397 | return _pick_backend(backends, preferred_backend) |
398 | |
399 | === modified file 'autopilot/run.py' |
400 | --- autopilot/run.py 2015-08-19 00:25:00 +0000 |
401 | +++ autopilot/run.py 2017-03-02 18:46:50 +0000 |
402 | @@ -749,5 +749,6 @@ |
403 | print(e) |
404 | exit(1) |
405 | |
406 | + |
407 | if __name__ == "__main__": |
408 | main() |
409 | |
410 | === modified file 'autopilot/testcase.py' |
411 | --- autopilot/testcase.py 2015-09-02 03:25:43 +0000 |
412 | +++ autopilot/testcase.py 2017-03-02 18:46:50 +0000 |
413 | @@ -173,13 +173,14 @@ |
414 | # Work around for bug lp:1297592. |
415 | _ensure_uinput_device_created() |
416 | |
417 | - try: |
418 | - self._app_snapshot = _get_process_snapshot() |
419 | - self.addCleanup(self._compare_system_with_app_snapshot) |
420 | - except RuntimeError: |
421 | - _logger.warning( |
422 | - "Process manager backend unavailable, application snapshot " |
423 | - "support disabled.") |
424 | + if get_display_server() == 'X11': |
425 | + try: |
426 | + self._app_snapshot = _get_process_snapshot() |
427 | + self.addCleanup(self._compare_system_with_app_snapshot) |
428 | + except RuntimeError: |
429 | + _logger.warning( |
430 | + "Process manager backend unavailable, application " |
431 | + "snapshot support disabled.") |
432 | |
433 | self.addOnException(self._take_screenshot_on_failure) |
434 | |
435 | |
436 | === modified file 'autopilot/tests/unit/introspection_base.py' |
437 | --- autopilot/tests/unit/introspection_base.py 2016-07-19 14:24:10 +0000 |
438 | +++ autopilot/tests/unit/introspection_base.py 2017-03-02 18:46:50 +0000 |
439 | @@ -38,6 +38,7 @@ |
440 | def get_properties(self): |
441 | return self.__dict__ |
442 | |
443 | + |
444 | get_mock_object = MockObject |
445 | |
446 | |
447 | |
448 | === modified file 'autopilot/tests/unit/test_application_launcher.py' |
449 | --- autopilot/tests/unit/test_application_launcher.py 2014-07-22 02:30:19 +0000 |
450 | +++ autopilot/tests/unit/test_application_launcher.py 2017-03-02 18:46:50 +0000 |
451 | @@ -1,7 +1,7 @@ |
452 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
453 | # |
454 | # Autopilot Functional Test Tool |
455 | -# Copyright (C) 2013 Canonical |
456 | +# Copyright (C) 2013,2017 Canonical |
457 | # |
458 | # This program is free software: you can redistribute it and/or modify |
459 | # it under the terms of the GNU General Public License as published by |
460 | @@ -33,8 +33,7 @@ |
461 | raises, |
462 | ) |
463 | from testtools.content import text_content |
464 | -import tempfile |
465 | -from unittest.mock import Mock, patch |
466 | +from unittest.mock import MagicMock, Mock, patch |
467 | |
468 | from autopilot.application import ( |
469 | ClickApplicationLauncher, |
470 | @@ -782,32 +781,30 @@ |
471 | app_id = self.getUniqueString() |
472 | case_addDetail = Mock() |
473 | launcher = UpstartApplicationLauncher(case_addDetail) |
474 | - with patch.object(_l.UbuntuAppLaunch, 'application_log_path') as p: |
475 | - p.return_value = None |
476 | + j = MagicMock(spec=_l.journal.Reader) |
477 | + with patch.object(_l.journal, 'Reader', return_value=j): |
478 | launcher._attach_application_log(app_id) |
479 | - |
480 | - p.assert_called_once_with(app_id) |
481 | + expected = launcher._get_user_unit_match(app_id) |
482 | + j.add_match.assert_called_once_with(_SYSTEMD_USER_UNIT=expected) |
483 | self.assertEqual(0, case_addDetail.call_count) |
484 | |
485 | - def test_attach_application_log_attaches_log_file(self): |
486 | + def test_attach_application_log_attaches_log(self): |
487 | token = self.getUniqueString() |
488 | case_addDetail = Mock() |
489 | launcher = UpstartApplicationLauncher(case_addDetail) |
490 | app_id = self.getUniqueString() |
491 | - with tempfile.NamedTemporaryFile(mode='w') as f: |
492 | - f.write(token) |
493 | - f.flush() |
494 | - with patch.object(_l.UbuntuAppLaunch, 'application_log_path', |
495 | - return_value=f.name): |
496 | - launcher._attach_application_log(app_id) |
497 | + j = MagicMock(spec=_l.journal.Reader) |
498 | + j.__iter__ = lambda x: iter([token]) |
499 | + with patch.object(_l.journal, 'Reader', return_value=j): |
500 | + launcher._attach_application_log(app_id) |
501 | |
502 | - self.assertEqual(1, case_addDetail.call_count) |
503 | - content_name, content_obj = case_addDetail.call_args[0] |
504 | - self.assertEqual( |
505 | - "Application Log (%s)" % app_id, |
506 | - content_name |
507 | - ) |
508 | - self.assertThat(content_obj.as_text(), Contains(token)) |
509 | + self.assertEqual(1, case_addDetail.call_count) |
510 | + content_name, content_obj = case_addDetail.call_args[0] |
511 | + self.assertEqual( |
512 | + "Application Log (%s)" % app_id, |
513 | + content_name |
514 | + ) |
515 | + self.assertThat(content_obj.as_text(), Contains(token)) |
516 | |
517 | def test_stop_adds_app_stopped_observer(self): |
518 | mock_add_detail = Mock() |
519 | |
520 | === modified file 'autopilot/tests/unit/test_platform.py' |
521 | --- autopilot/tests/unit/test_platform.py 2015-12-08 00:48:04 +0000 |
522 | +++ autopilot/tests/unit/test_platform.py 2017-03-02 18:46:50 +0000 |
523 | @@ -20,7 +20,6 @@ |
524 | """Tests for the autopilot platform code.""" |
525 | |
526 | |
527 | -from contextlib import contextmanager |
528 | from io import StringIO |
529 | from testtools import TestCase |
530 | from testtools.matchers import Equals |
531 | @@ -34,7 +33,6 @@ |
532 | |
533 | def setUp(self): |
534 | super().setUp() |
535 | - platform._display_is_mir.cache_clear() |
536 | |
537 | @patch('autopilot.platform._PlatformDetector') |
538 | def test_model_creates_platform_detector(self, mock_detector): |
539 | @@ -56,14 +54,6 @@ |
540 | mock_detector.image_codename = "test123" |
541 | self.assertThat(platform.image_codename(), Equals('test123')) |
542 | |
543 | - def test_is_x11_returns_False_on_failure(self): |
544 | - with _simulate_not_X11(): |
545 | - self.assertFalse(platform._display_is_x11()) |
546 | - |
547 | - def test_is_x11_returns_True_on_success(self): |
548 | - with _simulate_X11(): |
549 | - self.assertTrue(platform._display_is_x11()) |
550 | - |
551 | |
552 | class PlatformGetProcessNameTests(TestCase): |
553 | |
554 | @@ -247,15 +237,3 @@ |
555 | prop_file = StringIO("ro.product.model=maguro") |
556 | properties = platform._parse_build_properties_file(prop_file) |
557 | self.assertThat(properties, Equals({'ro.product.model': 'maguro'})) |
558 | - |
559 | - |
560 | -@contextmanager |
561 | -def _simulate_not_X11(): |
562 | - with patch.dict(platform.os.environ, dict(), clear=True): |
563 | - yield |
564 | - |
565 | - |
566 | -@contextmanager |
567 | -def _simulate_X11(): |
568 | - with patch.dict(platform.os.environ, dict(DISPLAY=':0'), clear=True): |
569 | - yield |
570 | |
571 | === modified file 'autopilot/tests/unit/test_query_resolution.py' |
572 | --- autopilot/tests/unit/test_query_resolution.py 2014-05-20 08:53:21 +0000 |
573 | +++ autopilot/tests/unit/test_query_resolution.py 2017-03-02 18:46:50 +0000 |
574 | @@ -16,85 +16,3 @@ |
575 | # You should have received a copy of the GNU General Public License |
576 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
577 | # |
578 | - |
579 | -from testtools import TestCase |
580 | -from testtools.matchers import raises |
581 | -from testscenarios import WithScenarios |
582 | -from textwrap import dedent |
583 | -from unittest.mock import patch |
584 | - |
585 | -from autopilot.display import _upa as upa |
586 | - |
587 | - |
588 | -class QueryResolutionFunctionTests(TestCase): |
589 | - |
590 | - @patch('subprocess.check_output', return_value=b'') |
591 | - def test_fbset_output_calls_subprocess(self, patched_check_output): |
592 | - upa._get_fbset_output() |
593 | - patched_check_output.assert_called_once_with( |
594 | - ["fbset", "-s", "-x"] |
595 | - ) |
596 | - |
597 | - def test_get_fbset_resolution(self): |
598 | - patched_fbset_resolution = dedent( |
599 | - ''' |
600 | - Mode "768x1280" |
601 | - # D: 0.002 MHz, H: 0.002 kHz, V: 0.002 Hz |
602 | - DotClock 0.003 |
603 | - HTimings 768 776 780 960 |
604 | - VTimings 1280 1288 1290 1312 |
605 | - Flags "-HSync" "-VSync" |
606 | - EndMode |
607 | - ''' |
608 | - ) |
609 | - with patch.object(upa, '_get_fbset_output') as patched_gfo: |
610 | - patched_gfo.return_value = patched_fbset_resolution |
611 | - observed = upa._get_fbset_resolution() |
612 | - self.assertEqual((768, 1280), observed) |
613 | - |
614 | - def test_get_fbset_resolution_raises_runtimeError(self): |
615 | - patched_fbset_resolution = 'something went wrong!' |
616 | - with patch.object(upa, '_get_fbset_output') as patched_gfo: |
617 | - patched_gfo.return_value = patched_fbset_resolution |
618 | - self.assertThat( |
619 | - upa._get_fbset_resolution, |
620 | - raises(RuntimeError), |
621 | - ) |
622 | - |
623 | - def test_hardcoded_raises_error_on_unknown_model(self): |
624 | - with patch.object(upa, 'image_codename', return_value="unknown"): |
625 | - self.assertThat( |
626 | - upa._get_hardcoded_resolution, |
627 | - raises( |
628 | - NotImplementedError( |
629 | - 'Device "unknown" is not supported by Autopilot.' |
630 | - ) |
631 | - ) |
632 | - ) |
633 | - |
634 | - def test_query_resolution_uses_fbset_first(self): |
635 | - with patch.object(upa, '_get_fbset_resolution', return_value=(1, 2)): |
636 | - self.assertEqual((1, 2), upa.query_resolution()) |
637 | - |
638 | - def test_query_resolution_uses_hardcoded_second(self): |
639 | - with patch.object(upa, '_get_fbset_resolution', side_effect=Exception): |
640 | - with patch.object( |
641 | - upa, '_get_hardcoded_resolution', return_value=(2, 3) |
642 | - ): |
643 | - self.assertEqual((2, 3), upa.query_resolution()) |
644 | - |
645 | - |
646 | -class HardCodedResolutionTests(WithScenarios, TestCase): |
647 | - |
648 | - scenarios = [ |
649 | - ("generic", dict(name="generic", expected=(480, 800))), |
650 | - ("mako", dict(name="mako", expected=(768, 1280))), |
651 | - ("maguro", dict(name="maguro", expected=(720, 1280))), |
652 | - ("manta", dict(name="manta", expected=(2560, 1600))), |
653 | - ("grouper", dict(name="grouper", expected=(800, 1280))), |
654 | - ] |
655 | - |
656 | - def test_hardcoded_resolutions_works_for_known_codenames(self): |
657 | - with patch.object(upa, 'image_codename', return_value=self.name): |
658 | - observed = upa._get_hardcoded_resolution() |
659 | - self.assertEqual(self.expected, observed) |
660 | |
661 | === modified file 'autopilot/utilities.py' |
662 | --- autopilot/utilities.py 2016-05-18 07:06:16 +0000 |
663 | +++ autopilot/utilities.py 2017-03-02 18:46:50 +0000 |
664 | @@ -430,6 +430,7 @@ |
665 | def total_time_slept(self): |
666 | return self._mock_count |
667 | |
668 | + |
669 | sleep = MockableSleep() |
670 | |
671 | |
672 | @@ -665,4 +666,5 @@ |
673 | process.get('pid') |
674 | ) |
675 | |
676 | + |
677 | process_iter = MockableProcessIter() |
678 | |
679 | === modified file 'debian/control' |
680 | --- debian/control 2016-08-10 16:36:11 +0000 |
681 | +++ debian/control 2017-03-02 18:46:50 +0000 |
682 | @@ -6,10 +6,9 @@ |
683 | Build-Depends: debhelper (>= 9.0.0), |
684 | dh-python, |
685 | dvipng, |
686 | - gir1.2-gconf-2.0, |
687 | gir1.2-gtk-3.0, |
688 | gir1.2-ibus-1.0, |
689 | - gir1.2-ubuntu-app-launch-2 | gir1.2-upstart-app-launch-2, |
690 | + gir1.2-ubuntu-app-launch-3 | gir1.2-ubuntu-app-launch-2, |
691 | graphviz, |
692 | libjs-jquery, |
693 | libjs-underscore, |
694 | @@ -28,6 +27,7 @@ |
695 | python3-setuptools, |
696 | python3-sphinx, |
697 | python3-subunit, |
698 | + python3-systemd, |
699 | python3-testscenarios, |
700 | python3-testtools, |
701 | python3-tz, |
702 | @@ -38,15 +38,16 @@ |
703 | upstart, |
704 | Standards-Version: 3.9.5 |
705 | Homepage: https://launchpad.net/autopilot |
706 | -Vcs-bzr: https://code.launchpad.net/+branch/ubuntu/autopilot |
707 | +Vcs-Bzr: https://code.launchpad.net/~autopilot/autopilot/trunk |
708 | X-Python-Version: >= 2.7 |
709 | X-Python3-Version: >= 3.3 |
710 | |
711 | Package: python3-autopilot |
712 | Architecture: all |
713 | -Depends: gir1.2-ubuntu-app-launch-2 | gir1.2-upstart-app-launch-2, |
714 | +Depends: gir1.2-ubuntu-app-launch-3 | gir1.2-ubuntu-app-launch-2, |
715 | libjs-jquery, |
716 | libjs-underscore, |
717 | + mir-utils, |
718 | python3-dateutil, |
719 | python3-dbus, |
720 | python3-decorator, |
721 | @@ -57,14 +58,14 @@ |
722 | python3-pil, |
723 | python3-psutil, |
724 | python3-subunit, |
725 | + python3-systemd, |
726 | python3-testscenarios, |
727 | python3-testtools, |
728 | python3-tz, |
729 | udev, |
730 | ${misc:Depends}, |
731 | ${python3:Depends}, |
732 | -Recommends: gir1.2-gconf-2.0, |
733 | - gir1.2-glib-2.0, |
734 | +Recommends: gir1.2-glib-2.0, |
735 | gir1.2-gtk-3.0, |
736 | gir1.2-ibus-1.0, |
737 | libautopilot-gtk (>= 1.4), |
738 | @@ -109,7 +110,6 @@ |
739 | Section: metapackages |
740 | Depends: at-spi2-core, |
741 | bamfdaemon, |
742 | - gir1.2-gconf-2.0, |
743 | gir1.2-glib-2.0, |
744 | gir1.2-gtk-3.0, |
745 | python3-autopilot, |