~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-02-18 13:27:08 UTC
  • mfrom: (4011.4.3 ssh-hints)
  • Revision ID: pqm@pqm.ubuntu.com-20090218132708-okubrahz9exvae9r
(Jelmer) Point out bzr+ssh:// to the user when they use ssh://.

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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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
 
 
25
import bzrlib
 
26
import bzrlib.errors as errors
 
27
from bzrlib.progress import (
 
28
    DotsProgressBar,
 
29
    ProgressBarStack,
 
30
    TTYProgressBar,
 
31
    )
 
32
from bzrlib.symbol_versioning import (
 
33
    deprecated_in,
 
34
    )
 
35
from bzrlib.tests import (
 
36
    TestCase,
 
37
    TestUIFactory,
 
38
    StringIOWrapper,
 
39
    )
 
40
from bzrlib.tests.test_progress import _TTYStringIO
 
41
from bzrlib.ui import (
 
42
    CLIUIFactory,
 
43
    SilentUIFactory,
 
44
    )
 
45
from bzrlib.ui.text import TextUIFactory
 
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
        pb = ui.nested_progress_bar()
 
67
        try:
 
68
            self.assertEqual('secret',
 
69
                             self.apply_redirected(ui.stdin, ui.stdout,
 
70
                                                   ui.stdout,
 
71
                                                   ui.get_password))
 
72
            # ': ' is appended to prompt
 
73
            self.assertEqual(': ', ui.stdout.getvalue())
 
74
            # stdin should be empty
 
75
            self.assertEqual('', ui.stdin.readline())
 
76
        finally:
 
77
            pb.finished()
 
78
 
 
79
    def test_text_factory_utf8_password(self):
 
80
        """Test an utf8 password.
 
81
 
 
82
        We can't predict what encoding users will have for stdin, so we force
 
83
        it to utf8 to test that we transport the password correctly.
 
84
        """
 
85
        ui = TestUIFactory(stdin=u'baz\u1234'.encode('utf8'),
 
86
                           stdout=StringIOWrapper())
 
87
        ui.stdin.encoding = 'utf8'
 
88
        ui.stdout.encoding = ui.stdin.encoding
 
89
        pb = ui.nested_progress_bar()
 
90
        try:
 
91
            password = self.apply_redirected(ui.stdin, ui.stdout, ui.stdout,
 
92
                                             ui.get_password,
 
93
                                             u'Hello \u1234 %(user)s',
 
94
                                             user=u'some\u1234')
 
95
            # We use StringIO objects, we need to decode them
 
96
            self.assertEqual(u'baz\u1234', password.decode('utf8'))
 
97
            self.assertEqual(u'Hello \u1234 some\u1234: ',
 
98
                             ui.stdout.getvalue().decode('utf8'))
 
99
            # stdin should be empty
 
100
            self.assertEqual('', ui.stdin.readline())
 
101
        finally:
 
102
            pb.finished()
 
103
 
 
104
    def test_progress_note(self):
 
105
        stderr = StringIO()
 
106
        stdout = StringIO()
 
107
        ui_factory = TextUIFactory(stdin=StringIO(''),
 
108
            stderr=stderr,
 
109
            stdout=stdout)
 
110
        pb = ui_factory.nested_progress_bar()
 
111
        try:
 
112
            result = pb.note('t')
 
113
            self.assertEqual(None, result)
 
114
            self.assertEqual("t\n", stdout.getvalue())
 
115
            # Since there was no update() call, there should be no clear() call
 
116
            self.failIf(re.search(r'^\r {10,}\r$',
 
117
                                  stderr.getvalue()) is not None,
 
118
                        'We cleared the stderr without anything to put there')
 
119
        finally:
 
120
            pb.finished()
 
121
 
 
122
    def test_progress_note_clears(self):
 
123
        stderr = StringIO()
 
124
        stdout = StringIO()
 
125
        # The PQM redirects the output to a file, so it
 
126
        # defaults to creating a Dots progress bar. we
 
127
        # need to force it to believe we are a TTY
 
128
        ui_factory = TextUIFactory(
 
129
            stdin=StringIO(''),
 
130
            stdout=stdout, stderr=stderr)
 
131
        pb = ui_factory.nested_progress_bar()
 
132
        try:
 
133
            # Create a progress update that isn't throttled
 
134
            pb.update('x', 1, 1)
 
135
            result = pb.note('t')
 
136
            self.assertEqual(None, result)
 
137
            self.assertEqual("t\n", stdout.getvalue())
 
138
            # the exact contents will depend on the terminal width and we don't
 
139
            # care about that right now - but you're probably running it on at
 
140
            # least a 10-character wide terminal :)
 
141
            self.assertContainsRe(stderr.getvalue(), r'\r {10,}\r$')
 
142
        finally:
 
143
            pb.finished()
 
144
 
 
145
    def test_progress_nested(self):
 
