~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_ui.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-04-09 23:12:55 UTC
  • mfrom: (3920.2.37 dpush)
  • Revision ID: pqm@pqm.ubuntu.com-20090409231255-o8w1g2q3igiyf8b2
(Jelmer) Add the dpush command.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005, 2008, 2009 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
18
18
"""
19
19
 
20
20
import os
 
21
from StringIO import StringIO
21
22
import re
 
23
import sys
22
24
import time
23
25
 
24
 
from StringIO import StringIO
25
 
 
26
 
from bzrlib import (
27
 
    config,
28
 
    errors,
29
 
    remote,
30
 
    repository,
31
 
    tests,
32
 
    ui as _mod_ui,
 
26
import bzrlib
 
27
import bzrlib.errors as errors
 
28
from bzrlib.progress import (
 
29
    DotsProgressBar,
 
30
    ProgressBarStack,
 
31
    ProgressTask,
 
32
    TTYProgressBar,
33
33
    )
34
34
from bzrlib.symbol_versioning import (
35
35
    deprecated_in,
36
36
    )
37
37
from bzrlib.tests import (
38
 
    fixtures,
39
 
    test_progress,
40
 
    )
41
 
from bzrlib.ui import text as _mod_ui_text
42
 
 
43
 
 
44
 
class TestUIConfiguration(tests.TestCaseWithTransport):
45
 
 
46
 
    def test_output_encoding_configuration(self):
47
 
        enc = fixtures.generate_unicode_encodings().next()
48
 
        config.GlobalConfig().set_user_option('output_encoding',
49
 
            enc)
50
 
        ui = tests.TestUIFactory(stdin=None,
51
 
            stdout=tests.StringIOWrapper(),
52
 
            stderr=tests.StringIOWrapper())
53
 
        os = ui.make_output_stream()
54
 
        self.assertEquals(os.encoding, enc)
55
 
 
56
 
 
57
 
class TestTextUIFactory(tests.TestCase):
 
38
    TestCase,
 
39
    TestUIFactory,
 
40
    StringIOWrapper,
 
41
    )
 
42
from bzrlib.tests.test_progress import _TTYStringIO
 
43
from bzrlib.ui import (
 
44
    CLIUIFactory,
 
45
    SilentUIFactory,
 
46
    )
 
47
from bzrlib.ui.text import (
 
48
    TextProgressView,
 
49
    TextUIFactory,
 
50
    )
 
51
 
 
52
 
 
53
class UITests(TestCase):
 
54
 
 
55
    def test_silent_factory(self):
 
56
        ui = SilentUIFactory()
 
57
        stdout = StringIO()
 
58
        self.assertEqual(None,
 
59
                         self.apply_redirected(None, stdout, stdout,
 
60
                                               ui.get_password))
 
61
        self.assertEqual('', stdout.getvalue())
 
62
        self.assertEqual(None,
 
63
                         self.apply_redirected(None, stdout, stdout,
 
64
                                               ui.get_password,
 
65
                                               u'Hello\u1234 %(user)s',
 
66
                                               user=u'some\u1234'))
 
67
        self.assertEqual('', stdout.getvalue())
58
68
 
59
69
    def test_text_factory_ascii_password(self):
60
 
        ui = tests.TestUIFactory(stdin='secret\n',
61
 
                                 stdout=tests.StringIOWrapper(),
62
 
                                 stderr=tests.StringIOWrapper())
 
70
        ui = TestUIFactory(stdin='secret\n', stdout=StringIOWrapper())
63
71
        pb = ui.nested_progress_bar()
64
72
        try:
65
73
            self.assertEqual('secret',
66
74
                             self.apply_redirected(ui.stdin, ui.stdout,
67
 
                                                   ui.stderr,
 
75
                                                   ui.stdout,
68
76
                                                   ui.get_password))
69
77
            # ': ' is appended to prompt
70
 
            self.assertEqual(': ', ui.stderr.getvalue())
71
 
            self.assertEqual('', ui.stdout.readline())
 
78
            self.assertEqual(': ', ui.stdout.getvalue())
72
79
            # stdin should be empty
73
80
            self.assertEqual('', ui.stdin.readline())
74
81
        finally:
80
87
        We can't predict what encoding users will have for stdin, so we force
81
88
        it to utf8 to test that we transport the password correctly.
82
89
        """
