/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_ui.py

  • Committer: Martin Pool
  • Date: 2009-08-04 11:40:59 UTC
  • mfrom: (4584 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4586.
  • Revision ID: mbp@sourcefrog.net-20090804114059-xptutagbs5jev3ry
merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
import sys
24
24
import time
25
25
 
26
 
import bzrlib
27
 
import bzrlib.errors as errors
 
26
from bzrlib import (
 
27
    errors,
 
28
    tests,
 
29
    ui as _mod_ui,
 
30
    )
28
31
from bzrlib.symbol_versioning import (
29
32
    deprecated_in,
30
33
    )
33
36
    TestUIFactory,
34
37
    StringIOWrapper,
35
38
    )
36
 
from bzrlib.tests.test_progress import _TTYStringIO
 
39
from bzrlib.tests.test_progress import (
 
40
    _NonTTYStringIO,
 
41
    _TTYStringIO,
 
42
    )
37
43
from bzrlib.ui import (
 
44
    CannedInputUIFactory,
38
45
    CLIUIFactory,
39
46
    SilentUIFactory,
 
47
    UIFactory,
 
48
    make_ui_for_terminal,
40
49
    )
41
50
from bzrlib.ui.text import (
42
51
    NullProgressView,
45
54
    )
46
55
 
47
56
 
48
 
class UITests(TestCase):
49
 
 
50
 
    def test_silent_factory(self):
51
 
        ui = SilentUIFactory()
52
 
        stdout = StringIO()
53
 
        self.assertEqual(None,
54
 
                         self.apply_redirected(None, stdout, stdout,
55
 
                                               ui.get_password))
56
 
        self.assertEqual('', stdout.getvalue())
57
 
        self.assertEqual(None,
58
 
                         self.apply_redirected(None, stdout, stdout,
59
 
                                               ui.get_password,
60
 
                                               u'Hello\u1234 %(user)s',
61
 
                                               user=u'some\u1234'))
62
 
        self.assertEqual('', stdout.getvalue())
 
57
class UITests(tests.TestCase):
63
58
 
64
59
    def test_text_factory_ascii_password(self):
65
 
        ui = TestUIFactory(stdin='secret\n', stdout=StringIOWrapper(),
66
 
                           stderr=StringIOWrapper())
 
60
        ui = tests.TestUIFactory(stdin='secret\n',
 
61
                                 stdout=tests.StringIOWrapper(),
 
62
                                 stderr=tests.StringIOWrapper())
67
63
        pb = ui.nested_progress_bar()
68
64
        try:
