~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_ui.py

  • Committer: Jelmer Vernooij
  • Date: 2009-01-28 18:42:55 UTC
  • mto: This revision was merged to the branch mainline in revision 3968.
  • Revision ID: jelmer@samba.org-20090128184255-bdmklkvm83ltk191
Update NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 Canonical Ltd
 
1
# Copyright (C) 2005, 2008, 2009 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
24
24
 
25
25
import bzrlib
26
26
import bzrlib.errors as errors
27
 
from bzrlib.progress import TTYProgressBar, ProgressBarStack
28
 
from bzrlib.tests import TestCase
 
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
    )
29
40
from bzrlib.tests.test_progress import _TTYStringIO
30
 
from bzrlib.ui import SilentUIFactory
 
41
from bzrlib.ui import (
 
42
    CLIUIFactory,
 
43
    SilentUIFactory,
 
44
    )
31
45
from bzrlib.ui.text import TextUIFactory
32
46
 
33
47
 
35
49
 
36
50
    def test_silent_factory(self):
37
51
        ui = SilentUIFactory()
38
 
        pb = ui.nested_progress_bar()
39
 
        try:
40
 
            # TODO: Test that there is no output from SilentUIFactory
41
 
    
42
 
            self.assertEquals(ui.get_password(), None)
43
 
            self.assertEquals(ui.get_password(u'Hello There \u1234 %(user)s',
44
 
                                              user=u'some\u1234')
45
 
                             , None)
46
 
        finally:
47
 
            pb.finished()
48
 
 
49
 
    def test_text_factory(self):
50
 
        ui = TextUIFactory()
51
 
        pb = ui.nested_progress_bar()
52
 
        pb.finished()
53
 
        # TODO: Test the output from TextUIFactory, perhaps by overriding sys.stdout
54
 
 
55
 
        # Unfortunately we can't actually test the ui.get_password() because 
56
 
        # that would actually prompt the user for a password during the test suite
57
 
        # This has been tested manually with both LANG=en_US.utf-8 and LANG=C
58
 
        # print
59
 
        # self.assertEquals(ui.get_password(u"%(user)s please type 'bogus'",
60
 
        #                                   user=u'some\u1234')
61
 
        #                  , 'bogus')
62
 
 
 
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()
63
103
 
64
104
    def test_progress_note(self):
65
105
        stderr = StringIO()
66
106
        stdout = StringIO()
67
 
        ui_factory = TextUIFactory(bar_type=TTYProgressBar)
 
107
        ui_factory = TextUIFactory(stdin=StringIO(''),
 
108
            stderr=stderr,
 
109
            stdout=stdout)
68
110
        pb = ui_factory.nested_progress_bar()
69
111
        try:
70
 
            pb.to_messages_file = stdout
71
 
            ui_factory._progress_bar_stack.bottom().to_file = stderr
72
112
            result = pb.note('t')
73
113
            self.assertEqual(None, result)
74
114
            self.assertEqual("t\n", stdout.getvalue())
75
115
            # Since there was no update() call, there should be no clear() call
76
 
            self.failIf(re.search(r'^\r {10,}\r$', stderr.getvalue()) is not None,
 
116
            self.failIf(re.search(r'^\r {10,}\r$',
 
117
                                  stderr.getvalue()) is not None,
77
118
                        'We cleared the stderr without anything to put there')
78
119
        finally:
79
120
            pb.finished()
84
125
        # The PQM redirects the output to a file, so it
85
126
        # defaults to creating a Dots progress bar. we
86
127
        # need to force it to believe we are a TTY
87
 
        ui_factory = TextUIFactory(bar_type=TTYProgressBar)
 
128
        ui_factory = TextUIFactory(
 
129
            stdin=StringIO(''),
 
130
            stdout=stdout, stderr=stderr)
88
131
        pb = ui_factory.nested_progress_bar()
89
132
        try:
90
 
            pb.to_messages_file = stdout
91
 
            ui_factory._progress_bar_stack.bottom().to_file = stderr
92
133
            # Create a progress update that isn't throttled
93
 
            pb.start_time -= 10
94
134
            pb.update('x', 1, 1)
95
135
            result = pb.note('t')
96
136
            self.assertEqual(None, result)
104
144
 
105
145
    def test_progress_nested(self):
106
146
        # test factory based nested and popping.
107
 
        ui = TextUIFactory()
 
147
        ui = TextUIFactory(None, None, None)
108
148
        pb1 = ui.nested_progress_bar()
109
149
        pb2 = ui.nested_progress_bar()
110
 
        self.assertRaises(errors.MissingProgressBarFinish, pb1.finished)
 
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,))
111
156
        pb2.finished()
112
157
        pb1.finished()
113
158
 
117
162
        stderr = StringIO()
118
163
        stdout = StringIO()
119
164
        # make a stack, which accepts parameters like a pb.
120
 
        stack = ProgressBarStack(to_file=stderr, to_messages_file=stdout)
 
165
        stack = self.applyDeprecated(
 
166
            deprecated_in((1, 12, 0)),
 
167
            ProgressBarStack,
 
168
            to_file=stderr, to_messages_file=stdout)
121
169
        # but is not one
122
170
        self.assertFalse(getattr(stack, 'note', False))
123
171
        pb1 = stack.get_nested()
124
172
        pb2 = stack.get_nested()