83
 
        ui = tests.TestUIFactory(stdin=u'baz\u1234'.encode('utf8'),
84
 
                                 stdout=tests.StringIOWrapper(),
85
 
                                 stderr=tests.StringIOWrapper())
86
 
        ui.stderr.encoding = ui.stdout.encoding = ui.stdin.encoding = 'utf8'
 
90
        ui = TestUIFactory(stdin=u'baz\u1234'.encode('utf8'),
 
91
                           stdout=StringIOWrapper())
 
92
        ui.stdin.encoding = 'utf8'
 
93
        ui.stdout.encoding = ui.stdin.encoding
87
94
        pb = ui.nested_progress_bar()
88
95
        try:
89
 
            password = self.apply_redirected(ui.stdin, ui.stdout, ui.stderr,
 
96
            password = self.apply_redirected(ui.stdin, ui.stdout, ui.stdout,
90
97
                                             ui.get_password,
91
98
                                             u'Hello \u1234 %(user)s',
92
99
                                             user=u'some\u1234')
93
100
            # We use StringIO objects, we need to decode them
94
101
            self.assertEqual(u'baz\u1234', password.decode('utf8'))
95
102
            self.assertEqual(u'Hello \u1234 some\u1234: ',
96
 
                             ui.stderr.getvalue().decode('utf8'))
97
 
            # stdin and stdout should be empty
 
103
                             ui.stdout.getvalue().decode('utf8'))
 
104
            # stdin should be empty
98
105
            self.assertEqual('', ui.stdin.readline())
99
 
            self.assertEqual('', ui.stdout.readline())
100
106
        finally:
101
107
            pb.finished()
102
108
 
103
109
    def test_progress_note(self):
104
 
        stderr = tests.StringIOWrapper()
105
 
        stdout = tests.StringIOWrapper()
106
 
        ui_factory = _mod_ui_text.TextUIFactory(stdin=tests.StringIOWrapper(''),
107
 
                                                stderr=stderr,
108
 
                                                stdout=stdout)
 
110
        stderr = StringIO()
 
111
        stdout = StringIO()
 
112
        ui_factory = TextUIFactory(stdin=StringIO(''),
 
113
            stderr=stderr,
 
114
            stdout=stdout)
109
115
        pb = ui_factory.nested_progress_bar()
110
116
        try:
111
 
            result = self.applyDeprecated(deprecated_in((2, 1, 0)),
112
 
                pb.note,
113
 
                't')
 
117
            result = pb.note('t')
114
118
            self.assertEqual(None, result)
115
119
            self.assertEqual("t\n", stdout.getvalue())
116
120
            # Since there was no update() call, there should be no clear() call
121
125
            pb.finished()
122
126
 
123
127
    def test_progress_note_clears(self):
124
 
        stderr = test_progress._TTYStringIO()
125
 
        stdout = test_progress._TTYStringIO()
126
 
        # so that we get a TextProgressBar
127
 
        os.environ['TERM'] = 'xterm'
