Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6d45972

Browse files
committed
Add test for bug "[ 846133 ] os.chmod/os.utime/shutil do not work with
unicode filenames" Reorganize tests into functions so more combinations of unicode/encoded/ascii can be tested, and while I was at it, upgrade to unittest based test.
1 parent b337dd9 commit 6d45972

2 files changed

Lines changed: 148 additions & 78 deletions

File tree

Lib/test/output/test_unicode_file

Lines changed: 0 additions & 2 deletions
This file was deleted.

Lib/test/test_unicode_file.py

Lines changed: 148 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,169 @@
11
# Test some Unicode file name semantics
22
# We dont test many operations on files other than
33
# that their names can be used with Unicode characters.
4-
import os, glob
4+
import os, glob, time, shutil
55

6-
from test.test_support import verify, TestSkipped, TESTFN_UNICODE
7-
from test.test_support import TESTFN_ENCODING
6+
import unittest
7+
from test.test_support import run_suite, TestSkipped, TESTFN_UNICODE
8+
from test.test_support import TESTFN_ENCODING, TESTFN_UNICODE_UNENCODEABLE
89
try:
910
TESTFN_ENCODED = TESTFN_UNICODE.encode(TESTFN_ENCODING)
1011
except (UnicodeError, TypeError):
1112
# Either the file system encoding is None, or the file name
1213
# cannot be encoded in the file system encoding.
1314
raise TestSkipped("No Unicode filesystem semantics on this platform.")
1415

15-
# Check with creation as Unicode string.
16-
f = open(TESTFN_UNICODE, 'wb')
17-
if not os.path.isfile(TESTFN_UNICODE):
18-
print "File doesn't exist after creating it"
16+
def remove_if_exists(filename):
17+
if os.path.exists(filename):
18+
os.unlink(filename)
1919

20-
if not os.path.isfile(TESTFN_ENCODED):
21-
print "File doesn't exist (encoded string) after creating it"
20+
class TestUnicodeFiles(unittest.TestCase):
21+
# The 'do_' functions are the actual tests. They generally assume the
22+
# file already exists etc.
23+
24+
# Do all the tests we can given only a single filename. The file should
25+
# exist.
26+
def _do_single(self, filename):
27+
self.failUnless(os.path.exists(filename))
28+
self.failUnless(os.path.isfile(filename))
29+
self.failUnless(os.path.exists(os.path.abspath(filename)))
30+
self.failUnless(os.path.isfile(os.path.abspath(filename)))
31+
os.chmod(filename, 0777)
32+
os.utime(filename, None)
33+
os.utime(filename, (time.time(), time.time()))
34+
# Copy/rename etc tests using the same filename
35+
self._do_copyish(filename, filename)
36+
# Filename should appear in glob output
37+
self.failUnless(
38+
os.path.abspath(filename)==os.path.abspath(glob.glob(filename)[0]))
39+
# basename should appear in listdir.
40+
path, base = os.path.split(os.path.abspath(filename))
41+
self.failUnless(base in os.listdir(path))
42+
43+
# Do as many "equivalancy' tests as we can - ie, check that although we
44+
# have different types for the filename, they refer to the same file.
45+
def _do_equivilent(self, filename1, filename2):
46+
# Note we only check "filename1 against filename2" - we don't bother
47+
# checking "filename2 against 1", as we assume we are called again with
48+
# the args reversed.
49+
self.failUnless(type(filename1)!=type(filename2),
50+
"No point checking equivalent filenames of the same type")
51+
# stat and lstat should return the same results.
52+
self.failUnlessEqual(os.stat(filename1),
53+
os.stat(filename2))
54+
self.failUnlessEqual(os.lstat(filename1),
55+
os.lstat(filename2))
56+
# Copy/rename etc tests using equivalent filename
57+
self._do_copyish(filename1, filename2)
2258

23-
f.close()
59+
# Tests that copy, move, etc one file to another.
60+
def _do_copyish(self, filename1, filename2):
61+
# Should be able to rename the file using either name.
62+
self.failUnless(os.path.isfile(filename1)) # must exist.
63+
os.rename(filename1, filename2 + ".new")
64+
self.failUnless(os.path.isfile(filename1+".new"))
65+
os.rename(filename1 + ".new", filename2)
66+
self.failUnless(os.path.isfile(filename2))
2467

