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