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',
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$')
111
127
def test_text_ui_get_boolean(self):
112
128
stdin = tests.StringIOWrapper("y\n" # True
116
130
"yes with garbage\nY\n" # True
117
131
"not an answer\nno\n" # False
118
132
"I'm sure!\nyes\n" # True
121
135
stdout = tests.StringIOWrapper()
122
136
stderr = tests.StringIOWrapper()
123
137
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
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""))
128
self.assertEqual(True, factory.get_boolean(u""))
129
self.assertEqual(False, factory.get_boolean(u""))
130
self.assertEqual(True, factory.get_boolean(u""))
131
self.assertEqual(False, factory.get_boolean(u""))
132
self.assertEqual("foo\n", factory.stdin.read())
133
# stdin should be empty
134
self.assertEqual('', factory.stdin.readline())
135
# return false on EOF
136
self.assertEqual(False, factory.get_boolean(u""))
138
def test_text_ui_choose_bad_parameters(self):
139
stdin = tests.StringIOWrapper()
140
stdout = tests.StringIOWrapper()
141
stderr = tests.StringIOWrapper()
142
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
143
# invalid default index
144
self.assertRaises(ValueError, factory.choose, u"", u"&Yes\n&No", 3)
146
self.assertRaises(ValueError, factory.choose, u"", u"&choice\n&ChOiCe")
147
# duplicated shortcut
148
self.assertRaises(ValueError, factory.choose, u"", u"&choice1\nchoi&ce2")
150
def test_text_ui_choose_prompt(self):
151
stdin = tests.StringIOWrapper()
152
stdout = tests.StringIOWrapper()
153
stderr = tests.StringIOWrapper()
154
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
155
# choices with explicit shortcuts
156
factory.choose(u"prompt", u"&yes\n&No\nmore &info")
157
self.assertEqual("prompt ([y]es, [N]o, more [i]nfo): \n", factory.stderr.getvalue())
158
# automatic shortcuts
159
factory.stderr.truncate(0)
160
factory.choose(u"prompt", u"yes\nNo\nmore info")
161
self.assertEqual("prompt ([y]es, [N]o, [m]ore info): \n", factory.stderr.getvalue())
163
def test_text_ui_choose_return_values(self):
164
choose = lambda: factory.choose(u"", u"&Yes\n&No\nMaybe\nmore &info", 3)
165
stdin = tests.StringIOWrapper("y\n" # 0
169
"b\na\nd \n" # bad shortcuts, all ignored
170
"yes with garbage\nY\n" # 0
171
"not an answer\nno\n" # 1
172
"info\nmore info\n" # 3
175
stdout = tests.StringIOWrapper()
176
stderr = tests.StringIOWrapper()
177
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
178
self.assertEqual(0, choose())
179
self.assertEqual(1, choose())
180
self.assertEqual(3, choose())
181
self.assertEqual(1, choose())
182
self.assertEqual(0, choose())
183
self.assertEqual(1, choose())
184
self.assertEqual(3, choose())
185
self.assertEqual(2, choose())
186
self.assertEqual("foo\n", factory.stdin.read())
187
# stdin should be empty
188
self.assertEqual('', factory.stdin.readline())
190
self.assertEqual(None, choose())
192
def test_text_ui_choose_no_default(self):
193
stdin = tests.StringIOWrapper(" \n" # no default, invalid!
196
stdout = tests.StringIOWrapper()
197
stderr = tests.StringIOWrapper()
198
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
199
self.assertEqual(0, factory.choose(u"", u"&Yes\n&No"))
200
self.assertEqual("foo\n", factory.stdin.read())
138
self.assertEqual(True, factory.get_boolean(""))
139
self.assertEqual(False, factory.get_boolean(""))
140
self.assertEqual(True, factory.get_boolean(""))
141
self.assertEqual(False, factory.get_boolean(""))
142
self.assertEqual(True, factory.get_boolean(""))
143
self.assertEqual(False, factory.get_boolean(""))
144
self.assertEqual("foo\n", factory.stdin.read())
145
# stdin should be empty
146
self.assertEqual('', factory.stdin.readline())
202
148
def test_text_ui_get_integer(self):
203
149
stdin = tests.StringIOWrapper(
207
153
stdout = tests.StringIOWrapper()
208
154
stderr = tests.StringIOWrapper()
209
155
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
210
self.assertEqual(1, factory.get_integer(u""))
211
self.assertEqual(-2, factory.get_integer(u""))
212
self.assertEqual(42, factory.get_integer(u""))
156
self.assertEqual(1, factory.get_integer(""))
157
self.assertEqual(-2, factory.get_integer(""))
158
self.assertEqual(42, factory.get_integer(""))
214
160
def test_text_factory_prompt(self):
215
161
# see <https://launchpad.net/bugs/365891>
216
162
StringIO = tests.StringIOWrapper
217
163
factory = _mod_ui_text.TextUIFactory(StringIO(), StringIO(), StringIO())
218
factory.prompt(u'foo %2e')
164
factory.prompt('foo %2e')
219
165
self.assertEqual('', factory.stdout.getvalue())
220
166
self.assertEqual('foo %2e', factory.stderr.getvalue())
222
168
def test_text_factory_prompts_and_clears(self):
223
169
# a get_boolean call should clear the pb before prompting
224
170
out = test_progress._TTYStringIO()
225
self.overrideEnv('TERM', 'xterm')
171
os.environ['TERM'] = 'xterm'
226
172
factory = _mod_ui_text.TextUIFactory(
227
173
stdin=tests.StringIOWrapper("yada\ny\n"),
228
174
stdout=out, stderr=out)
229
factory._avail_width = lambda: 79
230
175
pb = factory.nested_progress_bar()
231
176
pb.show_bar = False
232
177
pb.show_spinner = False
300
245
self.assertIsInstance(ui_factory._progress_view,
301
246
_mod_ui_text.NullProgressView)
303
def test_text_ui_show_user_warning(self):
304
from bzrlib.repofmt.groupcompress_repo import RepositoryFormat2a
305
from bzrlib.repofmt.knitpack_repo import RepositoryFormatKnitPack5
308
ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
309
remote_fmt = remote.RemoteRepositoryFormat()
310
remote_fmt._network_name = RepositoryFormatKnitPack5().network_name()
311
ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
312
to_format=remote_fmt)
313
self.assertEquals('', out.getvalue())
314
self.assertEquals("Doing on-the-fly conversion from RepositoryFormat2a() to "
315
"RemoteRepositoryFormat(_network_name='Bazaar RepositoryFormatKnitPack5 "
316
"(bzr 1.6)\\n').\nThis may take some time. Upgrade the repositories to "
317
"the same format for better performance.\n",
319
# and now with it suppressed please
322
ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
323
ui.suppressed_warnings.add('cross_format_fetch')
324
ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
325
to_format=remote_fmt)
326
self.assertEquals('', out.getvalue())
327
self.assertEquals('', err.getvalue())
330
249
class TestTextUIOutputStream(tests.TestCase):
331
250
"""Tests for output stream that synchronizes with progress bar."""
442
368
def test_canned_input_get_input(self):
443
369
uif = _mod_ui.CannedInputUIFactory([True, 'mbp', 'password', 42])
444
self.assertEqual(True, uif.get_boolean(u'Extra cheese?'))
445
self.assertEqual('mbp', uif.get_username(u'Enter your user name'))
370
self.assertEqual(True, uif.get_boolean('Extra cheese?'))
371
self.assertEqual('mbp', uif.get_username('Enter your user name'))
446
372
self.assertEqual('password',
447
uif.get_password(u'Password for %(host)s',
373
uif.get_password('Password for %(host)s',
448
374
host='example.com'))
449
self.assertEqual(42, uif.get_integer(u'And all that jazz ?'))
375
self.assertEqual(42, uif.get_integer('And all that jazz ?'))
452
378
class TestBoolFromString(tests.TestCase):
503
429
self.assertIsNone('0', av)
504
430
self.assertIsNone('on', av)
505
431
self.assertIsNone('off', av)
508
class TestConfirmationUserInterfacePolicy(tests.TestCase):
510
def test_confirm_action_default(self):
511
base_ui = _mod_ui.NoninteractiveUIFactory()
512
for answer in [True, False]:
514
_mod_ui.ConfirmationUserInterfacePolicy(base_ui, answer, {})
515
.confirm_action("Do something?",
516
"bzrlib.tests.do_something", {}),
519
def test_confirm_action_specific(self):
520
base_ui = _mod_ui.NoninteractiveUIFactory()
521
for default_answer in [True, False]:
522
for specific_answer in [True, False]:
523
for conf_id in ['given_id', 'other_id']:
524
wrapper = _mod_ui.ConfirmationUserInterfacePolicy(
525
base_ui, default_answer, dict(given_id=specific_answer))
526
result = wrapper.confirm_action("Do something?", conf_id, {})
527
if conf_id == 'given_id':
528
self.assertEquals(result, specific_answer)
530
self.assertEquals(result, default_answer)
533
base_ui = _mod_ui.NoninteractiveUIFactory()
534
wrapper = _mod_ui.ConfirmationUserInterfacePolicy(
535
base_ui, True, dict(a=2))
536
self.assertThat(repr(wrapper),
537
Equals("ConfirmationUserInterfacePolicy("
538
"NoninteractiveUIFactory(), True, {'a': 2})"))
541
class TestProgressRecordingUI(tests.TestCase):
542
"""Test test-oriented UIFactory that records progress updates"""
544
def test_nested_ignore_depth_beyond_one(self):
545
# we only want to capture the first level out progress, not
546
# want sub-components might do. So we have nested bars ignored.
547
factory = ProgressRecordingUIFactory()
548
pb1 = factory.nested_progress_bar()
549
pb1.update('foo', 0, 1)
550
pb2 = factory.nested_progress_bar()
551
pb2.update('foo', 0, 1)
554
self.assertEqual([("update", 0, 1, 'foo')], factory._calls)