~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_ui.py

  • Committer: Martin Pool
  • Date: 2010-06-02 05:03:31 UTC
  • mto: This revision was merged to the branch mainline in revision 5279.
  • Revision ID: mbp@canonical.com-20100602050331-n2p1qt8hfsahspnv
Correct more sloppy use of the term 'Linux'

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2008, 2009 Canonical Ltd
 
1
# Copyright (C) 2005-2010 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
22
21
import re
23
 
import sys
24
22
import time
25
23
 
 
24
from StringIO import StringIO
 
25
 
26
26
from bzrlib import (
27
27
    errors,
 
28
    remote,
 
29
    repository,
28
30
    tests,
29
31
    ui as _mod_ui,
30
32
    )
31
33
from bzrlib.symbol_versioning import (
32
34
    deprecated_in,
33
35
    )
34
 
from bzrlib.tests import (
35
 
    TestCase,
36
 
    TestUIFactory,
37
 
    StringIOWrapper,
38
 
    )
39
 
from bzrlib.tests.test_progress import (
40
 
    _NonTTYStringIO,
41
 
    _TTYStringIO,
42
 
    )
43
 
from bzrlib.ui import (
44
 
    CannedInputUIFactory,
45
 
    CLIUIFactory,
46
 
    SilentUIFactory,
47
 
    UIFactory,
48
 
    make_ui_for_terminal,
49
 
    )
50
 
from bzrlib.ui.text import (
51
 
    NullProgressView,
52
 
    TextProgressView,
53
 
    TextUIFactory,
54
 
    )
55
 
 
56
 
 
57
 
class UITests(tests.TestCase):
 
36
from bzrlib.tests import test_progress
 
37
from bzrlib.ui import text as _mod_ui_text
 
38
 
 
39
 
 
40
class TestTextUIFactory(tests.TestCase):
58
41
 
59
42
    def test_text_factory_ascii_password(self):
60
43
        ui = tests.TestUIFactory(stdin='secret\n',
100
83
        finally:
101
84
            pb.finished()
102
85
 
103
 
    def test_progress_construction(self):
104
 
        """TextUIFactory constructs the right progress view.
105
 
        """
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,))
152
 
 
153
86
    def test_progress_note(self):
154
 
        stderr = StringIO()
155
 
        stdout = StringIO()
156
 
        ui_factory = TextUIFactory(stdin=StringIO(''),
157
 
            stderr=stderr,
158
 
            stdout=stdout)
 
87
        stderr = tests.StringIOWrapper()
 
88
        stdout = tests.StringIOWrapper()
 
89
        ui_factory = _mod_ui_text.TextUIFactory(stdin=tests.StringIOWrapper(''),
 
90
                                                stderr=stderr,
 
91
                                                stdout=stdout)
159
92
        pb = ui_factory.nested_progress_bar()
160
93
        try:
161
 
            result = pb.note('t')
 
94
            result = self.applyDeprecated(deprecated_in((2, 1, 0)),
 
95
                pb.note,
 
96
                't')
162
97
            self.assertEqual(None, result)
163
98
            self.assertEqual("t\n", stdout.getvalue())
164
99
            # Since there was no update() call, there should be no clear() call
169
104
            pb.finished()
170
105
 
171
106
    def test_progress_note_clears(self):
172
 
        stderr = _TTYStringIO()
173
 
        stdout = _TTYStringIO()
 
107
        stderr = test_progress._TTYStringIO()
 
108
        stdout = test_progress._TTYStringIO()
174
109
        # so that we get a TextProgressBar
175
110
        os.environ['TERM'] = 'xterm'
176
 
        ui_factory = TextUIFactory(
177
 
            stdin=StringIO(''),
 
111
        ui_factory = _mod_ui_text.TextUIFactory(
 
112
            stdin=tests.StringIOWrapper(''),
178
113
            stdout=stdout, stderr=stderr)
179
114
        self.assertIsInstance(ui_factory._progress_view,
180
 
            TextProgressView)
 
115
                              _mod_ui_text.TextProgressView)
181
116
        pb = ui_factory.nested_progress_bar()
182
117
        try:
183
118
            # Create a progress update that isn't throttled
184
119
            pb.update('x', 1, 1)
185
 
            result = pb.note('t')
 
120
            result = self.applyDeprecated(deprecated_in((2, 1, 0)),
 
121
                pb.note, 't')
186
122
            self.assertEqual(None, result)
187
123
            self.assertEqual("t\n", stdout.getvalue())
188
124
            # the exact contents will depend on the terminal width and we don't