128
 
        ui_factory = _mod_ui_text.TextUIFactory(
129
 
            stdin=tests.StringIOWrapper(''),
 
128
        stderr = StringIO()
 
129
        stdout = StringIO()
 
130
        # The PQM redirects the output to a file, so it
 
131
        # defaults to creating a Dots progress bar. we
 
132
        # need to force it to believe we are a TTY
 
133
        ui_factory = TextUIFactory(
 
134
            stdin=StringIO(''),
130
135
            stdout=stdout, stderr=stderr)
131
 
        self.assertIsInstance(ui_factory._progress_view,
132
 
                              _mod_ui_text.TextProgressView)
133
136
        pb = ui_factory.nested_progress_bar()
134
137
        try:
135
138
            # Create a progress update that isn't throttled
136
139
            pb.update('x', 1, 1)
137
 
            result = self.applyDeprecated(deprecated_in((2, 1, 0)),
138
 
                pb.note, 't')
 
140
            result = pb.note('t')
139
141
            self.assertEqual(None, result)
140
142
            self.assertEqual("t\n", stdout.getvalue())
141
143
            # the exact contents will depend on the terminal width and we don't
145
147
        finally:
146
148
            pb.finished()
147
149
 
148
 
    def test_text_ui_get_boolean(self):
149
 
        stdin = tests.StringIOWrapper("y\n" # True
150
 
                                      "n\n" # False
151
 
                                      "yes with garbage\nY\n" # True
152
 
                                      "not an answer\nno\n" # False
153
 
                                      "I'm sure!\nyes\n" # True
154
 
                                      "NO\n" # False
155
 
                                      "foo\n")
156
 
        stdout = tests.StringIOWrapper()
157
 
        stderr = tests.StringIOWrapper()
158
 
        factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
159
 
        self.assertEqual(True, factory.get_boolean(""))
160
 
        self.assertEqual(False, factory.get_boolean(""))
161
 
        self.assertEqual(True, factory.get_boolean(""))
162
 
        self.assertEqual(False, factory.get_boolean(""))
163
 
        self.assertEqual(True, factory.get_boolean(""))
 
150
    def test_progress_nested(self):
 
151
        # test factory based nested and popping.
 
152
        ui = TextUIFactory(None, None, None)
 
153
        pb1 = ui.nested_progress_bar()
 
154
        pb2 = ui.nested_progress_bar()
 
155
        # You do get a warning if the outermost progress bar wasn't finished
 
156
        # first - it's not clear if this is really useful or if it should just
 
157
        # become orphaned -- mbp 20090120
 
158
        warnings, _ = self.callCatchWarnings(pb1.finished)
 
159
        if len(warnings) != 1:
 
160
            self.fail("unexpected warnings: %r" % (warnings,))
 
161
        pb2.finished()
 
162
        pb1.finished()
 
163
 
 
164
    def test_progress_stack(self):
 
165
        # test the progress bar stack which the default text factory
 
166
        # uses.
 
167
        stderr = StringIO()
 
168
        stdout = StringIO()
 
169
        # make a stack, which accepts parameters like a pb.
 
170
        stack = self.applyDeprecated(
 
171
            deprecated_in((1, 12, 0)),
 
172
            ProgressBarStack,
 
173
            to_file=stderr, to_messages_file=stdout)
 
174
        # but is not one
 
175
        self.assertFalse(getattr(stack, 'note', False))
 
176
        pb1 = stack.get_nested()
 
177
        pb2 = stack.get_nested()
 
178
        warnings, _ = self.callCatchWarnings(pb1.finished)
 
179
        self.assertEqual(len(warnings), 1)
 
180
        pb2.finished()
 
181
        pb1.finished()
 
182
        # the text ui factory never actually removes the stack once its setup.
 
183
        # we need to be able to nest again correctly from here.
 
184
        pb1 = stack.get_nested()
 
185
        pb2 = stack.get_nested()
 
186
        warnings, _ = self.callCatchWarnings(pb1.finished)
 
187
        self.assertEqual(len(warnings), 1)
 
188
        pb2.finished()
 
189
        pb1.finished()
 
190
 
 
191
    def assert_get_bool_acceptance_of_user_input(self, factory):
 
192
        factory.stdin = StringIO("y\nyes with garbage\n"
 
193
                                 "yes\nn\nnot an answer\n"
 
194
                                 "no\nfoo\n")
 
195
        factory.stdout = StringIO()
 
196
        # there is no output from the base factory
 
197
        self.assertEqual(True, factory.get_boolean(""))
 
198
        self.assertEqual(True, factory.get_boolean(""))
 
199
        self.assertEqual(False, factory.get_boolean(""))
164
200
        self.assertEqual(False, factory.get_boolean(""))
165
201
        self.assertEqual("foo\n", factory.stdin.read())
166
202
        # stdin should be empty
167
203
        self.assertEqual('', factory.stdin.readline())
168
204
 
169
 
    def test_text_ui_get_integer(self):
170
 
        stdin = tests.StringIOWrapper(
171
 
            "1\n"
172
 
            "  -2  \n"
173
 
            "hmmm\nwhat else ?\nCome on\nok 42\n4.24\n42\n")
174
 
        stdout = tests.StringIOWrapper()
175
 
        stderr = tests.StringIOWrapper()
176
 
        factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
177
 
        self.assertEqual(1, factory.get_integer(""))
178
 
        self.assertEqual(-2, factory.get_integer(""))
179
 
        self.assertEqual(42, factory.get_integer(""))
180
 
 
181
 
    def test_text_factory_prompt(self):
182
 
        # see <https://launchpad.net/bugs/365891>
183
 
        StringIO = tests.StringIOWrapper
184
 
        factory = _mod_ui_text.TextUIFactory(StringIO(), StringIO(), StringIO())
185
 
        factory.prompt('foo %2e')
186
 
        self.assertEqual('', factory.stdout.getvalue())
187
 
        self.assertEqual('foo %2e', factory.stderr.getvalue())
 
205
    def test_silent_ui_getbool(self):
 
206
        factory = SilentUIFactory()
 
207
        self.assert_get_bool_acceptance_of_user_input(factory)
 
208
 
 
209
    def test_silent_factory_prompts_silently(self):
 
210
        factory = SilentUIFactory()
 
211
        stdout = StringIO()
 
212
        factory.stdin = StringIO("y\n")
 
213
        self.assertEqual(True,
 
214
                         self.apply_redirected(None, stdout, stdout,
 
215
                                               factory.get_boolean, "foo"))
 
216
        self.assertEqual("", stdout.getvalue())
 
217
        # stdin should be empty
 
218
        self.assertEqual('', factory.stdin.readline())
 
219
 
 
220
    def test_text_ui_getbool(self):
 
221
        factory = TextUIFactory(None, None, None)
 
222
        self.assert_get_bool_acceptance_of_user_input(factory)
188
223
 
189
224
    def test_text_factory_prompts_and_clears(self):
190
225
        # a get_boolean call should clear the pb before prompting
191
 
        out = test_progress._TTYStringIO()
192
 
        os.environ['TERM'] = 'xterm'
193
 
        factory = _mod_ui_text.TextUIFactory(
194
 
            stdin=tests.StringIOWrapper("yada\ny\n"),
195
 
            stdout=out, stderr=out)
 
226
        out = _TTYStringIO()
 
227
        factory = TextUIFactory(stdin=StringIO("yada\ny\n"), stdout=out, stderr=out)
196
228
        pb = factory.nested_progress_bar()
197
229
        pb.show_bar = False
198
230
        pb.show_spinner = False
212
244
        self.assertEqual('', factory.stdin.readline())
213
245
 
214
246
    def test_text_tick_after_update(self):
215
 
        ui_factory = _mod_ui_text.TextUIFactory(stdout=tests.StringIOWrapper(),
216
 
                                                stderr=tests.StringIOWrapper())
 
247
        ui_factory = TextUIFactory(stdout=StringIO(), stderr=StringIO())
217
248
        pb = ui_factory.nested_progress_bar()
218
249
        try:
219
250
            pb.update('task', 0, 3)
223
254
        finally:
224
255
            pb.finished()
225
256
 
 
257
    def test_silent_ui_getusername(self):
 
258
        factory = SilentUIFactory()
 
259
        factory.stdin = StringIO("someuser\n\n")
 
260
        factory.stdout = StringIO()
 
261
        self.assertEquals(None, 
 
262
            factory.get_username(u'Hello\u1234 %(host)s', host=u'some\u1234'))
 
263
        self.assertEquals("", factory.stdout.getvalue())
 
264
        self.assertEquals("someuser\n\n", factory.stdin.getvalue())
 
265
 
226
266
    def test_text_ui_getusername(self):
227
 
        factory = _mod_ui_text.TextUIFactory(None, None, None)
228
 
        factory.stdin = tests.StringIOWrapper("someuser\n\n")
229
 
        factory.stdout = tests.StringIOWrapper()
230
 
        factory.stderr = tests.StringIOWrapper()
 
267
        factory = TextUIFactory(None, None, None)
 
268
        factory.stdin = StringIO("someuser\n\n")
 
269
        factory.stdout = StringIO()
231
270
        factory.stdout.encoding = "utf8"
232
271
        # there is no output from the base factory
233
 
        self.assertEqual("someuser",
234
 
                         factory.get_username('Hello %(host)s', host='some'))
235
 
        self.assertEquals("Hello some: ", factory.stderr.getvalue())
236
 
        self.assertEquals('', factory.stdout.getvalue())
 
272
        self.assertEqual("someuser", 
 
273
            factory.get_username('Hello %(host)s', host='some'))
 
274
        self.assertEquals("Hello some: ", factory.stdout.getvalue())
237
275
        self.assertEqual("", factory.get_username("Gebruiker"))
238
276
        # stdin should be empty
239
277
        self.assertEqual('', factory.stdin.readline())
240
278
 
241
279
    def test_text_ui_getusername_utf8(self):
242
 
        ui = tests.TestUIFactory(stdin=u'someuser\u1234'.encode('utf8'),
243
 
                                 stdout=tests.StringIOWrapper(),
244
 
                                 stderr=tests.StringIOWrapper())
245
 
        ui.stderr.encoding = ui.stdout.encoding = ui.stdin.encoding = "utf8"
 
280
        ui = TestUIFactory(stdin=u'someuser\u1234'.encode('utf8'),
 
281
                           stdout=StringIOWrapper())
 
282
        ui.stdin.encoding = "utf8"
 
283
        ui.stdout.encoding = ui.stdin.encoding
246
284
        pb = ui.nested_progress_bar()
247
285
        try:
248
286
            # there is no output from the base factory
249
 
            username = self.apply_redirected(ui.stdin, ui.stdout, ui.stderr,
 
287
            username = self.apply_redirected(ui.stdin, ui.stdout, ui.stdout,
250
288
                ui.get_username, u'Hello\u1234 %(host)s', host=u'some\u1234')
251
289
            self.assertEquals(u"someuser\u1234", username.decode('utf8'))
252
 
            self.assertEquals(u"Hello\u1234 some\u1234: ",
253
 
                              ui.stderr.getvalue().decode("utf8"))
254
 
            self.assertEquals('', ui.stdout.getvalue())
 
290
            self.assertEquals(u"Hello\u1234 some\u1234: ", 
 
291
                ui.stdout.getvalue().decode("utf8"))
255
292
        finally:
256
293
            pb.finished()
257
294
 
258
 
    def test_quietness(self):
259
 
        os.environ['BZR_PROGRESS_BAR'] = 'text'
260
 
        ui_factory = _mod_ui_text.TextUIFactory(None,
261
 
            test_progress._TTYStringIO(),
262
 
            test_progress._TTYStringIO())
263
 
        self.assertIsInstance(ui_factory._progress_view,
264
 
            _mod_ui_text.TextProgressView)
265
 
        ui_factory.be_quiet(True)
266
 
        self.assertIsInstance(ui_factory._progress_view,
267
 
            _mod_ui_text.NullProgressView)
268
 
 
269
 
    def test_text_ui_show_user_warning(self):
270
 
        from bzrlib.repofmt.groupcompress_repo import RepositoryFormat2a
271
 
        from bzrlib.repofmt.pack_repo import RepositoryFormatKnitPack5
272
 
        err = StringIO()
273
 
        out = StringIO()
274
 
        ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
275
 
        remote_fmt = remote.RemoteRepositoryFormat()
276
 
        remote_fmt._network_name = RepositoryFormatKnitPack5().network_name()
277
 
        ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
278
 
            to_format=remote_fmt)
279
 
        self.assertEquals('', out.getvalue())
280
 
        self.assertEquals("Doing on-the-fly conversion from RepositoryFormat2a() to "
281
 
            "RemoteRepositoryFormat(_network_name='Bazaar RepositoryFormatKnitPack5 "
282
 
            "(bzr 1.6)\\n').\nThis may take some time. Upgrade the repositories to "
283
 
            "the same format for better performance.\n",
284
 
            err.getvalue())
285
 
        # and now with it suppressed please
286
 
        err = StringIO()
287
 
        out = StringIO()
288
 
        ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
289
 
        ui.suppressed_warnings.add('cross_format_fetch')
290
 
        ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
291
 
            to_format=remote_fmt)
