17
17
"""Tests for the bzrlib ui
22
from StringIO import StringIO
24
from testtools.matchers import *
26
24
from bzrlib import (
32
from bzrlib.tests import (
29
from bzrlib.symbol_versioning import (
32
from bzrlib.tests import test_progress
36
33
from bzrlib.ui import text as _mod_ui_text
37
from bzrlib.tests.testui import (
38
ProgressRecordingUIFactory,
42
class TestUIConfiguration(tests.TestCaseWithTransport):
44
def test_output_encoding_configuration(self):
45
enc = fixtures.generate_unicode_encodings().next()
46
config.GlobalConfig().set_user_option('output_encoding',
48
ui = tests.TestUIFactory(stdin=None,
49
stdout=tests.StringIOWrapper(),
50
stderr=tests.StringIOWrapper())
51
output = ui.make_output_stream()
52
self.assertEquals(output.encoding, enc)
55
36
class TestTextUIFactory(tests.TestCase):
57
def make_test_ui_factory(self, stdin_contents):
58
ui = tests.TestUIFactory(stdin=stdin_contents,
59
stdout=tests.StringIOWrapper(),
60
stderr=tests.StringIOWrapper())
63
def test_text_factory_confirm(self):
64
# turns into reading a regular boolean
65
ui = self.make_test_ui_factory('n\n')
66
self.assertEquals(ui.confirm_action(u'Should %(thing)s pass?',
67
'bzrlib.tests.test_ui.confirmation',
71
38
def test_text_factory_ascii_password(self):
72
ui = self.make_test_ui_factory('secret\n')
39
ui = tests.TestUIFactory(stdin='secret\n',
40
stdout=tests.StringIOWrapper(),
41
stderr=tests.StringIOWrapper())
73
42
pb = ui.nested_progress_bar()
75
44
self.assertEqual('secret',
90
59
We can't predict what encoding users will have for stdin, so we force
91
60
it to utf8 to test that we transport the password correctly.
93
ui = self.make_test_ui_factory(u'baz\u1234'.encode('utf8'))
62
ui = tests.TestUIFactory(stdin=u'baz\u1234'.encode('utf8'),
63
stdout=tests.StringIOWrapper(),
64
stderr=tests.StringIOWrapper())
94
65
ui.stderr.encoding = ui.stdout.encoding = ui.stdin.encoding = 'utf8'
95
66
pb = ui.nested_progress_bar()
82
def test_progress_note(self):
83
stderr = tests.StringIOWrapper()
84
stdout = tests.StringIOWrapper()
85
ui_factory = _mod_ui_text.TextUIFactory(stdin=tests.StringIOWrapper(''),
88
pb = ui_factory.nested_progress_bar()
90
result = self.applyDeprecated(deprecated_in((2, 1, 0)),
93
self.assertEqual(None, result)
94
self.assertEqual("t\n", stdout.getvalue())
95
# Since there was no update() call, there should be no clear() call
96
self.failIf(re.search(r'^\r {10,}\r$',
97
stderr.getvalue()) is not None,
98
'We cleared the stderr without anything to put there')
102
def test_progress_note_clears(self):
103
stderr = test_progress._TTYStringIO()
104
stdout = test_progress._TTYStringIO()
105
# so that we get a TextProgressBar
106
os.environ['TERM'] = 'xterm'
107
ui_factory = _mod_ui_text.TextUIFactory(
108
stdin=tests.StringIOWrapper(''),
109
stdout=stdout, stderr=stderr)
110
self.assertIsInstance(ui_factory._progress_view,
111
_mod_ui_text.TextProgressView)
112
pb = ui_factory.nested_progress_bar()
114
# Create a progress update that isn't throttled
116
result = self.applyDeprecated(deprecated_in((2, 1, 0)),
118
self.assertEqual(None, result)
119
self.assertEqual("t\n", stdout.getvalue())
120
# the exact contents will depend on the terminal width and we don't
121
# care about that right now - but you're probably running it on at
122
# least a 10-character wide terminal :)
123
self.assertContainsRe(stderr.getvalue(), r'\r {10,}\r$')
127
def test_progress_nested(self):
128
# test factory based nested and popping.
129
ui = _mod_ui_text.TextUIFactory(None, None, None)
130
pb1 = ui.nested_progress_bar()
131
pb2 = ui.nested_progress_bar()
132
# You do get a warning if the outermost progress bar wasn't finished
133
# first - it's not clear if this is really useful or if it should just
134
# become orphaned -- mbp 20090120
135
warnings, _ = self.callCatchWarnings(pb1.finished)
136
if len(warnings) != 1:
137
self.fail("unexpected warnings: %r" % (warnings,))
111
141
def test_text_ui_get_boolean(self):
112
142
stdin = tests.StringIOWrapper("y\n" # True
119
149
stdout = tests.StringIOWrapper()
120
150
stderr = tests.StringIOWrapper()
121
151
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
122
self.assertEqual(True, factory.get_boolean(u""))
123
self.assertEqual(False, factory.get_boolean(u""))
124
self.assertEqual(True, factory.get_boolean(u""))
125
self.assertEqual(False, factory.get_boolean(u""))
126
self.assertEqual(True, factory.get_boolean(u""))
127
self.assertEqual(False, factory.get_boolean(u""))
152
self.assertEqual(True, factory.get_boolean(""))
153
self.assertEqual(False, factory.get_boolean(""))
154
self.assertEqual(True, factory.get_boolean(""))
155
self.assertEqual(False, factory.get_boolean(""))
156
self.assertEqual(True, factory.get_boolean(""))
157
self.assertEqual(False, factory.get_boolean(""))
128
158
self.assertEqual("foo\n", factory.stdin.read())
129
159
# stdin should be empty
130
160
self.assertEqual('', factory.stdin.readline())
137
167
stdout = tests.StringIOWrapper()
138
168
stderr = tests.StringIOWrapper()
139
169
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
140
self.assertEqual(1, factory.get_integer(u""))
141
self.assertEqual(-2, factory.get_integer(u""))
142
self.assertEqual(42, factory.get_integer(u""))
170
self.assertEqual(1, factory.get_integer(""))
171
self.assertEqual(-2, factory.get_integer(""))
172
self.assertEqual(42, factory.get_integer(""))
144
174
def test_text_factory_prompt(self):
145
175
# see <https://launchpad.net/bugs/365891>
146
176
StringIO = tests.StringIOWrapper
147
177
factory = _mod_ui_text.TextUIFactory(StringIO(), StringIO(), StringIO())
148
factory.prompt(u'foo %2e')
178
factory.prompt('foo %2e')
149
179
self.assertEqual('', factory.stdout.getvalue())
150
180
self.assertEqual('foo %2e', factory.stderr.getvalue())
152
182
def test_text_factory_prompts_and_clears(self):
153
183
# a get_boolean call should clear the pb before prompting
154
184
out = test_progress._TTYStringIO()
155
self.overrideEnv('TERM', 'xterm')
185
os.environ['TERM'] = 'xterm'
156
186
factory = _mod_ui_text.TextUIFactory(
157
187
stdin=tests.StringIOWrapper("yada\ny\n"),
158
188
stdout=out, stderr=out)
159
factory._avail_width = lambda: 79
160
189
pb = factory.nested_progress_bar()
161
190
pb.show_bar = False
162
191
pb.show_spinner = False
166
195
self.apply_redirected(None, factory.stdout,
168
197
factory.get_boolean,
169
u"what do you want"))
170
199
output = out.getvalue()
171
self.assertContainsRe(output,
173
self.assertContainsRe(output,
200
self.assertContainsRe(factory.stdout.getvalue(),
202
self.assertContainsRe(factory.stdout.getvalue(),
174
203
r"what do you want\? \[y/n\]: what do you want\? \[y/n\]: ")
175
204
# stdin should have been totally consumed
176
205
self.assertEqual('', factory.stdin.readline())
195
224
factory.stdout.encoding = "utf8"
196
225
# there is no output from the base factory
197
226
self.assertEqual("someuser",
198
factory.get_username(u'Hello %(host)s', host='some'))
227
factory.get_username('Hello %(host)s', host='some'))
199
228
self.assertEquals("Hello some: ", factory.stderr.getvalue())
200
229
self.assertEquals('', factory.stdout.getvalue())
201
self.assertEqual("", factory.get_username(u"Gebruiker"))
230
self.assertEqual("", factory.get_username("Gebruiker"))
202
231
# stdin should be empty
203
232
self.assertEqual('', factory.stdin.readline())
222
def test_quietness(self):
223
self.overrideEnv('BZR_PROGRESS_BAR', 'text')
224
ui_factory = _mod_ui_text.TextUIFactory(None,
225
test_progress._TTYStringIO(),
226
test_progress._TTYStringIO())
227
self.assertIsInstance(ui_factory._progress_view,
228
_mod_ui_text.TextProgressView)
229
ui_factory.be_quiet(True)
230
self.assertIsInstance(ui_factory._progress_view,
231
_mod_ui_text.NullProgressView)
233
def test_text_ui_show_user_warning(self):
234
from bzrlib.repofmt.groupcompress_repo import RepositoryFormat2a
235
from bzrlib.repofmt.knitpack_repo import RepositoryFormatKnitPack5
238
ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
239
remote_fmt = remote.RemoteRepositoryFormat()
240
remote_fmt._network_name = RepositoryFormatKnitPack5().network_name()
241
ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
242
to_format=remote_fmt)
243
self.assertEquals('', out.getvalue())
244
self.assertEquals("Doing on-the-fly conversion from RepositoryFormat2a() to "
245
"RemoteRepositoryFormat(_network_name='Bazaar RepositoryFormatKnitPack5 "
246
"(bzr 1.6)\\n').\nThis may take some time. Upgrade the repositories to "
247
"the same format for better performance.\n",
249
# and now with it suppressed please
252
ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
253
ui.suppressed_warnings.add('cross_format_fetch')
254
ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
255
to_format=remote_fmt)
256
self.assertEquals('', out.getvalue())
257
self.assertEquals('', err.getvalue())
260
252
class TestTextUIOutputStream(tests.TestCase):
261
253
"""Tests for output stream that synchronizes with progress bar."""
307
299
# however, it can still be forced on
308
300
(FileStringIO, 'dumb', 'text', _mod_ui_text.TextProgressView),
310
self.overrideEnv('TERM', term)
311
self.overrideEnv('BZR_PROGRESS_BAR', pb)
302
os.environ['TERM'] = term
304
if 'BZR_PROGRESS_BAR' in os.environ:
305
del os.environ['BZR_PROGRESS_BAR']
307
os.environ['BZR_PROGRESS_BAR'] = pb
312
308
stdin = file_class('')
313
309
stderr = file_class()
314
310
stdout = file_class()
325
321
stderr = test_progress._NonTTYStringIO()
326
322
stdout = test_progress._NonTTYStringIO()
327
323
for term_type in ['dumb', None, 'xterm']:
328
self.overrideEnv('TERM', term_type)
324
if term_type is None:
325
del os.environ['TERM']
327
os.environ['TERM'] = term_type
329
328
uif = _mod_ui.make_ui_for_terminal(stdin, stdout, stderr)
330
329
self.assertIsInstance(uif, _mod_ui_text.TextUIFactory,
331
330
'TERM=%r' % (term_type,))
352
351
self.assertRaises(
353
352
NotImplementedError,
354
353
self.apply_redirected,
355
None, stdout, stdout, factory.get_boolean, u"foo")
354
None, stdout, stdout, factory.get_boolean, "foo")
358
357
class TestUIFactoryTests(tests.TestCase):
360
359
def test_test_ui_factory_progress(self):
361
360
# there's no output; we just want to make sure this doesn't crash -
362
# see https://bugs.launchpad.net/bzr/+bug/408201
361
# see https://bugs.edge.launchpad.net/bzr/+bug/408201
363
362
ui = tests.TestUIFactory()
364
363
pb = ui.nested_progress_bar()
365
364
pb.update('hello')
372
371
def test_canned_input_get_input(self):
373
372
uif = _mod_ui.CannedInputUIFactory([True, 'mbp', 'password', 42])
374
self.assertEqual(True, uif.get_boolean(u'Extra cheese?'))
375
self.assertEqual('mbp', uif.get_username(u'Enter your user name'))
373
self.assertEqual(True, uif.get_boolean('Extra cheese?'))
374
self.assertEqual('mbp', uif.get_username('Enter your user name'))
376
375
self.assertEqual('password',
377
uif.get_password(u'Password for %(host)s',
376
uif.get_password('Password for %(host)s',
378
377
host='example.com'))
379
self.assertEqual(42, uif.get_integer(u'And all that jazz ?'))
378
self.assertEqual(42, uif.get_integer('And all that jazz ?'))
382
381
class TestBoolFromString(tests.TestCase):
433
432
self.assertIsNone('0', av)
434
433
self.assertIsNone('on', av)
435
434
self.assertIsNone('off', av)
438
class TestConfirmationUserInterfacePolicy(tests.TestCase):
440
def test_confirm_action_default(self):
441
base_ui = _mod_ui.NoninteractiveUIFactory()
442
for answer in [True, False]:
444
_mod_ui.ConfirmationUserInterfacePolicy(base_ui, answer, {})
445
.confirm_action("Do something?",
446
"bzrlib.tests.do_something", {}),
449
def test_confirm_action_specific(self):
450
base_ui = _mod_ui.NoninteractiveUIFactory()
451
for default_answer in [True, False]:
452
for specific_answer in [True, False]:
453
for conf_id in ['given_id', 'other_id']:
454
wrapper = _mod_ui.ConfirmationUserInterfacePolicy(
455
base_ui, default_answer, dict(given_id=specific_answer))
456
result = wrapper.confirm_action("Do something?", conf_id, {})
457
if conf_id == 'given_id':
458
self.assertEquals(result, specific_answer)
460
self.assertEquals(result, default_answer)
463
base_ui = _mod_ui.NoninteractiveUIFactory()
464
wrapper = _mod_ui.ConfirmationUserInterfacePolicy(
465
base_ui, True, dict(a=2))
466
self.assertThat(repr(wrapper),
467
Equals("ConfirmationUserInterfacePolicy("
468
"NoninteractiveUIFactory(), True, {'a': 2})"))
471
class TestProgressRecordingUI(tests.TestCase):
472
"""Test test-oriented UIFactory that records progress updates"""
474
def test_nested_ignore_depth_beyond_one(self):
475
# we only want to capture the first level out progress, not
476
# want sub-components might do. So we have nested bars ignored.
477
factory = ProgressRecordingUIFactory()
478
pb1 = factory.nested_progress_bar()
479
pb1.update('foo', 0, 1)
480
pb2 = factory.nested_progress_bar()
481
pb2.update('foo', 0, 1)
484
self.assertEqual([("update", 0, 1, 'foo')], factory._calls)