~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_ui.py

  • Committer: Vincent Ladeuil
  • Date: 2009-06-18 19:45:24 UTC
  • mto: This revision was merged to the branch mainline in revision 4466.
  • Revision ID: v.ladeuil+lp@free.fr-20090618194524-poedor61th3op5dm
Cleanup.

* bzrlib/tests/test__known_graph.py:
(TestKnownGraph): Delete dominator tests.

* bzrlib/_known_graph_pyx.pyx: 
Cleanup all references to old version and linear dominators :-/

* bzrlib/_known_graph_py.py: 
Cleanup all references to old version and linear dominators :-/

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005, 2008, 2009 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
"""Tests for the bzrlib ui
 
18
"""
 
19
 
 
20
import os
 
21
from StringIO import StringIO
 
22
import re
 
23
import sys
 
24
import time
 
25
 
 
26
import bzrlib
 
27
import bzrlib.errors as errors
 
28
from bzrlib.symbol_versioning import (
 
29
    deprecated_in,
 
30
    )
 
31
from bzrlib.tests import (
 
32
    TestCase,
 
33
    TestUIFactory,
 
34
    StringIOWrapper,
 
35
    )
 
36
from bzrlib.tests.test_progress import _TTYStringIO
 
37
from bzrlib.ui import (
 
38
    CLIUIFactory,
 
39
    SilentUIFactory,
 
40
    )
 
41
from bzrlib.ui.text import (
 
42
    NullProgressView,
 
43
    TextProgressView,
 
44
    TextUIFactory,
 
45
    )
 
46
 
 
47
 
 
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())
 
63
 
 
64
    def test_text_factory_ascii_password(self):
 
65
        ui = TestUIFactory(stdin='secret\n', stdout=StringIOWrapper(),
 
66
                           stderr=StringIOWrapper())
 
67
        pb = ui.nested_progress_bar()
 
68
        try:
 
69
            self.assertEqual('secret',
 
70
                             self.apply_redirected(ui.stdin, ui.stdout,
 
71
                                                   ui.stderr,
 
72
                                                   ui.get_password))
 
73
            # ': ' is appended to prompt
 
74
            self.assertEqual(': ', ui.stderr.getvalue())
 
75
            self.assertEqual('', ui.stdout.readline())
 
76
            # stdin should be empty
 
77
            self.assertEqual('', ui.stdin.readline())
 
78
        finally:
 
79
            pb.finished()
 
80
 
 
81
    def test_text_factory_utf8_password(self):
 
82
        """Test an utf8 password.
 
83
 
 
84
        We can't predict what encoding users will have for stdin, so we force
 
85
        it to utf8 to test that we transport the password correctly.
 
86
        """
 
87
        ui = TestUIFactory(stdin=u'baz\u1234'.encode('utf8'),
 
88
                           stdout=StringIOWrapper(),
 
89
                           stderr=StringIOWrapper())
 
90
        ui.stderr.encoding = ui.stdout.encoding = ui.stdin.encoding = 'utf8'
 
91
        pb = ui.nested_progress_bar()
 
92
        try:
 
93
            password = self.apply_redirected(ui.stdin, ui.stdout, ui.stderr,
 
94
                                             ui.get_password,
 
95
                                             u'Hello \u1234 %(user)s',
 
96
                                             user=u'some\u1234')
 
97
            # We use StringIO objects, we need to decode them
 
98
            self.assertEqual(u'baz\u1234', password.decode('utf8'))
 
99
            self.assertEqual(u'Hello \u1234 some\u1234: ',
 
100
                             ui.stderr.getvalue().decode('utf8'))
 
101
            # stdin and stdout should be empty
 
102
            self.assertEqual('', ui.stdin.readline())
 
103
            self.assertEqual('', ui.stdout.readline())
 
104
        finally:
 
105
            pb.finished()
 
106
 
 
107
    def test_progress_construction(self):
 
108
        """TextUIFactory constructs the right progress view.
 
109
        """
 
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)
 
125
 
 
126
    def test_progress_note(self):
 
127
        stderr = StringIO()
 
128
        stdout = StringIO()
 
129
        ui_factory = TextUIFactory(stdin=StringIO(''),
 
130
            stderr=stderr,
 
131
            stdout=stdout)
 
132
        pb = ui_factory.nested_progress_bar()
 
133
        try:
 
134
            result = pb.note('t')
 
135
            self.assertEqual(None, result)
 
136
            self.assertEqual("t\n", stdout.getvalue())
 
137
            # Since there was no update() call, there should be no clear() call
 
138
            self.failIf(re.search(r'^\r {10,}\r$',
 
139
                                  stderr.getvalue()) is not None,
 
140
                        'We cleared the stderr without anything to put there')
 
141
        finally:
 
142
            pb.finished()
 
143
 
 
144
    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
 
150
        ui_factory = TextUIFactory(
 
151
            stdin=StringIO(''),
 
152
            stdout=stdout, stderr=stderr)
 
153
        pb = ui_factory.nested_progress_bar()
 
154
        try:
 
155
            # Create a progress update that isn't throttled
 
156
            pb.update('x', 1, 1)
 
157
            result = pb.note('t')
 
158
            self.assertEqual(None, result)
 
159
            self.assertEqual("t\n", stdout.getvalue())
 
