~bzr-pqm/bzr/bzr.dev

6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1
# Copyright (C) 2009, 2010, 2011, 2016 Canonical Ltd
4711.1.2 by Martin Pool
Start adding tests.per_uifactory
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
4711.1.4 by Martin Pool
Change per_uifactory to use subclassing rather than scenarios
17
"""Tests run per UIFactory."""
18
19
# Testing UIFactories is a bit interesting because we require they all support a
20
# common interface, but the way they implement it can vary very widely.  Between
21
# text, batch-mode, graphical and other potential UIFactories, the requirements
22
# to set up a factory, to make it respond to requests, and to simulate user
23
# input can vary a lot.
24
#
25
# We want tests that therefore allow for the evaluation of the result to vary
26
# per implementation, but we want to check that the supported facilities are
27
# the same across all UIFactorys, unless they're specifically skipped.
28
#
29
# Our normal approach is to use test scenarios but that seems to just end up
30
# creating test-like objects inside the scenario.  Therefore we fall back to
31
# the older method of putting the common tests in a mixin.
32
#
33
# Plugins that add new UIFactorys can create their own subclasses.
4711.1.2 by Martin Pool
Start adding tests.per_uifactory
34
35
36
from cStringIO import StringIO
37
import unittest
38
39
40
from bzrlib import (
41
    tests,
4906.1.2 by John Arbash Meinel
Get the basic interface tested.
42
    transport,
4711.1.2 by Martin Pool
Start adding tests.per_uifactory
43
    ui,
44
    )
45
46
4711.1.4 by Martin Pool
Change per_uifactory to use subclassing rather than scenarios
47
class UIFactoryTestMixin(object):
48
    """Common tests for UIFactories.
49
50
    These are supposed to be expressed with no assumptions about how the
51
    UIFactory implements the method, only that it does implement them (or
52
    fails cleanly), and that the concrete subclass will make arrangements to
53
    build a factory and to examine its behaviour.
54
55
    Note that this is *not* a TestCase, because it can't be directly run, but
56
    the concrete subclasses should be.
57
    """
58
4961.1.2 by Martin Pool
quietness-state is now tracked on UIFactory
59
    def test_be_quiet(self):
60
        self.factory.be_quiet(True)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
61
        self.assertEqual(True, self.factory.is_quiet())
4961.1.2 by Martin Pool
quietness-state is now tracked on UIFactory
62
        self.factory.be_quiet(False)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
63
        self.assertEqual(False, self.factory.is_quiet())
4961.1.2 by Martin Pool
quietness-state is now tracked on UIFactory
64
5416.1.1 by Martin Pool
Use a structured ui_factory.confirm_action rather than just get_boolean
65
    def test_confirm_action(self):
66
        # confirm_action should be answered by every ui factory; even
67
        # noninteractive ones should have a reasonable default
68
        self._load_responses([True])
5863.6.2 by Jelmer Vernooij
Fix more.
69
        result = self.factory.confirm_action(u'Break a lock?',
70
             'bzr.lock.break.confirm',
5416.1.1 by Martin Pool
Use a structured ui_factory.confirm_action rather than just get_boolean
71
            {})
72
        # will be true either because we read it from the input or because
73
        # that's the default
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
74
        self.assertEqual(result, True)
5416.1.1 by Martin Pool
Use a structured ui_factory.confirm_action rather than just get_boolean
75
4711.1.4 by Martin Pool
Change per_uifactory to use subclassing rather than scenarios
76
    def test_note(self):
77
        self.factory.note("a note to the user")
4711.1.7 by Martin Pool
Add UIFactory.show_error, show_warning, show_message
78
        self._check_note("a note to the user")
79
80
    def test_show_error(self):
81
        msg = 'an error occurred'
82
        self.factory.show_error(msg)
83
        self._check_show_error(msg)
4711.1.4 by Martin Pool
Change per_uifactory to use subclassing rather than scenarios
84
4711.1.8 by Martin Pool
Add show_warning and show_message tests and implementations
85
    def test_show_message(self):