192
128
        finally:
193
129
            pb.finished()
194
130
 
195
 
    def test_progress_nested(self):
196
 
        # test factory based nested and popping.
197
 
        ui = TextUIFactory(None, None, None)
198
 
        pb1 = ui.nested_progress_bar()
199
 
        pb2 = ui.nested_progress_bar()
200
 
        # You do get a warning if the outermost progress bar wasn't finished
201
 
        # first - it's not clear if this is really useful or if it should just
202
 
        # become orphaned -- mbp 20090120
203
 
        warnings, _ = self.callCatchWarnings(pb1.finished)
204
 
        if len(warnings) != 1:
205
 
            self.fail("unexpected warnings: %r" % (warnings,))
206
 
        pb2.finished()
207
 
        pb1.finished()
208
 
 
209
131
    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)
 
132
        stdin = tests.StringIOWrapper("y\n" # True
 
133
                                      "n\n" # False
 
134
                                      "yes with garbage\nY\n" # True
 
135
                                      "not an answer\nno\n" # False
 
136
                                      "I'm sure!\nyes\n" # True
 
137
                                      "NO\n" # False
 
138
                                      "foo\n")
 
139
        stdout = tests.StringIOWrapper()
 
140
        stderr = tests.StringIOWrapper()
 
141
        factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
220
142
        self.assertEqual(True, factory.get_boolean(""))
221
143
        self.assertEqual(False, factory.get_boolean(""))
222
144
        self.assertEqual(True, factory.get_boolean(""))
227
149
        # stdin should be empty
228
150
        self.assertEqual('', factory.stdin.readline())
229
151
 
 
152
    def test_text_ui_get_integer(self):
 
153
        stdin = tests.StringIOWrapper(
 
154
            "1\n"
 
155
            "  -2  \n"
 
156
            "hmmm\nwhat else ?\nCome on\nok 42\n4.24\n42\n")
 
157
        stdout = tests.StringIOWrapper()
 
158
        stderr = tests.StringIOWrapper()
 
159
        factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
 
160
        self.assertEqual(1, factory.get_integer(""))
 
161
        self.assertEqual(-2, factory.get_integer(""))
 
162
        self.assertEqual(42, factory.get_integer(""))
 
163
 
230
164
    def test_text_factory_prompt(self):
231
165
        # see <https://launchpad.net/bugs/365891>
232
 
        factory = TextUIFactory(StringIO(), StringIO(), StringIO())
 
166
        StringIO = tests.StringIOWrapper
 
167
        factory = _mod_ui_text.TextUIFactory(StringIO(), StringIO(), StringIO())
233
168
        factory.prompt('foo %2e')
234
169
        self.assertEqual('', factory.stdout.getvalue())
235
170
        self.assertEqual('foo %2e', factory.stderr.getvalue())
236
171
 
237
172
    def test_text_factory_prompts_and_clears(self):
238
173
        # a get_boolean call should clear the pb before prompting
239
 
        out = _TTYStringIO()
 
174
        out = test_progress._TTYStringIO()
240
175
        os.environ['TERM'] = 'xterm'
241
 
        factory = TextUIFactory(stdin=StringIO("yada\ny\n"), stdout=out, stderr=out)
 
176
        factory = _mod_ui_text.TextUIFactory(
 
177
            stdin=tests.StringIOWrapper("yada\ny\n"),
 
178
            stdout=out, stderr=out)
242
179
        pb = factory.nested_progress_bar()
243
180
        pb.show_bar = False
244
181
        pb.show_spinner = False
258
195
        self.assertEqual('', factory.stdin.readline())
259
196
 
260
197
    def test_text_tick_after_update(self):
261
 
        ui_factory = TextUIFactory(stdout=StringIO(), stderr=StringIO())
 
198
        ui_factory = _mod_ui_text.TextUIFactory(stdout=tests.StringIOWrapper(),
 
199
                                                stderr=tests.StringIOWrapper())
262
200
        pb = ui_factory.nested_progress_bar()
263
201
        try:
264
202
            pb.update('task', 0, 3)
269
207
            pb.finished()
270
208
 
271
209
    def test_text_ui_getusername(self):
272
 
        factory = TextUIFactory(None, None, None)
273
 
        factory.stdin = StringIO("someuser\n\n")
274
 
        factory.stdout = StringIO()
275
 
        factory.stderr = StringIO()
 
210
        factory = _mod_ui_text.TextUIFactory(None, None, None)
 
211
        factory.stdin = tests.StringIOWrapper("someuser\n\n")
 
212
        factory.stdout = tests.StringIOWrapper()
 
