~bzr-pqm/bzr/bzr.dev

2192.1.2 by Alexander Belchenko
Tests for osutils.get_terminal_encoding()
1
# Copyright (C) 2005, 2006 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 osutils wrapper."""
18
19
import codecs
2192.1.9 by Alexander Belchenko
final fix suggested by John Meinel
20
import locale
2192.1.7 by Alexander Belchenko
get_user_encoding: if locale.Error raised we need to set user_encoding to 'ascii' as warning says
21
import os
2192.1.2 by Alexander Belchenko
Tests for osutils.get_terminal_encoding()
22
import sys
23
24
import bzrlib
25
from bzrlib import (
26
    errors,
27
    osutils,
28
    )
29
from bzrlib.tests import (
30
        StringIOWrapper,
31
        TestCase, 
32
        )
33
34
35
class FakeCodec(object):
2192.1.8 by Alexander Belchenko
Rework tests after John's review
36
    """Special class that helps testing over several non-existed encodings.
2192.1.2 by Alexander Belchenko
Tests for osutils.get_terminal_encoding()
37
    
2192.1.8 by Alexander Belchenko
Rework tests after John's review
38
    Clients can add new encoding names, but because of how codecs is
39
    implemented they cannot be removed. Be careful with naming to avoid
40
    collisions between tests.
2192.1.2 by Alexander Belchenko
Tests for osutils.get_terminal_encoding()
41
    """
42
    _registered = False
43
    _enabled_encodings = set()
44
45
    def add(self, encoding_name):
2192.1.8 by Alexander Belchenko
Rework tests after John's review
46
        """Adding encoding name to fake.
47
48
        :type   encoding_name:  lowercase plain string
49
        """
2192.1.2 by Alexander Belchenko
Tests for osutils.get_terminal_encoding()
50
        if not self._registered:
51
            codecs.register(self)
52
            self._registered = True
2192.1.8 by Alexander Belchenko
Rework tests after John's review
53
        if encoding_name is not None:
54
            self._enabled_encodings.add(encoding_name)
2192.1.2 by Alexander Belchenko
Tests for osutils.get_terminal_encoding()
55
        
56
    def __call__(self, encoding_name):
57
        """Called indirectly by codecs module during lookup"""
58
        if encoding_name in self._enabled_encodings:
59
            return codecs.lookup('latin-1')
2192.1.6 by Alexander Belchenko
Fixes after Aaron's review
60
2192.1.2 by Alexander Belchenko
Tests for osutils.get_terminal_encoding()
61
62
fake_codec = FakeCodec()
63
64
65
class TestFakeCodec(TestCase):
66
    
67
    def test_fake_codec(self):
68
        self.assertRaises(LookupError, codecs.lookup, 'fake')
69
70
        fake_codec.add('fake')
71
        codecs.lookup('fake')
72
73
74
class TestTerminalEncoding(TestCase):
75
    """Test the auto-detection of proper terminal encoding."""
76
77
    def setUp(self):
78
        self._stdout = sys.stdout
79
        self._stderr = sys.stderr
80
        self._stdin = sys.stdin
81
        self._user_encoding = bzrlib.user_encoding
82
83
        self.addCleanup(self._reset)
84
85
    def make_wrapped_streams(self, 
86
                             stdout_encoding,
87
                             stderr_encoding,
88
                             stdin_encoding,
89
                             user_encoding='user_encoding',
90
                             enable_fake_encodings=True):
91
        sys.stdout = StringIOWrapper()
92
        sys.stdout.encoding = stdout_encoding
93
        sys.stderr = StringIOWrapper()
94
        sys.stderr.encoding = stderr_encoding
95
        sys.stdin = StringIOWrapper()
96
        sys.stdin.encoding = stdin_encoding
97
        bzrlib.user_encoding = user_encoding
2192.1.8 by Alexander Belchenko
Rework tests after John's review
98
        if enable_fake_encodings:
99
            fake_codec.add(stdout_encoding)
100
            fake_codec.add(stderr_encoding)
101
            fake_codec.add(stdin_encoding)
2192.1.2 by Alexander Belchenko
Tests for osutils.get_terminal_encoding()
102
103
    def _reset(self):
104
        sys.stdout = self._stdout
105
        sys.stderr = self._stderr
106
        sys.stdin = self._stdin
107
        bzrlib.user_encoding = self._user_encoding
108
109
    def test_get_terminal_encoding(self):
110
        self.make_wrapped_streams('stdout_encoding',
111
                                  'stderr_encoding',
112
                                  'stdin_encoding')
113
114
        # first preference is stdout encoding
115
        self.assertEqual('stdout_encoding', osutils.get_terminal_encoding())
116
117
        sys.stdout.encoding = None
118
        # if sys.stdout is None, fall back to sys.stdin
119
        self.assertEqual('stdin_encoding', osutils.get_terminal_encoding())
120
121
        sys.stdin.encoding = None
122
        # and in the worst case, use bzrlib.user_encoding
123
        self.assertEqual('user_encoding', osutils.get_terminal_encoding())
124
125
    def test_terminal_cp0(self):
2192.1.6 by Alexander Belchenko
Fixes after Aaron's review
126
        # test cp0 encoding (Windows returns cp0 when there is no encoding)
2192.1.2 by Alexander Belchenko
Tests for osutils.get_terminal_encoding()
127
        self.make_wrapped_streams('cp0',
2192.1.8 by Alexander Belchenko
Rework tests after John's review
128
                                  'cp0',
129
                                  'cp0',
2192.1.2 by Alexander Belchenko
Tests for osutils.get_terminal_encoding()
130
                                  user_encoding='latin-1',
131
                                  enable_fake_encodings=False)
