80
85
it to utf8 to test that we transport the password correctly.
82
87
ui = TestUIFactory(stdin=u'baz\u1234'.encode('utf8'),
83
stdout=StringIOWrapper())
84
ui.stdin.encoding = 'utf8'
85
ui.stdout.encoding = ui.stdin.encoding
88
stdout=StringIOWrapper(),
89
stderr=StringIOWrapper())
90
ui.stderr.encoding = ui.stdout.encoding = ui.stdin.encoding = 'utf8'
86
91
pb = ui.nested_progress_bar()
88
password = self.apply_redirected(ui.stdin, ui.stdout, ui.stdout,
93
password = self.apply_redirected(ui.stdin, ui.stdout, ui.stderr,
90
95
u'Hello \u1234 %(user)s',
91
96
user=u'some\u1234')
92
97
# We use StringIO objects, we need to decode them
93
98
self.assertEqual(u'baz\u1234', password.decode('utf8'))
94
99
self.assertEqual(u'Hello \u1234 some\u1234: ',
95
ui.stdout.getvalue().decode('utf8'))
96
# stdin should be empty
100
ui.stderr.getvalue().decode('utf8'))
101
# stdin and stdout should be empty
97
102
self.assertEqual('', ui.stdin.readline())
103
self.assertEqual('', ui.stdout.readline())
107
def test_progress_construction(self):
108
"""TextUIFactory constructs the right progress view.
110
os.environ['BZR_PROGRESS_BAR'] = 'none'
111
self.assertIsInstance(TextUIFactory()._progress_view,
114
os.environ['BZR_PROGRESS_BAR'] = 'text'
115
self.assertIsInstance(TextUIFactory()._progress_view,
118
os.environ['BZR_PROGRESS_BAR'] = 'text'
119
self.assertIsInstance(TextUIFactory()._progress_view,
122
del os.environ['BZR_PROGRESS_BAR']
123
self.assertIsInstance(TextUIFactory()._progress_view,
101
126
def test_progress_note(self):
102
127
stderr = StringIO()
103
128
stdout = StringIO()
104
ui_factory = TextUIFactory(bar_type=TTYProgressBar)
129
ui_factory = TextUIFactory(stdin=StringIO(''),
105
132
pb = ui_factory.nested_progress_bar()
107
pb.to_messages_file = stdout
108
ui_factory._progress_bar_stack.bottom().to_file = stderr
109
134
result = pb.note('t')
110
135
self.assertEqual(None, result)
111
136
self.assertEqual("t\n", stdout.getvalue())
143
167
def test_progress_nested(self):
144
168
# test factory based nested and popping.
169
ui = TextUIFactory(None, None, None)
146
170
pb1 = ui.nested_progress_bar()
147
171
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)
172
# You do get a warning if the outermost progress bar wasn't finished
173
# first - it's not clear if this is really useful or if it should just
174
# become orphaned -- mbp 20090120
175
warnings, _ = self.callCatchWarnings(pb1.finished)
176
if len(warnings) != 1:
177
self.fail("unexpected warnings: %r" % (warnings,))
185
181
def assert_get_bool_acceptance_of_user_input(self, factory):
186
182
factory.stdin = StringIO("y\nyes with garbage\n"
187
183
"yes\nn\nnot an answer\n"
189
185
factory.stdout = StringIO()
186
factory.stderr = StringIO()
190
187
# there is no output from the base factory
191
188
self.assertEqual(True, factory.get_boolean(""))
192
189
self.assertEqual(True, factory.get_boolean(""))
212
209
self.assertEqual('', factory.stdin.readline())
214
211
def test_text_ui_getbool(self):
215
factory = TextUIFactory()
212
factory = TextUIFactory(None, None, None)
216
213
self.assert_get_bool_acceptance_of_user_input(factory)
215
def test_text_factory_prompt(self):
216
# see <https://launchpad.net/bugs/365891>
217
factory = TextUIFactory(None, StringIO(), StringIO(), StringIO())
218
factory.prompt('foo %2e')
219
self.assertEqual('', factory.stdout.getvalue())
220
self.assertEqual('foo %2e', factory.stderr.getvalue())
218
222
def test_text_factory_prompts_and_clears(self):
219
223
# a get_boolean call should clear the pb before prompting
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)
225
factory = TextUIFactory(stdin=StringIO("yada\ny\n"), stdout=out, stderr=out)
226
pb = factory.nested_progress_bar()
228
pb.show_spinner = False
229
pb.show_count = False
230
pb.update("foo", 0, 1)
228
231
self.assertEqual(True,
229
232
self.apply_redirected(None, factory.stdout,
231
234
factory.get_boolean,
232
235
"what do you want"))
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())
236
output = out.getvalue()
237
self.assertContainsRe(factory.stdout.getvalue(),
239
self.assertContainsRe(factory.stdout.getvalue(),
240
r"what do you want\? \[y/n\]: what do you want\? \[y/n\]: ")
241
# stdin should have been totally consumed
242
self.assertEqual('', factory.stdin.readline())
244
def test_text_tick_after_update(self):
245
ui_factory = TextUIFactory(stdout=StringIO(), stderr=StringIO())
246
pb = ui_factory.nested_progress_bar()
248
pb.update('task', 0, 3)
249
# Reset the clock, so that it actually tries to repaint itself
250
ui_factory._progress_view._last_repaint = time.time() - 1.0
255
def test_silent_ui_getusername(self):
256
factory = SilentUIFactory()
257
factory.stdin = StringIO("someuser\n\n")
258
factory.stdout = StringIO()
259
factory.stderr = StringIO()
260
self.assertEquals(None,
261
factory.get_username(u'Hello\u1234 %(host)s', host=u'some\u1234'))
262
self.assertEquals("", factory.stdout.getvalue())
263
self.assertEquals("", factory.stderr.getvalue())
264
self.assertEquals("someuser\n\n", factory.stdin.getvalue())
266
def test_text_ui_getusername(self):
267
factory = TextUIFactory(None, None, None)
268
factory.stdin = StringIO("someuser\n\n")
269
factory.stdout = StringIO()
270
factory.stderr = StringIO()
271
factory.stdout.encoding = "utf8"
272
# there is no output from the base factory
273
self.assertEqual("someuser",
274
factory.get_username('Hello %(host)s', host='some'))
275
self.assertEquals("Hello some: ", factory.stderr.getvalue())
276
self.assertEquals('', factory.stdout.getvalue())
277
self.assertEqual("", factory.get_username("Gebruiker"))
237
278
# stdin should be empty
238
279
self.assertEqual('', factory.stdin.readline())
281
def test_text_ui_getusername_utf8(self):
282
ui = TestUIFactory(stdin=u'someuser\u1234'.encode('utf8'),
283
stdout=StringIOWrapper(), stderr=StringIOWrapper())
284
ui.stderr.encoding = ui.stdout.encoding = ui.stdin.encoding = "utf8"
285
pb = ui.nested_progress_bar()
287
# there is no output from the base factory
288
username = self.apply_redirected(ui.stdin, ui.stdout, ui.stderr,
289
ui.get_username, u'Hello\u1234 %(host)s', host=u'some\u1234')
290
self.assertEquals(u"someuser\u1234", username.decode('utf8'))
291
self.assertEquals(u"Hello\u1234 some\u1234: ",
292
ui.stderr.getvalue().decode("utf8"))
293
self.assertEquals('', ui.stdout.getvalue())
298
class TestTextProgressView(TestCase):
299
"""Tests for text display of progress bars.
301
# XXX: These might be a bit easier to write if the rendering and
302
# state-maintaining parts of TextProgressView were more separate, and if
303
# the progress task called back directly to its own view not to the ui
304
# factory. -- mbp 20090312
306
def _make_factory(self):
308
uif = TextUIFactory(stderr=out)
309
uif._progress_view._width = 80
312
def test_render_progress_easy(self):
313
"""Just one task and one quarter done"""
314
out, uif = self._make_factory()
315
task = uif.nested_progress_bar()
316
task.update('reticulating splines', 5, 20)
318
'\r[####/ ] reticulating splines 5/20 \r'
321
def test_render_progress_nested(self):
322
"""Tasks proportionally contribute to overall progress"""
323
out, uif = self._make_factory()
324
task = uif.nested_progress_bar()
325
task.update('reticulating splines', 0, 2)
326
task2 = uif.nested_progress_bar()
327
task2.update('stage2', 1, 2)
328
# so we're in the first half of the main task, and half way through
331
r'[####\ ] reticulating splines:stage2 1/2'
332
, uif._progress_view._render_line())
333
# if the nested task is complete, then we're all the way through the
334
# first half of the overall work
335
task2.update('stage2', 2, 2)
337
r'[#########| ] reticulating splines:stage2 2/2'
338
, uif._progress_view._render_line())
340
def test_render_progress_sub_nested(self):
341
"""Intermediate tasks don't mess up calculation."""
342
out, uif = self._make_factory()
343
task_a = uif.nested_progress_bar()
344
task_a.update('a', 0, 2)
345
task_b = uif.nested_progress_bar()
347
task_c = uif.nested_progress_bar()
348
task_c.update('c', 1, 2)
349
# the top-level task is in its first half; the middle one has no
350
# progress indication, just a label; and the bottom one is half done,
351
# so the overall fraction is 1/4
353
r'[####| ] a:b:c 1/2'
354
, uif._progress_view._render_line())