1
# Copyright (C) 2009, 2010 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
"""Tests run per UIFactory."""
19
# Testing UIFactories is a bit interesting because we require they all support a
20
# common interface, but the way they implement it can vary very widely. Between
21
# text, batch-mode, graphical and other potential UIFactories, the requirements
22
# to set up a factory, to make it respond to requests, and to simulate user
23
# input can vary a lot.
25
# We want tests that therefore allow for the evaluation of the result to vary
26
# per implementation, but we want to check that the supported facilities are
27
# the same across all UIFactorys, unless they're specifically skipped.
29
# Our normal approach is to use test scenarios but that seems to just end up
30
# creating test-like objects inside the scenario. Therefore we fall back to
31
# the older method of putting the common tests in a mixin.
33
# Plugins that add new UIFactorys can create their own subclasses.
36
from cStringIO import StringIO
47
class UIFactoryTestMixin(object):
48
"""Common tests for UIFactories.
50
These are supposed to be expressed with no assumptions about how the
51
UIFactory implements the method, only that it does implement them (or
52
fails cleanly), and that the concrete subclass will make arrangements to
53
build a factory and to examine its behaviour.
55
Note that this is *not* a TestCase, because it can't be directly run, but
56
the concrete subclasses should be.
59
def test_be_quiet(self):
60
self.factory.be_quiet(True)
61
self.assertEquals(True, self.factory.is_quiet())
62
self.factory.be_quiet(False)
63
self.assertEquals(False, self.factory.is_quiet())
66
self.factory.note("a note to the user")
67
self._check_note("a note to the user")
69
def test_show_error(self):
70
msg = 'an error occurred'
71
self.factory.show_error(msg)
72
self._check_show_error(msg)
74
def test_show_message(self):
76
self.factory.show_message(msg)
77
self._check_show_message(msg)
79
def test_show_warning(self):
81
self.factory.show_warning(msg)
82
self._check_show_warning(msg)
84
def test_make_output_stream(self):
85
# All UIs must now be able to at least accept output, even if they
87
output_stream = self.factory.make_output_stream()
88
output_stream.write('hello!')
90
def test_transport_activity(self):
91
# It doesn't matter what the implementation does, we just want to make
92
# sure the interface is there
93
t = transport.get_transport('memory:///')
94
self.factory.report_transport_activity(t, 1000, 'write')
95
self.factory.report_transport_activity(t, 2000, 'read')
96
self.factory.report_transport_activity(t, 4000, None)
97
self.factory.log_transport_activity()
98
self._check_log_transport_activity_noarg()
99
self.factory.log_transport_activity(display=True)
100
self._check_log_transport_activity_display()
102
def test_no_transport_activity(self):
103
# No activity to report
104
t = transport.get_transport('memory:///')
105
self.factory.log_transport_activity(display=True)
106
self._check_log_transport_activity_display_no_bytes()
109
class TestTextUIFactory(tests.TestCase, UIFactoryTestMixin):
112
super(TestTextUIFactory, self).setUp()
113
self.stdin = StringIO()
114
self.stdout = StringIO()
115
self.stderr = StringIO()
116
self.factory = ui.text.TextUIFactory(self.stdin, self.stdout,
119
def _check_note(self, note_text):
120
self.assertEquals("%s\n" % note_text,
121
self.stdout.getvalue())
123
def _check_show_error(self, msg):
124
self.assertEquals("bzr: error: %s\n" % msg,
125
self.stderr.getvalue())
126
self.assertEquals("", self.stdout.getvalue())
128
def _check_show_message(self, msg):
129
self.assertEquals("%s\n" % msg,
130
self.stdout.getvalue())
131
self.assertEquals("", self.stderr.getvalue())
133
def _check_show_warning(self, msg):
134
self.assertEquals("bzr: warning: %s\n" % msg,
135
self.stderr.getvalue())
136
self.assertEquals("", self.stdout.getvalue())
138
def _check_log_transport_activity_noarg(self):
139
self.assertEqual('', self.stdout.getvalue())
140
self.assertContainsRe(self.stderr.getvalue(), r'\d+KB\s+\dKB/s |')
141
self.assertNotContainsRe(self.stderr.getvalue(), r'Transferred:')
143
def _check_log_transport_activity_display(self):
144
self.assertEqual('', self.stdout.getvalue())
145
# Without a TTY, we shouldn't display anything
146
self.assertEqual('', self.stderr.getvalue())
148
def _check_log_transport_activity_display_no_bytes(self):
149
self.assertEqual('', self.stdout.getvalue())
150
# Without a TTY, we shouldn't display anything
151
self.assertEqual('', self.stderr.getvalue())
154
class TestTTYTextUIFactory(TestTextUIFactory):
157
super(TestTTYTextUIFactory, self).setUp()
159
class TTYStringIO(object):
160
"""Thunk over to StringIO() for everything but 'isatty'"""
163
self.__dict__['_sio'] = StringIO()
168
def __getattr__(self, name):
169
return getattr(self._sio, name)
171
def __setattr__(self, name, value):
172
return setattr(self._sio, name, value)
174
# Remove 'TERM' == 'dumb' which causes us to *not* treat output as a
175
# real terminal, even though isatty returns True
176
self._captureVar('TERM', None)
177
self.stderr = TTYStringIO()
178
self.stdout = TTYStringIO()
179
self.factory = ui.text.TextUIFactory(self.stdin, self.stdout,
182
def _check_log_transport_activity_display(self):
183
self.assertEqual('', self.stdout.getvalue())
184
# Displaying the result should write to the progress stream
185
self.assertContainsRe(self.stderr.getvalue(),
187
r' \(\d+\.\dK/s r:2K w:1K u:4K\)')
189
def _check_log_transport_activity_display_no_bytes(self):
190
self.assertEqual('', self.stdout.getvalue())
191
# Without actual bytes transferred, we should report nothing
192
self.assertEqual('', self.stderr.getvalue())
195
class TestSilentUIFactory(tests.TestCase, UIFactoryTestMixin):
196
# discards output, therefore tests for output expect nothing
199
super(TestSilentUIFactory, self).setUp()
200
self.factory = ui.SilentUIFactory()
202
def _check_note(self, note_text):
203
# it's just discarded
206
def _check_show_error(self, msg):
209
def _check_show_message(self, msg):
212
def _check_show_warning(self, msg):
215
def _check_log_transport_activity_noarg(self):
218
def _check_log_transport_activity_display(self):
221
def _check_log_transport_activity_display_no_bytes(self):
225
class TestCannedInputUIFactory(tests.TestCase, UIFactoryTestMixin):
226
# discards output, reads input from variables
229
super(TestCannedInputUIFactory, self).setUp()
230
self.factory = ui.CannedInputUIFactory([])
232
def _check_note(self, note_text):
235
def _check_show_error(self, msg):
238
def _check_show_message(self, msg):
241
def _check_show_warning(self, msg):
244
def _check_log_transport_activity_noarg(self):
247
def _check_log_transport_activity_display(self):
250
def _check_log_transport_activity_display_no_bytes(self):