146
        # test factory based nested and popping.
 
147
        ui = TextUIFactory(None, None, None)
 
148
        pb1 = ui.nested_progress_bar()
 
149
        pb2 = ui.nested_progress_bar()
 
150
        # You do get a warning if the outermost progress bar wasn't finished
 
151
        # first - it's not clear if this is really useful or if it should just
 
152
        # become orphaned -- mbp 20090120
 
153
        warnings, _ = self.callCatchWarnings(pb1.finished)
 
154
        if len(warnings) != 1:
 
155
            self.fail("unexpected warnings: %r" % (warnings,))
 
156
        pb2.finished()
 
157
        pb1.finished()
 
158
 
 
159
    def test_progress_stack(self):
 
160
        # test the progress bar stack which the default text factory 
 
161
        # uses.
 
162
        stderr = StringIO()
 
163
        stdout = StringIO()
 
164
        # make a stack, which accepts parameters like a pb.
 
165
        stack = self.applyDeprecated(
 
166
            deprecated_in((1, 12, 0)),
 
167
            ProgressBarStack,
 
168
            to_file=stderr, to_messages_file=stdout)
 
169
        # but is not one
 
170
        self.assertFalse(getattr(stack, 'note', False))
 
171
        pb1 = stack.get_nested()
 
172
        pb2 = stack.get_nested()
 
173
        warnings, _ = self.callCatchWarnings(pb1.finished)
 
174
        self.assertEqual(len(warnings), 1)
 
175
        pb2.finished()
 
176
        pb1.finished()
 
177
        # the text ui factory never actually removes the stack once its setup.
 
178
        # we need to be able to nest again correctly from here.
 
179
        pb1 = stack.get_nested()
 
180
        pb2 = stack.get_nested()
 
181
        warnings, _ = self.callCatchWarnings(pb1.finished)
 
182
        self.assertEqual(len(warnings), 1)
 
183
        pb2.finished()
 
184
        pb1.finished()
 
185
 
 
186
    def assert_get_bool_acceptance_of_user_input(self, factory):
 
187
        factory.stdin = StringIO("y\nyes with garbage\n"
 
188
                                 "yes\nn\nnot an answer\n"
 
189
                                 "no\nfoo\n")
 
190
        factory.stdout = StringIO()
 
191
        # there is no output from the base factory
 
192
        self.assertEqual(True, factory.get_boolean(""))
 
193
        self.assertEqual(True, factory.get_boolean(""))
 
194
        self.assertEqual(False, factory.get_boolean(""))
 
195
        self.assertEqual(False, factory.get_boolean(""))
 
196
        self.assertEqual("foo\n", factory.stdin.read())
 
197
        # stdin should be empty
 
198
        self.assertEqual('', factory.stdin.readline())
 
199
 
 
200
    def test_silent_ui_getbool(self):
 
201
        factory = SilentUIFactory()
 
202
        self.assert_get_bool_acceptance_of_user_input(factory)
 
203
 
 
204
    def test_silent_factory_prompts_silently(self):
 
205
        factory = SilentUIFactory()
 
206
        stdout = StringIO()
 
207
        factory.stdin = StringIO("y\n")
 
208
        self.assertEqual(True,
 
209
                         self.apply_redirected(None, stdout, stdout,
 
210
                                               factory.get_boolean, "foo"))
 
211
        self.assertEqual("", stdout.getvalue())
 
212
        # stdin should be empty
 
213
        self.assertEqual('', factory.stdin.readline())
 
214
 
 
215
    def test_text_ui_getbool(self):
 
216
        factory = TextUIFactory(None, None, None)
 
217
        self.assert_get_bool_acceptance_of_user_input(factory)
 
218
 
 
219
    def test_text_factory_prompts_and_clears(self):
 
220
        # a get_boolean call should clear the pb before prompting
 
221
        out = _TTYStringIO()
 
222
        factory = TextUIFactory(stdin=StringIO("yada\ny\n"), stdout=out, stderr=out)
 
223
        pb = factory.nested_progress_bar()
 
224
        pb.show_bar = False
 
225
        pb.show_spinner = False
 
226
        pb.show_count = False
 
227
        pb.update("foo", 0, 1)
 
228
        self.assertEqual(True,
 
229
                         self.apply_redirected(None, factory.stdout,
 
230
                                               factory.stdout,
 
231
                                               factory.get_boolean,
 
232
                                               "what do you want"))
 
233
        output = out.getvalue()
 
234
        self.assertContainsRe(factory.stdout.getvalue(),
 
235
            "foo *\r\r  *\r*")
 
236
        self.assertContainsRe(factory.stdout.getvalue(),
 
237
            r"what do you want\? \[y/n\]: what do you want\? \[y/n\]: ")
 
238
        # stdin should have been totally consumed
 
239
        self.assertEqual('', factory.stdin.readline())