69
65
            self.assertEqual('secret',
84
80
        We can't predict what encoding users will have for stdin, so we force
85
81
        it to utf8 to test that we transport the password correctly.
86
82
        """
87
 
        ui = TestUIFactory(stdin=u'baz\u1234'.encode('utf8'),
88
 
                           stdout=StringIOWrapper(),
89
 
                           stderr=StringIOWrapper())
 
83
        ui = tests.TestUIFactory(stdin=u'baz\u1234'.encode('utf8'),
 
84
                                 stdout=tests.StringIOWrapper(),
 
85
                                 stderr=tests.StringIOWrapper())
90
86
        ui.stderr.encoding = ui.stdout.encoding = ui.stdin.encoding = 'utf8'
91
87
        pb = ui.nested_progress_bar()
92
88
        try:
107
103
    def test_progress_construction(self):
108
104
        """TextUIFactory constructs the right progress view.
109
105
        """
110
 
        os.environ['BZR_PROGRESS_BAR'] = 'none'
111
 
        self.assertIsInstance(TextUIFactory()._progress_view,
112
 
            NullProgressView)
113
 
 
114
 
        os.environ['BZR_PROGRESS_BAR'] = 'text'
115
 
        self.assertIsInstance(TextUIFactory()._progress_view,
116
 
            TextProgressView)
117
 
 
118
 
        os.environ['BZR_PROGRESS_BAR'] = 'text'
119
 
        self.assertIsInstance(TextUIFactory()._progress_view,
120
 
            TextProgressView)
121
 
 
122
 
        del os.environ['BZR_PROGRESS_BAR']
123
 
        self.assertIsInstance(TextUIFactory()._progress_view,
124
 
            TextProgressView)
 
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),
 
122
            ):
 
123
            os.environ['TERM'] = term
 
124
            if pb is None:
 
125
                if 'BZR_PROGRESS_BAR' in os.environ:
 
126
                    del os.environ['BZR_PROGRESS_BAR']
 
127
            else:
 
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(),
 
136
                expected_pb_class,
 
137
                "TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
 
138
 
 
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']
 
147
            else:
 
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,))
125
152
 
126
153
    def test_progress_note(self):
127
154
        stderr = StringIO()
142
169
            pb.finished()
143
170
 
144
171
    def test_progress_note_clears(self):
145
 
        stderr = StringIO()
146
 
        stdout = StringIO()
147
 
        # The PQM redirects the output to a file, so it
148
 
        # defaults to creating a Dots progress bar. we
149
 
        # need to force it to believe we are a TTY
 
172
        stderr = _TTYStringIO()
 
173
        stdout = _TTYStringIO()
 
174
        # so that we get a TextProgressBar
 
175
        os.environ['TERM'] = 'xterm'
150
176
        ui_factory = TextUIFactory(
151
177
            stdin=StringIO(''),
152
178
            stdout=stdout, stderr=stderr)
 
179
        self.assertIsInstance(ui_factory._progress_view,
 
180
            TextProgressView)
153
181
        pb = ui_factory.nested_progress_bar()
154
182
        try:
155
183
            # Create a progress update that isn't throttled
178
206
        pb2.finished()
179
207
        pb1.finished()
180
208
 
181
 
    def assert_get_bool_acceptance_of_user_input(self, factory):
182
 
        factory.stdin = StringIO("y\nyes with garbage\n"
183
 
                                 "yes\nn\nnot an answer\n"
184
 
                                 "no\nfoo\n")
185
 
        factory.stdout = StringIO()
186
 
        factory.stderr = StringIO()
187
 
        # there is no output from the base factory
188
 
        self.assertEqual(True, factory.get_boolean(""))
189
 
        self.assertEqual(True, factory.get_boolean(""))
190
 
        self.assertEqual(False, factory.get_boolean(""))
 
209
    def test_text_ui_get_boolean(self):
 
210
        stdin = StringIO("y\n" # True
 
211
                         "n\n" # False
 
212
                         "yes with garbage\nY\n" # True
 
213
                         "not an answer\nno\n" # False
 
214
                         "I'm sure!\nyes\n" # True
 
215
                         "NO\n" # False
 
216
                         "foo\n")
 
217
        stdout = StringIO()
 
218
        stderr = StringIO()
 
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(""))
191
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())
195
229
 
196
 
    def test_silent_ui_getbool(self):
197
 
        factory = SilentUIFactory()
198
 
        self.assert_get_bool_acceptance_of_user_input(factory)
199
 
 
200
 
    def test_silent_factory_prompts_silently(self):
201
 
        factory = SilentUIFactory()
202
 
        stdout = StringIO()
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())
210
 
 
211
 
    def test_text_ui_getbool(self):
212
 
        factory = TextUIFactory(None, None, None)
213
 
        self.assert_get_bool_acceptance_of_user_input(factory)
214
 
 
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())
222
237
    def test_text_factory_prompts_and_clears(self):
223
238
        # a get_boolean call should clear the pb before prompting
224
239
        out = _TTYStringIO()
 
240
        os.environ['TERM'] = 'xterm'
225
241
        factory = TextUIFactory(stdin=StringIO("yada\ny\n"), stdout=out, stderr=out)
226
242
        pb = factory.nested_progress_bar()
227
243
        pb.show_bar = False
252
268
        finally:
253
269
            pb.finished()
254
270
 
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())
265
 
 
266
271
    def test_text_ui_getusername(self):
267
272
        factory = TextUIFactory(None, None, None)
268
273
        factory.stdin = StringIO("someuser\n\n")
279
284
        self.assertEqual('', factory.stdin.readline())
280
285
 
281
286
    def test_text_ui_getusername_utf8(self):
282
 
        ui = TestUIFactory(stdin=u'someuser\u1234'.encode('utf8'),
283
 
                           stdout=StringIOWrapper(), stderr=StringIOWrapper())
 
287
        ui = tests.TestUIFactory(stdin=u'someuser\u1234'.encode('utf8'),
 
288
                                 stdout=tests.StringIOWrapper(),
 
289
                                 stderr=tests.StringIOWrapper())
284
290
        ui.stderr.encoding = ui.stdout.encoding = ui.stdin.encoding = "utf8"
285
291
        pb = ui.nested_progress_bar()
286
292
        try:
295
301
            pb.finished()
296
302
 
297
303
 
298
 
class TestTextProgressView(TestCase):
299
 
    """Tests for text display of progress bars.
300
 
    """
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
 
304
class CLIUITests(TestCase):
 
305
 
 
306
    def test_cli_factory_deprecated(self):
 
307
        uif = self.applyDeprecated(deprecated_in((1, 18, 0)),
 
308
            CLIUIFactory,
 
309
            StringIO(), StringIO(), StringIO())
 
310
        self.assertIsInstance(uif, UIFactory)
 
311
 
 
312
 
 
313
class SilentUITests(TestCase):
 
314
 
 
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
 
318
        # can't succeed.
 
319
        ui = SilentUIFactory()
 
320
        stdout = StringIO()
 
321
        self.assertRaises(
 
322
            NotImplementedError,
 
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())
 
327
 
 
328
    def test_silent_ui_getbool(self):
 
329
        factory = SilentUIFactory()
 
330
        stdout = StringIO()
 
331
        self.assertRaises(
 
332
            NotImplementedError,
 
333
            self.apply_redirected,
 
334
            None, stdout, stdout, factory.get_boolean, "foo")
 
335
 
 
336
 
 
337
class TestUIFactoryTests(TestCase):
 
338
 
 
339
    def test_test_ui_factory_progress(self):
 
340
        # there's no output; we just want to make sure this doesn't crash -
 
341
        # see https://bugs.edge.launchpad.net/bzr/+bug/408201
 
342
        ui = TestUIFactory()
 
343
        pb = ui.nested_progress_bar()
 
344
        pb.update('hello')
 
345
        pb.tick()
 
346
        pb.finished()
 
347
 
 
348
 
 
349
class CannedInputUIFactoryTests(TestCase):
305
350
    
306
 
    def _make_factory(self):
307
 
        out = StringIO()
308
 
        uif = TextUIFactory(stderr=out)
309
 
        uif._progress_view._width = 80
310
 
        return out, uif
311
 
 
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)
317
 
        self.assertEqual(
318
 
'\r[####/               ] reticulating splines 5/20                               \r'
319
 
            , out.getvalue())
320
 
 
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
329
 
        # that
330
 
        self.assertEqual(
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)
336
 
        self.assertEqual(
337
 
r'[#########|          ] reticulating splines:stage2 2/2'
338
 
            , uif._progress_view._render_line())
339
 
 
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()
346
 
        task_b.update('b')
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
352
 
        self.assertEqual(
353
 
            r'[####|               ] a:b:c 1/2'
354
 
            , uif._progress_view._render_line())
355
 
 
 
351
    def test_canned_input_get_input(self):
 
352
        uif = CannedInputUIFactory([True, 'mbp', 'password'])
 
353
        self.assertEqual(uif.get_boolean('Extra cheese?'), True)
 
354
        self.assertEqual(uif.get_username('Enter your user name'), 'mbp')
 
355
        self.assertEqual(uif.get_password('Password for %(host)s', host='example.com'),
 
356
            'password')
 
357
 
 
358
 
 
359
class TestBoolFromString(tests.TestCase):
 
360
 
 
361
    def assertIsTrue(self, s, accepted_values=None):
 
362
        res = _mod_ui.bool_from_string(s, accepted_values=accepted_values)
 
363
        self.assertEquals(True, res)
 
364
 
 
365
    def assertIsFalse(self, s, accepted_values=None):
 
366
        res = _mod_ui.bool_from_string(s, accepted_values=accepted_values)
 
367
        self.assertEquals(False, res)
 
368
 
 
369
    def assertIsNone(self, s, accepted_values=None):
 
370
        res = _mod_ui.bool_from_string(s, accepted_values=accepted_values)
 
371
        self.assertIs(None, res)
 
372
 
 
373
    def test_know_valid_values(self):
 
374
        self.assertIsTrue('true')
 
375
        self.assertIsFalse('false')
 
376
        self.assertIsTrue('1')
 
377
        self.assertIsFalse('0')
 
378
        self.assertIsTrue('on')
 
379
        self.assertIsFalse('off')
 
380
        self.assertIsTrue('yes')
 
381
        self.assertIsFalse('no')
 
382
        self.assertIsTrue('y')
 
383
        self.assertIsFalse('n')
 
384
        # Also try some case variations
 
385
        self.assertIsTrue('True')
 
386
        self.assertIsFalse('False')
 
387
        self.assertIsTrue('On')
 
388
        self.assertIsFalse('Off')
 
389
        self.assertIsTrue('ON')
 
390
        self.assertIsFalse('OFF')
 
391
        self.assertIsTrue('oN')
 
392
        self.assertIsFalse('oFf')
 
393
 
 
394
    def test_invalid_values(self):
 
395
        self.assertIsNone(None)
 
396
        self.assertIsNone('doubt')
 
397
        self.assertIsNone('frue')
 
398
        self.assertIsNone('talse')
 
399
        self.assertIsNone('42')
 
400
 
 
401
    def test_provided_values(self):
 
402
        av = dict(y=True, n=False, yes=True, no=False)
 
403
        self.assertIsTrue('y', av)
 
404
        self.assertIsTrue('Y', av)
 
405
        self.assertIsTrue('Yes', av)
 
406
        self.assertIsFalse('n', av)
 
407
        self.assertIsFalse('N', av)
 
408
        self.assertIsFalse('No', av)
 
409
        self.assertIsNone('1', av)
 
410
        self.assertIsNone('0', av)
 
411
        self.assertIsNone('on', av)
 
412
        self.assertIsNone('off', av)