160
            # the exact contents will depend on the terminal width and we don't
 
161
            # care about that right now - but you're probably running it on at
 
162
            # least a 10-character wide terminal :)
 
163
            self.assertContainsRe(stderr.getvalue(), r'\r {10,}\r$')
 
164
        finally:
 
165
            pb.finished()
 
166
 
 
167
    def test_progress_nested(self):
 
168
        # test factory based nested and popping.
 
169
        ui = TextUIFactory(None, None, None)
 
170
        pb1 = ui.nested_progress_bar()
 
171
        pb2 = ui.nested_progress_bar()
 
172
        # You do get a warning if the outermost progress bar wasn't finished
 
173
        # first - it's not clear if this is really useful or if it should just
 
174
        # become orphaned -- mbp 20090120
 
175
        warnings, _ = self.callCatchWarnings(pb1.finished)
 
176
        if len(warnings) != 1:
 
177
            self.fail("unexpected warnings: %r" % (warnings,))
 
178
        pb2.finished()
 
179
        pb1.finished()
 
180
 
 
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(""))
 
191
        self.assertEqual(False, factory.get_boolean(""))
 
192
        self.assertEqual("foo\n", factory.stdin.read())
 
193
        # stdin should be empty
 
194
        self.assertEqual('', factory.stdin.readline())
 
195
 
 
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
    def test_text_factory_prompt(self):
 
216
        # see <https://launchpad.net/bugs/365891>
 
217
        factory = TextUIFactory(None, StringIO(), StringIO(), StringIO())
 
218
        factory.prompt('foo %2e')
 
219
        self.assertEqual('', factory.stdout.getvalue())
 
220
        self.assertEqual('foo %2e', factory.stderr.getvalue())
 
221
 
 
222
    def test_text_factory_prompts_and_clears(self):
 
223
        # a get_boolean call should clear the pb before prompting
 
224
        out = _TTYStringIO()
 
225
        factory = TextUIFactory(stdin=StringIO("yada\ny\n"), stdout=out, stderr=out)
 
226
        pb = factory.nested_progress_bar()
 
227
        pb.show_bar = False
 
228
        pb.show_spinner = False
 
229
        pb.show_count = False
 
230
        pb.update("foo", 0, 1)
 
231
        self.assertEqual(True,
 
232
                         self.apply_redirected(None, factory.stdout,
 
233
                                               factory.stdout,
 
234
                                               factory.get_boolean,
 
235
                                               "what do you want"))
 
236
        output = out.getvalue()
 
237
        self.assertContainsRe(factory.stdout.getvalue(),
 
238
            "foo *\r\r  *\r*")
 
239
        self.assertContainsRe(factory.stdout.getvalue(),
 
240
            r"what do you want\? \[y/n\]: what do you want\? \[y/n\]: ")
 
241
        # stdin should have been totally consumed
 
242
        self.assertEqual('', factory.stdin.readline())
 
243
 
 
244
    def test_text_tick_after_update(self):
 
245
        ui_factory = TextUIFactory(stdout=StringIO(), stderr=StringIO())
 
246
        pb = ui_factory.nested_progress_bar()
 
247
        try:
 
248
            pb.update('task', 0, 3)
 
249
            # Reset the clock, so that it actually tries to repaint itself
 
250
            ui_factory._progress_view._last_repaint = time.time() - 1.0
 
251
            pb.tick()
 
252
        finally:
 
253
            pb.finished()
 
254
 
 
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
    def test_text_ui_getusername(self):
 
267
        factory = TextUIFactory(None, None, None)
 
268
        factory.stdin = StringIO("someuser\n\n")
 
269
        factory.stdout = StringIO()
 
270
        factory.stderr = StringIO()
 
271
        factory.stdout.encoding = "utf8"
 
272
        # there is no output from the base factory
 
273
        self.assertEqual("someuser",
 
274
                         factory.get_username('Hello %(host)s', host='some'))
 
275
        self.assertEquals("Hello some: ", factory.stderr.getvalue())
 
276
        self.assertEquals('', factory.stdout.getvalue())
 
277
        self.assertEqual("", factory.get_username("Gebruiker"))
 
278
        # stdin should be empty
 
279
        self.assertEqual('', factory.stdin.readline())
 
280
 
 
281
    def test_text_ui_getusername_utf8(self):
 
282
        ui = TestUIFactory(stdin=u'someuser\u1234'.encode('utf8'),
 
283
                           stdout=StringIOWrapper(), stderr=StringIOWrapper())
 
284
        ui.stderr.encoding = ui.stdout.encoding = ui.stdin.encoding = "utf8"
 
285
        pb = ui.nested_progress_bar()
 
286
        try:
 
287
            # there is no output from the base factory
 
288
            username = self.apply_redirected(ui.stdin, ui.stdout, ui.stderr,
 
289
                ui.get_username, u'Hello\u1234 %(host)s', host=u'some\u1234')
 
290
            self.assertEquals(u"someuser\u1234", username.decode('utf8'))
 
291
            self.assertEquals(u"Hello\u1234 some\u1234: ",
 
292
                              ui.stderr.getvalue().decode("utf8"))
 
293
            self.assertEquals('', ui.stdout.getvalue())
 
294
        finally:
 
295
            pb.finished()
 
296
 
 
297
 
 
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
 
305
    
 
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