From 6d459725a3f2f904a525739a63792b702aa32384 Mon Sep 17 00:00:00 2001 From: Mark Hammond Date: Wed, 3 Dec 2003 01:29:56 +0000 Subject: 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. --- Lib/test/test_unicode_file.py | 224 ++++++++++++++++++++++++++++-------------- 1 file changed, 148 insertions(+), 76 deletions(-) (limited to 'Lib/test/test_unicode_file.py') diff --git a/Lib/test/test_unicode_file.py b/Lib/test/test_unicode_file.py index b8b1848f9c..467b78ec16 100644 --- a/Lib/test/test_unicode_file.py +++ b/Lib/test/test_unicode_file.py @@ -1,10 +1,11 @@ # Test some Unicode file name semantics # We dont test many operations on files other than # that their names can be used with Unicode characters. -import os, glob +import os, glob, time, shutil -from test.test_support import verify, TestSkipped, TESTFN_UNICODE -from test.test_support import TESTFN_ENCODING +import unittest +from test.test_support import run_suite, TestSkipped, TESTFN_UNICODE +from test.test_support import TESTFN_ENCODING, TESTFN_UNICODE_UNENCODEABLE try: TESTFN_ENCODED = TESTFN_UNICODE.encode(TESTFN_ENCODING) except (UnicodeError, TypeError): @@ -12,86 +13,157 @@ except (UnicodeError, TypeError): # cannot be encoded in the file system encoding. raise TestSkipped("No Unicode filesystem semantics on this platform.") -# Check with creation as Unicode string. -f = open(TESTFN_UNICODE, 'wb') -if not os.path.isfile(TESTFN_UNICODE): - print "File doesn't exist after creating it" +def remove_if_exists(filename): + if os.path.exists(filename): + os.unlink(filename) -if not os.path.isfile(TESTFN_ENCODED): - print "File doesn't exist (encoded string) after creating it" +class TestUnicodeFiles(unittest.TestCase): + # The 'do_' functions are the actual tests. They generally assume the + # file already exists etc. + + # Do all the tests we can given only a single filename. The file should + # exist. + def _do_single(self, filename): + self.failUnless(os.path.exists(filename)) + self.failUnless(os.path.isfile(filename)) + self.failUnless(os.path.exists(os.path.abspath(filename))) + self.failUnless(os.path.isfile(os.path.abspath(filename))) + os.chmod(filename, 0777) + os.utime(filename, None) + os.utime(filename, (time.time(), time.time())) + # Copy/rename etc tests using the same filename + self._do_copyish(filename, filename) + # Filename should appear in glob output + self.failUnless( + os.path.abspath(filename)==os.path.abspath(glob.glob(filename)[0])) + # basename should appear in listdir. + path, base = os.path.split(os.path.abspath(filename)) + self.failUnless(base in os.listdir(path)) + + # Do as many "equivalancy' tests as we can - ie, check that although we + # have different types for the filename, they refer to the same file. + def _do_equivilent(self, filename1, filename2): + # Note we only check "filename1 against filename2" - we don't bother + # checking "filename2 against 1", as we assume we are called again with + # the args reversed. + self.failUnless(type(filename1)!=type(filename2), + "No point checking equivalent filenames of the same type") + # stat and lstat should return the same results. + self.failUnlessEqual(os.stat(filename1), + os.stat(filename2)) + self.failUnlessEqual(os.lstat(filename1), + os.lstat(filename2)) + # Copy/rename etc tests using equivalent filename + self._do_copyish(filename1, filename2) -f.close() + # Tests that copy, move, etc one file to another. + def _do_copyish(self, filename1, filename2): + # Should be able to rename the file using either name. + self.failUnless(os.path.isfile(filename1)) # must exist. + os.rename(filename1, filename2 + ".new") + self.failUnless(os.path.isfile(filename1+".new")) + os.rename(filename1 + ".new", filename2) + self.failUnless(os.path.isfile(filename2)) -# Test stat and chmod -if os.stat(TESTFN_ENCODED) != os.stat(TESTFN_UNICODE): - print "os.stat() did not agree on the 2 filenames" -if os.lstat(TESTFN_ENCODED) != os.lstat(TESTFN_UNICODE): - print "os.lstat() did not agree on the 2 filenames" -os.chmod(TESTFN_ENCODED, 0777) -os.chmod(TESTFN_UNICODE, 0777) + # Try using shutil on the filenames. + try: + filename1==filename2 + except UnicodeDecodeError: + # these filenames can't be compared - shutil.copy tries to do + # just that. This is really a bug in 'shutil' - if one of shutil's + # 2 params are Unicode and the other isn't, it should coerce the + # string to Unicode with the filesystem encoding before comparison. + pass + else: + # filenames can be compared. + shutil.copy(filename1, filename2 + ".new") + os.unlink(filename1 + ".new") # remove using equiv name. + # And a couple of moves, one using each name. + shutil.move(filename1, filename2 + ".new") + self.failUnless(not os.path.exists(filename2)) + shutil.move(filename1 + ".new", filename2) + self.failUnless(os.path.exists(filename1)) + # Note - due to the implementation of shutil.move, + # it tries a rename first. This only fails on Windows when on + # different file systems - and this test can't ensure that. + # So we test the shutil.copy2 function, which is the thing most + # likely to fail. + shutil.copy2(filename1, filename2 + ".new") + os.unlink(filename1 + ".new") -# Test rename -try: - os.unlink(TESTFN_ENCODED + ".new") -except os.error: - pass -os.rename(TESTFN_ENCODED, TESTFN_ENCODED + ".new") -os.rename(TESTFN_UNICODE+".new", TESTFN_ENCODED) - -os.unlink(TESTFN_ENCODED) -if os.path.isfile(TESTFN_ENCODED) or \ - os.path.isfile(TESTFN_UNICODE): - print "File exists after deleting it" + def _do_directory(self, make_name, chdir_name, getcwd_func): + cwd = os.getcwd() + if os.path.isdir(make_name): + os.rmdir(make_name) + os.mkdir(make_name) + try: + os.chdir(chdir_name) + try: + self.failUnlessEqual(os.path.basename(getcwd_func()), + make_name) + finally: + os.chdir(cwd) + finally: + os.rmdir(make_name) -# Check with creation as encoded string. -f = open(TESTFN_ENCODED, 'wb') -if not os.path.isfile(TESTFN_UNICODE) or \ - not os.path.isfile(TESTFN_ENCODED): - print "File doesn't exist after creating it" + # The '_test' functions 'entry points with params' - ie, what the + # top-level 'test' functions would be if they could take params + def _test_single(self, filename): + remove_if_exists(filename) + f = file(filename, "w") + f.close() + try: + self._do_single(filename) + finally: + os.unlink(filename) + self.failUnless(not os.path.exists(filename)) + # and again with os.open. + f = os.open(filename, os.O_CREAT) + os.close(f) + try: + self._do_single(filename) + finally: + os.unlink(filename) + + def _test_equivalent(self, filename1, filename2): + remove_if_exists(filename1) + self.failUnless(not os.path.exists(filename2)) + f = file(filename1, "w") + f.close() + try: + self._do_equivilent(filename1, filename2) + finally: + os.unlink(filename1) -path, base = os.path.split(os.path.abspath(TESTFN_ENCODED)) -# Until PEP 277 is adopted, this test is not portable -# if base not in os.listdir(path): -# print "Filename did not appear in os.listdir()" -# path, base = os.path.split(os.path.abspath(TESTFN_UNICODE)) -# if base not in os.listdir(path): -# print "Unicode filename did not appear in os.listdir()" + # The 'test' functions are unittest entry points, and simply call our + # _test functions with each of the filename combinations we wish to test + def test_single_files(self): + self._test_single(TESTFN_ENCODED) + self._test_single(TESTFN_UNICODE) + self._test_single(TESTFN_UNICODE_UNENCODEABLE) -if os.path.abspath(TESTFN_ENCODED) != os.path.abspath(glob.glob(TESTFN_ENCODED)[0]): - print "Filename did not appear in glob.glob()" -if os.path.abspath(TESTFN_UNICODE) != os.path.abspath(glob.glob(TESTFN_UNICODE)[0]): - print "Unicode filename did not appear in glob.glob()" + def test_equivalent_files(self): + self._test_equivalent(TESTFN_ENCODED, TESTFN_UNICODE) + self._test_equivalent(TESTFN_UNICODE, TESTFN_ENCODED) -f.close() -os.unlink(TESTFN_UNICODE) -if os.path.isfile(TESTFN_ENCODED) or \ - os.path.isfile(TESTFN_UNICODE): - print "File exists after deleting it" + def test_directories(self): + # For all 'equivilent' combinations: + # Make dir with encoded, chdir with unicode, checkdir with encoded + # (or unicode/encoded/unicode, etc + ext = ".dir" + self._do_directory(TESTFN_ENCODED+ext, TESTFN_ENCODED+ext, os.getcwd) + self._do_directory(TESTFN_ENCODED+ext, TESTFN_UNICODE+ext, os.getcwd) + self._do_directory(TESTFN_UNICODE+ext, TESTFN_ENCODED+ext, os.getcwdu) + self._do_directory(TESTFN_UNICODE+ext, TESTFN_UNICODE+ext, os.getcwdu) + # Our directory name that can't use a non-unicode name. + self._do_directory(TESTFN_UNICODE_UNENCODEABLE+ext, + TESTFN_UNICODE_UNENCODEABLE+ext, + os.getcwdu) -# test os.open -f = os.open(TESTFN_ENCODED, os.O_CREAT) -if not os.path.isfile(TESTFN_UNICODE) or \ - not os.path.isfile(TESTFN_ENCODED): - print "File doesn't exist after creating it" -os.close(f) -os.unlink(TESTFN_UNICODE) +def test_main(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(TestUnicodeFiles)) + run_suite(suite) -# Test directories etc -cwd = os.getcwd() -abs_encoded = os.path.abspath(TESTFN_ENCODED) + ".dir" -abs_unicode = os.path.abspath(TESTFN_UNICODE) + ".dir" -os.mkdir(abs_encoded) -try: - os.chdir(abs_encoded) - os.chdir(abs_unicode) -finally: - os.chdir(cwd) - os.rmdir(abs_unicode) -os.mkdir(abs_unicode) -try: - os.chdir(abs_encoded) - os.chdir(abs_unicode) -finally: - os.chdir(cwd) - os.rmdir(abs_encoded) -print "All the Unicode tests appeared to work" +if __name__ == "__main__": + test_main() -- cgit v1.2.1