test_unicode_file.py revision 6d459725a3f2f904a525739a63792b702aa32384
1# Test some Unicode file name semantics 2# We dont test many operations on files other than 3# that their names can be used with Unicode characters. 4import os, glob, time, shutil 5 6import unittest 7from test.test_support import run_suite, TestSkipped, TESTFN_UNICODE 8from test.test_support import TESTFN_ENCODING, TESTFN_UNICODE_UNENCODEABLE 9try: 10 TESTFN_ENCODED = TESTFN_UNICODE.encode(TESTFN_ENCODING) 11except (UnicodeError, TypeError): 12 # Either the file system encoding is None, or the file name 13 # cannot be encoded in the file system encoding. 14 raise TestSkipped("No Unicode filesystem semantics on this platform.") 15 16def remove_if_exists(filename): 17 if os.path.exists(filename): 18 os.unlink(filename) 19 20class 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) 58 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)) 67 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") 93 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) 108 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) 137 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) 144 145 def test_equivalent_files(self): 146 self._test_equivalent(TESTFN_ENCODED, TESTFN_UNICODE) 147 self._test_equivalent(TESTFN_UNICODE, TESTFN_ENCODED) 148 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) 162 163def test_main(): 164 suite = unittest.TestSuite() 165 suite.addTest(unittest.makeSuite(TestUnicodeFiles)) 166 run_suite(suite) 167 168if __name__ == "__main__": 169 test_main() 170