292
 
        self.assertEquals('', out.getvalue())
293
 
        self.assertEquals('', err.getvalue())
294
 
 
295
 
 
296
 
class TestTextUIOutputStream(tests.TestCase):
297
 
    """Tests for output stream that synchronizes with progress bar."""
298
 
 
299
 
    def test_output_clears_terminal(self):
300
 
        stdout = tests.StringIOWrapper()
301
 
        stderr = tests.StringIOWrapper()
302
 
        clear_calls = []
303
 
 
304
 
        uif =  _mod_ui_text.TextUIFactory(None, stdout, stderr)
305
 
        uif.clear_term = lambda: clear_calls.append('clear')
306
 
 
307
 
        stream = _mod_ui_text.TextUIOutputStream(uif, uif.stdout)
308
 
        stream.write("Hello world!\n")
309
 
        stream.write("there's more...\n")
310
 
        stream.writelines(["1\n", "2\n", "3\n"])
311
 
 
312
 
        self.assertEqual(stdout.getvalue(),
313
 
            "Hello world!\n"
314
 
            "there's more...\n"
315
 
            "1\n2\n3\n")
316
 
        self.assertEqual(['clear', 'clear', 'clear'],
317
 
            clear_calls)
318
 
 
319
 
        stream.flush()
320
 
 
321
 
 
322
 