132
133
        # cp0 is invalid encoding. We should fall back to user_encoding
134
        self.assertEqual('latin-1', osutils.get_terminal_encoding())
135
136
        # check stderr
137
        self.assertEquals('', sys.stderr.getvalue())
138
2192.1.8 by Alexander Belchenko
Rework tests after John's review
139
    def test_terminal_cp_unknown(self):
2192.1.2 by Alexander Belchenko
Tests for osutils.get_terminal_encoding()
140
        # test against really unknown encoding
141
        # catch warning at stderr
2192.1.8 by Alexander Belchenko
Rework tests after John's review
142
        self.make_wrapped_streams('cp-unknown',
143
                                  'cp-unknown',
144
                                  'cp-unknown',
2192.1.2 by Alexander Belchenko
Tests for osutils.get_terminal_encoding()
145
                                  user_encoding='latin-1',
146
                                  enable_fake_encodings=False)
147
        
148
        self.assertEqual('latin-1', osutils.get_terminal_encoding())
149
150
        # check stderr
2192.1.10 by Alexander Belchenko
merge bzr.dev
151
        self.assertEquals('bzr: warning: unknown terminal encoding cp-unknown.\n'
2192.1.2 by Alexander Belchenko
Tests for osutils.get_terminal_encoding()
152
                          '  Using encoding latin-1 instead.\n', 
153
                          sys.stderr.getvalue())
2192.1.3 by Alexander Belchenko
Tests for osutils.get_user_encoding
154
155
156
class TestUserEncoding(TestCase):
157
    """Test detection of default user encoding."""
158
    
159
    def setUp(self):
160
        self._stderr = sys.stderr
161
        self._getpreferredencoding = locale.getpreferredencoding
162
        self.addCleanup(self._reset)
163
        sys.stderr = StringIOWrapper()
2192.1.7 by Alexander Belchenko
get_user_encoding: if locale.Error raised we need to set user_encoding to 'ascii' as warning says
164
        # save $LANG
165
        self._LANG = os.environ.get('LANG')
2192.1.3 by Alexander Belchenko
Tests for osutils.get_user_encoding
166
167
    def _reset(self):
168
        locale.getpreferredencoding = self._getpreferredencoding
169
        sys.stderr = self._stderr
2192.1.7 by Alexander Belchenko
get_user_encoding: if locale.Error raised we need to set user_encoding to 'ascii' as warning says
170
        # restore $LANG
2192.1.8 by Alexander Belchenko
Rework tests after John's review
171
        osutils.set_or_unset_env('LANG', self._LANG)
2192.1.3 by Alexander Belchenko
Tests for osutils.get_user_encoding
172
173
    def test_get_user_encoding(self):
174
        def f():
175
            return 'user_encoding'
176
177
        locale.getpreferredencoding = f
178
        fake_codec.add('user_encoding')
179
        self.assertEquals('user_encoding', osutils.get_user_encoding(use_cache=False))
180
        self.assertEquals('', sys.stderr.getvalue())
181
182
    def test_user_cp0(self):
183
        def f():
184
            return 'cp0'
185
186
        locale.getpreferredencoding = f
187
        self.assertEquals('ascii', osutils.get_user_encoding(use_cache=False))
188
        self.assertEquals('', sys.stderr.getvalue())
189
2192.1.8 by Alexander Belchenko
Rework tests after John's review
190
    def test_user_cp_unknown(self):
2192.1.3 by Alexander Belchenko
Tests for osutils.get_user_encoding
191
        def f():
2192.1.8 by Alexander Belchenko
Rework tests after John's review
192
            return 'cp-unknown'
2192.1.3 by Alexander Belchenko
Tests for osutils.get_user_encoding
193
194
        locale.getpreferredencoding = f
195
        self.assertEquals('ascii', osutils.get_user_encoding(use_cache=False))
2192.1.8 by Alexander Belchenko
Rework tests after John's review
196
        self.assertEquals('bzr: warning: unknown encoding cp-unknown.'
2192.1.3 by Alexander Belchenko
Tests for osutils.get_user_encoding
197
                          ' Continuing with ascii encoding.\n',
198
                          sys.stderr.getvalue())
2192.1.7 by Alexander Belchenko
get_user_encoding: if locale.Error raised we need to set user_encoding to 'ascii' as warning says
199
3405.3.1 by Neil Martinsen-Burrell
accept for an encoding to mean ascii
200
    def test_user_empty(self):
201
        """Running bzr from a vim script gives '' for a preferred locale"""
202
        def f():
203
            return ''
204
205
        locale.getpreferredencoding = f
206
        self.assertEquals('ascii', osutils.get_user_encoding(use_cache=False))
207
        self.assertEquals('', sys.stderr.getvalue())
208
2192.1.7 by Alexander Belchenko
get_user_encoding: if locale.Error raised we need to set user_encoding to 'ascii' as warning says
209
    def test_user_locale_error(self):
210
        def f():
211
            raise locale.Error, 'unsupported locale'
212
213
        locale.getpreferredencoding = f
214
        os.environ['LANG'] = 'BOGUS'
215
        self.assertEquals('ascii', osutils.get_user_encoding(use_cache=False))
216
        self.assertEquals('bzr: warning: unsupported locale\n'
217
                          '  Could not determine what text encoding to use.\n'
218
                          '  This error usually means your Python interpreter\n'
219
                          '  doesn\'t support the locale set by $LANG (BOGUS)\n'
220
                          '  Continuing with ascii encoding.\n',
221
                          sys.stderr.getvalue())