1
# Copyright (C) 2005, 2006, 2008, 2009, 2011 Canonical Ltd
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.
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.
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
17
"""Test that various operations work in a non-ASCII environment."""
21
from unicodedata import normalize
23
from bzrlib import osutils
24
from bzrlib.osutils import pathjoin
25
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
28
class NonAsciiTest(TestCaseWithTransport):
30
def test_add_in_nonascii_branch(self):
31
"""Test adding in a non-ASCII branch."""
34
wt = self.make_branch_and_tree(br_dir)
35
except UnicodeEncodeError:
36
raise TestSkipped("filesystem can't accomodate nonascii names")
38
file(pathjoin(br_dir, "a"), "w").write("hello")
39
wt.add(["a"], ["a-id"])
43
a_circle_d = u'a\u030a'
47
z_umlat_d = u'Z\u030c'
48
squared_c = u'\xbc' # This gets mapped to '2' if we use NFK[CD]
50
quarter_c = u'\xb2' # Gets mapped to u'1\u20444' (1/4) if we use NFK[CD]
54
class TestNormalization(TestCase):
55
"""Verify that we have our normalizations correct."""
57
def test_normalize(self):
58
self.assertEqual(a_circle_d, normalize('NFD', a_circle_c))
59
self.assertEqual(a_circle_c, normalize('NFC', a_circle_d))
60
self.assertEqual(a_dots_d, normalize('NFD', a_dots_c))
61
self.assertEqual(a_dots_c, normalize('NFC', a_dots_d))
62
self.assertEqual(z_umlat_d, normalize('NFD', z_umlat_c))
63
self.assertEqual(z_umlat_c, normalize('NFC', z_umlat_d))
64
self.assertEqual(squared_d, normalize('NFC', squared_c))
65
self.assertEqual(squared_c, normalize('NFD', squared_d))
66
self.assertEqual(quarter_d, normalize('NFC', quarter_c))
67
self.assertEqual(quarter_c, normalize('NFD', quarter_d))
70
class NormalizedFilename(TestCaseWithTransport):
71
"""Test normalized_filename and associated helpers"""
73
def test__accessible_normalized_filename(self):
74
anf = osutils._accessible_normalized_filename
75
# normalized_filename should allow plain ascii strings
76
# not just unicode strings
77
self.assertEqual((u'ascii', True), anf('ascii'))
78
self.assertEqual((a_circle_c, True), anf(a_circle_c))
79
self.assertEqual((a_circle_c, True), anf(a_circle_d))
80
self.assertEqual((a_dots_c, True), anf(a_dots_c))
81
self.assertEqual((a_dots_c, True), anf(a_dots_d))
82
self.assertEqual((z_umlat_c, True), anf(z_umlat_c))
83
self.assertEqual((z_umlat_c, True), anf(z_umlat_d))
84
self.assertEqual((squared_c, True), anf(squared_c))
85
self.assertEqual((squared_c, True), anf(squared_d))
86
self.assertEqual((quarter_c, True), anf(quarter_c))
87
self.assertEqual((quarter_c, True), anf(quarter_d))
89
def test__inaccessible_normalized_filename(self):
90
inf = osutils._inaccessible_normalized_filename
91
# normalized_filename should allow plain ascii strings
92
# not just unicode strings
93
self.assertEqual((u'ascii', True), inf('ascii'))
94
self.assertEqual((a_circle_c, True), inf(a_circle_c))
95
self.assertEqual((a_circle_c, False), inf(a_circle_d))
96
self.assertEqual((a_dots_c, True), inf(a_dots_c))
97
self.assertEqual((a_dots_c, False), inf(a_dots_d))
98
self.assertEqual((z_umlat_c, True), inf(z_umlat_c))
99
self.assertEqual((z_umlat_c, False), inf(z_umlat_d))
100
self.assertEqual((squared_c, True), inf(squared_c))
101
self.assertEqual((squared_c, True), inf(squared_d))
102
self.assertEqual((quarter_c, True), inf(quarter_c))
103
self.assertEqual((quarter_c, True), inf(quarter_d))
105
def test_functions(self):
106
if osutils.normalizes_filenames():
107
self.assertEqual(osutils.normalized_filename,
108
osutils._accessible_normalized_filename)
110
self.assertEqual(osutils.normalized_filename,
111
osutils._inaccessible_normalized_filename)
113
def test_platform(self):
114
# With FAT32 and certain encodings on win32
115
# a_circle_c and a_dots_c actually map to the same file
116
# adding a suffix kicks in the 'preserving but insensitive'
117
# route, and maintains the right files
118
files = [a_circle_c+'.1', a_dots_c+'.2', z_umlat_c+'.3']
120
self.build_tree(files)
122
raise TestSkipped("filesystem cannot create unicode files")
124
if sys.platform == 'darwin':
125
expected = sorted([a_circle_d+'.1', a_dots_d+'.2', z_umlat_d+'.3'])
127
expected = sorted(files)
129
present = sorted(os.listdir(u'.'))
130
self.assertEqual(expected, present)
132
def test_access_normalized(self):
133
# We should always be able to access files created with
134
# normalized filenames
135
# With FAT32 and certain encodings on win32
136
# a_circle_c and a_dots_c actually map to the same file
137
# adding a suffix kicks in the 'preserving but insensitive'
138
# route, and maintains the right files
139
files = [a_circle_c+'.1', a_dots_c+'.2', z_umlat_c+'.3',
140
squared_c+'.4', quarter_c+'.5']
142
self.build_tree(files, line_endings='native')
144
raise TestSkipped("filesystem cannot create unicode files")
147
# We should get an exception if we can't open the file at
149
path, can_access = osutils.normalized_filename(fname)
151
self.assertEqual(path, fname)
152
self.assertTrue(can_access)
157
shouldbe = 'contents of %s%s' % (path.encode('utf8'),
162
self.assertEqual(shouldbe, actual,
163
'contents of %r is incorrect: %r != %r'
164
% (path, shouldbe, actual))
166
def test_access_non_normalized(self):
167
# Sometimes we can access non-normalized files by their normalized
168
# path, verify that normalized_filename returns the right info
169
files = [a_circle_d+'.1', a_dots_d+'.2', z_umlat_d+'.3']
172
self.build_tree(files)
174
raise TestSkipped("filesystem cannot create unicode files")
177
# We should get an exception if we can't open the file at
179
path, can_access = osutils.normalized_filename(fname)
181
self.assertNotEqual(path, fname)
183
# We should always be able to access them from the name
184
# they were created with
185
f = open(fname, 'rb')
188
# And normalized_filename sholud tell us correctly if we can
189
# access them by an alternate name
194
self.assertRaises(IOError, open, path, 'rb')