class UITests(tests.TestCase):
323
 
 
324
 
    def test_progress_construction(self):
325
 
        """TextUIFactory constructs the right progress view.
326
 
        """
327
 
        TTYStringIO = test_progress._TTYStringIO
328
 
        FileStringIO = tests.StringIOWrapper
329
 
        for (file_class, term, pb, expected_pb_class) in (
330
 
            # on an xterm, either use them or not as the user requests,
331
 
            # otherwise default on
332
 
            (TTYStringIO, 'xterm', 'none', _mod_ui_text.NullProgressView),
333
 
            (TTYStringIO, 'xterm', 'text', _mod_ui_text.TextProgressView),
334
 
            (TTYStringIO, 'xterm', None, _mod_ui_text.TextProgressView),
335
 
            # on a dumb terminal, again if there's explicit configuration do
336
 
            # it, otherwise default off
337
 
            (TTYStringIO, 'dumb', 'none', _mod_ui_text.NullProgressView),
338
 
            (TTYStringIO, 'dumb', 'text', _mod_ui_text.TextProgressView),
339
 
            (TTYStringIO, 'dumb', None, _mod_ui_text.NullProgressView),
340
 
            # on a non-tty terminal, it's null regardless of $TERM
341
 
            (FileStringIO, 'xterm', None, _mod_ui_text.NullProgressView),
342
 
            (FileStringIO, 'dumb', None, _mod_ui_text.NullProgressView),
343
 
            # however, it can still be forced on
344
 
            (FileStringIO, 'dumb', 'text', _mod_ui_text.TextProgressView),
345
 
            ):
