~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_ui.py

  • Committer: John Arbash Meinel
  • Date: 2010-02-17 17:11:16 UTC
  • mfrom: (4797.2.17 2.1)
  • mto: (4797.2.18 2.1)
  • mto: This revision was merged to the branch mainline in revision 5055.
  • Revision ID: john@arbash-meinel.com-20100217171116-h7t9223ystbnx5h8
merge bzr.2.1 in preparation for NEWS entry.

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
 
26
24
from bzrlib import (
31
29
from bzrlib.symbol_versioning import (
32
30
    deprecated_in,
33
31
    )
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
 
    SilentUIFactory,
46
 
    UIFactory,
47
 
    make_ui_for_terminal,
48
 
    )
49
 
from bzrlib.ui.text import (
50
 
    NullProgressView,
51
 
    TextProgressView,
52
 
    TextUIFactory,
53
 
    )
 
32
from bzrlib.tests import test_progress
 
33
from bzrlib.ui import text as _mod_ui_text
54
34
 
55
35
 
56
36
class TestTextUIFactory(tests.TestCase):
100
80
            pb.finished()
101
81
 
102
82
    def test_progress_note(self):
103
 
        stderr = StringIO()
104
 
        stdout = StringIO()
105
 
        ui_factory = TextUIFactory(stdin=StringIO(''),
106
 
            stderr=stderr,
107
 
            stdout=stdout)
 
83
        stderr = tests.StringIOWrapper()
 
84
        stdout = tests.StringIOWrapper()
 
85
        ui_factory = _mod_ui_text.TextUIFactory(stdin=tests.StringIOWrapper(''),
 
86
                                                stderr=stderr,
 
87
                                                stdout=stdout)
108
88
        pb = ui_factory.nested_progress_bar()
109
89
        try:
