127
def test_text_ui_get_boolean(self):
128
stdin = tests.StringIOWrapper("y\n" # True
130
"yes with garbage\nY\n" # True
131
"not an answer\nno\n" # False
132
"I'm sure!\nyes\n" # True
135
stdout = tests.StringIOWrapper()
136
stderr = tests.StringIOWrapper()
137
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
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
def test_progress_nested(self):
144
# test factory based nested and popping.
146
pb1 = ui.nested_progress_bar()
147
pb2 = ui.nested_progress_bar()
148
self.assertRaises(errors.MissingProgressBarFinish, pb1.finished)
152
def test_progress_stack(self):
153
# test the progress bar stack which the default text factory
157
# make a stack, which accepts parameters like a pb.
158
stack = ProgressBarStack(to_file=stderr, to_messages_file=stdout)
160
self.assertFalse(getattr(stack, 'note', False))
161
pb1 = stack.get_nested()
162
pb2 = stack.get_nested()
163
self.assertRaises(errors.MissingProgressBarFinish, pb1.finished)
166
# the text ui factory never actually removes the stack once its setup.
167
# we need to be able to nest again correctly from here.
168
pb1 = stack.get_nested()
169
pb2 = stack.get_nested()
170
self.assertRaises(errors.MissingProgressBarFinish, pb1.finished)
174
def test_text_factory_setting_progress_bar(self):
175
# we should be able to choose the progress bar type used.
176
factory = TextUIFactory(bar_type=DotsProgressBar)
177
bar = factory.nested_progress_bar()
179
self.assertIsInstance(bar, DotsProgressBar)
181
def test_cli_stdin_is_default_stdin(self):
182
factory = CLIUIFactory()
183
self.assertEqual(sys.stdin, factory.stdin)
185
def assert_get_bool_acceptance_of_user_input(self, factory):
186
factory.stdin = StringIO("y\nyes with garbage\n"
187
"yes\nn\nnot an answer\n"
189
factory.stdout = StringIO()
190
# there is no output from the base factory
191
self.assertEqual(True, factory.get_boolean(""))
192
self.assertEqual(True, factory.get_boolean(""))
193
self.assertEqual(False, factory.get_boolean(""))
143
194
self.assertEqual(False, factory.get_boolean(""))
144
195
self.assertEqual("foo\n", factory.stdin.read())
145
196
# stdin should be empty
146
197
self.assertEqual('', factory.stdin.readline())
148
def test_text_ui_get_integer(self):
149
stdin = tests.StringIOWrapper(
152
"hmmm\nwhat else ?\nCome on\nok 42\n4.24\n42\n")
153
stdout = tests.StringIOWrapper()
154
stderr = tests.StringIOWrapper()
155
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
156
self.assertEqual(1, factory.get_integer(""))
157
self.assertEqual(-2, factory.get_integer(""))
158
self.assertEqual(42, factory.get_integer(""))
160
def test_text_factory_prompt(self):
161
# see <https://launchpad.net/bugs/365891>
162
StringIO = tests.StringIOWrapper
163
factory = _mod_ui_text.TextUIFactory(StringIO(), StringIO(), StringIO())
164
factory.prompt('foo %2e')
165
self.assertEqual('', factory.stdout.getvalue())
166
self.assertEqual('foo %2e', factory.stderr.getvalue())
199
def test_silent_ui_getbool(self):
200
factory = SilentUIFactory()
201
self.assert_get_bool_acceptance_of_user_input(factory)
203
def test_silent_factory_prompts_silently(self):
204
factory = SilentUIFactory()
206
factory.stdin = StringIO("y\n")
207
self.assertEqual(True,
208
self.apply_redirected(None, stdout, stdout,
209
factory.get_boolean, "foo"))
210
self.assertEqual("", stdout.getvalue())
211
# stdin should be empty
212
self.assertEqual('', factory.stdin.readline())
214
def test_text_ui_getbool(self):
215
factory = TextUIFactory()
216
self.assert_get_bool_acceptance_of_user_input(factory)
168
218
def test_text_factory_prompts_and_clears(self):
169
219
# a get_boolean call should clear the pb before prompting
170
out = test_progress._TTYStringIO()
171
os.environ['TERM'] = 'xterm'
172
factory = _mod_ui_text.TextUIFactory(
173
stdin=tests.StringIOWrapper("yada\ny\n"),
174
stdout=out, stderr=out)
175
pb = factory.nested_progress_bar()
177
pb.show_spinner = False
178
pb.show_count = False
179
pb.update("foo", 0, 1)
220
factory = TextUIFactory(bar_type=DotsProgressBar)
221
factory.stdout = _TTYStringIO()
222
factory.stdin = StringIO("yada\ny\n")
223
pb = self.apply_redirected(factory.stdin, factory.stdout,
224
factory.stdout, factory.nested_progress_bar)
226
self.apply_redirected(factory.stdin, factory.stdout,
227
factory.stdout, pb.update, "foo", 0, 1)
180
228
self.assertEqual(True,
181
229
self.apply_redirected(None, factory.stdout,
183
231
factory.get_boolean,
184
232
"what do you want"))
185
output = out.getvalue()
186
self.assertContainsRe(factory.stdout.getvalue(),
188
self.assertContainsRe(factory.stdout.getvalue(),
189
r"what do you want\? \[y/n\]: what do you want\? \[y/n\]: ")
190
# stdin should have been totally consumed
191
self.assertEqual('', factory.stdin.readline())
193
def test_text_tick_after_update(self):
194
ui_factory = _mod_ui_text.TextUIFactory(stdout=tests.StringIOWrapper(),
195
stderr=tests.StringIOWrapper())
196
pb = ui_factory.nested_progress_bar()
198
pb.update('task', 0, 3)
199
# Reset the clock, so that it actually tries to repaint itself
200
ui_factory._progress_view._last_repaint = time.time() - 1.0
205
def test_text_ui_getusername(self):
206
factory = _mod_ui_text.TextUIFactory(None, None, None)
207
factory.stdin = tests.StringIOWrapper("someuser\n\n")
208
factory.stdout = tests.StringIOWrapper()
209
factory.stderr = tests.StringIOWrapper()
210
factory.stdout.encoding = "utf8"
211
# there is no output from the base factory
212
self.assertEqual("someuser",
213
factory.get_username('Hello %(host)s', host='some'))
214
self.assertEquals("Hello some: ", factory.stderr.getvalue())
215
self.assertEquals('', factory.stdout.getvalue())
216
self.assertEqual("", factory.get_username("Gebruiker"))
233
output = factory.stdout.getvalue()
234
self.assertEqual("foo: .\n"
235
"what do you want? [y/n]: what do you want? [y/n]: ",
236
factory.stdout.getvalue())
217
237
# stdin should be empty
218
238
self.assertEqual('', factory.stdin.readline())
220
def test_text_ui_getusername_utf8(self):
221
ui = tests.TestUIFactory(stdin=u'someuser\u1234'.encode('utf8'),
222
stdout=tests.StringIOWrapper(),
223
stderr=tests.StringIOWrapper())
224
ui.stderr.encoding = ui.stdout.encoding = ui.stdin.encoding = "utf8"
225
pb = ui.nested_progress_bar()
227
# there is no output from the base factory
228
username = self.apply_redirected(ui.stdin, ui.stdout, ui.stderr,
229
ui.get_username, u'Hello\u1234 %(host)s', host=u'some\u1234')
230
self.assertEquals(u"someuser\u1234", username.decode('utf8'))
231
self.assertEquals(u"Hello\u1234 some\u1234: ",
232
ui.stderr.getvalue().decode("utf8"))
233
self.assertEquals('', ui.stdout.getvalue())
237
def test_quietness(self):
238
os.environ['BZR_PROGRESS_BAR'] = 'text'
239
ui_factory = _mod_ui_text.TextUIFactory(None,
240
test_progress._TTYStringIO(),
241
test_progress._TTYStringIO())
242
self.assertIsInstance(ui_factory._progress_view,
243
_mod_ui_text.TextProgressView)
244
ui_factory.be_quiet(True)
245
self.assertIsInstance(ui_factory._progress_view,
246
_mod_ui_text.NullProgressView)
249
class TestTextUIOutputStream(tests.TestCase):
250
"""Tests for output stream that synchronizes with progress bar."""
252
def test_output_clears_terminal(self):
253
stdout = tests.StringIOWrapper()
254
stderr = tests.StringIOWrapper()
257
uif = _mod_ui_text.TextUIFactory(None, stdout, stderr)
258
uif.clear_term = lambda: clear_calls.append('clear')
260
stream = _mod_ui_text.TextUIOutputStream(uif, uif.stdout)
261
stream.write("Hello world!\n")
262
stream.write("there's more...\n")
263
stream.writelines(["1\n", "2\n", "3\n"])
265
self.assertEqual(stdout.getvalue(),
269
self.assertEqual(['clear', 'clear', 'clear'],
275
class UITests(tests.TestCase):
277
def test_progress_construction(self):
278
"""TextUIFactory constructs the right progress view.
280
TTYStringIO = test_progress._TTYStringIO
281
FileStringIO = tests.StringIOWrapper
282
for (file_class, term, pb, expected_pb_class) in (
283
# on an xterm, either use them or not as the user requests,
284
# otherwise default on
285
(TTYStringIO, 'xterm', 'none', _mod_ui_text.NullProgressView),
286
(TTYStringIO, 'xterm', 'text', _mod_ui_text.TextProgressView),
287
(TTYStringIO, 'xterm', None, _mod_ui_text.TextProgressView),
288
# on a dumb terminal, again if there's explicit configuration do
289
# it, otherwise default off
290
(TTYStringIO, 'dumb', 'none', _mod_ui_text.NullProgressView),
291
(TTYStringIO, 'dumb', 'text', _mod_ui_text.TextProgressView),
292
(TTYStringIO, 'dumb', None, _mod_ui_text.NullProgressView),
293
# on a non-tty terminal, it's null regardless of $TERM
294
(FileStringIO, 'xterm', None, _mod_ui_text.NullProgressView),
295
(FileStringIO, 'dumb', None, _mod_ui_text.NullProgressView),
296
# however, it can still be forced on
297
(FileStringIO, 'dumb', 'text', _mod_ui_text.TextProgressView),
299
os.environ['TERM'] = term
301
if 'BZR_PROGRESS_BAR' in os.environ:
302
del os.environ['BZR_PROGRESS_BAR']
304
os.environ['BZR_PROGRESS_BAR'] = pb
305
stdin = file_class('')
306
stderr = file_class()
307
stdout = file_class()
308
uif = _mod_ui.make_ui_for_terminal(stdin, stdout, stderr)
309
self.assertIsInstance(uif, _mod_ui_text.TextUIFactory,
310
"TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
311
self.assertIsInstance(uif.make_progress_view(),
313
"TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
315
def test_text_ui_non_terminal(self):
316
"""Even on non-ttys, make_ui_for_terminal gives a text ui."""
317
stdin = test_progress._NonTTYStringIO('')
318
stderr = test_progress._NonTTYStringIO()
319
stdout = test_progress._NonTTYStringIO()
320
for term_type in ['dumb', None, 'xterm']:
321
if term_type is None:
322
del os.environ['TERM']
324
os.environ['TERM'] = term_type
325
uif = _mod_ui.make_ui_for_terminal(stdin, stdout, stderr)
326
self.assertIsInstance(uif, _mod_ui_text.TextUIFactory,
327
'TERM=%r' % (term_type,))
330
class SilentUITests(tests.TestCase):
332
def test_silent_factory_get_password(self):
333
# A silent factory that can't do user interaction can't get a
334
# password. Possibly it should raise a more specific error but it
336
ui = _mod_ui.SilentUIFactory()
337
stdout = tests.StringIOWrapper()
340
self.apply_redirected,
341
None, stdout, stdout, ui.get_password)
342
# and it didn't write anything out either
343
self.assertEqual('', stdout.getvalue())
345
def test_silent_ui_getbool(self):
346
factory = _mod_ui.SilentUIFactory()
347
stdout = tests.StringIOWrapper()
350
self.apply_redirected,
351
None, stdout, stdout, factory.get_boolean, "foo")
354
class TestUIFactoryTests(tests.TestCase):
356
def test_test_ui_factory_progress(self):
357
# there's no output; we just want to make sure this doesn't crash -
358
# see https://bugs.edge.launchpad.net/bzr/+bug/408201
359
ui = tests.TestUIFactory()
360
pb = ui.nested_progress_bar()
366
class CannedInputUIFactoryTests(tests.TestCase):
368
def test_canned_input_get_input(self):
369
uif = _mod_ui.CannedInputUIFactory([True, 'mbp', 'password', 42])
370
self.assertEqual(True, uif.get_boolean('Extra cheese?'))
371
self.assertEqual('mbp', uif.get_username('Enter your user name'))
372
self.assertEqual('password',
373
uif.get_password('Password for %(host)s',
375
self.assertEqual(42, uif.get_integer('And all that jazz ?'))
378
class TestBoolFromString(tests.TestCase):
380
def assertIsTrue(self, s, accepted_values=None):
381
res = _mod_ui.bool_from_string(s, accepted_values=accepted_values)
382
self.assertEquals(True, res)
384
def assertIsFalse(self, s, accepted_values=None):
385
res = _mod_ui.bool_from_string(s, accepted_values=accepted_values)
386
self.assertEquals(False, res)
388
def assertIsNone(self, s, accepted_values=None):
389
res = _mod_ui.bool_from_string(s, accepted_values=accepted_values)
390
self.assertIs(None, res)
392
def test_know_valid_values(self):
393
self.assertIsTrue('true')
394
self.assertIsFalse('false')
395
self.assertIsTrue('1')
396
self.assertIsFalse('0')
397
self.assertIsTrue('on')
398
self.assertIsFalse('off')
399
self.assertIsTrue('yes')
400
self.assertIsFalse('no')
401
self.assertIsTrue('y')
402
self.assertIsFalse('n')
403
# Also try some case variations
404
self.assertIsTrue('True')
405
self.assertIsFalse('False')
406
self.assertIsTrue('On')
407
self.assertIsFalse('Off')
408
self.assertIsTrue('ON')
409
self.assertIsFalse('OFF')
410
self.assertIsTrue('oN')
411
self.assertIsFalse('oFf')
413
def test_invalid_values(self):
414
self.assertIsNone(None)
415
self.assertIsNone('doubt')
416
self.assertIsNone('frue')
417
self.assertIsNone('talse')
418
self.assertIsNone('42')
420
def test_provided_values(self):
421
av = dict(y=True, n=False, yes=True, no=False)
422
self.assertIsTrue('y', av)
423
self.assertIsTrue('Y', av)
424
self.assertIsTrue('Yes', av)
425
self.assertIsFalse('n', av)
426
self.assertIsFalse('N', av)
427
self.assertIsFalse('No', av)
428
self.assertIsNone('1', av)
429
self.assertIsNone('0', av)
430
self.assertIsNone('on', av)
431
self.assertIsNone('off', av)