25-
# Test stat and chmod
26-
if os.stat(TESTFN_ENCODED) != os.stat(TESTFN_UNICODE):
27-
print "os.stat() did not agree on the 2 filenames"
28-
if os.lstat(TESTFN_ENCODED) != os.lstat(TESTFN_UNICODE):
29-
print "os.lstat() did not agree on the 2 filenames"
30-
os.chmod(TESTFN_ENCODED, 0777)
31-
os.chmod(TESTFN_UNICODE, 0777)
68+
# Try using shutil on the filenames.
69+
try:
70+
filename1==filename2
71+
except UnicodeDecodeError:
72+
# these filenames can't be compared - shutil.copy tries to do
73+
# just that. This is really a bug in 'shutil' - if one of shutil's
74+
# 2 params are Unicode and the other isn't, it should coerce the
75+
# string to Unicode with the filesystem encoding before comparison.
76+
pass
77+
else:
78+
# filenames can be compared.
79+
shutil.copy(filename1, filename2 + ".new")
80+
os.unlink(filename1 + ".new") # remove using equiv name.
81+
# And a couple of moves, one using each name.
82+
shutil.move(filename1, filename2 + ".new")
83+
self.failUnless(not os.path.exists(filename2))
84+
shutil.move(filename1 + ".new", filename2)
85+
self.failUnless(os.path.exists(filename1))
86+
# Note - due to the implementation of shutil.move,
87+
# it tries a rename first. This only fails on Windows when on
88+
# different file systems - and this test can't ensure that.
89+
# So we test the shutil.copy2 function, which is the thing most
90+
# likely to fail.
91+
shutil.copy2(filename1, filename2 + ".new")
92+
os.unlink(filename1 + ".new")
3293

33-
# Test rename
34-
try:
35-
os.unlink(TESTFN_ENCODED + ".new")
36-
except os.error:
37-
pass
38-
os.rename(TESTFN_ENCODED, TESTFN_ENCODED + ".new")
39-
os.rename(TESTFN_UNICODE+".new", TESTFN_ENCODED)
40-
41-
os.unlink(TESTFN_ENCODED)
42-
if os.path.isfile(TESTFN_ENCODED) or \
43-
os.path.isfile(TESTFN_UNICODE):
44-
print "File exists after deleting it"
94+
def _do_directory(self, make_name, chdir_name, getcwd_func):
95+
cwd = os.getcwd()
96+
if os.path.isdir(make_name):
97+
os.rmdir(make_name)
98+
os.mkdir(make_name)
99+
try:
100+
os.chdir(chdir_name)
101+
try:
102+
self.failUnlessEqual(os.path.basename(getcwd_func()),
103+
make_name)
104+
finally:
105+
os.chdir(cwd)
106+
finally:
107+
os.rmdir(make_name)
45108

46-
# Check with creation as encoded string.
47-
f = open(TESTFN_ENCODED, 'wb')
48-
if not os.path.isfile(TESTFN_UNICODE) or \
49-
not os.path.isfile(TESTFN_ENCODED):
50-
print "File doesn't exist after creating it"
109+
# The '_test' functions 'entry points with params' - ie, what the
110+
# top-level 'test' functions would be if they could take params
111+
def _test_single(self, filename):
112+
remove_if_exists(filename)
113+
f = file(filename, "w")
114+
f.close()
115+
try:
116+
self._do_single(filename)
117+
finally:
118+
os.unlink(filename)
119+
self.failUnless(not os.path.exists(filename))
120+
# and again with os.open.
121+
f = os.open(filename, os.O_CREAT)
122+
os.close(f)
123+
try:
124+
self._do_single(filename)
125+
finally:
126+
os.unlink(filename)
127+
128+
def _test_equivalent(self, filename1, filename2):
129+
remove_if_exists(filename1)
130+
self.failUnless(not os.path.exists(filename2))
131+
f = file(filename1, "w")
132+
f.close()
133+
try:
134+
self._do_equivilent(filename1, filename2)
135+
finally:
136+
os.unlink(filename1)
51137

