Merge lp:autopilot into lp:autopilot/1.6

Proposed by dobey
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
Reviewer Review Type Date Requested Status
Autopilot Hackers Pending
Review via email: mp+318824@code.launchpad.net

Commit message

New upstream release.

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
=== modified file 'README'
--- README 2016-08-04 05:32:39 +0000
+++ README 2017-03-02 18:46:50 +0000
@@ -72,6 +72,12 @@
72If you are in the root of the autopilot source tree this will run/list the tests from72If you are in the root of the autopilot source tree this will run/list the tests from
73within that local module. Otherwise autopilot will look in the system python path.73within that local module. Otherwise autopilot will look in the system python path.
7474
75Release Autopilot
76=================
771. Open a new request on bileto: https://bileto.ubuntu.com/ with the lp:autopilot -> lp:autopilot/1.5 merge proposal
782. 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)
793. Build the silo and run the tests
804. Once happy with all tests approve and publish the result
7581
76Release Manual Tests82Release Manual Tests
77====================83====================
7884
=== modified file 'autopilot/application/_launcher.py'
--- autopilot/application/_launcher.py 2015-12-08 21:42:14 +0000
+++ autopilot/application/_launcher.py 2017-03-02 18:46:50 +0000
@@ -1,7 +1,7 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2#2#
3# Autopilot Functional Test Tool3# Autopilot Functional Test Tool
4# Copyright (C) 2013 Canonical4# Copyright (C) 2013,2017 Canonical
5#5#
6# This program is free software: you can redistribute it and/or modify6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by7# it under the terms of the GNU General Public License as published by
@@ -20,21 +20,20 @@
20"""Base module for application launchers."""20"""Base module for application launchers."""
2121
22import fixtures22import fixtures
23from gi.repository import GLib23from gi import require_version
24try:24try:
25 from gi import require_version25 require_version('UbuntuAppLaunch', '3')
26except ValueError:
26 require_version('UbuntuAppLaunch', '2')27 require_version('UbuntuAppLaunch', '2')
27 from gi.repository import UbuntuAppLaunch28from gi.repository import GLib, UbuntuAppLaunch
28except ImportError:29
29 # Note: the renamed package is not in Trusty.
30 from gi.repository import UpstartAppLaunch as UbuntuAppLaunch
31import json30import json
32import logging31import logging
33import os32import os
34import psutil33import psutil
35import subprocess34import subprocess
36import signal35import signal
37from testtools.content import content_from_file36from systemd import journal
38from autopilot.utilities import safe_text_content37from autopilot.utilities import safe_text_content
3938
40from autopilot._timeout import Timeout39from autopilot._timeout import Timeout
@@ -186,13 +185,20 @@
186 self.addCleanup(self._stop_application, app_id)185 self.addCleanup(self._stop_application, app_id)
187 self.addCleanup(self._attach_application_log, app_id)186 self.addCleanup(self._attach_application_log, app_id)
188187
188 @staticmethod
189 def _get_user_unit_match(app_id):
190 return 'ubuntu-app-launch-*-%s-*.service' % app_id
191
189 def _attach_application_log(self, app_id):192 def _attach_application_log(self, app_id):
190 log_path = UbuntuAppLaunch.application_log_path(app_id)193 j = journal.Reader()
191 if log_path and os.path.exists(log_path):194 j.log_level(journal.LOG_INFO)
192 self.caseAddDetail(195 j.add_match(_SYSTEMD_USER_UNIT=self._get_user_unit_match(app_id))
193 "Application Log (%s)" % app_id,196 log_data = ''
194 content_from_file(log_path)197 for i in j:
195 )198 log_data += str(i) + '\n'
199 if len(log_data) > 0:
200 self.caseAddDetail('Application Log (%s)' % app_id,
201 safe_text_content(log_data))
196202
197 def _stop_application(self, app_id):203 def _stop_application(self, app_id):
198 state = {}204 state = {}
199205
=== modified file 'autopilot/display/__init__.py'
--- autopilot/display/__init__.py 2014-07-09 00:21:04 +0000
+++ autopilot/display/__init__.py 2017-03-02 18:46:50 +0000
@@ -40,9 +40,9 @@
40def is_rect_on_screen(screen_number, rect):40def is_rect_on_screen(screen_number, rect):
41 """Return True if *rect* is **entirely** on the specified screen, with no41 """Return True if *rect* is **entirely** on the specified screen, with no
42 overlap."""42 overlap."""
43 (x, y, w, h) = rect43 x, y, w, h = rect
44 (mx, my, mw, mh) = Display.create().get_screen_geometry(screen_number)44 mx, my, mw, mh = Display.create().get_screen_geometry(screen_number)
45 return (x >= mx and x + w <= mx + mw and y >= my and y + h <= my + mh)45 return x >= mx and x + w <= mx + mw and y >= my and y + h <= my + mh
4646
4747
48def is_point_on_screen(screen_number, point):48def is_point_on_screen(screen_number, point):
@@ -52,8 +52,8 @@
5252
53 """53 """
54 x, y = point54 x, y = point
55 (mx, my, mw, mh) = Display.create().get_screen_geometry(screen_number)55 mx, my, mw, mh = Display.create().get_screen_geometry(screen_number)
56 return (x >= mx and x < mx + mw and y >= my and y < my + mh)56 return mx <= x < mx + mw and my <= y < my + mh
5757
5858
59def is_point_on_any_screen(point):59def is_point_on_any_screen(point):
@@ -71,45 +71,6 @@
71 Mouse.create().move(x, y, False)71 Mouse.create().move(x, y, False)
7272
7373
74# veebers TODO: Write this so it's usable.
75# def drag_window_to_screen(self, window, screen):
76# """Drags *window* to *screen*
77
78# :param BamfWindow window: The window to drag
79# :param integer screen: The screen to drag the *window* to
80# :raises: **TypeError** if *window* is not a BamfWindow
81
82# """
83# if not isinstance(window, BamfWindow):
84# raise TypeError("Window must be a BamfWindow")
85
86# if window.monitor == screen:
87# logger.debug(
88# "Window %r is already on screen %d." % (window.x_id, screen))
89# return
90
91# assert(not window.is_maximized)
92# (win_x, win_y, win_w, win_h) = window.geometry
93# (mx, my, mw, mh) = self.get_screen_geometry(screen)
94
95# logger.debug("Dragging window %r to screen %d." % (window.x_id, screen))
96
97# mouse = Mouse()
98# keyboard = Keyboard()
99# mouse.move(win_x + win_w/2, win_y + win_h/2)
100# keyboard.press("Alt")
101# mouse.press()
102# keyboard.release("Alt")
103
104# # We do the movements in two steps, to reduce the risk of being
105# # blocked by the pointer barrier
106# target_x = mx + mw/2
107# target_y = my + mh/2
108# mouse.move(win_x, target_y, rate=20, time_between_events=0.005)
109# mouse.move(target_x, target_y, rate=20, time_between_events=0.005)
110# mouse.release()
111
112
113class Display(object):74class Display(object):
11475
115 """The base class/inteface for the display devices."""76 """The base class/inteface for the display devices."""
@@ -146,8 +107,8 @@
146 return Display()107 return Display()
147108
148 backends = OrderedDict()109 backends = OrderedDict()
110 backends['UPA'] = get_upa_display
149 backends['X11'] = get_x11_display111 backends['X11'] = get_x11_display
150 backends['UPA'] = get_upa_display
151 return _pick_backend(backends, preferred_backend)112 return _pick_backend(backends, preferred_backend)
152113
153 class BlacklistedDriverError(RuntimeError):114 class BlacklistedDriverError(RuntimeError):
154115
=== modified file 'autopilot/display/_upa.py'
--- autopilot/display/_upa.py 2014-03-25 14:42:25 +0000
+++ autopilot/display/_upa.py 2017-03-02 18:46:50 +0000
@@ -17,44 +17,33 @@
17# along with this program. If not, see <http://www.gnu.org/licenses/>.17# along with this program. If not, see <http://www.gnu.org/licenses/>.
18#18#
1919
20import os
21import subprocess
2022
21from autopilot.display import Display as DisplayBase23from autopilot.display import Display as DisplayBase
22from autopilot.platform import image_codename24from autopilot.platform import get_display_server, image_codename
23import subprocess25
26DISPLAY_SERVER_X11 = 'X11'
27DISPLAY_SERVER_MIR = 'MIR'
28ENV_MIR_SOCKET = 'MIR_SERVER_HOST_SOCKET'
2429
2530
26def query_resolution():31def query_resolution():
27 try:32 display_server = get_display_server()
28 return _get_fbset_resolution()33 if display_server == DISPLAY_SERVER_X11:
29 except Exception:34 return _get_resolution_from_xrandr()
35 elif display_server == DISPLAY_SERVER_MIR:
36 return _get_resolution_from_mirout()
37 else:
30 return _get_hardcoded_resolution()38 return _get_hardcoded_resolution()
3139
3240
33def _get_fbset_resolution():
34 """Return the resolution, as determined by fbset, or None."""
35 fbset_output = _get_fbset_output()
36 for line in fbset_output.split('\n'):
37 line = line.strip()
38 if line.startswith('Mode'):
39 quoted_resolution = line.split()[1]
40 resolution_string = quoted_resolution.strip('"')
41 return tuple(int(piece) for piece in resolution_string.split('x'))
42 raise RuntimeError("No modes found from fbset output")
43
44
45def _get_fbset_output():
46 return subprocess.check_output(["fbset", "-s", "-x"]).decode().strip()
47
48
49def _get_hardcoded_resolution():41def _get_hardcoded_resolution():
50 name = image_codename()42 name = image_codename()
5143
52 resolutions = {44 resolutions = {
53 "generic": (480, 800),45 "Aquaris_M10_HD": (800, 1280),
54 "mako": (768, 1280),46 "Desktop": (1920, 1080)
55 "maguro": (720, 1280),
56 "manta": (2560, 1600),
57 "grouper": (800, 1280),
58 }47 }
5948
60 if name not in resolutions:49 if name not in resolutions:
@@ -64,6 +53,35 @@
64 return resolutions[name]53 return resolutions[name]
6554
6655
56def _get_stdout_for_command(command, *args):
57 full_command = [command]
58 full_command.extend(args)
59 return subprocess.check_output(
60 full_command,
61 universal_newlines=True,
62 stderr=subprocess.DEVNULL,
63 ).split('\n')
64
65
66def _get_resolution(server_output):
67 relevant_line = list(filter(lambda line: '*' in line, server_output))[0]
68 if relevant_line:
69 return tuple([int(i) for i in relevant_line.split()[0].split('x')])
70 raise ValueError(
71 'Failed to get display resolution, is a display connected?'
72 )
73
74
75def _get_resolution_from_xrandr():
76 return _get_resolution(_get_stdout_for_command('xrandr', '--current'))
77
78
79def _get_resolution_from_mirout():
80 return _get_resolution(
81 _get_stdout_for_command('mirout', os.environ.get(ENV_MIR_SOCKET))
82 )
83
84
67class Display(DisplayBase):85class Display(DisplayBase):
68 """The base class/inteface for the display devices"""86 """The base class/inteface for the display devices"""
6987
@@ -91,4 +109,4 @@
91 :return: Tuple containing (x, y, width, height).109 :return: Tuple containing (x, y, width, height).
92110
93 """111 """
94 return (0, 0, self._X, self._Y)112 return 0, 0, self._X, self._Y
95113
=== modified file 'autopilot/input/__init__.py'
--- autopilot/input/__init__.py 2016-01-08 09:35:07 +0000
+++ autopilot/input/__init__.py 2017-03-02 18:46:50 +0000
@@ -126,9 +126,9 @@
126 raise126 raise
127127
128 backends = OrderedDict()128 backends = OrderedDict()
129 backends['X11'] = get_x11_kb
130 backends['UInput'] = get_uinput_kb129 backends['UInput'] = get_uinput_kb
131 backends['OSK'] = get_osk_kb130 backends['OSK'] = get_osk_kb
131 backends['X11'] = get_x11_kb
132 return _pick_backend(backends, preferred_backend)132 return _pick_backend(backends, preferred_backend)
133133
134 @contextmanager134 @contextmanager
@@ -283,21 +283,15 @@
283 from autopilot.input._X11 import Mouse283 from autopilot.input._X11 import Mouse
284 return Mouse()284 return Mouse()
285285
286 from autopilot.platform import model286 def get_uinput_mouse():
287 if model() != 'Desktop':287 # Return the Touch device for now as Mouse under a Mir desktop
288 _logger.info(288 # is a challenge for now.
289 "You cannot create a Mouse on the devices where X11 is not "289 from autopilot.input._uinput import Touch
290 "available. consider using a Touch or Pointer device. "290 return Touch()
291 "For more information, see: "
292 "http://unity.ubuntu.com/autopilot/api/input.html"
293 "#autopilot-unified-input-system"
294 )
295 raise RuntimeError(
296 "Cannot create a Mouse on devices where X11 is not available."
297 )
298291
299 backends = OrderedDict()292 backends = OrderedDict()
300 backends['X11'] = get_x11_mouse293 backends['X11'] = get_x11_mouse
294 backends['UInput'] = get_uinput_mouse
301 return _pick_backend(backends, preferred_backend)295 return _pick_backend(backends, preferred_backend)
302296
303 @property297 @property
304298
=== modified file 'autopilot/introspection/types.py'
--- autopilot/introspection/types.py 2015-12-08 01:07:10 +0000
+++ autopilot/introspection/types.py 2017-03-02 18:46:50 +0000
@@ -255,6 +255,7 @@
255def _create_generic_repr(target_type):255def _create_generic_repr(target_type):
256 return compatible_repr(lambda self: repr(target_type(self)))256 return compatible_repr(lambda self: repr(target_type(self)))
257257
258
258_bytes_repr = _create_generic_repr(bytes)259_bytes_repr = _create_generic_repr(bytes)
259_text_repr = _create_generic_repr(str)260_text_repr = _create_generic_repr(str)
260_dict_repr = _create_generic_repr(dict)261_dict_repr = _create_generic_repr(dict)
261262
=== modified file 'autopilot/introspection/utilities.py'
--- autopilot/introspection/utilities.py 2016-07-14 08:18:20 +0000
+++ autopilot/introspection/utilities.py 2017-03-02 18:46:50 +0000
@@ -138,4 +138,5 @@
138 """138 """
139 return self._query_pids_for_process(process_name)139 return self._query_pids_for_process(process_name)
140140
141
141process_util = ProcessUtil()142process_util = ProcessUtil()
142143
=== modified file 'autopilot/platform.py'
--- autopilot/platform.py 2014-07-23 01:59:47 +0000
+++ autopilot/platform.py 2017-03-02 18:46:50 +0000
@@ -19,8 +19,6 @@
1919
2020
21import os21import os
22import psutil
23from functools import lru_cache
2422
25"""23"""
26Platform identification utilities for Autopilot.24Platform identification utilities for Autopilot.
@@ -143,27 +141,10 @@
143def get_display_server():141def get_display_server():
144 """Returns display server type.142 """Returns display server type.
145143
146 :returns: string indicating display server type. Either "X11", "MIR" or144 :returns: string indicating display server type.
147 "UNKNOWN"
148145
149 """146 """
150 if _display_is_x11():147 return os.environ.get('XDG_SESSION_TYPE', 'UNKNOWN').upper()
151 return "X11"
152 elif _display_is_mir():
153 return "MIR"
154 else:
155 return "UNKNOWN"
156
157
158def _display_is_x11():
159 return 'DISPLAY' in os.environ
160
161
162@lru_cache()
163def _display_is_mir():
164 return "unity-system-compositor" in [
165 _get_process_name(p.name) for p in psutil.process_iter()
166 ]
167148
168149
169# Different vers. of psutil across Trusty and Utopic have name as either a150# Different vers. of psutil across Trusty and Utopic have name as either a
170151
=== modified file 'autopilot/process/__init__.py'
--- autopilot/process/__init__.py 2015-05-04 06:28:37 +0000
+++ autopilot/process/__init__.py 2017-03-02 18:46:50 +0000
@@ -89,10 +89,6 @@
89 from autopilot.process._bamf import ProcessManager89 from autopilot.process._bamf import ProcessManager
90 return ProcessManager()90 return ProcessManager()
9191
92 def get_upa_pm():
93 from autopilot.process._upa import ProcessManager
94 return ProcessManager()
95
96 backends = OrderedDict()92 backends = OrderedDict()
97 backends['BAMF'] = get_bamf_pm93 backends['BAMF'] = get_bamf_pm
98 return _pick_backend(backends, preferred_backend)94 return _pick_backend(backends, preferred_backend)
9995
=== modified file 'autopilot/run.py'
--- autopilot/run.py 2015-08-19 00:25:00 +0000
+++ autopilot/run.py 2017-03-02 18:46:50 +0000
@@ -749,5 +749,6 @@
749 print(e)749 print(e)
750 exit(1)750 exit(1)
751751
752
752if __name__ == "__main__":753if __name__ == "__main__":
753 main()754 main()
754755
=== modified file 'autopilot/testcase.py'
--- autopilot/testcase.py 2015-09-02 03:25:43 +0000
+++ autopilot/testcase.py 2017-03-02 18:46:50 +0000
@@ -173,13 +173,14 @@
173 # Work around for bug lp:1297592.173 # Work around for bug lp:1297592.
174 _ensure_uinput_device_created()174 _ensure_uinput_device_created()
175175
176 try:176 if get_display_server() == 'X11':
177 self._app_snapshot = _get_process_snapshot()177 try:
178 self.addCleanup(self._compare_system_with_app_snapshot)178 self._app_snapshot = _get_process_snapshot()
179 except RuntimeError:179 self.addCleanup(self._compare_system_with_app_snapshot)
180 _logger.warning(180 except RuntimeError:
181 "Process manager backend unavailable, application snapshot "181 _logger.warning(
182 "support disabled.")182 "Process manager backend unavailable, application "
183 "snapshot support disabled.")
183184
184 self.addOnException(self._take_screenshot_on_failure)185 self.addOnException(self._take_screenshot_on_failure)
185186
186187
=== modified file 'autopilot/tests/unit/introspection_base.py'
--- autopilot/tests/unit/introspection_base.py 2016-07-19 14:24:10 +0000
+++ autopilot/tests/unit/introspection_base.py 2017-03-02 18:46:50 +0000
@@ -38,6 +38,7 @@
38 def get_properties(self):38 def get_properties(self):
39 return self.__dict__39 return self.__dict__
4040
41
41get_mock_object = MockObject42get_mock_object = MockObject
4243
4344
4445
=== modified file 'autopilot/tests/unit/test_application_launcher.py'
--- autopilot/tests/unit/test_application_launcher.py 2014-07-22 02:30:19 +0000
+++ autopilot/tests/unit/test_application_launcher.py 2017-03-02 18:46:50 +0000
@@ -1,7 +1,7 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2#2#
3# Autopilot Functional Test Tool3# Autopilot Functional Test Tool
4# Copyright (C) 2013 Canonical4# Copyright (C) 2013,2017 Canonical
5#5#
6# This program is free software: you can redistribute it and/or modify6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by7# it under the terms of the GNU General Public License as published by
@@ -33,8 +33,7 @@
33 raises,33 raises,
34)34)
35from testtools.content import text_content35from testtools.content import text_content
36import tempfile36from unittest.mock import MagicMock, Mock, patch
37from unittest.mock import Mock, patch
3837
39from autopilot.application import (38from autopilot.application import (
40 ClickApplicationLauncher,39 ClickApplicationLauncher,
@@ -782,32 +781,30 @@
782 app_id = self.getUniqueString()781 app_id = self.getUniqueString()
783 case_addDetail = Mock()782 case_addDetail = Mock()
784 launcher = UpstartApplicationLauncher(case_addDetail)783 launcher = UpstartApplicationLauncher(case_addDetail)
785 with patch.object(_l.UbuntuAppLaunch, 'application_log_path') as p:784 j = MagicMock(spec=_l.journal.Reader)
786 p.return_value = None785 with patch.object(_l.journal, 'Reader', return_value=j):
787 launcher._attach_application_log(app_id)786 launcher._attach_application_log(app_id)
788787 expected = launcher._get_user_unit_match(app_id)
789 p.assert_called_once_with(app_id)788 j.add_match.assert_called_once_with(_SYSTEMD_USER_UNIT=expected)
790 self.assertEqual(0, case_addDetail.call_count)789 self.assertEqual(0, case_addDetail.call_count)
791790
792 def test_attach_application_log_attaches_log_file(self):791 def test_attach_application_log_attaches_log(self):
793 token = self.getUniqueString()792 token = self.getUniqueString()
794 case_addDetail = Mock()793 case_addDetail = Mock()
795 launcher = UpstartApplicationLauncher(case_addDetail)794 launcher = UpstartApplicationLauncher(case_addDetail)
796 app_id = self.getUniqueString()795 app_id = self.getUniqueString()
797 with tempfile.NamedTemporaryFile(mode='w') as f:796 j = MagicMock(spec=_l.journal.Reader)
798 f.write(token)797 j.__iter__ = lambda x: iter([token])
799 f.flush()798 with patch.object(_l.journal, 'Reader', return_value=j):
800 with patch.object(_l.UbuntuAppLaunch, 'application_log_path',799 launcher._attach_application_log(app_id)
801 return_value=f.name):
802 launcher._attach_application_log(app_id)
803800
804 self.assertEqual(1, case_addDetail.call_count)801 self.assertEqual(1, case_addDetail.call_count)
805 content_name, content_obj = case_addDetail.call_args[0]802 content_name, content_obj = case_addDetail.call_args[0]
806 self.assertEqual(803 self.assertEqual(
807 "Application Log (%s)" % app_id,804 "Application Log (%s)" % app_id,
808 content_name805 content_name
809 )806 )
810 self.assertThat(content_obj.as_text(), Contains(token))807 self.assertThat(content_obj.as_text(), Contains(token))
811808
812 def test_stop_adds_app_stopped_observer(self):809 def test_stop_adds_app_stopped_observer(self):
813 mock_add_detail = Mock()810 mock_add_detail = Mock()
814811
=== modified file 'autopilot/tests/unit/test_platform.py'
--- autopilot/tests/unit/test_platform.py 2015-12-08 00:48:04 +0000
+++ autopilot/tests/unit/test_platform.py 2017-03-02 18:46:50 +0000
@@ -20,7 +20,6 @@
20"""Tests for the autopilot platform code."""20"""Tests for the autopilot platform code."""
2121
2222
23from contextlib import contextmanager
24from io import StringIO23from io import StringIO
25from testtools import TestCase24from testtools import TestCase
26from testtools.matchers import Equals25from testtools.matchers import Equals
@@ -34,7 +33,6 @@
3433
35 def setUp(self):34 def setUp(self):
36 super().setUp()35 super().setUp()
37 platform._display_is_mir.cache_clear()
3836
39 @patch('autopilot.platform._PlatformDetector')37 @patch('autopilot.platform._PlatformDetector')
40 def test_model_creates_platform_detector(self, mock_detector):38 def test_model_creates_platform_detector(self, mock_detector):
@@ -56,14 +54,6 @@
56 mock_detector.image_codename = "test123"54 mock_detector.image_codename = "test123"
57 self.assertThat(platform.image_codename(), Equals('test123'))55 self.assertThat(platform.image_codename(), Equals('test123'))
5856
59 def test_is_x11_returns_False_on_failure(self):
60 with _simulate_not_X11():
61 self.assertFalse(platform._display_is_x11())
62
63 def test_is_x11_returns_True_on_success(self):
64 with _simulate_X11():
65 self.assertTrue(platform._display_is_x11())
66
6757
68class PlatformGetProcessNameTests(TestCase):58class PlatformGetProcessNameTests(TestCase):
6959
@@ -247,15 +237,3 @@
247 prop_file = StringIO("ro.product.model=maguro")237 prop_file = StringIO("ro.product.model=maguro")
248 properties = platform._parse_build_properties_file(prop_file)238 properties = platform._parse_build_properties_file(prop_file)
249 self.assertThat(properties, Equals({'ro.product.model': 'maguro'}))239 self.assertThat(properties, Equals({'ro.product.model': 'maguro'}))
250
251
252@contextmanager
253def _simulate_not_X11():
254 with patch.dict(platform.os.environ, dict(), clear=True):
255 yield
256
257
258@contextmanager
259def _simulate_X11():
260 with patch.dict(platform.os.environ, dict(DISPLAY=':0'), clear=True):
261 yield
262240
=== modified file 'autopilot/tests/unit/test_query_resolution.py'
--- autopilot/tests/unit/test_query_resolution.py 2014-05-20 08:53:21 +0000
+++ autopilot/tests/unit/test_query_resolution.py 2017-03-02 18:46:50 +0000
@@ -16,85 +16,3 @@
16# You should have received a copy of the GNU General Public License16# You should have received a copy of the GNU General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.17# along with this program. If not, see <http://www.gnu.org/licenses/>.
18#18#
19
20from testtools import TestCase
21from testtools.matchers import raises
22from testscenarios import WithScenarios
23from textwrap import dedent
24from unittest.mock import patch
25
26from autopilot.display import _upa as upa
27
28
29class QueryResolutionFunctionTests(TestCase):
30
31 @patch('subprocess.check_output', return_value=b'')
32 def test_fbset_output_calls_subprocess(self, patched_check_output):
33 upa._get_fbset_output()
34 patched_check_output.assert_called_once_with(
35 ["fbset", "-s", "-x"]
36 )
37
38 def test_get_fbset_resolution(self):
39 patched_fbset_resolution = dedent(
40 '''
41 Mode "768x1280"
42 # D: 0.002 MHz, H: 0.002 kHz, V: 0.002 Hz
43 DotClock 0.003
44 HTimings 768 776 780 960
45 VTimings 1280 1288 1290 1312
46 Flags "-HSync" "-VSync"
47 EndMode
48 '''
49 )
50 with patch.object(upa, '_get_fbset_output') as patched_gfo:
51 patched_gfo.return_value = patched_fbset_resolution
52 observed = upa._get_fbset_resolution()
53 self.assertEqual((768, 1280), observed)
54
55 def test_get_fbset_resolution_raises_runtimeError(self):
56 patched_fbset_resolution = 'something went wrong!'
57 with patch.object(upa, '_get_fbset_output') as patched_gfo:
58 patched_gfo.return_value = patched_fbset_resolution
59 self.assertThat(
60 upa._get_fbset_resolution,
61 raises(RuntimeError),
62 )
63
64 def test_hardcoded_raises_error_on_unknown_model(self):
65 with patch.object(upa, 'image_codename', return_value="unknown"):
66 self.assertThat(
67 upa._get_hardcoded_resolution,
68 raises(
69 NotImplementedError(
70 'Device "unknown" is not supported by Autopilot.'
71 )
72 )
73 )
74
75 def test_query_resolution_uses_fbset_first(self):
76 with patch.object(upa, '_get_fbset_resolution', return_value=(1, 2)):
77 self.assertEqual((1, 2), upa.query_resolution())
78
79 def test_query_resolution_uses_hardcoded_second(self):
80 with patch.object(upa, '_get_fbset_resolution', side_effect=Exception):
81 with patch.object(
82 upa, '_get_hardcoded_resolution', return_value=(2, 3)
83 ):
84 self.assertEqual((2, 3), upa.query_resolution())
85
86
87class HardCodedResolutionTests(WithScenarios, TestCase):
88
89 scenarios = [
90 ("generic", dict(name="generic", expected=(480, 800))),
91 ("mako", dict(name="mako", expected=(768, 1280))),
92 ("maguro", dict(name="maguro", expected=(720, 1280))),
93 ("manta", dict(name="manta", expected=(2560, 1600))),
94 ("grouper", dict(name="grouper", expected=(800, 1280))),
95 ]
96
97 def test_hardcoded_resolutions_works_for_known_codenames(self):
98 with patch.object(upa, 'image_codename', return_value=self.name):
99 observed = upa._get_hardcoded_resolution()
100 self.assertEqual(self.expected, observed)
10119
=== modified file 'autopilot/utilities.py'
--- autopilot/utilities.py 2016-05-18 07:06:16 +0000
+++ autopilot/utilities.py 2017-03-02 18:46:50 +0000
@@ -430,6 +430,7 @@
430 def total_time_slept(self):430 def total_time_slept(self):
431 return self._mock_count431 return self._mock_count
432432
433
433sleep = MockableSleep()434sleep = MockableSleep()
434435
435436
@@ -665,4 +666,5 @@
665 process.get('pid')666 process.get('pid')
666 )667 )
667668
669
668process_iter = MockableProcessIter()670process_iter = MockableProcessIter()
669671
=== modified file 'debian/control'
--- debian/control 2016-08-10 16:36:11 +0000
+++ debian/control 2017-03-02 18:46:50 +0000
@@ -6,10 +6,9 @@
6Build-Depends: debhelper (>= 9.0.0),6Build-Depends: debhelper (>= 9.0.0),
7 dh-python,7 dh-python,
8 dvipng,8 dvipng,
9 gir1.2-gconf-2.0,
10 gir1.2-gtk-3.0,9 gir1.2-gtk-3.0,
11 gir1.2-ibus-1.0,10 gir1.2-ibus-1.0,
12 gir1.2-ubuntu-app-launch-2 | gir1.2-upstart-app-launch-2,11 gir1.2-ubuntu-app-launch-3 | gir1.2-ubuntu-app-launch-2,
13 graphviz,12 graphviz,
14 libjs-jquery,13 libjs-jquery,
15 libjs-underscore,14 libjs-underscore,
@@ -28,6 +27,7 @@
28 python3-setuptools,27 python3-setuptools,
29 python3-sphinx,28 python3-sphinx,
30 python3-subunit,29 python3-subunit,
30 python3-systemd,
31 python3-testscenarios,31 python3-testscenarios,
32 python3-testtools,32 python3-testtools,
33 python3-tz,33 python3-tz,
@@ -38,15 +38,16 @@
38 upstart,38 upstart,
39Standards-Version: 3.9.539Standards-Version: 3.9.5
40Homepage: https://launchpad.net/autopilot40Homepage: https://launchpad.net/autopilot
41Vcs-bzr: https://code.launchpad.net/+branch/ubuntu/autopilot41Vcs-Bzr: https://code.launchpad.net/~autopilot/autopilot/trunk
42X-Python-Version: >= 2.742X-Python-Version: >= 2.7
43X-Python3-Version: >= 3.343X-Python3-Version: >= 3.3
4444
45Package: python3-autopilot45Package: python3-autopilot
46Architecture: all46Architecture: all
47Depends: gir1.2-ubuntu-app-launch-2 | gir1.2-upstart-app-launch-2,47Depends: gir1.2-ubuntu-app-launch-3 | gir1.2-ubuntu-app-launch-2,
48 libjs-jquery,48 libjs-jquery,
49 libjs-underscore,49 libjs-underscore,
50 mir-utils,
50 python3-dateutil,51 python3-dateutil,
51 python3-dbus,52 python3-dbus,
52 python3-decorator,53 python3-decorator,
@@ -57,14 +58,14 @@
57 python3-pil,58 python3-pil,
58 python3-psutil,59 python3-psutil,
59 python3-subunit,60 python3-subunit,
61 python3-systemd,
60 python3-testscenarios,62 python3-testscenarios,
61 python3-testtools,63 python3-testtools,
62 python3-tz,64 python3-tz,
63 udev,65 udev,
64 ${misc:Depends},66 ${misc:Depends},
65 ${python3:Depends},67 ${python3:Depends},
66Recommends: gir1.2-gconf-2.0,68Recommends: gir1.2-glib-2.0,
67 gir1.2-glib-2.0,
68 gir1.2-gtk-3.0,69 gir1.2-gtk-3.0,
69 gir1.2-ibus-1.0,70 gir1.2-ibus-1.0,
70 libautopilot-gtk (>= 1.4),71 libautopilot-gtk (>= 1.4),
@@ -109,7 +110,6 @@
109Section: metapackages110Section: metapackages
110Depends: at-spi2-core,111Depends: at-spi2-core,
111 bamfdaemon,112 bamfdaemon,
112 gir1.2-gconf-2.0,
113 gir1.2-glib-2.0,113 gir1.2-glib-2.0,
114 gir1.2-gtk-3.0,114 gir1.2-gtk-3.0,
115 python3-autopilot,115 python3-autopilot,

Subscribers

People subscribed via source and target branches