Home | History | Annotate | Download | only in system
      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 import os
     35 import stat
     36 import sys
     37 import tempfile
     38 import webkitpy.thirdparty.unittest2 as unittest
     39 
     40 from webkitpy.common.system.filesystem import FileSystem
     41 
     42 
     43 class GenericFileSystemTests(object):
     44     """Tests that should pass on either a real or mock filesystem."""
     45     # pylint gets confused about this being a mixin: pylint: disable=E1101
     46     def setup_generic_test_dir(self):
     47         fs = self.fs
     48         self.generic_test_dir = str(self.fs.mkdtemp())
     49         self.orig_cwd = fs.getcwd()
     50         fs.chdir(self.generic_test_dir)
     51         fs.write_text_file('foo.txt', 'foo')
     52         fs.write_text_file('foobar', 'foobar')
     53         fs.maybe_make_directory('foodir')
     54         fs.write_text_file(fs.join('foodir', 'baz'), 'baz')
     55         fs.chdir(self.orig_cwd)
     56 
     57     def teardown_generic_test_dir(self):
     58         self.fs.rmtree(self.generic_test_dir)
     59         self.fs.chdir(self.orig_cwd)
     60         self.generic_test_dir = None
     61 
     62     def test_glob__trailing_asterisk(self):
     63         self.fs.chdir(self.generic_test_dir)
     64         self.assertEqual(set(self.fs.glob('fo*')), set(['foo.txt', 'foobar', 'foodir']))
     65 
     66     def test_glob__leading_asterisk(self):
     67         self.fs.chdir(self.generic_test_dir)
     68         self.assertEqual(set(self.fs.glob('*xt')), set(['foo.txt']))
     69 
     70     def test_glob__middle_asterisk(self):
     71         self.fs.chdir(self.generic_test_dir)
     72         self.assertEqual(set(self.fs.glob('f*r')), set(['foobar', 'foodir']))
     73 
     74     def test_glob__period_is_escaped(self):
     75         self.fs.chdir(self.generic_test_dir)
     76         self.assertEqual(set(self.fs.glob('foo.*')), set(['foo.txt']))
     77 
     78     def test_relpath_unix(self):
     79         if sys.platform == 'win32':
     80             return
     81         self.assertEqual(self.fs.relpath('aaa/bbb'), 'aaa/bbb')
     82         self.assertEqual(self.fs.relpath('aaa/bbb/'), 'aaa/bbb')
     83         self.assertEqual(self.fs.relpath('aaa/bbb/.'), 'aaa/bbb')
     84         self.assertEqual(self.fs.relpath('aaa/./bbb'), 'aaa/bbb')
     85         self.assertEqual(self.fs.relpath('aaa/../bbb/'), 'bbb')
     86         self.assertEqual(self.fs.relpath('aaa/bbb', 'aaa/bbb'), '.')
     87         self.assertEqual(self.fs.relpath('aaa/bbb/ccc', 'aaa/bbb'), 'ccc')
     88         self.assertEqual(self.fs.relpath('aaa/./ccc', 'aaa/bbb'), '../ccc')
     89         self.assertEqual(self.fs.relpath('aaa/../ccc', 'aaa/bbb'), '../../ccc')
     90         self.assertEqual(self.fs.relpath('aaa/bbb', 'aaa/ccc'), '../bbb')
     91         self.assertEqual(self.fs.relpath('aaa/bbb', 'ccc/ddd'), '../../aaa/bbb')
     92         self.assertEqual(self.fs.relpath('aaa/bbb', 'aaa/b'), '../bbb')
     93         self.assertEqual(self.fs.relpath('aaa/bbb', 'a/bbb'), '../../aaa/bbb')
     94 
     95     def test_relpath_win32(self):
     96         if sys.platform != 'win32':
     97             return
     98         self.assertEqual(self.fs.relpath('aaa\\bbb'), 'aaa\\bbb')
     99         self.assertEqual(self.fs.relpath('aaa\\bbb\\'), 'aaa\\bbb')
    100         self.assertEqual(self.fs.relpath('aaa\\bbb\\.'), 'aaa\\bbb')
    101         self.assertEqual(self.fs.relpath('aaa\\.\\bbb'), 'aaa\\bbb')
    102         self.assertEqual(self.fs.relpath('aaa\\..\\bbb\\'), 'bbb')
    103         self.assertEqual(self.fs.relpath('aaa\\bbb', 'aaa\\bbb'), '.')
    104         self.assertEqual(self.fs.relpath('aaa\\bbb\\ccc', 'aaa\\bbb'), 'ccc')
    105         self.assertEqual(self.fs.relpath('aaa\\.\\ccc', 'aaa\\bbb'), '..\\ccc')
    106         self.assertEqual(self.fs.relpath('aaa\\..\\ccc', 'aaa\\bbb'), '..\\..\\ccc')
    107         self.assertEqual(self.fs.relpath('aaa\\bbb', 'aaa\\ccc'), '..\\bbb')
    108         self.assertEqual(self.fs.relpath('aaa\\bbb', 'ccc\\ddd'), '..\\..\\aaa\\bbb')
    109         self.assertEqual(self.fs.relpath('aaa\\bbb', 'aaa\\b'), '..\\bbb')
    110         self.assertEqual(self.fs.relpath('aaa\\bbb', 'a\\bbb'), '..\\..\\aaa\\bbb')
    111 
    112     def test_rmtree(self):
    113         self.fs.chdir(self.generic_test_dir)
    114         self.fs.rmtree('foo')
    115         self.assertTrue(self.fs.exists('foodir'))
    116         self.assertTrue(self.fs.exists(self.fs.join('foodir', 'baz')))
    117         self.fs.rmtree('foodir')
    118         self.assertFalse(self.fs.exists('foodir'))
    119         self.assertFalse(self.fs.exists(self.fs.join('foodir', 'baz')))
    120 
    121 
    122 class RealFileSystemTest(unittest.TestCase, GenericFileSystemTests):
    123     def setUp(self):
    124         self.fs = FileSystem()
    125         self.setup_generic_test_dir()
    126 
    127         self._this_dir = os.path.dirname(os.path.abspath(__file__))
    128         self._missing_file = os.path.join(self._this_dir, 'missing_file.py')
    129         self._this_file = os.path.join(self._this_dir, 'filesystem_unittest.py')
    130 
    131     def tearDown(self):
    132         self.teardown_generic_test_dir()
    133         self.fs = None
    134 
    135     def test_chdir(self):
    136         fs = FileSystem()
    137         cwd = fs.getcwd()
    138         newdir = '/'
    139         if sys.platform == 'win32':
    140             newdir = 'c:\\'
    141         fs.chdir(newdir)
    142         self.assertEqual(fs.getcwd(), newdir)
    143         fs.chdir(cwd)
    144 
    145     def test_chdir__notexists(self):
    146         fs = FileSystem()
    147         newdir = '/dirdoesnotexist'
    148         if sys.platform == 'win32':
    149             newdir = 'c:\\dirdoesnotexist'
    150         self.assertRaises(OSError, fs.chdir, newdir)
    151 
    152     def test_exists__true(self):
    153         fs = FileSystem()
    154         self.assertTrue(fs.exists(self._this_file))
    155 
    156     def test_exists__false(self):
    157         fs = FileSystem()
    158         self.assertFalse(fs.exists(self._missing_file))
    159 
    160     def test_getcwd(self):
    161         fs = FileSystem()
    162         self.assertTrue(fs.exists(fs.getcwd()))
    163 
    164     def test_isdir__true(self):
    165         fs = FileSystem()
    166         self.assertTrue(fs.isdir(self._this_dir))
    167 
    168     def test_isdir__false(self):
    169         fs = FileSystem()
    170         self.assertFalse(fs.isdir(self._this_file))
    171 
    172     def test_join(self):
    173         fs = FileSystem()
    174         self.assertEqual(fs.join('foo', 'bar'),
    175                          os.path.join('foo', 'bar'))
    176 
    177     def test_listdir(self):
    178         fs = FileSystem()
    179         with fs.mkdtemp(prefix='filesystem_unittest_') as d:
    180             self.assertEqual(fs.listdir(d), [])
    181             new_file = os.path.join(d, 'foo')
    182             fs.write_text_file(new_file, u'foo')
    183             self.assertEqual(fs.listdir(d), ['foo'])
    184             os.remove(new_file)
    185 
    186     def test_maybe_make_directory__success(self):
    187         fs = FileSystem()
    188 
    189         with fs.mkdtemp(prefix='filesystem_unittest_') as base_path:
    190             sub_path = os.path.join(base_path, "newdir")
    191             self.assertFalse(os.path.exists(sub_path))
    192             self.assertFalse(fs.isdir(sub_path))
    193 
    194             fs.maybe_make_directory(sub_path)
    195             self.assertTrue(os.path.exists(sub_path))
    196             self.assertTrue(fs.isdir(sub_path))
    197 
    198             # Make sure we can re-create it.
    199             fs.maybe_make_directory(sub_path)
    200             self.assertTrue(os.path.exists(sub_path))
    201             self.assertTrue(fs.isdir(sub_path))
    202 
    203             # Clean up.
    204             os.rmdir(sub_path)
    205 
    206         self.assertFalse(os.path.exists(base_path))
    207         self.assertFalse(fs.isdir(base_path))
    208 
    209     def test_maybe_make_directory__failure(self):
    210         # FIXME: os.chmod() doesn't work on Windows to set directories
    211         # as readonly, so we skip this test for now.
    212         if sys.platform in ('win32', 'cygwin'):
    213             return
    214 
    215         fs = FileSystem()
    216         with fs.mkdtemp(prefix='filesystem_unittest_') as d:
    217             # Remove write permissions on the parent directory.
    218             os.chmod(d, stat.S_IRUSR)
    219 
    220             # Now try to create a sub directory - should fail.
    221             sub_dir = fs.join(d, 'subdir')
    222             self.assertRaises(OSError, fs.maybe_make_directory, sub_dir)
    223 
    224             # Clean up in case the test failed and we did create the
    225             # directory.
    226             if os.path.exists(sub_dir):
    227                 os.rmdir(sub_dir)
    228 
    229     def test_read_and_write_text_file(self):
    230         fs = FileSystem()
    231         text_path = None
    232 
    233         unicode_text_string = u'\u016An\u012Dc\u014Dde\u033D'
    234         hex_equivalent = '\xC5\xAA\x6E\xC4\xAD\x63\xC5\x8D\x64\x65\xCC\xBD'
    235         try:
    236             text_path = tempfile.mktemp(prefix='tree_unittest_')
    237             file = fs.open_text_file_for_writing(text_path)
    238             file.write(unicode_text_string)
    239             file.close()
    240 
    241             file = fs.open_text_file_for_reading(text_path)
    242             read_text = file.read()
    243             file.close()
    244 
    245             self.assertEqual(read_text, unicode_text_string)
    246         finally:
    247             if text_path and fs.isfile(text_path):
    248                 os.remove(text_path)
    249 
    250     def test_read_and_write_file(self):
    251         fs = FileSystem()
    252         text_path = None
    253         binary_path = None
    254 
    255         unicode_text_string = u'\u016An\u012Dc\u014Dde\u033D'
    256         hex_equivalent = '\xC5\xAA\x6E\xC4\xAD\x63\xC5\x8D\x64\x65\xCC\xBD'
    257         try:
    258             text_path = tempfile.mktemp(prefix='tree_unittest_')
    259             binary_path = tempfile.mktemp(prefix='tree_unittest_')
    260             fs.write_text_file(text_path, unicode_text_string)
    261             contents = fs.read_binary_file(text_path)
    262             self.assertEqual(contents, hex_equivalent)
    263 
    264             fs.write_binary_file(binary_path, hex_equivalent)
    265             text_contents = fs.read_text_file(binary_path)
    266             self.assertEqual(text_contents, unicode_text_string)
    267         finally:
    268             if text_path and fs.isfile(text_path):
    269                 os.remove(text_path)
    270             if binary_path and fs.isfile(binary_path):
    271                 os.remove(binary_path)
    272 
    273     def test_read_binary_file__missing(self):
    274         fs = FileSystem()
    275         self.assertRaises(IOError, fs.read_binary_file, self._missing_file)
    276 
    277     def test_read_text_file__missing(self):
    278         fs = FileSystem()
    279         self.assertRaises(IOError, fs.read_text_file, self._missing_file)
    280 
    281     def test_remove_file_with_retry(self):
    282         RealFileSystemTest._remove_failures = 2
    283 
    284         def remove_with_exception(filename):
    285             RealFileSystemTest._remove_failures -= 1
    286             if RealFileSystemTest._remove_failures >= 0:
    287                 try:
    288                     raise WindowsError
    289                 except NameError:
    290                     raise FileSystem._WindowsError
    291 
    292         fs = FileSystem()
    293         self.assertTrue(fs.remove('filename', remove_with_exception))
    294         self.assertEqual(-1, RealFileSystemTest._remove_failures)
    295 
    296     def test_sep(self):
    297         fs = FileSystem()
    298 
    299         self.assertEqual(fs.sep, os.sep)
    300         self.assertEqual(fs.join("foo", "bar"),
    301                           os.path.join("foo", "bar"))
    302