125
 
        self.assertRaises(errors.MissingProgressBarFinish, pb1.finished)
 
173
        warnings, _ = self.callCatchWarnings(pb1.finished)
 
174
        self.assertEqual(len(warnings), 1)
126
175
        pb2.finished()
127
176
        pb1.finished()
128
177
        # the text ui factory never actually removes the stack once its setup.
129
178
        # we need to be able to nest again correctly from here.
130
179
        pb1 = stack.get_nested()
131
180
        pb2 = stack.get_nested()
132
 
        self.assertRaises(errors.MissingProgressBarFinish, pb1.finished)
 
181
        warnings, _ = self.callCatchWarnings(pb1.finished)
 
182
        self.assertEqual(len(warnings), 1)
133
183
        pb2.finished()
134
184
        pb1.finished()
135
185
 
136
 
    def test_text_factory_setting_progress_bar(self):
137
 
        # we should be able to choose the progress bar type used.
138
 
        factory = bzrlib.ui.text.TextUIFactory(
139
 
            bar_type=bzrlib.progress.DotsProgressBar)
140
 
        bar = factory.nested_progress_bar()
141
 
        bar.finished()
142
 
        self.assertIsInstance(bar, bzrlib.progress.DotsProgressBar)
143
 
 
144
 
    def test_cli_stdin_is_default_stdin(self):
145
 
        factory = bzrlib.ui.CLIUIFactory()
146
 
        self.assertEqual(sys.stdin, factory.stdin)
147
 
 
148
186
    def assert_get_bool_acceptance_of_user_input(self, factory):
149
 
        factory.stdin = StringIO("y\nyes with garbage\nyes\nn\nnot an answer\nno\nfoo\n")
 
187
        factory.stdin = StringIO("y\nyes with garbage\n"
 
188
                                 "yes\nn\nnot an answer\n"
 
189
                                 "no\nfoo\n")
150
190
        factory.stdout = StringIO()
151
191
        # there is no output from the base factory
152
192
        self.assertEqual(True, factory.get_boolean(""))
154
194
        self.assertEqual(False, factory.get_boolean(""))
155
195
        self.assertEqual(False, factory.get_boolean(""))
156
196
        self.assertEqual("foo\n", factory.stdin.read())
 
197
        # stdin should be empty
 
198
        self.assertEqual('', factory.stdin.readline())
157
199
 
158
200
    def test_silent_ui_getbool(self):
159
 
        factory = bzrlib.ui.SilentUIFactory()
 
201
        factory = SilentUIFactory()
160
202
        self.assert_get_bool_acceptance_of_user_input(factory)
161
203
 
162
204
    def test_silent_factory_prompts_silently(self):
163
 
        factory = bzrlib.ui.SilentUIFactory()
 
205
        factory = SilentUIFactory()
164
206
        stdout = StringIO()
165
207
        factory.stdin = StringIO("y\n")
166
 
        self.assertEqual(
167
 
            True,
168
 
            self.apply_redirected(
169
 
                None, stdout, stdout, factory.get_boolean, "foo")
170
 
            )
 
208
        self.assertEqual(True,
 
209
                         self.apply_redirected(None, stdout, stdout,
 
210
                                               factory.get_boolean, "foo"))
171
211
        self.assertEqual("", stdout.getvalue())
172
 
        
 
212
        # stdin should be empty
 
213
        self.assertEqual('', factory.stdin.readline())
 
214
 
173
215
    def test_text_ui_getbool(self):
174
 
        factory = bzrlib.ui.text.TextUIFactory()
 
216
        factory = TextUIFactory(None, None, None)
175
217
        self.assert_get_bool_acceptance_of_user_input(factory)
176
218
 
177
219
    def test_text_factory_prompts_and_clears(self):
178
220
        # a get_boolean call should clear the pb before prompting
179
 
        factory = bzrlib.ui.text.TextUIFactory()
180
 
        factory.stdout = _TTYStringIO()
181
 
        factory.stdin = StringIO("yada\ny\n")
182
 
        pb = self.apply_redirected(
183
 
            factory.stdin, factory.stdout, factory.stdout, factory.nested_progress_bar)
184
 
        pb.start_time = None
185
 
        self.apply_redirected(
186
 
            factory.stdin, factory.stdout, factory.stdout, pb.update, "foo", 0, 1)
187
 
        self.assertEqual(
188
 
            True,
189
 
            self.apply_redirected(
190
 
                None, factory.stdout, factory.stdout, factory.get_boolean, "what do you want")
191
 
            )
192
 
        # FIXME: This assumes the factory's going to produce a spinner-style
193
 
        # progress bar, but it won't if this is run from a dumb terminal (e.g.
194
 
        # from inside gvim.) -- mbp 20061014
195
 
        #
196
 
        # use a regular expression so that we don't depend on the particular
197
 
        # screen width - could also set and restore $COLUMN if that has
198
 
        # priority on all platforms, but it doesn't at present.
199
 
        output = factory.stdout.getvalue()
200
 
        if not re.match(
201
 
            "\r/ \\[    *\\] foo 0/1"
202
 
            "\r   *" 
203
 
            "\rwhat do you want\\? \\[y/n\\]:what do you want\\? \\[y/n\\]:", 
204
 
            output):
205
 
            self.fail("didn't match factory output %r, %r" % (factory, output))
 
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())