2
2
Autopilot tests for Unity.
b'\\ No newline at end of file'
6
from compizconfig import Setting, Plugin
9
from StringIO import StringIO
10
from subprocess import call, Popen, PIPE, STDOUT
11
from tempfile import mktemp
12
from testscenarios import TestWithScenarios
13
from testtools import TestCase
14
from testtools.content import text_content
15
from testtools.matchers import Equals
18
from autopilot.emulators.bamf import Bamf
19
from autopilot.emulators.unity import (
24
from autopilot.emulators.unity.dash import Dash
25
from autopilot.emulators.unity.launcher import LauncherController
26
from autopilot.emulators.unity.switcher import Switcher
27
from autopilot.emulators.unity.workspace import WorkspaceManager
28
from autopilot.emulators.X11 import Keyboard, Mouse
29
from autopilot.glibrunner import GlibRunner
30
from autopilot.globals import (global_context,
31
video_recording_enabled,
32
video_record_directory,
34
from autopilot.keybindings import KeybindingsHelper
37
logger = logging.getLogger(__name__)
40
class LoggedTestCase(TestWithScenarios, TestCase):
41
"""Initialize the logging for the test case."""
44
self._setUpTestLogging()
45
self._setUpUnityLogging()
46
# The reason that the super setup is done here is due to making sure
47
# that the logging is properly set up prior to calling it.
48
super(LoggedTestCase, self).setUp()
50
def _setUpTestLogging(self):
51
class MyFormatter(logging.Formatter):
53
def formatTime(self, record, datefmt=None):
54
ct = self.converter(record.created)
56
s = time.strftime(datefmt, ct)
58
t = time.strftime("%H:%M:%S", ct)
59
s = "%s.%03d" % (t, record.msecs)
62
self._log_buffer = StringIO()
63
root_logger = logging.getLogger()
64
root_logger.setLevel(logging.DEBUG)
65
handler = logging.StreamHandler(stream=self._log_buffer)
66
log_format = "%(asctime)s %(levelname)s %(module)s:%(lineno)d - %(message)s"
67
handler.setFormatter(MyFormatter(log_format))
68
root_logger.addHandler(handler)
69
#Tear down logging in a cleanUp handler, so it's done after all other
70
# tearDown() calls and cleanup handlers.
71
self.addCleanup(self._tearDownLogging)
73
def _tearDownLogging(self):
74
logger = logging.getLogger()
75
for handler in logger.handlers:
77
self._log_buffer.seek(0)
78
self.addDetail('test-log', text_content(self._log_buffer.getvalue()))
79
logger.removeHandler(handler)
80
# Calling del to remove the handler and flush the buffer. We are
81
# abusing the log handlers here a little.
84
def _setUpUnityLogging(self):
85
self._unity_log_file_name = mktemp(prefix=self.shortDescription())
86
start_log_to_file(self._unity_log_file_name)
87
self.addCleanup(self._tearDownUnityLogging)
89
def _tearDownUnityLogging(self):
91
with open(self._unity_log_file_name) as unity_log:
92
self.addDetail('unity-log', text_content(unity_log.read()))
93
os.remove(self._unity_log_file_name)
94
self._unity_log_file_name = ""
96
def set_unity_log_level(component, level):
97
"""Set the unity log level for 'component' to 'level'.
99
Valid levels are: TRACE, DEBUG, INFO, WARNING and ERROR.
101
Components are dotted unity component names. The empty string specifies
102
the root logging component.
104
set_log_severity(component, level)
107
class VideoCapturedTestCase(LoggedTestCase):
108
"""Video capture autopilot tests, saving the results if the test failed."""
110
_recording_app = '/usr/bin/recordmydesktop'
111
_recording_opts = ['--no-sound', '--no-frame', '-o',]
114
super(VideoCapturedTestCase, self).setUp()
115
global video_recording_enabled
116
if video_recording_enabled and not self._have_recording_app():
117
video_recording_enabled = False
118
logger.warning("Disabling video capture since '%s' is not present", self._recording_app)
120
if video_recording_enabled:
121
self._test_passed = True
122
self.addOnException(self._on_test_failed)
123
self.addCleanup(self._stop_video_capture)
124
self._start_video_capture()
126
def _have_recording_app(self):
127
return os.path.exists(self._recording_app)
129
def _start_video_capture(self):
130
args = self._get_capture_command_line()
131
self._capture_file = self._get_capture_output_file()
132
self._ensure_directory_exists_but_not_file(self._capture_file)
133
args.append(self._capture_file)
134
logger.debug("Starting: %r", args)
135
self._capture_process = Popen(args, stdout=PIPE, stderr=STDOUT)
137
def _stop_video_capture(self):
138
"""Stop the video capture. If the test failed, save the resulting file."""
140
if self._test_passed:
141
# We use kill here because we don't want the recording app to start
142
# encoding the video file (since we're removing it anyway.)
143
self._capture_process.kill()
144
self._capture_process.wait()
146
self._capture_process.terminate()
147
self._capture_process.wait()
148
if self._capture_process.returncode != 0:
149
self.addDetail('video capture log', text_content(self._capture_process.stdout.read()))
150
self._capture_process = None
152
def _get_capture_command_line(self):
153
return [self._recording_app] + self._recording_opts
155
def _get_capture_output_file(self):
156
return os.path.join(video_record_directory, '%s.ogv' % (self.shortDescription()))
158
def _ensure_directory_exists_but_not_file(self, file_path):
159
dirpath = os.path.dirname(file_path)
160
if not os.path.exists(dirpath):
162
elif os.path.exists(file_path):
163
logger.warning("Video capture file '%s' already exists, deleting.", file_path)
166
def _on_test_failed(self, ex_info):
167
"""Called when a test fails."""
168
self._test_passed = False
171
class AutopilotTestCase(VideoCapturedTestCase, KeybindingsHelper):
172
"""Wrapper around testtools.TestCase that takes care of some cleaning."""
174
run_test_with = GlibRunner
178
'desktop-file': 'gucharmap.desktop',
179
'process-name': 'gucharmap',
182
'desktop-file': 'gcalctool.desktop',
183
'process-name': 'gcalctool',
186
'desktop-file': 'mahjongg.desktop',
187
'process-name': 'mahjongg',
190
'desktop-file': 'remmina.desktop',
191
'process-name': 'remmina',
194
'desktop-file': 'gedit.desktop',
195
'process-name': 'gedit',
200
super(AutopilotTestCase, self).setUp()
202
self.keyboard = Keyboard()
205
self.switcher = Switcher()
206
self.workspace = WorkspaceManager()
207
self.launcher = self._get_launcher_controller()
208
self.addCleanup(self.workspace.switch_to, self.workspace.current_workspace)
209
self.addCleanup(Keyboard.cleanup)
210
self.addCleanup(Mouse.cleanup)
212
def start_app(self, app_name):
213
"""Start one of the known apps, and kill it on tear down."""
214
logger.info("Starting application '%s'", app_name)
215
app = self.KNOWN_APPS[app_name]
216
self.bamf.launch_application(app['desktop-file'])
217
self.addCleanup(call, ["killall", app['process-name']])
219
def close_all_app(self, app_name):
220
"""Close all instances of the app_name."""
221
app = self.KNOWN_APPS[app_name]
222
call(["killall", app['process-name']])
223
super(LoggedTestCase, self).tearDown()
225
def get_app_instances(self, app_name):
226
"""Get BamfApplication instances for app_name."""
227
desktop_file = self.KNOWN_APPS[app_name]['desktop-file']
228
return self.bamf.get_running_applications_by_desktop_file(desktop_file)
230
def app_is_running(self, app_name):
231
"""Returns true if an instance of the application is running."""
232
apps = self.get_app_instances(app_name)
235
def set_unity_option(self, option_name, option_value):
236
"""Set an option in the unity compiz plugin options.
238
The value will be set for the current test only.
241
self.set_compiz_option("unityshell", option_name, option_value)
243
def set_compiz_option(self, plugin_name, setting_name, setting_value):
244
"""Set setting `setting_name` in compiz plugin `plugin_name` to value `setting_value`
247
old_value = self._set_compiz_option(plugin_name, setting_name, setting_value)
248
self.addCleanup(self._set_compiz_option, plugin_name, setting_name, old_value)
250
def _set_compiz_option(self, plugin_name, option_name, option_value):
251
logger.info("Setting compiz option '%s' in plugin '%s' to %r",
252
option_name, plugin_name, option_value)
253
plugin = Plugin(global_context, plugin_name)
254
setting = Setting(plugin, option_name)
255
old_value = setting.Value
256
setting.Value = option_value
257
global_context.Write()
260
def _get_launcher_controller(self):
261
controllers = LauncherController.get_all_instances()
262
self.assertThat(len(controllers), Equals(1))
263
return controllers[0]