38
34
from bzrlib.tests import (
42
from bzrlib.ui import text as _mod_ui_text
43
from bzrlib.tests.testui import (
44
ProgressRecordingUIFactory,
48
class TestUIConfiguration(tests.TestCaseWithTransport):
50
def test_output_encoding_configuration(self):
51
enc = fixtures.generate_unicode_encodings().next()
52
config.GlobalConfig().set_user_option('output_encoding',
54
ui = tests.TestUIFactory(stdin=None,
55
stdout=tests.StringIOWrapper(),
56
stderr=tests.StringIOWrapper())
57
output = ui.make_output_stream()
58
self.assertEquals(output.encoding, enc)
61
class TestTextUIFactory(tests.TestCase):
63
def make_test_ui_factory(self, stdin_contents):
64
ui = tests.TestUIFactory(stdin=stdin_contents,
65
stdout=tests.StringIOWrapper(),
66
stderr=tests.StringIOWrapper())
69
def test_text_factory_confirm(self):
70
# turns into reading a regular boolean
71
ui = self.make_test_ui_factory('n\n')
72
self.assertEquals(ui.confirm_action('Should %(thing)s pass?',
73
'bzrlib.tests.test_ui.confirmation',
39
from bzrlib.tests.test_progress import (
43
from bzrlib.ui import (
50
from bzrlib.ui.text import (
57
class UITests(tests.TestCase):
77
59
def test_text_factory_ascii_password(self):
78
ui = self.make_test_ui_factory('secret\n')
60
ui = tests.TestUIFactory(stdin='secret\n',
61
stdout=tests.StringIOWrapper(),
62
stderr=tests.StringIOWrapper())
79
63
pb = ui.nested_progress_bar()
81
65
self.assertEqual('secret',
103
def test_progress_construction(self):
104
"""TextUIFactory constructs the right progress view.
106
for (file_class, term, pb, expected_pb_class) in (
107
# on an xterm, either use them or not as the user requests,
108
# otherwise default on
109
(_TTYStringIO, 'xterm', 'none', NullProgressView),
110
(_TTYStringIO, 'xterm', 'text', TextProgressView),
111
(_TTYStringIO, 'xterm', None, TextProgressView),
112
# on a dumb terminal, again if there's explicit configuration do
113
# it, otherwise default off
114
(_TTYStringIO, 'dumb', 'none', NullProgressView),
115
(_TTYStringIO, 'dumb', 'text', TextProgressView),
116
(_TTYStringIO, 'dumb', None, NullProgressView),
117
# on a non-tty terminal, it's null regardless of $TERM
118
(StringIO, 'xterm', None, NullProgressView),
119
(StringIO, 'dumb', None, NullProgressView),
120
# however, it can still be forced on
121
(StringIO, 'dumb', 'text', TextProgressView),
123
os.environ['TERM'] = term
125
if 'BZR_PROGRESS_BAR' in os.environ:
126
del os.environ['BZR_PROGRESS_BAR']
128
os.environ['BZR_PROGRESS_BAR'] = pb
129
stdin = file_class('')
130
stderr = file_class()
131
stdout = file_class()
132
uif = make_ui_for_terminal(stdin, stdout, stderr)
133
self.assertIsInstance(uif, TextUIFactory,
134
"TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
135
self.assertIsInstance(uif.make_progress_view(),
137
"TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
139
def test_text_ui_non_terminal(self):
140
"""Even on non-ttys, make_ui_for_terminal gives a text ui."""
141
stdin = _NonTTYStringIO('')
142
stderr = _NonTTYStringIO()
143
stdout = _NonTTYStringIO()
144
for term_type in ['dumb', None, 'xterm']:
145
if term_type is None:
146
del os.environ['TERM']
148
os.environ['TERM'] = term_type
149
uif = make_ui_for_terminal(stdin, stdout, stderr)
150
self.assertIsInstance(uif, TextUIFactory,
151
'TERM=%r' % (term_type,))
153
def test_progress_note(self):
156
ui_factory = TextUIFactory(stdin=StringIO(''),
159
pb = ui_factory.nested_progress_bar()
161
result = pb.note('t')
162
self.assertEqual(None, result)
163
self.assertEqual("t\n", stdout.getvalue())
164
# Since there was no update() call, there should be no clear() call
165
self.failIf(re.search(r'^\r {10,}\r$',
166
stderr.getvalue()) is not None,
167
'We cleared the stderr without anything to put there')
171
def test_progress_note_clears(self):
172
stderr = _TTYStringIO()
173
stdout = _TTYStringIO()
174
# so that we get a TextProgressBar
175
os.environ['TERM'] = 'xterm'
176
ui_factory = TextUIFactory(
178
stdout=stdout, stderr=stderr)
179
self.assertIsInstance(ui_factory._progress_view,
181
pb = ui_factory.nested_progress_bar()
183
# Create a progress update that isn't throttled
185
result = pb.note('t')
186
self.assertEqual(None, result)
187
self.assertEqual("t\n", stdout.getvalue())
188
# the exact contents will depend on the terminal width and we don't
189
# care about that right now - but you're probably running it on at
190
# least a 10-character wide terminal :)
191
self.assertContainsRe(stderr.getvalue(), r'\r {10,}\r$')
195
def test_progress_nested(self):
196
# test factory based nested and popping.
197
ui = TextUIFactory(None, None, None)
198
pb1 = ui.nested_progress_bar()
199
pb2 = ui.nested_progress_bar()
200
# You do get a warning if the outermost progress bar wasn't finished
201
# first - it's not clear if this is really useful or if it should just
202
# become orphaned -- mbp 20090120
203
warnings, _ = self.callCatchWarnings(pb1.finished)
204
if len(warnings) != 1:
205
self.fail("unexpected warnings: %r" % (warnings,))
117
209
def test_text_ui_get_boolean(self):
118
stdin = tests.StringIOWrapper("y\n" # True
120
"yes with garbage\nY\n" # True
121
"not an answer\nno\n" # False
122
"I'm sure!\nyes\n" # True
125
stdout = tests.StringIOWrapper()
126
stderr = tests.StringIOWrapper()
127
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
210
stdin = StringIO("y\n" # True
212
"yes with garbage\nY\n" # True
213
"not an answer\nno\n" # False
214
"I'm sure!\nyes\n" # True
219
factory = TextUIFactory(stdin, stdout, stderr)
128
220
self.assertEqual(True, factory.get_boolean(""))
129
221
self.assertEqual(False, factory.get_boolean(""))
130
222
self.assertEqual(True, factory.get_boolean(""))
135
227
# stdin should be empty
136
228
self.assertEqual('', factory.stdin.readline())
138
def test_text_ui_get_integer(self):
139
stdin = tests.StringIOWrapper(
142
"hmmm\nwhat else ?\nCome on\nok 42\n4.24\n42\n")
143
stdout = tests.StringIOWrapper()
144
stderr = tests.StringIOWrapper()
145
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
146
self.assertEqual(1, factory.get_integer(""))
147
self.assertEqual(-2, factory.get_integer(""))
148
self.assertEqual(42, factory.get_integer(""))
150
230
def test_text_factory_prompt(self):
151
231
# see <https://launchpad.net/bugs/365891>
152
StringIO = tests.StringIOWrapper
153
factory = _mod_ui_text.TextUIFactory(StringIO(), StringIO(), StringIO())
232
factory = TextUIFactory(StringIO(), StringIO(), StringIO())
154
233
factory.prompt('foo %2e')
155
234
self.assertEqual('', factory.stdout.getvalue())
156
235
self.assertEqual('foo %2e', factory.stderr.getvalue())
158
237
def test_text_factory_prompts_and_clears(self):
159
238
# a get_boolean call should clear the pb before prompting
160
out = test_progress._TTYStringIO()
161
240
os.environ['TERM'] = 'xterm'
162
factory = _mod_ui_text.TextUIFactory(
163
stdin=tests.StringIOWrapper("yada\ny\n"),
164
stdout=out, stderr=out)
165
factory._avail_width = lambda: 79
241
factory = TextUIFactory(stdin=StringIO("yada\ny\n"), stdout=out, stderr=out)
166
242
pb = factory.nested_progress_bar()
167
243
pb.show_bar = False
168
244
pb.show_spinner = False
228
def test_quietness(self):
229
os.environ['BZR_PROGRESS_BAR'] = 'text'
230
ui_factory = _mod_ui_text.TextUIFactory(None,
231
test_progress._TTYStringIO(),
232
test_progress._TTYStringIO())
233
self.assertIsInstance(ui_factory._progress_view,
234
_mod_ui_text.TextProgressView)
235
ui_factory.be_quiet(True)
236
self.assertIsInstance(ui_factory._progress_view,
237
_mod_ui_text.NullProgressView)
239
def test_text_ui_show_user_warning(self):
240
from bzrlib.repofmt.groupcompress_repo import RepositoryFormat2a
241
from bzrlib.repofmt.pack_repo import RepositoryFormatKnitPack5
244
ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
245
remote_fmt = remote.RemoteRepositoryFormat()
246
remote_fmt._network_name = RepositoryFormatKnitPack5().network_name()
247
ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
248
to_format=remote_fmt)
249
self.assertEquals('', out.getvalue())
250
self.assertEquals("Doing on-the-fly conversion from RepositoryFormat2a() to "
251
"RemoteRepositoryFormat(_network_name='Bazaar RepositoryFormatKnitPack5 "
252
"(bzr 1.6)\\n').\nThis may take some time. Upgrade the repositories to "
253
"the same format for better performance.\n",
255
# and now with it suppressed please
258
ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
259
ui.suppressed_warnings.add('cross_format_fetch')
260
ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
261
to_format=remote_fmt)
262
self.assertEquals('', out.getvalue())
263
self.assertEquals('', err.getvalue())
266
class TestTextUIOutputStream(tests.TestCase):
267
"""Tests for output stream that synchronizes with progress bar."""
269
def test_output_clears_terminal(self):
270
stdout = tests.StringIOWrapper()
271
stderr = tests.StringIOWrapper()
274
uif = _mod_ui_text.TextUIFactory(None, stdout, stderr)
275
uif.clear_term = lambda: clear_calls.append('clear')
277
stream = _mod_ui_text.TextUIOutputStream(uif, uif.stdout)
278
stream.write("Hello world!\n")
279
stream.write("there's more...\n")
280
stream.writelines(["1\n", "2\n", "3\n"])
282
self.assertEqual(stdout.getvalue(),
286
self.assertEqual(['clear', 'clear', 'clear'],
292
class UITests(tests.TestCase):
294
def test_progress_construction(self):
295
"""TextUIFactory constructs the right progress view.
297
TTYStringIO = test_progress._TTYStringIO
298
FileStringIO = tests.StringIOWrapper
299
for (file_class, term, pb, expected_pb_class) in (
300
# on an xterm, either use them or not as the user requests,
301
# otherwise default on
302
(TTYStringIO, 'xterm', 'none', _mod_ui_text.NullProgressView),
303
(TTYStringIO, 'xterm', 'text', _mod_ui_text.TextProgressView),
304
(TTYStringIO, 'xterm', None, _mod_ui_text.TextProgressView),
305
# on a dumb terminal, again if there's explicit configuration do
306
# it, otherwise default off
307
(TTYStringIO, 'dumb', 'none', _mod_ui_text.NullProgressView),
308
(TTYStringIO, 'dumb', 'text', _mod_ui_text.TextProgressView),
309
(TTYStringIO, 'dumb', None, _mod_ui_text.NullProgressView),
310
# on a non-tty terminal, it's null regardless of $TERM
311
(FileStringIO, 'xterm', None, _mod_ui_text.NullProgressView),
312
(FileStringIO, 'dumb', None, _mod_ui_text.NullProgressView),
313
# however, it can still be forced on
314
(FileStringIO, 'dumb', 'text', _mod_ui_text.TextProgressView),
316
os.environ['TERM'] = term
318
if 'BZR_PROGRESS_BAR' in os.environ:
319
del os.environ['BZR_PROGRESS_BAR']
321
os.environ['BZR_PROGRESS_BAR'] = pb
322
stdin = file_class('')
323
stderr = file_class()
324
stdout = file_class()
325
uif = _mod_ui.make_ui_for_terminal(stdin, stdout, stderr)
326
self.assertIsInstance(uif, _mod_ui_text.TextUIFactory,
327
"TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
328
self.assertIsInstance(uif.make_progress_view(),
330
"TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
332
def test_text_ui_non_terminal(self):
333
"""Even on non-ttys, make_ui_for_terminal gives a text ui."""
334
stdin = test_progress._NonTTYStringIO('')
335
stderr = test_progress._NonTTYStringIO()
336
stdout = test_progress._NonTTYStringIO()
337
for term_type in ['dumb', None, 'xterm']:
338
if term_type is None:
339
del os.environ['TERM']
341
os.environ['TERM'] = term_type
342
uif = _mod_ui.make_ui_for_terminal(stdin, stdout, stderr)
343
self.assertIsInstance(uif, _mod_ui_text.TextUIFactory,
344
'TERM=%r' % (term_type,))
347
class SilentUITests(tests.TestCase):
304
class CLIUITests(TestCase):
306
def test_cli_factory_deprecated(self):
307
uif = self.applyDeprecated(deprecated_in((1, 18, 0)),
309
StringIO(), StringIO(), StringIO())
310
self.assertIsInstance(uif, UIFactory)
313
class SilentUITests(TestCase):
349
315
def test_silent_factory_get_password(self):
350
316
# A silent factory that can't do user interaction can't get a
351
317
# password. Possibly it should raise a more specific error but it
353
ui = _mod_ui.SilentUIFactory()
354
stdout = tests.StringIOWrapper()
319
ui = SilentUIFactory()
355
321
self.assertRaises(
356
322
NotImplementedError,
357
323
self.apply_redirected,
360
326
self.assertEqual('', stdout.getvalue())
362
328
def test_silent_ui_getbool(self):
363
factory = _mod_ui.SilentUIFactory()
364
stdout = tests.StringIOWrapper()
329
factory = SilentUIFactory()
365
331
self.assertRaises(
366
332
NotImplementedError,
367
333
self.apply_redirected,
368
334
None, stdout, stdout, factory.get_boolean, "foo")
371
class TestUIFactoryTests(tests.TestCase):
337
class TestUIFactoryTests(TestCase):
373
339
def test_test_ui_factory_progress(self):
374
340
# there's no output; we just want to make sure this doesn't crash -
375
# see https://bugs.launchpad.net/bzr/+bug/408201
376
ui = tests.TestUIFactory()
341
# see https://bugs.edge.launchpad.net/bzr/+bug/408201
377
343
pb = ui.nested_progress_bar()
378
344
pb.update('hello')
383
class CannedInputUIFactoryTests(tests.TestCase):
349
class CannedInputUIFactoryTests(TestCase):
385
351
def test_canned_input_get_input(self):
386
uif = _mod_ui.CannedInputUIFactory([True, 'mbp', 'password', 42])
387
self.assertEqual(True, uif.get_boolean('Extra cheese?'))
388
self.assertEqual('mbp', uif.get_username('Enter your user name'))
389
self.assertEqual('password',
390
uif.get_password('Password for %(host)s',
392
self.assertEqual(42, uif.get_integer('And all that jazz ?'))
352
uif = CannedInputUIFactory([True, 'mbp', 'password'])
353
self.assertEqual(uif.get_boolean('Extra cheese?'), True)
354
self.assertEqual(uif.get_username('Enter your user name'), 'mbp')
355
self.assertEqual(uif.get_password('Password for %(host)s', host='example.com'),
395
359
class TestBoolFromString(tests.TestCase):
446
410
self.assertIsNone('0', av)
447
411
self.assertIsNone('on', av)
448
412
self.assertIsNone('off', av)
451
class TestConfirmationUserInterfacePolicy(tests.TestCase):
453
def test_confirm_action_default(self):
454
base_ui = _mod_ui.NoninteractiveUIFactory()
455
for answer in [True, False]:
457
_mod_ui.ConfirmationUserInterfacePolicy(base_ui, answer, {})
458
.confirm_action("Do something?",
459
"bzrlib.tests.do_something", {}),
462
def test_confirm_action_specific(self):
463
base_ui = _mod_ui.NoninteractiveUIFactory()
464
for default_answer in [True, False]:
465
for specific_answer in [True, False]:
466
for conf_id in ['given_id', 'other_id']:
467
wrapper = _mod_ui.ConfirmationUserInterfacePolicy(
468
base_ui, default_answer, dict(given_id=specific_answer))
469
result = wrapper.confirm_action("Do something?", conf_id, {})
470
if conf_id == 'given_id':
471
self.assertEquals(result, specific_answer)
473
self.assertEquals(result, default_answer)
476
base_ui = _mod_ui.NoninteractiveUIFactory()
477
wrapper = _mod_ui.ConfirmationUserInterfacePolicy(
478
base_ui, True, dict(a=2))
479
self.assertThat(repr(wrapper),
480
Equals("ConfirmationUserInterfacePolicy("
481
"NoninteractiveUIFactory(), True, {'a': 2})"))
484
class TestProgressRecordingUI(tests.TestCase):
485
"""Test test-oriented UIFactory that records progress updates"""
487
def test_nested_ignore_depth_beyond_one(self):
488
# we only want to capture the first level out progress, not
489
# want sub-components might do. So we have nested bars ignored.
490
factory = ProgressRecordingUIFactory()
491
pb1 = factory.nested_progress_bar()
492
pb1.update('foo', 0, 1)
493
pb2 = factory.nested_progress_bar()
494
pb2.update('foo', 0, 1)
497
self.assertEqual([("update", 0, 1, 'foo')], factory._calls)