/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

build_tree_contents can create symlinks

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, 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
21
22
import re
 
23
import sys
22
24
import time
23
25
 
24
 
from StringIO import StringIO
25
 
 
26
26
from bzrlib import (
27
27
    errors,
28
28
    remote,
33
33
from bzrlib.symbol_versioning import (
34
34
    deprecated_in,
35
35
    )
36
 
from bzrlib.tests import test_progress
37
 
from bzrlib.ui import text as _mod_ui_text
38
 
 
39
 
 
40
 
class TestTextUIFactory(tests.TestCase):
 
36
from bzrlib.tests import (
 
37
    TestCase,
 
38
    TestUIFactory,
 
39
    StringIOWrapper,
 
40
    )
 
41
from bzrlib.tests.test_progress import (
 
42
    _NonTTYStringIO,
 
43
    _TTYStringIO,
 
44
    )
 
45
from bzrlib.ui import (
 
46
    CannedInputUIFactory,
 
47
    CLIUIFactory,
 
48
    SilentUIFactory,
 
49
    UIFactory,
 
50
    make_ui_for_terminal,
 
51
    )
 
52
from bzrlib.ui.text import (
 
53
    NullProgressView,
 
54
    TextProgressView,
 
55
    TextUIFactory,
 
56
    )
 
57
 
 
58
 
 
59
class UITests(tests.TestCase):
41
60
 
42
61
    def test_text_factory_ascii_password(self):
43
62
        ui = tests.TestUIFactory(stdin='secret\n',
83
102
        finally:
84
103
            pb.finished()
85
104
 
 
105
    def test_progress_construction(self):
 
106
        """TextUIFactory constructs the right progress view.
 
107
        """
 
108
        for (file_class, term, pb, expected_pb_class) in (
 
109
            # on an xterm, either use them or not as the user requests,
 
110
            # otherwise default on
 
111
            (_TTYStringIO, 'xterm', 'none', NullProgressView),
 
112
            (_TTYStringIO, 'xterm', 'text', TextProgressView),
 
113
            (_TTYStringIO, 'xterm', None, TextProgressView),
 
114
            # on a dumb terminal, again if there's explicit configuration do
 
115
            # it, otherwise default off
 
116
            (_TTYStringIO, 'dumb', 'none', NullProgressView),
 
117
            (_TTYStringIO, 'dumb', 'text', TextProgressView),
 
118
            (_TTYStringIO, 'dumb', None, NullProgressView),
 
119
            # on a non-tty terminal, it's null regardless of $TERM
 
120
            (StringIO, 'xterm', None, NullProgressView),
 
121
            (StringIO, 'dumb', None, NullProgressView),
 
122
            # however, it can still be forced on
 
123
            (StringIO, 'dumb', 'text', TextProgressView),
 
124
            ):
 
125
            os.environ['TERM'] = term
 
126
            if pb is None:
 
127
                if 'BZR_PROGRESS_BAR' in os.environ:
 
128
                    del os.environ['BZR_PROGRESS_BAR']
 
129
            else:
 
130
                os.environ['BZR_PROGRESS_BAR'] = pb
 
131
            stdin = file_class('')
 
132
            stderr = file_class()
 
133
            stdout = file_class()
 
134
            uif = make_ui_for_terminal(stdin, stdout, stderr)
 
135
            self.assertIsInstance(uif, TextUIFactory,
 
136
                "TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
 
137
            self.assertIsInstance(uif.make_progress_view(),
 
138
                expected_pb_class,
 
139
                "TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
 
140
 
 
141
    def test_text_ui_non_terminal(self):
 
142
        """Even on non-ttys, make_ui_for_terminal gives a text ui."""
 
143
        stdin = _NonTTYStringIO('')
 
144
        stderr = _NonTTYStringIO()
 
145
        stdout = _NonTTYStringIO()
 
146
        for term_type in ['dumb', None, 'xterm']:
 
147
            if term_type is None:
 
148
                del os.environ['TERM']
 
149
            else:
 
150
                os.environ['TERM'] = term_type
 
151
            uif = make_ui_for_terminal(stdin, stdout, stderr)
 
152
            self.assertIsInstance(uif, TextUIFactory,
 
153
                'TERM=%r' % (term_type,))
 
154
 
86
155
    def test_progress_note(self):
87
 
        stderr = tests.StringIOWrapper()
88
 
        stdout = tests.StringIOWrapper()
89
 
        ui_factory = _mod_ui_text.TextUIFactory(stdin=tests.StringIOWrapper(''),
90
 
                                                stderr=stderr,
91
 
                                                stdout=stdout)
 
156
        stderr = StringIO()
 
157
        stdout = StringIO()
 
158
        ui_factory = TextUIFactory(stdin=StringIO(''),
 
159
            stderr=stderr,
 
160
            stdout=stdout)
92
161
        pb = ui_factory.nested_progress_bar()
93
162
        try:
94
 
            result = self.applyDeprecated(deprecated_in((2, 1, 0)),
95
 
                pb.note,
96
 
                't')
 
163
            result = pb.note('t')
97
164
            self.assertEqual(None, result)
98
165
            self.assertEqual("t\n", stdout.getvalue())
99
166
            # Since there was no update() call, there should be no clear() call
104
171
            pb.finished()
105
172
 
106
173
    def test_progress_note_clears(self):
107
 
        stderr = test_progress._TTYStringIO()
108
 
        stdout = test_progress._TTYStringIO()
 
174
        stderr = _TTYStringIO()
 
175
        stdout = _TTYStringIO()
109
176
        # so that we get a TextProgressBar
110
177
        os.environ['TERM'] = 'xterm'
111
 
        ui_factory = _mod_ui_text.TextUIFactory(
112
 
            stdin=tests.StringIOWrapper(''),
 
178
        ui_factory = TextUIFactory(
 
179
            stdin=StringIO(''),
113
180
            stdout=stdout, stderr=stderr)
114
181
        self.assertIsInstance(ui_factory._progress_view,
115
 
                              _mod_ui_text.TextProgressView)
 
182
            TextProgressView)
116
183
        pb = ui_factory.nested_progress_bar()
117
184
        try:
118
185
            # Create a progress update that isn't throttled
119
186
            pb.update('x', 1, 1)
120
 
            result = self.applyDeprecated(deprecated_in((2, 1, 0)),
121
 
                pb.note, 't')
 
187
            result = pb.note('t')
122
188
            self.assertEqual(None, result)
123
189
            self.assertEqual("t\n", stdout.getvalue())
124
190
            # the exact contents will depend on the terminal width and we don't
128
194
        finally:
129
195
            pb.finished()
130
196
 
 
197
    def test_progress_nested(self):
 
198
        # test factory based nested and popping.
 
199
        ui = TextUIFactory(None, None, None)
 
200
        pb1 = ui.nested_progress_bar()
 
201
        pb2 = ui.nested_progress_bar()
 
202
        # You do get a warning if the outermost progress bar wasn't finished
 
203
        # first - it's not clear if this is really useful or if it should just
 
204
        # become orphaned -- mbp 20090120
 
205
        warnings, _ = self.callCatchWarnings(pb1.finished)
 
206
        if len(warnings) != 1:
 
207
            self.fail("unexpected warnings: %r" % (warnings,))
 
208
        pb2.finished()
 
209
        pb1.finished()
 
210
 
131
211
    def test_text_ui_get_boolean(self):
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)
 
212
        stdin = StringIO("y\n" # True
 
213
                         "n\n" # False
 
214
                         "yes with garbage\nY\n" # True
 
215
                         "not an answer\nno\n" # False
 
216
                         "I'm sure!\nyes\n" # True
 
217
                         "NO\n" # False
 
218
                         "foo\n")
 
219
        stdout = StringIO()
 
220
        stderr = StringIO()
 
221
        factory = TextUIFactory(stdin, stdout, stderr)
142
222
        self.assertEqual(True, factory.get_boolean(""))
143
223
        self.assertEqual(False, factory.get_boolean(""))
144
224
        self.assertEqual(True, factory.get_boolean(""))
149
229
        # stdin should be empty
150
230
        self.assertEqual('', factory.stdin.readline())
151
231
 
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
 
 
164
232
    def test_text_factory_prompt(self):
165
233
        # see <https://launchpad.net/bugs/365891>
166
 
        StringIO = tests.StringIOWrapper
167
 
        factory = _mod_ui_text.TextUIFactory(StringIO(), StringIO(), StringIO())
 
234
        factory = TextUIFactory(StringIO(), StringIO(), StringIO())
168
235
        factory.prompt('foo %2e')
169
236
        self.assertEqual('', factory.stdout.getvalue())
170
237
        self.assertEqual('foo %2e', factory.stderr.getvalue())
171
238
 
172
239
    def test_text_factory_prompts_and_clears(self):
173
240
        # a get_boolean call should clear the pb before prompting
174
 
        out = test_progress._TTYStringIO()
 
241
        out = _TTYStringIO()
175
242
        os.environ['TERM'] = 'xterm'
176
 
        factory = _mod_ui_text.TextUIFactory(
177
 
            stdin=tests.StringIOWrapper("yada\ny\n"),
178
 
            stdout=out, stderr=out)
 
243
        factory = TextUIFactory(stdin=StringIO("yada\ny\n"), stdout=out, stderr=out)
179
244
        pb = factory.nested_progress_bar()
180
245
        pb.show_bar = False
181
246
        pb.show_spinner = False
195
260
        self.assertEqual('', factory.stdin.readline())
196
261
 
197
262
    def test_text_tick_after_update(self):
198
 
        ui_factory = _mod_ui_text.TextUIFactory(stdout=tests.StringIOWrapper(),
199
 
                                                stderr=tests.StringIOWrapper())
 
263
        ui_factory = TextUIFactory(stdout=StringIO(), stderr=StringIO())
200
264
        pb = ui_factory.nested_progress_bar()
201
265
        try:
202
266
            pb.update('task', 0, 3)
207
271
            pb.finished()
208
272
 
209
273
    def test_text_ui_getusername(self):
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()
 
274
        factory = TextUIFactory(None, None, None)
 
275
        factory.stdin = StringIO("someuser\n\n")
 
276
        factory.stdout = StringIO()
 
277
        factory.stderr = StringIO()
214
278
        factory.stdout.encoding = "utf8"
215
279
        # there is no output from the base factory
216
280
        self.assertEqual("someuser",
238
302
        finally:
239
303
            pb.finished()
240
304
 
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
305
    def test_text_ui_show_user_warning(self):
253
306
        from bzrlib.repofmt.groupcompress_repo import RepositoryFormat2a
254
307
        from bzrlib.repofmt.pack_repo import RepositoryFormatKnitPack5
276
329
        self.assertEquals('', err.getvalue())
277
330
 
278
331
 
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):
 
332
class CLIUITests(TestCase):
 
333
 
 
334
    def test_cli_factory_deprecated(self):
 
335
        uif = self.applyDeprecated(deprecated_in((1, 18, 0)),
 
336
            CLIUIFactory,
 
337
            StringIO(), StringIO(), StringIO())
 
338
        self.assertIsInstance(uif, UIFactory)
 
339
 
 
340
 
 
341
class SilentUITests(TestCase):
361
342
 
362
343
    def test_silent_factory_get_password(self):
363
344
        # A silent factory that can't do user interaction can't get a
364
345
        # password.  Possibly it should raise a more specific error but it
365
346
        # can't succeed.
366
 
        ui = _mod_ui.SilentUIFactory()
367
 
        stdout = tests.StringIOWrapper()
 
347
        ui = SilentUIFactory()
 
348
        stdout = StringIO()
368
349
        self.assertRaises(
369
350
            NotImplementedError,
370
351
            self.apply_redirected,
373
354
        self.assertEqual('', stdout.getvalue())
374
355
 
375
356
    def test_silent_ui_getbool(self):
376
 
        factory = _mod_ui.SilentUIFactory()
377
 
        stdout = tests.StringIOWrapper()
 
357
        factory = SilentUIFactory()
 
358
        stdout = StringIO()
378
359
        self.assertRaises(
379
360
            NotImplementedError,
380
361
            self.apply_redirected,
381
362
            None, stdout, stdout, factory.get_boolean, "foo")
382
363
 
383
364
 
384
 
class TestUIFactoryTests(tests.TestCase):
 
365
class TestUIFactoryTests(TestCase):
385
366
 
386
367
    def test_test_ui_factory_progress(self):
387
368
        # there's no output; we just want to make sure this doesn't crash -
388
369
        # see https://bugs.edge.launchpad.net/bzr/+bug/408201
389
 
        ui = tests.TestUIFactory()
 
370
        ui = TestUIFactory()
390
371
        pb = ui.nested_progress_bar()
391
372
        pb.update('hello')
392
373
        pb.tick()
393
374
        pb.finished()
394
375
 
395
376
 
396
 
class CannedInputUIFactoryTests(tests.TestCase):
397
 
 
 
377
class CannedInputUIFactoryTests(TestCase):
 
378
    
398
379
    def test_canned_input_get_input(self):
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 ?'))
 
380
        uif = CannedInputUIFactory([True, 'mbp', 'password'])
 
381
        self.assertEqual(uif.get_boolean('Extra cheese?'), True)
 
382
        self.assertEqual(uif.get_username('Enter your user name'), 'mbp')
 
383
        self.assertEqual(uif.get_password('Password for %(host)s', host='example.com'),
 
384
            'password')
406
385
 
407
386
 
408
387
class TestBoolFromString(tests.TestCase):