213
        factory.stderr = tests.StringIOWrapper()
276
214
        factory.stdout.encoding = "utf8"
277
215
        # there is no output from the base factory
278
216
        self.assertEqual("someuser",
300
238
        finally:
301
239
            pb.finished()
302
240
 
303
 
 
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):
 
241
    def test_quietness(self):
 
242
        os.environ['BZR_PROGRESS_BAR'] = 'text'
 
243
        ui_factory = _mod_ui_text.TextUIFactory(None,
 
244
            test_progress._TTYStringIO(),
 
245
            test_progress._TTYStringIO())
 
246
        self.assertIsInstance(ui_factory._progress_view,
 
247
            _mod_ui_text.TextProgressView)
 
248
        ui_factory.be_quiet(True)
 
249
        self.assertIsInstance(ui_factory._progress_view,
 
250
            _mod_ui_text.NullProgressView)
 
251
 
 
252
    def test_text_ui_show_user_warning(self):
 
253
        from bzrlib.repofmt.groupcompress_repo import RepositoryFormat2a
 
254
        from bzrlib.repofmt.pack_repo import RepositoryFormatKnitPack5
 
255
        err = StringIO()
 
256
        out = StringIO()
 
257
        ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
 
258
        remote_fmt = remote.RemoteRepositoryFormat()
 
259
        remote_fmt._network_name = RepositoryFormatKnitPack5().network_name()
 
260
        ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
 
261
            to_format=remote_fmt)
 
262
        self.assertEquals('', out.getvalue())
 
263
        self.assertEquals("Doing on-the-fly conversion from RepositoryFormat2a() to "
 
264
            "RemoteRepositoryFormat(_network_name='Bazaar RepositoryFormatKnitPack5 "
 
265
            "(bzr 1.6)\\n').\nThis may take some time. Upgrade the repositories to "
 
266
            "the same format for better performance.\n",
 
267
            err.getvalue())
 
268
        # and now with it suppressed please
 
269
        err = StringIO()
 
270
        out = StringIO()
 
271
        ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
 
272
        ui.suppressed_warnings.add('cross_format_fetch')
 
273
        ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
 
274
            to_format=remote_fmt)
 
275
        self.assertEquals('', out.getvalue())
 
276
        self.assertEquals('', err.getvalue())
 
277
 
 
278
 
 
279
class TestTextUIOutputStream(tests.TestCase):
 
280
    """Tests for output stream that synchronizes with progress bar."""
 
281
 
 
282
    def test_output_clears_terminal(self):
 
283
        stdout = tests.StringIOWrapper()
 
284
        stderr = tests.StringIOWrapper()
 
285
        clear_calls = []
 
286
 
 
287
        uif =  _mod_ui_text.TextUIFactory(None, stdout, stderr)
 
288
        uif.clear_term = lambda: clear_calls.append('clear')
 
289
 
 
290
        stream = _mod_ui_text.TextUIOutputStream(uif, uif.stdout)
 
291
        stream.write("Hello world!\n")
 
292
        stream.write("there's more...\n")
 
293
        stream.writelines(["1\n", "2\n", "3\n"])
 
294
 
 
295
        self.assertEqual(stdout.getvalue(),
 
296
            "Hello world!\n"
 
297
            "there's more...\n"
 
298
            "1\n2\n3\n")
 
299
        self.assertEqual(['clear', 'clear', 'clear'],
 
300
            clear_calls)
 
301
 
 
302
        stream.flush()
 
303
 
 
304
 
 
305
class UITests(tests.TestCase):
 
306
 
 
307
    def test_progress_construction(self):
 
308
        """TextUIFactory constructs the right progress view.
 
309
        """
 
310
        TTYStringIO = test_progress._TTYStringIO
 
311
        FileStringIO = tests.StringIOWrapper
 
312
        for (file_class, term, pb, expected_pb_class) in (
 
313
            # on an xterm, either use them or not as the user requests,
 
314
            # otherwise default on
 
315
            (TTYStringIO, 'xterm', 'none', _mod_ui_text.NullProgressView),
 
316
            (TTYStringIO, 'xterm', 'text', _mod_ui_text.TextProgressView),
 
317
            (TTYStringIO, 'xterm', None, _mod_ui_text.TextProgressView),
 
318
            # on a dumb terminal, again if there's explicit configuration do
 
319
            # it, otherwise default off
 
320
            (TTYStringIO, 'dumb', 'none', _mod_ui_text.NullProgressView),
 
321
            (TTYStringIO, 'dumb', 'text', _mod_ui_text.TextProgressView),
 
322
            (TTYStringIO, 'dumb', None, _mod_ui_text.NullProgressView),
 
323
            # on a non-tty terminal, it's null regardless of $TERM
 
324
            (FileStringIO, 'xterm', None, _mod_ui_text.NullProgressView),
 
325
            (FileStringIO, 'dumb', None, _mod_ui_text.NullProgressView),
 
326
            # however, it can still be forced on
 
327
            (FileStringIO, 'dumb', 'text', _mod_ui_text.TextProgressView),
 
328
            ):
 
