14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
"""Tests for the breezy ui
17
"""Tests for the breezy ui."""
22
from StringIO import StringIO
24
21
from testtools.matchers import *
32
from breezy.tests import (
35
from breezy.ui import text as _mod_ui_text
36
from breezy.tests.testui import (
33
from ..ui import text as _mod_ui_text
37
35
ProgressRecordingUIFactory,
41
class TTYStringIO(StringIO):
42
"""A helper class which makes a StringIO look like a terminal"""
48
class NonTTYStringIO(StringIO):
49
"""Helper that implements isatty() but returns False"""
55
class TestUIConfiguration(tests.TestCaseWithTransport):
39
class TestUIConfiguration(tests.TestCase):
57
41
def test_output_encoding_configuration(self):
58
42
enc = fixtures.generate_unicode_encodings().next()
59
43
config.GlobalStack().set('output_encoding', enc)
60
ui = tests.TestUIFactory(stdin=None,
61
stdout=tests.StringIOWrapper(),
62
stderr=tests.StringIOWrapper())
44
IO = ui_testing.BytesIOWithEncoding
45
ui = _mod_ui.make_ui_for_terminal(IO(), IO(), IO())
63
46
output = ui.make_output_stream()
64
47
self.assertEqual(output.encoding, enc)
67
50
class TestTextUIFactory(tests.TestCase):
69
def make_test_ui_factory(self, stdin_contents):
70
ui = tests.TestUIFactory(stdin=stdin_contents,
71
stdout=tests.StringIOWrapper(),
72
stderr=tests.StringIOWrapper())
75
52
def test_text_factory_confirm(self):
76
53
# turns into reading a regular boolean
77
ui = self.make_test_ui_factory('n\n')
54
ui = ui_testing.TestUIFactory('n\n')
78
55
self.assertEqual(ui.confirm_action(u'Should %(thing)s pass?',
79
56
'breezy.tests.test_ui.confirmation',
80
57
{'thing': 'this'},),
83
60
def test_text_factory_ascii_password(self):
84
ui = self.make_test_ui_factory('secret\n')
61
ui = ui_testing.TestUIFactory('secret\n')
85
62
pb = ui.nested_progress_bar()
87
64
self.assertEqual('secret',
99
def test_text_factory_utf8_password(self):
100
"""Test an utf8 password."""
101
ui = _mod_ui_text.TextUIFactory(None, None, None)
102
ui.stdin = tests.StringIOWrapper(u'baz\u1234'.encode('utf8'))
103
ui.stdout = tests.StringIOWrapper()
104
ui.stderr = tests.StringIOWrapper()
105
ui.stderr.encoding = ui.stdout.encoding = ui.stdin.encoding = 'utf8'
76
def test_text_factory_unicode_password(self):
77
"""Test a unicode password."""
78
ui = ui_testing.TextUIFactory(u'baz\u1234')
106
79
password = ui.get_password(u'Hello \u1234 %(user)s', user=u'some\u1234')
107
80
self.assertEqual(u'baz\u1234', password)
108
self.assertEqual(u'Hello \u1234 some\u1234: ',
109
ui.stderr.getvalue().decode('utf8'))
81
self.assertEqual(u'Hello \u1234 some\u1234: ', ui.stderr.getvalue())
110
82
# stdin and stdout should be empty
111
83
self.assertEqual('', ui.stdin.readline())
112
84
self.assertEqual('', ui.stdout.getvalue())
114
86
def test_text_ui_get_boolean(self):
115
stdin = tests.StringIOWrapper("y\n" # True
119
"yes with garbage\nY\n" # True
120
"not an answer\nno\n" # False
121
"I'm sure!\nyes\n" # True
124
stdout = tests.StringIOWrapper()
125
stderr = tests.StringIOWrapper()
126
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
92
"yes with garbage\nY\n" # True
93
"not an answer\nno\n" # False
94
"I'm sure!\nyes\n" # True
97
factory = ui_testing.TextUIFactory(stdin_text)
127
98
self.assertEqual(True, factory.get_boolean(u""))
128
99
self.assertEqual(False, factory.get_boolean(u""))
129
100
self.assertEqual(True, factory.get_boolean(u""))
139
110
self.assertEqual(False, factory.get_boolean(u""))
141
112
def test_text_ui_choose_bad_parameters(self):
142
stdin = tests.StringIOWrapper()
143
stdout = tests.StringIOWrapper()
144
stderr = tests.StringIOWrapper()
145
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
113
factory = ui_testing.TextUIFactory(u"")
146
114
# invalid default index
147
115
self.assertRaises(ValueError, factory.choose, u"", u"&Yes\n&No", 3)
148
116
# duplicated choice
150
118
# duplicated shortcut
151
119
self.assertRaises(ValueError, factory.choose, u"", u"&choice1\nchoi&ce2")
153
def test_text_ui_choose_prompt(self):
154
stdin = tests.StringIOWrapper()
155
stdout = tests.StringIOWrapper()
156
stderr = tests.StringIOWrapper()
157
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
121
def test_text_ui_choose_prompt_explicit(self):
158
122
# choices with explicit shortcuts
123
factory = ui_testing.TextUIFactory(u"")
159
124
factory.choose(u"prompt", u"&yes\n&No\nmore &info")
160
125
self.assertEqual("prompt ([y]es, [N]o, more [i]nfo): \n", factory.stderr.getvalue())
127
def test_text_ui_choose_prompt_automatic(self):
161
128
# automatic shortcuts
162
factory.stderr.truncate(0)
129
factory = ui_testing.TextUIFactory(u"")
163
130
factory.choose(u"prompt", u"yes\nNo\nmore info")
164
131
self.assertEqual("prompt ([y]es, [N]o, [m]ore info): \n", factory.stderr.getvalue())
166
133
def test_text_ui_choose_return_values(self):
167
134
choose = lambda: factory.choose(u"", u"&Yes\n&No\nMaybe\nmore &info", 3)
168
stdin = tests.StringIOWrapper("y\n" # 0
172
"b\na\nd \n" # bad shortcuts, all ignored
173
"yes with garbage\nY\n" # 0
174
"not an answer\nno\n" # 1
175
"info\nmore info\n" # 3
178
stdout = tests.StringIOWrapper()
179
stderr = tests.StringIOWrapper()
180
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
140
"b\na\nd \n" # bad shortcuts, all ignored
141
"yes with garbage\nY\n" # 0
142
"not an answer\nno\n" # 1
143
"info\nmore info\n" # 3
146
factory = ui_testing.TextUIFactory(stdin_text)
181
147
self.assertEqual(0, choose())
182
148
self.assertEqual(1, choose())
183
149
self.assertEqual(3, choose())
193
159
self.assertEqual(None, choose())
195
161
def test_text_ui_choose_no_default(self):
196
stdin = tests.StringIOWrapper(" \n" # no default, invalid!
199
stdout = tests.StringIOWrapper()
200
stderr = tests.StringIOWrapper()
201
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
163
" \n" # no default, invalid!
166
factory = ui_testing.TextUIFactory(stdin_text)
202
167
self.assertEqual(0, factory.choose(u"", u"&Yes\n&No"))
203
168
self.assertEqual("foo\n", factory.stdin.read())
205
170
def test_text_ui_get_integer(self):
206
stdin = tests.StringIOWrapper(
209
174
"hmmm\nwhat else ?\nCome on\nok 42\n4.24\n42\n")
210
stdout = tests.StringIOWrapper()
211
stderr = tests.StringIOWrapper()
212
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
175
factory = ui_testing.TextUIFactory(stdin_text)
213
176
self.assertEqual(1, factory.get_integer(u""))
214
177
self.assertEqual(-2, factory.get_integer(u""))
215
178
self.assertEqual(42, factory.get_integer(u""))
217
180
def test_text_factory_prompt(self):
218
181
# see <https://launchpad.net/bugs/365891>
219
StringIO = tests.StringIOWrapper
220
factory = _mod_ui_text.TextUIFactory(StringIO(), StringIO(), StringIO())
182
factory = ui_testing.TextUIFactory()
221
183
factory.prompt(u'foo %2e')
222
184
self.assertEqual('', factory.stdout.getvalue())
223
185
self.assertEqual('foo %2e', factory.stderr.getvalue())
225
187
def test_text_factory_prompts_and_clears(self):
226
188
# a get_boolean call should clear the pb before prompting
189
out = ui_testing.StringIOAsTTY()
228
190
self.overrideEnv('TERM', 'xterm')
229
factory = _mod_ui_text.TextUIFactory(
230
stdin=tests.StringIOWrapper("yada\ny\n"),
231
stdout=out, stderr=out)
232
factory._avail_width = lambda: 79
191
factory = ui_testing.TextUIFactory("yada\ny\n", stdout=out, stderr=out)
233
192
pb = factory.nested_progress_bar()
193
pb._avail_width = lambda: 79
234
194
pb.show_bar = False
235
195
pb.show_spinner = False
236
196
pb.show_count = False
263
222
def test_text_ui_getusername(self):
264
ui = _mod_ui_text.TextUIFactory(None, None, None)
265
ui.stdin = tests.StringIOWrapper('someuser\n\n')
266
ui.stdout = tests.StringIOWrapper()
267
ui.stderr = tests.StringIOWrapper()
268
ui.stdout.encoding = 'utf8'
223
ui = ui_testing.TextUIFactory('someuser\n\n')
269
224
self.assertEqual('someuser',
270
225
ui.get_username(u'Hello %(host)s', host='some'))
271
226
self.assertEqual('Hello some: ', ui.stderr.getvalue())
274
229
# stdin should be empty
275
230
self.assertEqual('', ui.stdin.readline())
277
def test_text_ui_getusername_utf8(self):
278
ui = _mod_ui_text.TextUIFactory(None, None, None)
279
ui.stdin = tests.StringIOWrapper(u'someuser\u1234'.encode('utf8'))
280
ui.stdout = tests.StringIOWrapper()
281
ui.stderr = tests.StringIOWrapper()
282
ui.stderr.encoding = ui.stdout.encoding = ui.stdin.encoding = "utf8"
232
def test_text_ui_getusername_unicode(self):
233
ui = ui_testing.TextUIFactory(u'someuser\u1234')
283
234
username = ui.get_username(u'Hello %(host)s', host=u'some\u1234')
284
235
self.assertEqual(u"someuser\u1234", username)
285
self.assertEqual(u"Hello some\u1234: ",
286
ui.stderr.getvalue().decode("utf8"))
236
self.assertEqual(u"Hello some\u1234: ", ui.stderr.getvalue())
287
237
self.assertEqual('', ui.stdout.getvalue())
289
239
def test_quietness(self):
290
240
self.overrideEnv('BRZ_PROGRESS_BAR', 'text')
291
ui_factory = _mod_ui_text.TextUIFactory(None,
241
ui_factory = ui_testing.TextUIFactory(
242
stderr=ui_testing.StringIOAsTTY())
294
243
self.assertIsInstance(ui_factory._progress_view,
295
244
_mod_ui_text.TextProgressView)
296
245
ui_factory.be_quiet(True)
298
247
_mod_ui_text.NullProgressView)
300
249
def test_text_ui_show_user_warning(self):
301
from breezy.repofmt.groupcompress_repo import RepositoryFormat2a
302
from breezy.repofmt.knitpack_repo import RepositoryFormatKnitPack5
305
ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
250
from ..repofmt.groupcompress_repo import RepositoryFormat2a
251
from ..repofmt.knitpack_repo import RepositoryFormatKnitPack5
252
ui = ui_testing.TextUIFactory()
306
253
remote_fmt = remote.RemoteRepositoryFormat()
307
254
remote_fmt._network_name = RepositoryFormatKnitPack5().network_name()
308
255
ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
309
256
to_format=remote_fmt)
310
self.assertEqual('', out.getvalue())
257
self.assertEqual('', ui.stdout.getvalue())
311
258
self.assertEqual("Doing on-the-fly conversion from RepositoryFormat2a() to "
312
259
"RemoteRepositoryFormat(_network_name='Bazaar RepositoryFormatKnitPack5 "
313
260
"(bzr 1.6)\\n').\nThis may take some time. Upgrade the repositories to "
314
261
"the same format for better performance.\n",
262
ui.stderr.getvalue())
316
263
# and now with it suppressed please
319
ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
264
ui = ui_testing.TextUIFactory()
320
265
ui.suppressed_warnings.add('cross_format_fetch')
321
266
ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
322
267
to_format=remote_fmt)
323
self.assertEqual('', out.getvalue())
324
self.assertEqual('', err.getvalue())
268
self.assertEqual('', ui.stdout.getvalue())
269
self.assertEqual('', ui.stderr.getvalue())
327
272
class TestTextUIOutputStream(tests.TestCase):
328
273
"""Tests for output stream that synchronizes with progress bar."""
330
275
def test_output_clears_terminal(self):
331
stdout = tests.StringIOWrapper()
332
stderr = tests.StringIOWrapper()
335
uif = _mod_ui_text.TextUIFactory(None, stdout, stderr)
278
uif = ui_testing.TextUIFactory()
336
279
uif.clear_term = lambda: clear_calls.append('clear')
338
stream = _mod_ui_text.TextUIOutputStream(uif, uif.stdout)
339
stream.write("Hello world!\n")
340
stream.write("there's more...\n")
341
stream.writelines(["1\n", "2\n", "3\n"])
281
stream = _mod_ui_text.TextUIOutputStream(uif, uif.stdout, 'utf-8', 'strict')
282
stream.write(u"Hello world!\n")
283
stream.write(u"there's more...\n")
284
stream.writelines([u"1\n", u"2\n", u"3\n"])
343
self.assertEqual(stdout.getvalue(),
286
self.assertEqual(uif.stdout.getvalue(),
347
290
self.assertEqual(['clear', 'clear', 'clear'],
355
298
def test_progress_construction(self):
356
299
"""TextUIFactory constructs the right progress view.
358
FileStringIO = tests.StringIOWrapper
301
FileStringIO = ui_testing.StringIOWithEncoding
302
TTYStringIO = ui_testing.StringIOAsTTY
359
303
for (file_class, term, pb, expected_pb_class) in (
360
304
# on an xterm, either use them or not as the user requests,
361
305
# otherwise default on
388
332
def test_text_ui_non_terminal(self):
389
333
"""Even on non-ttys, make_ui_for_terminal gives a text ui."""
390
stdin = NonTTYStringIO('')
391
stderr = NonTTYStringIO()
392
stdout = NonTTYStringIO()
334
stdin = stderr = stdout = ui_testing.StringIOWithEncoding()
393
335
for term_type in ['dumb', None, 'xterm']:
394
336
self.overrideEnv('TERM', term_type)
395
337
uif = _mod_ui.make_ui_for_terminal(stdin, stdout, stderr)