346
 
            os.environ['TERM'] = term
347
 
            if pb is None:
348
 
                if 'BZR_PROGRESS_BAR' in os.environ:
349
 
                    del os.environ['BZR_PROGRESS_BAR']
350
 
            else:
351
 
                os.environ['BZR_PROGRESS_BAR'] = pb
352
 
            stdin = file_class('')
353
 
            stderr = file_class()
354
 
            stdout = file_class()
355
 
            uif = _mod_ui.make_ui_for_terminal(stdin, stdout, stderr)
356
 
            self.assertIsInstance(uif, _mod_ui_text.TextUIFactory,
357
 
                "TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
358
 
            self.assertIsInstance(uif.make_progress_view(),
359
 
                expected_pb_class,
360
 
                "TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
361
 
 
362
 
    def test_text_ui_non_terminal(self):
363
 
        """Even on non-ttys, make_ui_for_terminal gives a text ui."""
364
 
        stdin = test_progress._NonTTYStringIO('')
365
 
        stderr = test_progress._NonTTYStringIO()
366
 
        stdout = test_progress._NonTTYStringIO()
367
 
        for term_type in ['dumb', None, 'xterm']:
368
 
            if term_type is None:
369
 
                del os.environ['TERM']
370
 
            else:
371
 
                os.environ['TERM'] = term_type
372
 
            uif = _mod_ui.make_ui_for_terminal(stdin, stdout, stderr)
373
 
            self.assertIsInstance(uif, _mod_ui_text.TextUIFactory,
374
 
                'TERM=%r' % (term_type,))
375
 
 
376
 
 
377
 
class SilentUITests(tests.TestCase):
378
 
 
379
 
    def test_silent_factory_get_password(self):
380
 
        # A silent factory that can't do user interaction can't get a
381
 
        # password.  Possibly it should raise a more specific error but it
382
 
        # can't succeed.
383
 
        ui = _mod_ui.SilentUIFactory()
384
 
        stdout = tests.StringIOWrapper()
385
 
        self.assertRaises(
386
 
            NotImplementedError,
387
 
            self.apply_redirected,
388
 
            None, stdout, stdout, ui.get_password)
389
 
        # and it didn't write anything out either
390
 
        self.assertEqual('', stdout.getvalue())
391
 
 
392
 
    def test_silent_ui_getbool(self):
393
 
        factory = _mod_ui.SilentUIFactory()
394
 
        stdout = tests.StringIOWrapper()
395
 
        self.assertRaises(
396
 
            NotImplementedError,
397
 
            self.apply_redirected,
398
 
            None, stdout, stdout, factory.get_boolean, "foo")
399
 
 
400
 
 
401
 
class TestUIFactoryTests(tests.TestCase):
402
 
 
403
 
    def test_test_ui_factory_progress(self):
404
 
        # there's no output; we just want to make sure this doesn't crash -
405
 
        # see https://bugs.launchpad.net/bzr/+bug/408201
406
 
        ui = tests.TestUIFactory()
407
 
        pb = ui.nested_progress_bar()
408
 
        pb.update('hello')
409
 
        pb.tick()
410
 
        pb.finished()
411
 
 
412
 
 
413
 
class CannedInputUIFactoryTests(tests.TestCase):
414
 
 
415
 
    def test_canned_input_get_input(self):
416
 
        uif = _mod_ui.CannedInputUIFactory([True, 'mbp', 'password', 42])
417
 
        self.assertEqual(True, uif.get_boolean('Extra cheese?'))
418
 
        self.assertEqual('mbp', uif.get_username('Enter your user name'))
419
 
        self.assertEqual('password',
420
 
                         uif.get_password('Password for %(host)s',
421
 
                                          host='example.com'))
422
 
        self.assertEqual(42, uif.get_integer('And all that jazz ?'))
423
 
 
424
 
 
425
 
class TestBoolFromString(tests.TestCase):
426
 
 
427
 
    def assertIsTrue(self, s, accepted_values=None):
428
 
        res = _mod_ui.bool_from_string(s, accepted_values=accepted_values)
429
 
        self.assertEquals(True, res)
430
 
 
431
 
    def assertIsFalse(self, s, accepted_values=None):
432
 
        res = _mod_ui.bool_from_string(s, accepted_values=accepted_values)
433
 
        self.assertEquals(False, res)
434
 
 
435
 
    def assertIsNone(self, s, accepted_values=None):
436
 
        res = _mod_ui.bool_from_string(s, accepted_values=accepted_values)
437
 
        self.assertIs(None, res)
438
 
 
439
 
    def test_know_valid_values(self):
440
 
        self.assertIsTrue('true')
441
 
        self.assertIsFalse('false')
442
 
        self.assertIsTrue('1')
443
 
        self.assertIsFalse('0')
444
 
        self.assertIsTrue('on')
445
 
        self.assertIsFalse('off')
446
 
        self.assertIsTrue('yes')
447
 
        self.assertIsFalse('no')
448
 
        self.assertIsTrue('y')
449
 
        self.assertIsFalse('n')
450
 
        # Also try some case variations
451
 
        self.assertIsTrue('True')
452
 
        self.assertIsFalse('False')
453
 
        self.assertIsTrue('On')
454
 
        self.assertIsFalse('Off')
455
 
        self.assertIsTrue('ON')
456
 
        self.assertIsFalse('OFF')
457
 
        self.assertIsTrue('oN')
458
 
        self.assertIsFalse('oFf')
459
 
 
460
 
    def test_invalid_values(self):
461
 
        self.assertIsNone(None)
462
 
        self.assertIsNone('doubt')
463
 
        self.assertIsNone('frue')
464
 
        self.assertIsNone('talse')
465
 
        self.assertIsNone('42')
466
 
 
467
 
    def test_provided_values(self):
468
 
        av = dict(y=True, n=False, yes=True, no=False)
469
 
        self.assertIsTrue('y', av)
470
 
        self.assertIsTrue('Y', av)
471
 
        self.assertIsTrue('Yes', av)
472
 
        self.assertIsFalse('n', av)
473
 
        self.assertIsFalse('N', av)
474
 
        self.assertIsFalse('No', av)
475
 
        self.assertIsNone('1', av)
476
 
        self.assertIsNone('0', av)
477
 
        self.assertIsNone('on', av)
478
 
        self.assertIsNone('off', av)
 
295
 
 
296
class TestTextProgressView(TestCase):
 
297
    """Tests for text display of progress bars.
 
298
    """
 
299
    # XXX: These might be a bit easier to write if the rendering and
 
300
    # state-maintaining parts of TextProgressView were more separate, and if
 
301
    # the progress task called back directly to its own view not to the ui
 
302
    # factory. -- mbp 20090312
 
303
    
 
304
    def _make_factory(self):
 
305
        out = StringIO()
 
306
        uif = TextUIFactory(stderr=out)
 
307
        uif._progress_view._width = 80
 
308
        return out, uif
 
309
 
 
310
    def test_render_progress_easy(self):
 
311
        """Just one task and one quarter done"""
 
312
        out, uif = self._make_factory()
 
313
        task = uif.nested_progress_bar()
 
314
        task.update('reticulating splines', 5, 20)
 
315
        self.assertEqual(
 
316
'\r[####/               ] reticulating splines 5/20                               \r'
 
317
            , out.getvalue())
 
318
 
 
319
    def test_render_progress_nested(self):
 
320
        """Tasks proportionally contribute to overall progress"""
 
321
        out, uif = self._make_factory()
 
322
        task = uif.nested_progress_bar()
 
323
        task.update('reticulating splines', 0, 2)
 
324
        task2 = uif.nested_progress_bar()
 
325
        task2.update('stage2', 1, 2)
 
326
        # so we're in the first half of the main task, and half way through
 
327
        # that
 
328
        self.assertEqual(
 
329
r'[####\               ] reticulating splines:stage2 1/2'
 
330
            , uif._progress_view._render_line())
 
331
        # if the nested task is complete, then we're all the way through the
 
332
        # first half of the overall work
 
333
        task2.update('stage2', 2, 2)
 
334
        self.assertEqual(
 
335
r'[#########|          ] reticulating splines:stage2 2/2'
 
336
            , uif._progress_view._render_line())
 
337
 
 
338
    def test_render_progress_sub_nested(self):
 
339
        """Intermediate tasks don't mess up calculation."""
 
340
        out, uif = self._make_factory()
 
341
        task_a = uif.nested_progress_bar()
 
342
        task_a.update('a', 0, 2)
 
343
        task_b = uif.nested_progress_bar()
 
344
        task_b.update('b')
 
345
        task_c = uif.nested_progress_bar()
 
346
        task_c.update('c', 1, 2)
 
347
        # the top-level task is in its first half; the middle one has no
 
348
        # progress indication, just a label; and the bottom one is half done,
 
349
        # so the overall fraction is 1/4
 
350
        self.assertEqual(
 
351
            r'[####|               ] a:b:c 1/2'
 
352
            , uif._progress_view._render_line())
 
353