1 # vim: set fileencoding=utf-8 :
2 # Copyright (C) 2010 Google Inc. All rights reserved.
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
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
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.
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.
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.
34 from __future__ import with_statement
42 from filesystem import FileSystem
45 class GenericFileSystemTests(object):
46 """Tests that should pass on either a real or mock filesystem."""
47 def setup_generic_test_dir(self):
49 self.generic_test_dir = str(self.fs.mkdtemp())
50 self.orig_cwd = fs.getcwd()
51 fs.chdir(self.generic_test_dir)
52 fs.write_text_file('foo.txt', 'foo')
53 fs.write_text_file('foobar', 'foobar')
54 fs.maybe_make_directory('foodir')
55 fs.write_text_file(fs.join('foodir', 'baz'), 'baz')
56 fs.chdir(self.orig_cwd)
58 def teardown_generic_test_dir(self):
59 self.fs.rmtree(self.generic_test_dir)
60 self.fs.chdir(self.orig_cwd)
61 self.generic_test_dir = None
63 def test_glob__trailing_asterisk(self):
64 self.fs.chdir(self.generic_test_dir)
65 self.assertEquals(set(self.fs.glob('fo*')), set(['foo.txt', 'foobar', 'foodir']))
67 def test_glob__leading_asterisk(self):
68 self.fs.chdir(self.generic_test_dir)
69 self.assertEquals(set(self.fs.glob('*xt')), set(['foo.txt']))
71 def test_glob__middle_asterisk(self):
72 self.fs.chdir(self.generic_test_dir)
73 self.assertEquals(set(self.fs.glob('f*r')), set(['foobar', 'foodir']))
75 def test_glob__period_is_escaped(self):
76 self.fs.chdir(self.generic_test_dir)
77 self.assertEquals(set(self.fs.glob('foo.*')), set(['foo.txt']))
79 class RealFileSystemTest(unittest.TestCase, GenericFileSystemTests):
81 self.fs = FileSystem()
82 self.setup_generic_test_dir()
84 self._this_dir = os.path.dirname(os.path.abspath(__file__))
85 self._missing_file = os.path.join(self._this_dir, 'missing_file.py')
86 self._this_file = os.path.join(self._this_dir, 'filesystem_unittest.py')
89 self.teardown_generic_test_dir()
96 if sys.platform == 'win32':
99 self.assertEquals(fs.getcwd(), newdir)
102 def test_chdir__notexists(self):
104 newdir = '/dirdoesnotexist'
105 if sys.platform == 'win32':
106 newdir = 'c:\\dirdoesnotexist'
107 self.assertRaises(OSError, fs.chdir, newdir)
109 def test_exists__true(self):
111 self.assertTrue(fs.exists(self._this_file))
113 def test_exists__false(self):
115 self.assertFalse(fs.exists(self._missing_file))
117 def test_getcwd(self):
119 self.assertTrue(fs.exists(fs.getcwd()))
121 def test_isdir__true(self):
123 self.assertTrue(fs.isdir(self._this_dir))
125 def test_isdir__false(self):
127 self.assertFalse(fs.isdir(self._this_file))
131 self.assertEqual(fs.join('foo', 'bar'),
132 os.path.join('foo', 'bar'))
134 def test_listdir(self):
136 with fs.mkdtemp(prefix='filesystem_unittest_') as d:
137 self.assertEqual(fs.listdir(d), [])
138 new_file = os.path.join(d, 'foo')
139 fs.write_text_file(new_file, u'foo')
140 self.assertEqual(fs.listdir(d), ['foo'])
143 def test_maybe_make_directory__success(self):
146 with fs.mkdtemp(prefix='filesystem_unittest_') as base_path:
147 sub_path = os.path.join(base_path, "newdir")
148 self.assertFalse(os.path.exists(sub_path))
149 self.assertFalse(fs.isdir(sub_path))
151 fs.maybe_make_directory(sub_path)
152 self.assertTrue(os.path.exists(sub_path))
153 self.assertTrue(fs.isdir(sub_path))
155 # Make sure we can re-create it.
156 fs.maybe_make_directory(sub_path)
157 self.assertTrue(os.path.exists(sub_path))
158 self.assertTrue(fs.isdir(sub_path))
163 self.assertFalse(os.path.exists(base_path))
164 self.assertFalse(fs.isdir(base_path))
166 def test_maybe_make_directory__failure(self):
167 # FIXME: os.chmod() doesn't work on Windows to set directories
168 # as readonly, so we skip this test for now.
169 if sys.platform in ('win32', 'cygwin'):
173 with fs.mkdtemp(prefix='filesystem_unittest_') as d:
174 # Remove write permissions on the parent directory.
175 os.chmod(d, stat.S_IRUSR)
177 # Now try to create a sub directory - should fail.
178 sub_dir = fs.join(d, 'subdir')
179 self.assertRaises(OSError, fs.maybe_make_directory, sub_dir)
181 # Clean up in case the test failed and we did create the
183 if os.path.exists(sub_dir):
186 def test_read_and_write_text_file(self):
190 unicode_text_string = u'\u016An\u012Dc\u014Dde\u033D'
191 hex_equivalent = '\xC5\xAA\x6E\xC4\xAD\x63\xC5\x8D\x64\x65\xCC\xBD'
193 text_path = tempfile.mktemp(prefix='tree_unittest_')
194 file = fs.open_text_file_for_writing(text_path)
195 file.write(unicode_text_string)
198 file = fs.open_text_file_for_reading(text_path)
199 read_text = file.read()
202 self.assertEqual(read_text, unicode_text_string)
204 if text_path and fs.isfile(text_path):
207 def test_read_and_write_file(self):
212 unicode_text_string = u'\u016An\u012Dc\u014Dde\u033D'
213 hex_equivalent = '\xC5\xAA\x6E\xC4\xAD\x63\xC5\x8D\x64\x65\xCC\xBD'
215 text_path = tempfile.mktemp(prefix='tree_unittest_')
216 binary_path = tempfile.mktemp(prefix='tree_unittest_')
217 fs.write_text_file(text_path, unicode_text_string)
218 contents = fs.read_binary_file(text_path)
219 self.assertEqual(contents, hex_equivalent)
221 fs.write_binary_file(binary_path, hex_equivalent)
222 text_contents = fs.read_text_file(binary_path)
223 self.assertEqual(text_contents, unicode_text_string)
225 if text_path and fs.isfile(text_path):
227 if binary_path and fs.isfile(binary_path):
228 os.remove(binary_path)
230 def test_read_binary_file__missing(self):
232 self.assertRaises(IOError, fs.read_binary_file, self._missing_file)
234 def test_read_text_file__missing(self):
236 self.assertRaises(IOError, fs.read_text_file, self._missing_file)
238 def test_remove_file_with_retry(self):
239 RealFileSystemTest._remove_failures = 2
241 def remove_with_exception(filename):
242 RealFileSystemTest._remove_failures -= 1
243 if RealFileSystemTest._remove_failures >= 0:
247 raise FileSystem._WindowsError
250 self.assertTrue(fs.remove('filename', remove_with_exception))
251 self.assertEquals(-1, RealFileSystemTest._remove_failures)
256 self.assertEquals(fs.sep, os.sep)
257 self.assertEquals(fs.join("foo", "bar"),
258 os.path.join("foo", "bar"))
260 def test_sep__is_readonly(self):
264 self.assertRaises(AttributeError, assign_sep)
266 if __name__ == '__main__':