329
            os.environ['TERM'] = term
 
330
            if pb is None:
 
331
                if 'BZR_PROGRESS_BAR' in os.environ:
 
332
                    del os.environ['BZR_PROGRESS_BAR']
 
333
            else:
 
334
                os.environ['BZR_PROGRESS_BAR'] = pb
 
335
            stdin = file_class('')
 
336
            stderr = file_class()
 
337
            stdout = file_class()
 
338
            uif = _mod_ui.make_ui_for_terminal(stdin, stdout, stderr)
 
339
            self.assertIsInstance(uif, _mod_ui_text.TextUIFactory,
 
340
                "TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
 
341
            self.assertIsInstance(uif.make_progress_view(),
 
342
                expected_pb_class,
 
343
                "TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
 
344
 
 
345
    def test_text_ui_non_terminal(self):
 
346
        """Even on non-ttys, make_ui_for_terminal gives a text ui."""
 
347
        stdin = test_progress._NonTTYStringIO('')
 
348
        stderr = test_progress._NonTTYStringIO()
 
349
        stdout = test_progress._NonTTYStringIO()
 
350
        for term_type in ['dumb', None, 'xterm']:
 
351
            if term_type is None:
 
352
                del os.environ['TERM']
 
353
            else:
 
354
                os.environ['TERM'] = term_type
 
355
            uif = _mod_ui.make_ui_for_terminal(stdin, stdout, stderr)
 
356
            self.assertIsInstance(uif, _mod_ui_text.TextUIFactory,
 
357
                'TERM=%r' % (term_type,))
 
358
 
 
359
 
 
360
class SilentUITests(tests.TestCase):
314
361
 
315
362
    def test_silent_factory_get_password(self):
316
363
        # A silent factory that can't do user interaction can't get a
317
364
        # password.  Possibly it should raise a more specific error but it
318
365
        # can't succeed.
319
 
        ui = SilentUIFactory()
320
 
        stdout = StringIO()
 
366
        ui = _mod_ui.SilentUIFactory()
 
367
        stdout = tests.StringIOWrapper()
321
368
        self.assertRaises(
322
369
            NotImplementedError,
323
370
            self.apply_redirected,
326
373
        self.assertEqual('', stdout.getvalue())
327
374
 
328
375
    def test_silent_ui_getbool(self):
329
 
        factory = SilentUIFactory()
330
 
        stdout = StringIO()
 
376
        factory = _mod_ui.SilentUIFactory()
 
377
        stdout = tests.StringIOWrapper()
331
378
        self.assertRaises(
332
379
            NotImplementedError,
333
380
            self.apply_redirected,
334
381
            None, stdout, stdout, factory.get_boolean, "foo")
335
382
 
336
383
 
337
 
class TestUIFactoryTests(TestCase):
 
384
class TestUIFactoryTests(tests.TestCase):
338
385
 
339
386
    def test_test_ui_factory_progress(self):
340
387
        # 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()
 
388
        # see https://bugs.launchpad.net/bzr/+bug/408201
 
389
        ui = tests.TestUIFactory()
343
390
        pb = ui.nested_progress_bar()
344
391
        pb.update('hello')
345
392
        pb.tick()
346
393
        pb.finished()
347
394
 
348
395
 
349
 
class CannedInputUIFactoryTests(TestCase):
350
 
    
 
396
class CannedInputUIFactoryTests(tests.TestCase):
 
397
 
351
398
    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')
 
399
        uif = _mod_ui.CannedInputUIFactory([True, 'mbp', 'password', 42])
 
400
        self.assertEqual(True, uif.get_boolean('Extra cheese?'))
 
401
        self.assertEqual('mbp', uif.get_username('Enter your user name'))
 
402
        self.assertEqual('password',
 
403
                         uif.get_password('Password for %(host)s',
 
404
                                          host='example.com'))
 
405
        self.assertEqual(42, uif.get_integer('And all that jazz ?'))
357
406
 
358
407
 
359
408
class TestBoolFromString(tests.TestCase):