52-
path, base = os.path.split(os.path.abspath(TESTFN_ENCODED))
53-
# Until PEP 277 is adopted, this test is not portable
54-
# if base not in os.listdir(path):
55-
# print "Filename did not appear in os.listdir()"
56-
# path, base = os.path.split(os.path.abspath(TESTFN_UNICODE))
57-
# if base not in os.listdir(path):
58-
# print "Unicode filename did not appear in os.listdir()"
138+
# The 'test' functions are unittest entry points, and simply call our
139+
# _test functions with each of the filename combinations we wish to test
140+
def test_single_files(self):
141+
self._test_single(TESTFN_ENCODED)
142+
self._test_single(TESTFN_UNICODE)
143+
self._test_single(TESTFN_UNICODE_UNENCODEABLE)
59144

60-
if os.path.abspath(TESTFN_ENCODED) != os.path.abspath(glob.glob(TESTFN_ENCODED)[0]):
61-
print "Filename did not appear in glob.glob()"
62-
if os.path.abspath(TESTFN_UNICODE) != os.path.abspath(glob.glob(TESTFN_UNICODE)[0]):
63-
print "Unicode filename did not appear in glob.glob()"
145+
def test_equivalent_files(self):
146+
self._test_equivalent(TESTFN_ENCODED, TESTFN_UNICODE)
147+
self._test_equivalent(TESTFN_UNICODE, TESTFN_ENCODED)
64148

65-
f.close()
66-
os.unlink(TESTFN_UNICODE)
67-
if os.path.isfile(TESTFN_ENCODED) or \
68-
os.path.isfile(TESTFN_UNICODE):
69-
print "File exists after deleting it"
149+
def test_directories(self):
150+
# For all 'equivilent' combinations:
151+
# Make dir with encoded, chdir with unicode, checkdir with encoded
152+
# (or unicode/encoded/unicode, etc
153+
ext = ".dir"
154+
self._do_directory(TESTFN_ENCODED+ext, TESTFN_ENCODED+ext, os.getcwd)
155+
self._do_directory(TESTFN_ENCODED+ext, TESTFN_UNICODE+ext, os.getcwd)
156+
self._do_directory(TESTFN_UNICODE+ext, TESTFN_ENCODED+ext, os.getcwdu)
157+
self._do_directory(TESTFN_UNICODE+ext, TESTFN_UNICODE+ext, os.getcwdu)
158+
# Our directory name that can't use a non-unicode name.
159+
self._do_directory(TESTFN_UNICODE_UNENCODEABLE+ext,
160+
TESTFN_UNICODE_UNENCODEABLE+ext,
161+
os.getcwdu)
70162

71-
# test os.open
72-
f = os.open(TESTFN_ENCODED, os.O_CREAT)
73-
if not os.path.isfile(TESTFN_UNICODE) or \
74-
not os.path.isfile(TESTFN_ENCODED):
75-
print "File doesn't exist after creating it"
76-
os.close(f)
77-
os.unlink(TESTFN_UNICODE)
163+
def test_main():
164+
suite = unittest.TestSuite()
165+
suite.addTest(unittest.makeSuite(TestUnicodeFiles))
166+
run_suite(suite)
78167

79-
# Test directories etc
80-
cwd = os.getcwd()
81-
abs_encoded = os.path.abspath(TESTFN_ENCODED) + ".dir"
82-
abs_unicode = os.path.abspath(TESTFN_UNICODE) + ".dir"
83-
os.mkdir(abs_encoded)
84-
try:
85-
os.chdir(abs_encoded)
86-
os.chdir(abs_unicode)
87-
finally:
88-
os.chdir(cwd)
89-
os.rmdir(abs_unicode)
90-
os.mkdir(abs_unicode)
91-
try:
92-
os.chdir(abs_encoded)
93-
os.chdir(abs_unicode)
94-
finally:
95-
os.chdir(cwd)
96-
os.rmdir(abs_encoded)
97-
print "All the Unicode tests appeared to work"
168+
if __name__ == "__main__":
169+
test_main()

0 commit comments

Comments
 (0)