102
103
def test_progress_construction(self):
103
104
"""TextUIFactory constructs the right progress view.
105
os.environ['BZR_PROGRESS_BAR'] = 'none'
106
self.assertIsInstance(TextUIFactory()._progress_view,
109
os.environ['BZR_PROGRESS_BAR'] = 'text'
110
self.assertIsInstance(TextUIFactory()._progress_view,
113
os.environ['BZR_PROGRESS_BAR'] = 'text'
114
self.assertIsInstance(TextUIFactory()._progress_view,
117
del os.environ['BZR_PROGRESS_BAR']
118
self.assertIsInstance(TextUIFactory()._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,))
121
153
def test_progress_note(self):
122
154
stderr = StringIO()
176
def assert_get_bool_acceptance_of_user_input(self, factory):
177
factory.stdin = StringIO("y\nyes with garbage\n"
178
"yes\nn\nnot an answer\n"
183
factory.stdout = StringIO()
184
factory.stderr = StringIO()
185
# there is no output from the base factory
186
self.assertEqual(True, factory.get_boolean(""))
187
self.assertEqual(True, factory.get_boolean(""))
188
self.assertEqual(False, factory.get_boolean(""))
189
self.assertEqual(False, factory.get_boolean(""))
190
self.assertEqual(False, factory.get_boolean(""))
191
self.assertEqual(True, factory.get_boolean(""))
209
def test_text_ui_get_boolean(self):
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)
220
self.assertEqual(True, factory.get_boolean(""))
221
self.assertEqual(False, factory.get_boolean(""))
222
self.assertEqual(True, factory.get_boolean(""))
223
self.assertEqual(False, factory.get_boolean(""))
224
self.assertEqual(True, factory.get_boolean(""))
225
self.assertEqual(False, factory.get_boolean(""))
192
226
self.assertEqual("foo\n", factory.stdin.read())
193
227
# stdin should be empty
194
228
self.assertEqual('', factory.stdin.readline())
196
def test_silent_ui_getbool(self):
197
factory = _mod_ui.SilentUIFactory()
198
self.assert_get_bool_acceptance_of_user_input(factory)
200
def test_silent_factory_prompts_silently(self):
201
factory = _mod_ui.SilentUIFactory()
203
factory.stdin = StringIO("y\n")
204
self.assertEqual(True,
205
self.apply_redirected(None, stdout, stdout,
206
factory.get_boolean, "foo"))
207
self.assertEqual("", stdout.getvalue())
208
# stdin should be empty
209
self.assertEqual('', factory.stdin.readline())
211
def test_text_ui_getbool(self):
212
factory = TextUIFactory(None, None, None)
213
self.assert_get_bool_acceptance_of_user_input(factory)
215
230
def test_text_factory_prompt(self):
216
231
# see <https://launchpad.net/bugs/365891>
217
factory = TextUIFactory(None, StringIO(), StringIO(), StringIO())
232
factory = TextUIFactory(StringIO(), StringIO(), StringIO())
218
233
factory.prompt('foo %2e')
219
234
self.assertEqual('', factory.stdout.getvalue())
220
235
self.assertEqual('foo %2e', factory.stderr.getvalue())
300
class TestTextProgressView(tests.TestCase):
301
"""Tests for text display of progress bars.
303
# XXX: These might be a bit easier to write if the rendering and
304
# state-maintaining parts of TextProgressView were more separate, and if
305
# the progress task called back directly to its own view not to the ui
306
# factory. -- mbp 20090312
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):
315
def test_silent_factory_get_password(self):
316
# A silent factory that can't do user interaction can't get a
317
# password. Possibly it should raise a more specific error but it
319
ui = SilentUIFactory()
323
self.apply_redirected,
324
None, stdout, stdout, ui.get_password)
325
# and it didn't write anything out either
326
self.assertEqual('', stdout.getvalue())
328
def test_silent_ui_getbool(self):
329
factory = SilentUIFactory()
333
self.apply_redirected,
334
None, stdout, stdout, factory.get_boolean, "foo")
337
class CannedInputUIFactoryTests(TestCase):
308
def _make_factory(self):
310
uif = TextUIFactory(stderr=out)
311
uif._progress_view._width = 80
314
def test_render_progress_easy(self):
315
"""Just one task and one quarter done"""
316
out, uif = self._make_factory()
317
task = uif.nested_progress_bar()
318
task.update('reticulating splines', 5, 20)
320
'\r[####/ ] reticulating splines 5/20 \r'
323
def test_render_progress_nested(self):
324
"""Tasks proportionally contribute to overall progress"""
325
out, uif = self._make_factory()
326
task = uif.nested_progress_bar()
327
task.update('reticulating splines', 0, 2)
328
task2 = uif.nested_progress_bar()
329
task2.update('stage2', 1, 2)
330
# so we're in the first half of the main task, and half way through
333
r'[####\ ] reticulating splines:stage2 1/2'
334
, uif._progress_view._render_line())
335
# if the nested task is complete, then we're all the way through the
336
# first half of the overall work
337
task2.update('stage2', 2, 2)
339
r'[#########| ] reticulating splines:stage2 2/2'
340
, uif._progress_view._render_line())
342
def test_render_progress_sub_nested(self):
343
"""Intermediate tasks don't mess up calculation."""
344
out, uif = self._make_factory()
345
task_a = uif.nested_progress_bar()
346
task_a.update('a', 0, 2)
347
task_b = uif.nested_progress_bar()
349
task_c = uif.nested_progress_bar()
350
task_c.update('c', 1, 2)
351
# the top-level task is in its first half; the middle one has no
352
# progress indication, just a label; and the bottom one is half done,
353
# so the overall fraction is 1/4
355
r'[####| ] a:b:c 1/2'
356
, uif._progress_view._render_line())
339
def test_canned_input_get_input(self):
340
uif = CannedInputUIFactory([True, 'mbp', 'password'])
341
self.assertEqual(uif.get_boolean('Extra cheese?'), True)
342
self.assertEqual(uif.get_username('Enter your user name'), 'mbp')
343
self.assertEqual(uif.get_password('Password for %(host)s', host='example.com'),
347
class TestBoolFromString(tests.TestCase):
349
def assertIsTrue(self, s, accepted_values=None):
350
res = _mod_ui.bool_from_string(s, accepted_values=accepted_values)
351
self.assertEquals(True, res)
353
def assertIsFalse(self, s, accepted_values=None):
354
res = _mod_ui.bool_from_string(s, accepted_values=accepted_values)
355
self.assertEquals(False, res)
357
def assertIsNone(self, s, accepted_values=None):
358
res = _mod_ui.bool_from_string(s, accepted_values=accepted_values)
359
self.assertIs(None, res)
361
def test_know_valid_values(self):
362
self.assertIsTrue('true')
363
self.assertIsFalse('false')
364
self.assertIsTrue('1')
365
self.assertIsFalse('0')
366
self.assertIsTrue('on')
367
self.assertIsFalse('off')
368
self.assertIsTrue('yes')
369
self.assertIsFalse('no')
370
self.assertIsTrue('y')
371
self.assertIsFalse('n')
372
# Also try some case variations
373
self.assertIsTrue('True')
374
self.assertIsFalse('False')
375
self.assertIsTrue('On')
376
self.assertIsFalse('Off')
377
self.assertIsTrue('ON')
378
self.assertIsFalse('OFF')
379
self.assertIsTrue('oN')
380
self.assertIsFalse('oFf')
382
def test_invalid_values(self):
383
self.assertIsNone(None)
384
self.assertIsNone('doubt')
385
self.assertIsNone('frue')
386
self.assertIsNone('talse')
387
self.assertIsNone('42')
389
def test_provided_values(self):
390
av = dict(y=True, n=False, yes=True, no=False)
391
self.assertIsTrue('y', av)
392
self.assertIsTrue('Y', av)
393
self.assertIsTrue('Yes', av)
394
self.assertIsFalse('n', av)
395
self.assertIsFalse('N', av)
396
self.assertIsFalse('No', av)
397
self.assertIsNone('1', av)
398
self.assertIsNone('0', av)
399
self.assertIsNone('on', av)
400
self.assertIsNone('off', av)