1 # vim: set fileencoding=utf-8 : 2 # Copyright (C) 2010 Google Inc. All rights reserved. 3 # 4 # Redistribution and use in source and binary forms, with or without 5 # modification, are permitted provided that the following conditions are 6 # met: 7 # 8 # * Redistributions of source code must retain the above copyright 9 # notice, this list of conditions and the following disclaimer. 10 # * Redistributions in binary form must reproduce the above 11 # copyright notice, this list of conditions and the following disclaimer 12 # in the documentation and/or other materials provided with the 13 # distribution. 14 # * Neither the name of Google Inc. nor the names of its 15 # contributors may be used to endorse or promote products derived from 16 # this software without specific prior written permission. 17 # 18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 # NOTE: The fileencoding comment on the first line of the file is 31 # important; without it, Python will choke while trying to parse the file, 32 # since it includes non-ASCII characters. 33 34 from __future__ import with_statement 35 36 import os 37 import stat 38 import sys 39 import tempfile 40 import unittest 41 42 from filesystem import FileSystem 43 44 45 class FileSystemTest(unittest.TestCase): 46 def setUp(self): 47 self._this_dir = os.path.dirname(os.path.abspath(__file__)) 48 self._missing_file = os.path.join(self._this_dir, 'missing_file.py') 49 self._this_file = os.path.join(self._this_dir, 'filesystem_unittest.py') 50 51 def test_chdir(self): 52 fs = FileSystem() 53 cwd = fs.getcwd() 54 newdir = '/' 55 if sys.platform == 'win32': 56 newdir = 'c:\\' 57 fs.chdir(newdir) 58 self.assertEquals(fs.getcwd(), newdir) 59 fs.chdir(cwd) 60 61 def test_chdir__notexists(self): 62 fs = FileSystem() 63 newdir = '/dirdoesnotexist' 64 if sys.platform == 'win32': 65 newdir = 'c:\\dirdoesnotexist' 66 self.assertRaises(OSError, fs.chdir, newdir) 67 68 def test_exists__true(self): 69 fs = FileSystem() 70 self.assertTrue(fs.exists(self._this_file)) 71 72 def test_exists__false(self): 73 fs = FileSystem() 74 self.assertFalse(fs.exists(self._missing_file)) 75 76 def test_getcwd(self): 77 fs = FileSystem() 78 self.assertTrue(fs.exists(fs.getcwd())) 79 80 def test_isdir__true(self): 81 fs = FileSystem() 82 self.assertTrue(fs.isdir(self._this_dir)) 83 84 def test_isdir__false(self): 85 fs = FileSystem() 86 self.assertFalse(fs.isdir(self._this_file)) 87 88 def test_join(self): 89 fs = FileSystem() 90 self.assertEqual(fs.join('foo', 'bar'), 91 os.path.join('foo', 'bar')) 92 93 def test_listdir(self): 94 fs = FileSystem() 95 with fs.mkdtemp(prefix='filesystem_unittest_') as d: 96 self.assertEqual(fs.listdir(d), []) 97 new_file = os.path.join(d, 'foo') 98 fs.write_text_file(new_file, u'foo') 99 self.assertEqual(fs.listdir(d), ['foo']) 100 os.remove(new_file) 101 102 def test_maybe_make_directory__success(self): 103 fs = FileSystem() 104 105 with fs.mkdtemp(prefix='filesystem_unittest_') as base_path: 106 sub_path = os.path.join(base_path, "newdir") 107 self.assertFalse(os.path.exists(sub_path)) 108 self.assertFalse(fs.isdir(sub_path)) 109 110 fs.maybe_make_directory(sub_path) 111 self.assertTrue(os.path.exists(sub_path)) 112 self.assertTrue(fs.isdir(sub_path)) 113 114 # Make sure we can re-create it. 115 fs.maybe_make_directory(sub_path) 116 self.assertTrue(os.path.exists(sub_path)) 117 self.assertTrue(fs.isdir(sub_path)) 118 119 # Clean up. 120 os.rmdir(sub_path) 121 122 self.assertFalse(os.path.exists(base_path)) 123 self.assertFalse(fs.isdir(base_path)) 124 125 def test_maybe_make_directory__failure(self): 126 # FIXME: os.chmod() doesn't work on Windows to set directories 127 # as readonly, so we skip this test for now. 128 if sys.platform in ('win32', 'cygwin'): 129 return 130 131 fs = FileSystem() 132 with fs.mkdtemp(prefix='filesystem_unittest_') as d: 133 # Remove write permissions on the parent directory. 134 os.chmod(d, stat.S_IRUSR) 135 136 # Now try to create a sub directory - should fail. 137 sub_dir = fs.join(d, 'subdir') 138 self.assertRaises(OSError, fs.maybe_make_directory, sub_dir) 139 140 # Clean up in case the test failed and we did create the 141 # directory. 142 if os.path.exists(sub_dir): 143 os.rmdir(sub_dir) 144 145 def test_read_and_write_file(self): 146 fs = FileSystem() 147 text_path = None 148 binary_path = None 149 150 unicode_text_string = u'ncde' 151 hex_equivalent = '\xC5\xAA\x6E\xC4\xAD\x63\xC5\x8D\x64\x65\xCC\xBD' 152 try: 153 text_path = tempfile.mktemp(prefix='tree_unittest_') 154 binary_path = tempfile.mktemp(prefix='tree_unittest_') 155 fs.write_text_file(text_path, unicode_text_string) 156 contents = fs.read_binary_file(text_path) 157 self.assertEqual(contents, hex_equivalent) 158 159 fs.write_text_file(binary_path, hex_equivalent) 160 text_contents = fs.read_text_file(binary_path) 161 self.assertEqual(text_contents, unicode_text_string) 162 except: 163 if text_path: 164 os.remove(text_path) 165 if binary_path: 166 os.remove(binary_path) 167 168 def test_read_binary_file__missing(self): 169 fs = FileSystem() 170 self.assertRaises(IOError, fs.read_binary_file, self._missing_file) 171 172 def test_read_text_file__missing(self): 173 fs = FileSystem() 174 self.assertRaises(IOError, fs.read_text_file, self._missing_file) 175 176 def test_remove_file_with_retry(self): 177 FileSystemTest._remove_failures = 2 178 179 def remove_with_exception(filename): 180 FileSystemTest._remove_failures -= 1 181 if FileSystemTest._remove_failures >= 0: 182 try: 183 raise WindowsError 184 except NameError: 185 raise FileSystem._WindowsError 186 187 fs = FileSystem() 188 self.assertTrue(fs.remove('filename', remove_with_exception)) 189 self.assertEquals(-1, FileSystemTest._remove_failures) 190 191 def test_sep(self): 192 fs = FileSystem() 193 194 self.assertEquals(fs.sep, os.sep) 195 self.assertEquals(fs.join("foo", "bar"), 196 os.path.join("foo", "bar")) 197 198 def test_sep__is_readonly(self): 199 def assign_sep(): 200 fs.sep = ' ' 201 fs = FileSystem() 202 self.assertRaises(AttributeError, assign_sep) 203 204 205 if __name__ == '__main__': 206 unittest.main() 207