86
        msg = 'a message'
87
        self.factory.show_message(msg)
88
        self._check_show_message(msg)
89
90
    def test_show_warning(self):
91
        msg = 'a warning'
92
        self.factory.show_warning(msg)
93
        self._check_show_warning(msg)
94
4792.8.2 by Martin Pool
New method ui_factory.make_output_stream
95
    def test_make_output_stream(self):
4960.3.1 by Martin Pool
SilentUIFactory now accepts make_output_stream and discards what is written
96
        # All UIs must now be able to at least accept output, even if they
97
        # just discard it.
98
        output_stream = self.factory.make_output_stream()
4792.8.2 by Martin Pool
New method ui_factory.make_output_stream
99
        output_stream.write('hello!')
100
4906.1.2 by John Arbash Meinel
Get the basic interface tested.
101
    def test_transport_activity(self):
102
        # It doesn't matter what the implementation does, we just want to make
103
        # sure the interface is there
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
104
        t = transport.get_transport_from_url('memory:///')
4906.1.2 by John Arbash Meinel
Get the basic interface tested.
105
        self.factory.report_transport_activity(t, 1000, 'write')
106
        self.factory.report_transport_activity(t, 2000, 'read')
4906.1.4 by John Arbash Meinel
Play around with the ui display a bit more.
107
        self.factory.report_transport_activity(t, 4000, None)
4906.1.2 by John Arbash Meinel
Get the basic interface tested.
108
        self.factory.log_transport_activity()
109
        self._check_log_transport_activity_noarg()
110
        self.factory.log_transport_activity(display=True)
111
        self._check_log_transport_activity_display()
112
4906.1.7 by John Arbash Meinel
Switch to KiB/K for each value. Don't display if there are no bytes.
113
    def test_no_transport_activity(self):
114
        # No activity to report
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
115
        t = transport.get_transport_from_url('memory:///')
4906.1.7 by John Arbash Meinel
Switch to KiB/K for each value. Don't display if there are no bytes.
116
        self.factory.log_transport_activity(display=True)
117
        self._check_log_transport_activity_display_no_bytes()
118
4711.1.4 by Martin Pool
Change per_uifactory to use subclassing rather than scenarios
119
120
class TestTextUIFactory(tests.TestCase, UIFactoryTestMixin):
4711.1.2 by Martin Pool
Start adding tests.per_uifactory
121
122
    def setUp(self):
4711.1.4 by Martin Pool
Change per_uifactory to use subclassing rather than scenarios
123
        super(TestTextUIFactory, self).setUp()
4711.1.2 by Martin Pool
Start adding tests.per_uifactory
124
        self.stdin = StringIO()
125
        self.stdout = StringIO()
126
        self.stderr = StringIO()
127
        self.factory = ui.text.TextUIFactory(self.stdin, self.stdout,
128
            self.stderr)
129
4711.1.7 by Martin Pool
Add UIFactory.show_error, show_warning, show_message
130
    def _check_note(self, note_text):
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
131
        self.assertEqual("%s\n" % note_text,
4711.1.4 by Martin Pool
Change per_uifactory to use subclassing rather than scenarios
132
            self.stdout.getvalue())
4711.1.5 by Martin Pool
Add simple tests for CannedInputUIFactory and SilentUIFactory
133
4711.1.7 by Martin Pool
Add UIFactory.show_error, show_warning, show_message
134
    def _check_show_error(self, msg):
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
135
        self.assertEqual("bzr: error: %s\n" % msg,
4711.1.7 by Martin Pool
Add UIFactory.show_error, show_warning, show_message
136
            self.stderr.getvalue())
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
137
        self.assertEqual("", self.stdout.getvalue())
4711.1.7 by Martin Pool
Add UIFactory.show_error, show_warning, show_message
138
4711.1.8 by Martin Pool
Add show_warning and show_message tests and implementations
139
    def _check_show_message(self, msg):
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
140
        self.assertEqual("%s\n" % msg,
4711.1.8 by Martin Pool
Add show_warning and show_message tests and implementations
141
            self.stdout.getvalue())
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
142
        self.assertEqual("", self.stderr.getvalue())
