]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/test/test_stringutils.py
unicode: make test_cli test a non-ascii argument, and make the fallback term encoding...
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / test / test_stringutils.py
1 # coding=utf-8
2
3 TEST_FILENAMES = (
4   u'Ärtonwall.mp3',
5   u'test_file',
6   u'Blah blah.txt',
7 )
8
9 # The following main helps to generate a test class for other operating
10 # systems.
11
12 if __name__ == "__main__":
13     import sys, os
14     import tempfile
15     import shutil
16     import platform
17     
18     if len(sys.argv) != 2:
19         print "Usage: %s lumière" % sys.argv[0]
20         sys.exit(1)
21     
22     print
23     print "class MyWeirdOS(StringUtils, unittest.TestCase):"
24     print "    uname = '%s'" % ' '.join(platform.uname())
25     print "    argv = %s" % repr(sys.argv[1])
26     print "    platform = '%s'" % sys.platform
27     print "    filesystemencoding = '%s'" % sys.getfilesystemencoding()
28     print "    stdoutencoding = '%s'" % sys.stdout.encoding
29
30     try:
31         tmpdir = tempfile.mkdtemp()
32         for fname in TEST_FILENAMES:
33             open(os.path.join(tmpdir, fname), 'w').close() 
34
35         # Use Unicode API under Windows or MacOS X
36         if sys.platform in ('win32', 'darwin'):
37             dirlist = os.listdir(unicode(tmpdir))
38         else:
39             dirlist = os.listdir(tmpdir)
40
41         print "    dirlist = %s" % repr(dirlist)
42     except:
43         print "    # Oops, I cannot write filenames containing non-ascii characters"
44     print
45
46     shutil.rmtree(tmpdir)
47     sys.exit(0)
48
49 from twisted.trial import unittest
50 from mock import patch
51 import sys
52
53 from allmydata.util.stringutils import argv_to_unicode, unicode_to_url, \
54     unicode_to_stdout, unicode_platform, listdir_unicode, open_unicode, \
55     FilenameEncodingError, get_term_encoding
56 from twisted.python import usage
57
58 class StringUtilsErrors(unittest.TestCase):
59     @patch('sys.stdout')
60     def test_get_term_encoding(self, mock):
61         mock.encoding = None
62
63         self.failUnlessEqual(get_term_encoding().lower(), locale.getpreferredencoding().lower())
64
65     @patch('sys.stdout')
66     def test_argv_to_unicode(self, mock):
67         mock.encoding = 'utf-8'
68
69         self.failUnlessRaises(usage.UsageError,
70                               argv_to_unicode,
71                               u'lumière'.encode('latin1'))
72
73     def test_unicode_to_url(self):
74         pass
75
76     @patch('sys.stdout')
77     def test_unicode_to_stdout(self, mock):
78         # Encoding koi8-r cannot represent 'è'
79         mock.encoding = 'koi8-r'
80         self.failUnlessEqual(unicode_to_stdout(u'lumière'), 'lumi?re')
81
82     @patch('os.listdir')
83     def test_unicode_normalization(self, mock):
84         # Pretend to run on an Unicode platform such as Windows
85         orig_platform = sys.platform
86         sys.platform = 'win32'
87
88         mock.return_value = [u'A\u0308rtonwall.mp3']
89         self.failUnlessEqual(listdir_unicode(u'/dummy'), [u'\xc4rtonwall.mp3'])
90
91         sys.platform = orig_platform
92
93 # The following tests applies only to platforms which don't store filenames as
94 # Unicode entities on the filesystem.
95 class StringUtilsNonUnicodePlatform(unittest.TestCase):
96     def setUp(self):
97         # Mock sys.platform because unicode_platform() uses it
98         self.original_platform = sys.platform
99         sys.platform = 'linux'
100
101     def tearDown(self):
102         sys.platform = self.original_platform
103
104     @patch('sys.getfilesystemencoding')
105     @patch('os.listdir')
106     def test_listdir_unicode(self, mock_listdir, mock_getfilesystemencoding):
107         # What happen if a latin1-encoded filenames is encountered on an UTF-8
108         # filesystem?
109         mock_listdir.return_value = [
110             u'lumière'.encode('utf-8'),
111             u'lumière'.encode('latin1')]
112
113         mock_getfilesystemencoding.return_value = 'utf-8'
114        
115         self.failUnlessRaises(FilenameEncodingError,
116                               listdir_unicode,
117                               u'/dummy')
118         
119         # We're trying to list a directory whose name cannot be represented in
120         # the filesystem encoding.  This should fail.
121         mock_getfilesystemencoding.return_value = 'ascii'
122         self.failUnlessRaises(FilenameEncodingError,
123                               listdir_unicode,
124                               u'/lumière')
125
126     @patch('sys.getfilesystemencoding')
127     def test_open_unicode(self, mock):
128         mock.return_value = 'ascii'
129
130         self.failUnlessRaises(FilenameEncodingError,
131                               open_unicode,
132                               u'lumière')
133
134 class StringUtils:
135     def setUp(self):
136         # Mock sys.platform because unicode_platform() uses it
137         self.original_platform = sys.platform
138         sys.platform = self.platform
139
140     def tearDown(self):
141         sys.platform = self.original_platform
142
143     @patch('sys.stdout')
144     def test_argv_to_unicode(self, mock):
145         if 'argv' not in dir(self):
146             raise unittest.SkipTest("There's no way to pass non-ASCII arguments in CLI on this (mocked) platform")
147
148         mock.encoding = self.stdoutencoding
149
150         argu = u'lumière'
151         argv = self.argv
152
153         self.failUnlessEqual(argv_to_unicode(argv), argu)
154
155     def test_unicode_to_url(self):
156         self.failUnless(unicode_to_url(u'lumière'), u'lumière'.encode('utf-8'))
157
158     @patch('sys.stdout')
159     def test_unicode_to_stdout(self, mock):
160         if 'argv' not in dir(self):
161             raise unittest.SkipTest("There's no way to pass non-ASCII arguments in CLI on this (mocked) platform")
162
163         mock.encoding = self.stdoutencoding
164         self.failUnlessEqual(unicode_to_stdout(u'lumière'), self.argv)
165
166     def test_unicode_platform(self):
167         matrix = {
168           'linux2': False,
169           'openbsd4': False,
170           'win32':  True,
171           'darwin': True,
172         }
173
174         self.failUnlessEqual(unicode_platform(), matrix[self.platform])
175  
176     @patch('sys.getfilesystemencoding')
177     @patch('os.listdir')
178     def test_listdir_unicode(self, mock_listdir, mock_getfilesystemencoding):
179         if 'dirlist' not in dir(self):
180             raise unittest.SkipTest("No way to write non-ASCII filenames on this system")
181
182         mock_listdir.return_value = self.dirlist
183         mock_getfilesystemencoding.return_value = self.filesystemencoding
184        
185         filenames = listdir_unicode(u'/dummy')
186
187         for fname in TEST_FILENAMES:
188             self.failUnless(isinstance(fname, unicode))
189
190             if fname not in filenames:
191                 self.fail("Cannot find %r in %r" % (fname, filenames))
192
193     @patch('sys.getfilesystemencoding')
194     @patch('__builtin__.open')
195     def test_open_unicode(self, mock_open, mock_getfilesystemencoding):
196         mock_getfilesystemencoding.return_value = self.filesystemencoding
197
198         fn = u'/dummy_directory/lumière.txt'
199
200         try:
201             open_unicode(fn)
202         except FilenameEncodingError:
203             raise unittest.SkipTest("Cannot represent test filename on this (mocked) platform")
204
205         # Pass Unicode string to open() on Unicode platforms
206         if unicode_platform():
207             mock_open.assert_called_with(fn, 'r')
208
209         # Pass correctly encoded bytestrings to open() on non-Unicode platforms
210         else:
211             fn_bytestring = fn.encode(self.filesystemencoding)
212             mock_open.assert_called_with(fn_bytestring, 'r')
213
214 class UbuntuKarmicUTF8(StringUtils, unittest.TestCase):
215     uname = 'Linux korn 2.6.31-14-generic #48-Ubuntu SMP Fri Oct 16 14:05:01 UTC 2009 x86_64'
216     argv = 'lumi\xc3\xa8re'
217     platform = 'linux2'
218     filesystemencoding = 'UTF-8'
219     stdoutencoding = 'UTF-8'
220     dirlist = ['test_file', '\xc3\x84rtonwall.mp3', 'Blah blah.txt']
221
222
223 class UbuntuKarmicLatin1(StringUtils, unittest.TestCase):
224     uname = 'Linux korn 2.6.31-14-generic #48-Ubuntu SMP Fri Oct 16 14:05:01 UTC 2009 x86_64'
225     argv = 'lumi\xe8re'
226     platform = 'linux2'
227     filesystemencoding = 'ISO-8859-1'
228     stdoutencoding = 'ISO-8859-1'
229     dirlist = ['test_file', 'Blah blah.txt', '\xc4rtonwall.mp3']
230
231 class WindowsXP(StringUtils, unittest.TestCase):
232     uname = 'Windows XP 5.1.2600 x86 x86 Family 15 Model 75 Step ping 2, AuthenticAMD'
233     argv = 'lumi\xe8re'
234     platform = 'win32'
235     filesystemencoding = 'mbcs'
236     stdoutencoding = 'cp850'
237     dirlist = [u'Blah blah.txt', u'test_file', u'\xc4rtonwall.mp3']
238
239     todo = "Unicode arguments on the command-line is not yet supported under Windows, see bug #565."
240
241 class WindowsXP_UTF8(StringUtils, unittest.TestCase):
242     uname = 'Windows XP 5.1.2600 x86 x86 Family 15 Model 75 Step ping 2, AuthenticAMD'
243     argv = 'lumi\xe8re'
244     platform = 'win32'
245     filesystemencoding = 'mbcs'
246     stdoutencoding = 'cp65001'
247     dirlist = [u'Blah blah.txt', u'test_file', u'\xc4rtonwall.mp3']
248
249     todo = "Unicode arguments on the command-line is not yet supported under Windows, see bug #565."
250
251 class WindowsVista(StringUtils, unittest.TestCase):
252     uname = 'Windows Vista 6.0.6000 x86 x86 Family 6 Model 15 Stepping 11, GenuineIntel'
253     argv = 'lumi\xe8re'
254     platform = 'win32'
255     filesystemencoding = 'mbcs'
256     stdoutencoding = 'cp850'
257     dirlist = [u'Blah blah.txt', u'test_file', u'\xc4rtonwall.mp3']
258
259     todo = "Unicode arguments on the command-line is not yet supported under Windows, see bug #565."
260
261 class MacOSXLeopard(StringUtils, unittest.TestCase):
262     uname = 'Darwin g5.local 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:57:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_PPC Power Macintosh powerpc'
263     argv = 'lumi\xc3\xa8re'
264     platform = 'darwin'
265     filesystemencoding = 'utf-8'
266     stdoutencoding = 'UTF-8'
267     dirlist = [u'A\u0308rtonwall.mp3', u'Blah blah.txt', u'test_file']
268
269 class MacOSXLeopard7bit(StringUtils, unittest.TestCase):
270     uname = 'Darwin g5.local 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:57:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_PPC Power Macintosh powerpc'
271     #argv = 'lumiere'
272     platform = 'darwin'
273     filesystemencoding = 'utf-8'
274     stdoutencoding = 'US-ASCII'
275     dirlist = [u'A\u0308rtonwall.mp3', u'Blah blah.txt', u'test_file']
276
277 class OpenBSD(StringUtils, unittest.TestCase):
278     uname = 'OpenBSD 4.1 GENERIC#187 i386 Intel(R) Celeron(R) CPU 2.80GHz ("GenuineIntel" 686-class)'
279     #argv = 'lumiere'
280     platform = 'openbsd4'
281     filesystemencoding = '646'
282     stdoutencoding = '646'
283     # Oops, I cannot write filenames containing non-ascii characters