110
90
            result = self.applyDeprecated(deprecated_in((2, 1, 0)),
120
100
            pb.finished()
121
101
 
122
102
    def test_progress_note_clears(self):
123
 
        stderr = _TTYStringIO()
124
 
        stdout = _TTYStringIO()
 
103
        stderr = test_progress._TTYStringIO()
 
104
        stdout = test_progress._TTYStringIO()
125
105
        # so that we get a TextProgressBar
126
106
        os.environ['TERM'] = 'xterm'
127
 
        ui_factory = TextUIFactory(
128
 
            stdin=StringIO(''),
 
107
        ui_factory = _mod_ui_text.TextUIFactory(
 
108
            stdin=tests.StringIOWrapper(''),
129
109
            stdout=stdout, stderr=stderr)
130
110
        self.assertIsInstance(ui_factory._progress_view,
131
 
            TextProgressView)
 
111
                              _mod_ui_text.TextProgressView)
132
112
        pb = ui_factory.nested_progress_bar()
133
113
        try:
134
114
            # Create a progress update that isn't throttled
146
126
 
147
127
    def test_progress_nested(self):
148
128
        # test factory based nested and popping.
149
 
        ui = TextUIFactory(None, None, None)
 
129
        ui = _mod_ui_text.TextUIFactory(None, None, None)
150
130
        pb1 = ui.nested_progress_bar()
151
131
        pb2 = ui.nested_progress_bar()
152
132
        # You do get a warning if the outermost progress bar wasn't finished
159
139
        pb1.finished()
160
140
 
161
141
    def test_text_ui_get_boolean(self):
162
 
        stdin = StringIO("y\n" # True
163
 
                         "n\n" # False
164
 
                         "yes with garbage\nY\n" # True
165
 
                         "not an answer\nno\n" # False
166
 
                         "I'm sure!\nyes\n" # True
167
 
                         "NO\n" # False
168
 
                         "foo\n")
169
 
        stdout = StringIO()
170
 
        stderr = StringIO()
171
 
        factory = TextUIFactory(stdin, stdout, stderr)
 
142
        stdin = tests.StringIOWrapper("y\n" # True
 
143
                                      "n\n" # False
 
144
                                      "yes with garbage\nY\n" # True
 
145
                                      "not an answer\nno\n" # False
 
146
                                      "I'm sure!\nyes\n" # True
 
147
                                      "NO\n" # False
 
148
                                      "foo\n")
 
149
        stdout = tests.StringIOWrapper()
 
150
        stderr = tests.StringIOWrapper()
 
151
        factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
172
152
        self.assertEqual(True, factory.get_boolean(""))
173
153
        self.assertEqual(False, factory.get_boolean(""))
174
154
        self.assertEqual(True, factory.get_boolean(""))
179
159
        # stdin should be empty
180
160
        self.assertEqual('', factory.stdin.readline())
181
161
 
 
162
    def test_text_ui_get_integer(self):
 
163
        stdin = tests.StringIOWrapper(
 
164
            "1\n"
 
165
            "  -2  \n"
 
166
            "hmmm\nwhat else ?\nCome on\nok 42\n4.24\n42\n")
 
167
        stdout = tests.StringIOWrapper()
 
168
        stderr = tests.StringIOWrapper()
 
169
        factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
 
170
        self.assertEqual(1, factory.get_integer(""))
 
171
        self.assertEqual(-2, factory.get_integer(""))
 
172
        self.assertEqual(42, factory.get_integer(""))
 
173
 
182
174
    def test_text_factory_prompt(self):
183
175
        # see <https://launchpad.net/bugs/365891>
184
 
        factory = TextUIFactory(StringIO(), StringIO(), StringIO())
 
176
        StringIO = tests.StringIOWrapper
 
177
        factory = _mod_ui_text.TextUIFactory(StringIO(), StringIO(), StringIO())
185
178
        factory.prompt('foo %2e')
186
179
        self.assertEqual('', factory.stdout.getvalue())
187
180
        self.assertEqual('foo %2e', factory.stderr.getvalue())
188
181
 
189
182
    def test_text_factory_prompts_and_clears(self):
190
183
        # a get_boolean call should clear the pb before prompting
191
 
        out = _TTYStringIO()
 
184
        out = test_progress._TTYStringIO()
192
185
        os.environ['TERM'] = 'xterm'
193
 
        factory = TextUIFactory(stdin=StringIO("yada\ny\n"), stdout=out, stderr=out)
 
186
        factory = _mod_ui_text.TextUIFactory(
 
187
            stdin=tests.StringIOWrapper("yada\ny\n"),
 
188
            stdout=out, stderr=out)
194
189
        pb = factory.nested_progress_bar()
195
190
        pb.show_bar = False
196
191
        pb.show_spinner = False
210
205
        self.assertEqual('', factory.stdin.readline())
211
206
 
212
207
    def test_text_tick_after_update(self):
213
 
        ui_factory = TextUIFactory(stdout=StringIO(), stderr=StringIO())
 
208
        ui_factory = _mod_ui_text.TextUIFactory(stdout=tests.StringIOWrapper(),
 
209
                                                stderr=tests.StringIOWrapper())
214
210
        pb = ui_factory.nested_progress_bar()
215
211
        try:
216
212
            pb.update('task', 0, 3)
221
217
            pb.finished()
222
218
 
223
219
    def test_text_ui_getusername(self):
224
 
        factory = TextUIFactory(None, None, None)
225
 
        factory.stdin = StringIO("someuser\n\n")
226
 
        factory.stdout = StringIO()
227
 
        factory.stderr = StringIO()
 
220
        factory = _mod_ui_text.TextUIFactory(None, None, None)
 
221
        factory.stdin = tests.StringIOWrapper("someuser\n\n")
 
222
        factory.stdout = tests.StringIOWrapper()
 
223
        factory.stderr = tests.StringIOWrapper()
228
224
        factory.stdout.encoding = "utf8"
229
225
        # there is no output from the base factory
230
226
        self.assertEqual("someuser",
252
248
        finally:
253
249
            pb.finished()
254
250
 
 
251
    def test_quietness(self):
 
252
        os.environ['BZR_PROGRESS_BAR'] = 'text'
 
253
        ui_factory = _mod_ui_text.TextUIFactory(None,
 
254
            test_progress._TTYStringIO(),
 
255
            test_progress._TTYStringIO())
 
256
        self.assertIsInstance(ui_factory._progress_view,
 
257
            _mod_ui_text.TextProgressView)
 
258
        ui_factory.be_quiet(True)
 
259
        self.assertIsInstance(ui_factory._progress_view,
 
260
            _mod_ui_text.NullProgressView)
 
261
 
 
262
 
 
263
class TestTextUIOutputStream(tests.TestCase):
 
264
    """Tests for output stream that synchronizes with progress bar."""
 
265
 
 
266
    def test_output_clears_terminal(self):
 
267
        stdout = tests.StringIOWrapper()
 
268
        stderr = tests.StringIOWrapper()
 
269
        clear_calls = []
 
270
 
 
271
        uif =  _mod_ui_text.TextUIFactory(None, stdout, stderr)
 
272
        uif.clear_term = lambda: clear_calls.append('clear')
 
273
 
 
274
        stream = _mod_ui_text.TextUIOutputStream(uif, uif.stdout)
 
275
        stream.write("Hello world!\n")
 
276
        stream.write("there's more...\n")
 
277
        stream.writelines(["1\n", "2\n", "3\n"])
 
278
 
 
279
        self.assertEqual(stdout.getvalue(),
 
280
            "Hello world!\n"
 
281
            "there's more...\n"
 
282
            "1\n2\n3\n")
 
283
        self.assertEqual(['clear', 'clear', 'clear'],
 
284
            clear_calls)
 
285
 
 
286
        stream.flush()
 
287
 
255
288
 
256
289
class UITests(tests.TestCase):
257
290
 
258
291
    def test_progress_construction(self):
259
292
        """TextUIFactory constructs the right progress view.
260
293
        """
 
294
        TTYStringIO = test_progress._TTYStringIO
 
295
        FileStringIO = tests.StringIOWrapper
261
296
        for (file_class, term, pb, expected_pb_class) in (
262
297
            # on an xterm, either use them or not as the user requests,
263
298
            # otherwise default on
264
 
            (_TTYStringIO, 'xterm', 'none', NullProgressView),
265
 
            (_TTYStringIO, 'xterm', 'text', TextProgressView),
266
 
            (_TTYStringIO, 'xterm', None, TextProgressView),
 
299
            (TTYStringIO, 'xterm', 'none', _mod_ui_text.NullProgressView),
 
300
            (TTYStringIO, 'xterm', 'text', _mod_ui_text.TextProgressView),
 
301
            (TTYStringIO, 'xterm', None, _mod_ui_text.TextProgressView),
267
302
            # on a dumb terminal, again if there's explicit configuration do
268
303
            # it, otherwise default off
269
 
            (_TTYStringIO, 'dumb', 'none', NullProgressView),
270
 
            (_TTYStringIO, 'dumb', 'text', TextProgressView),
271
 
            (_TTYStringIO, 'dumb', None, NullProgressView),
 
304
            (TTYStringIO, 'dumb', 'none', _mod_ui_text.NullProgressView),
 
305
            (TTYStringIO, 'dumb', 'text', _mod_ui_text.TextProgressView),
 
306
            (TTYStringIO, 'dumb', None, _mod_ui_text.NullProgressView),
272
307
            # on a non-tty terminal, it's null regardless of $TERM
273
 
            (StringIO, 'xterm', None, NullProgressView),
274
 
            (StringIO, 'dumb', None, NullProgressView),
 
308
            (FileStringIO, 'xterm', None, _mod_ui_text.NullProgressView),
 
309
            (FileStringIO, 'dumb', None, _mod_ui_text.NullProgressView),
275
310
            # however, it can still be forced on
276
 
            (StringIO, 'dumb', 'text', TextProgressView),
 
311
            (FileStringIO, 'dumb', 'text', _mod_ui_text.TextProgressView),
277
312
            ):
278
313
            os.environ['TERM'] = term
279
314
            if pb is None:
284
319
            stdin = file_class('')
285
320
            stderr = file_class()
286
321
            stdout = file_class()
287
 
            uif = make_ui_for_terminal(stdin, stdout, stderr)
288
 
            self.assertIsInstance(uif, TextUIFactory,
 
322
            uif = _mod_ui.make_ui_for_terminal(stdin, stdout, stderr)
 
323
            self.assertIsInstance(uif, _mod_ui_text.TextUIFactory,
289
324
                "TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
290
325
            self.assertIsInstance(uif.make_progress_view(),
291
326
                expected_pb_class,
293
328
 
294
329
    def test_text_ui_non_terminal(self):
295
330
        """Even on non-ttys, make_ui_for_terminal gives a text ui."""
296
 
        stdin = _NonTTYStringIO('')
297
 
        stderr = _NonTTYStringIO()
298
 
        stdout = _NonTTYStringIO()
 
331
        stdin = test_progress._NonTTYStringIO('')
 
332
        stderr = test_progress._NonTTYStringIO()
 
333
        stdout = test_progress._NonTTYStringIO()
299
334
        for term_type in ['dumb', None, 'xterm']:
300
335
            if term_type is None:
301
336
                del os.environ['TERM']
302
337
            else:
303
338
                os.environ['TERM'] = term_type
304
 
            uif = make_ui_for_terminal(stdin, stdout, stderr)
305
 
            self.assertIsInstance(uif, TextUIFactory,
 
339
            uif = _mod_ui.make_ui_for_terminal(stdin, stdout, stderr)
 
340
            self.assertIsInstance(uif, _mod_ui_text.TextUIFactory,
306
341
                'TERM=%r' % (term_type,))
307
342
 
308
343
 
309
 
class SilentUITests(TestCase):
 
344
class SilentUITests(tests.TestCase):
310
345
 
311
346
    def test_silent_factory_get_password(self):
312
347
        # A silent factory that can't do user interaction can't get a
313
348
        # password.  Possibly it should raise a more specific error but it
314
349
        # can't succeed.
315
 
        ui = SilentUIFactory()
316
 
        stdout = StringIO()
 
350
        ui = _mod_ui.SilentUIFactory()
 
351
        stdout = tests.StringIOWrapper()
317
352
        self.assertRaises(
318
353
            NotImplementedError,
319
354
            self.apply_redirected,
322
357
        self.assertEqual('', stdout.getvalue())
323
358
 
324
359
    def test_silent_ui_getbool(self):
325
 
        factory = SilentUIFactory()
326
 
        stdout = StringIO()
 
360
        factory = _mod_ui.SilentUIFactory()
 
361
        stdout = tests.StringIOWrapper()
327
362
        self.assertRaises(
328
363
            NotImplementedError,
329
364
            self.apply_redirected,
330
365
            None, stdout, stdout, factory.get_boolean, "foo")
331
366
 
332
367
 
333
 
class TestUIFactoryTests(TestCase):
 
368
class TestUIFactoryTests(tests.TestCase):
334
369
 
335
370
    def test_test_ui_factory_progress(self):
336
371
        # there's no output; we just want to make sure this doesn't crash -
337
372
        # see https://bugs.edge.launchpad.net/bzr/+bug/408201
338
 
        ui = TestUIFactory()
 
373
        ui = tests.TestUIFactory()
339
374
        pb = ui.nested_progress_bar()
340
375
        pb.update('hello')
341
376
        pb.tick()
342
377
        pb.finished()
343
378
 
344
379
 
345
 
class CannedInputUIFactoryTests(TestCase):
346
 
    
 
380
class CannedInputUIFactoryTests(tests.TestCase):
 
381
 
347
382
    def test_canned_input_get_input(self):
348
 
        uif = CannedInputUIFactory([True, 'mbp', 'password'])
349
 
        self.assertEqual(uif.get_boolean('Extra cheese?'), True)
350
 
        self.assertEqual(uif.get_username('Enter your user name'), 'mbp')
351
 
        self.assertEqual(uif.get_password('Password for %(host)s', host='example.com'),
352
 
            'password')
 
383
        uif = _mod_ui.CannedInputUIFactory([True, 'mbp', 'password', 42])
 
384
        self.assertEqual(True, uif.get_boolean('Extra cheese?'))
 
385
        self.assertEqual('mbp', uif.get_username('Enter your user name'))
 
386
        self.assertEqual('password',
 
387
                         uif.get_password('Password for %(host)s',
 
388
                                          host='example.com'))
 
389
        self.assertEqual(42, uif.get_integer('And all that jazz ?'))
353
390
 
354
391
 
355
392
class TestBoolFromString(tests.TestCase):