4711.1.8 by Martin Pool
Add show_warning and show_message tests and implementations
143
144
    def _check_show_warning(self, msg):
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
145
        self.assertEqual("bzr: warning: %s\n" % msg,
4711.1.8 by Martin Pool
Add show_warning and show_message tests and implementations
146
            self.stderr.getvalue())
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
147
        self.assertEqual("", self.stdout.getvalue())
4711.1.8 by Martin Pool
Add show_warning and show_message tests and implementations
148
4906.1.2 by John Arbash Meinel
Get the basic interface tested.
149
    def _check_log_transport_activity_noarg(self):
150
        self.assertEqual('', self.stdout.getvalue())
4989.1.4 by Gordon Tyler
Updated tests for changes in output.
151
        self.assertContainsRe(self.stderr.getvalue(), r'\d+kB\s+\dkB/s |')
4906.1.10 by John Arbash Meinel
With the recent changes, transport activity doesn't get debounced.
152
        self.assertNotContainsRe(self.stderr.getvalue(), r'Transferred:')
4906.1.2 by John Arbash Meinel
Get the basic interface tested.
153
154
    def _check_log_transport_activity_display(self):
155
        self.assertEqual('', self.stdout.getvalue())
156
        # Without a TTY, we shouldn't display anything
157
        self.assertEqual('', self.stderr.getvalue())
158
4906.1.7 by John Arbash Meinel
Switch to KiB/K for each value. Don't display if there are no bytes.
159
    def _check_log_transport_activity_display_no_bytes(self):
160
        self.assertEqual('', self.stdout.getvalue())
161
        # Without a TTY, we shouldn't display anything
162
        self.assertEqual('', self.stderr.getvalue())
163
5416.1.1 by Martin Pool
Use a structured ui_factory.confirm_action rather than just get_boolean
164
    def _load_responses(self, responses):
165
        self.factory.stdin.seek(0)
166
        self.factory.stdin.writelines([(r and "y\n" or "n\n") for r in responses])
167
        self.factory.stdin.seek(0)
168
4906.1.2 by John Arbash Meinel
Get the basic interface tested.
169
170
class TestTTYTextUIFactory(TestTextUIFactory):
171
172
    def setUp(self):
173
        super(TestTTYTextUIFactory, self).setUp()
174
175
        class TTYStringIO(object):
176
            """Thunk over to StringIO() for everything but 'isatty'"""
177
178
            def __init__(self):
179
                self.__dict__['_sio'] = StringIO()
180
181
            def isatty(self):
182
                return True
183
184
            def __getattr__(self, name):
185
                return getattr(self._sio, name)
186
187
            def __setattr__(self, name, value):
188
                return setattr(self._sio, name, value)
4989.1.6 by Vincent Ladeuil
Add comments and update HACKING.txt about which units should be used.
189
4906.1.2 by John Arbash Meinel
Get the basic interface tested.
190
        # Remove 'TERM' == 'dumb' which causes us to *not* treat output as a
191
        # real terminal, even though isatty returns True
5570.3.6 by Vincent Ladeuil
Get rid of all _captureVar() calls, no test failures, pfew.
192
        self.overrideEnv('TERM', None)
4906.1.2 by John Arbash Meinel
Get the basic interface tested.
193
        self.stderr = TTYStringIO()
194
        self.stdout = TTYStringIO()
195
        self.factory = ui.text.TextUIFactory(self.stdin, self.stdout,
196
            self.stderr)
197
198
    def _check_log_transport_activity_display(self):
199
        self.assertEqual('', self.stdout.getvalue())
4989.1.6 by Vincent Ladeuil
Add comments and update HACKING.txt about which units should be used.
200
        # Displaying the result should write to the progress stream using
201
        # base-10 units (see HACKING.txt).
4906.1.5 by John Arbash Meinel
Include the KiB/s for the transfer.
202
        self.assertContainsRe(self.stderr.getvalue(),
4989.1.4 by Gordon Tyler
Updated tests for changes in output.
203
            r'Transferred: 7kB'
204
            r' \(\d+\.\dkB/s r:2kB w:1kB u:4kB\)')
4906.1.7 by John Arbash Meinel
Switch to KiB/K for each value. Don't display if there are no bytes.
205
206
    def _check_log_transport_activity_display_no_bytes(self):
207
        self.assertEqual('', self.stdout.getvalue())
208
        # Without actual bytes transferred, we should report nothing
209
        self.assertEqual('', self.stderr.getvalue())
4906.1.2 by John Arbash Meinel
Get the basic interface tested.
210
4711.1.5 by Martin Pool
Add simple tests for CannedInputUIFactory and SilentUIFactory
211
212
class TestSilentUIFactory(tests.TestCase, UIFactoryTestMixin):
213
    # discards output, therefore tests for output expect nothing
214
215
    def setUp(self):
216
        super(TestSilentUIFactory, self).setUp()
217
        self.factory = ui.SilentUIFactory()
218
4711.1.7 by Martin Pool
Add UIFactory.show_error, show_warning, show_message
219
    def _check_note(self, note_text):
4711.1.5 by Martin Pool
Add simple tests for CannedInputUIFactory and SilentUIFactory
220
        # it's just discarded
221
        pass
222
4711.1.7 by Martin Pool
Add UIFactory.show_error, show_warning, show_message
223
    def _check_show_error(self, msg):
224
        pass
225
4711.1.8 by Martin Pool
Add show_warning and show_message tests and implementations
226
    def _check_show_message(self, msg):
227
        pass
228
229
    def _check_show_warning(self, msg):
230
        pass
231
4906.1.2 by John Arbash Meinel
Get the basic interface tested.
232
    def _check_log_transport_activity_noarg(self):
233
        pass
234
235
    def _check_log_transport_activity_display(self):
236
        pass
237
4906.1.7 by John Arbash Meinel
Switch to KiB/K for each value. Don't display if there are no bytes.
238
    def _check_log_transport_activity_display_no_bytes(self):
239
        pass
240
5416.1.1 by Martin Pool
Use a structured ui_factory.confirm_action rather than just get_boolean
241
    def _load_responses(self, responses):
242
        pass
243
4711.1.5 by Martin Pool
Add simple tests for CannedInputUIFactory and SilentUIFactory
244
245
class TestCannedInputUIFactory(tests.TestCase, UIFactoryTestMixin):
246
    # discards output, reads input from variables
247
248
    def setUp(self):
249
        super(TestCannedInputUIFactory, self).setUp()
250
        self.factory = ui.CannedInputUIFactory([])
251
4711.1.7 by Martin Pool
Add UIFactory.show_error, show_warning, show_message
252
    def _check_note(self, note_text):
253
        pass
254
255
    def _check_show_error(self, msg):
256
        pass
257
4711.1.8 by Martin Pool
Add show_warning and show_message tests and implementations
258
    def _check_show_message(self, msg):
259
        pass
260
261
    def _check_show_warning(self, msg):
262
        pass
263
4906.1.2 by John Arbash Meinel
Get the basic interface tested.
264
    def _check_log_transport_activity_noarg(self):
265
        pass
4711.1.7 by Martin Pool
Add UIFactory.show_error, show_warning, show_message
266
4906.1.2 by John Arbash Meinel
Get the basic interface tested.
267
    def _check_log_transport_activity_display(self):
268
        pass
4906.1.7 by John Arbash Meinel
Switch to KiB/K for each value. Don't display if there are no bytes.
269
270
    def _check_log_transport_activity_display_no_bytes(self):
271
        pass
5416.1.1 by Martin Pool
Use a structured ui_factory.confirm_action rather than just get_boolean
272
273
    def _load_responses(self, responses):
274
        self.factory.responses.extend(responses)