Home | History | Annotate | Download | only in server2
      1 #!/usr/bin/env python
      2 # Copyright 2013 The Chromium Authors. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 import functools
      7 import os
      8 
      9 from compiled_file_system import Cache, CompiledFileSystem
     10 from copy import deepcopy
     11 from environment import GetAppVersion
     12 from file_system import FileNotFoundError
     13 from mock_file_system import MockFileSystem
     14 from object_store_creator import ObjectStoreCreator
     15 from test_file_system import TestFileSystem
     16 from test_object_store import TestObjectStore
     17 import unittest
     18 
     19 _TEST_DATA = {
     20   '404.html': '404.html contents',
     21   'apps': {
     22     'a11y.html': 'a11y.html contents',
     23     'about_apps.html': 'about_apps.html contents',
     24     'fakedir': {
     25       'file.html': 'file.html contents'
     26     },
     27     'deepdir': {
     28       'deepfile.html': 'deepfile.html contents',
     29       'deeper': {
     30         'deepest.html': 'deepest.html contents',
     31       },
     32     }
     33   },
     34   'extensions': {
     35     'activeTab.html': 'activeTab.html contents',
     36     'alarms.html': 'alarms.html contents'
     37   }
     38 }
     39 
     40 identity = lambda _, x: x
     41 
     42 def _GetTestCompiledFsCreator():
     43   '''Returns a function which creates CompiledFileSystem views of
     44   TestFileSystems backed by _TEST_DATA.
     45   '''
     46   return functools.partial(
     47       CompiledFileSystem.Factory(
     48           ObjectStoreCreator(start_empty=False,
     49                              store_type=TestObjectStore,
     50                              disable_wrappers=True),
     51       ).Create,
     52       TestFileSystem(deepcopy(_TEST_DATA)))
     53 
     54 class CompiledFileSystemTest(unittest.TestCase):
     55   def testPopulateNamespace(self):
     56     def CheckNamespace(expected_file, expected_list, fs):
     57       self.assertEqual(expected_file, fs._file_object_store.namespace)
     58       self.assertEqual(expected_list, fs._list_object_store.namespace)
     59     compiled_fs_creator = _GetTestCompiledFsCreator()
     60     f = lambda x: x
     61     CheckNamespace(
     62         'class=CompiledFileSystem&'
     63             'category=CompiledFileSystemTest/TestFileSystem/file&'
     64             'app_version=%s' % GetAppVersion(),
     65         'class=CompiledFileSystem&'
     66             'category=CompiledFileSystemTest/TestFileSystem/list&'
     67             'app_version=%s' % GetAppVersion(),
     68         compiled_fs_creator(f, CompiledFileSystemTest))
     69     CheckNamespace(
     70         'class=CompiledFileSystem&'
     71             'category=CompiledFileSystemTest/TestFileSystem/foo/file&'
     72             'app_version=%s' % GetAppVersion(),
     73         'class=CompiledFileSystem&'
     74             'category=CompiledFileSystemTest/TestFileSystem/foo/list&'
     75             'app_version=%s' % GetAppVersion(),
     76         compiled_fs_creator(f, CompiledFileSystemTest, category='foo'))
     77 
     78   def testPopulateFromFile(self):
     79     def Sleepy(key, val):
     80       return '%s%s' % ('Z' * len(key), 'z' * len(val))
     81     compiled_fs = _GetTestCompiledFsCreator()(Sleepy, CompiledFileSystemTest)
     82     self.assertEqual('ZZZZZZZZzzzzzzzzzzzzzzzzz',
     83                      compiled_fs.GetFromFile('404.html').Get())
     84     self.assertEqual('ZZZZZZZZZZZZZZzzzzzzzzzzzzzzzzzz',
     85                      compiled_fs.GetFromFile('apps/a11y.html').Get())
     86     self.assertEqual('ZZZZZZZZZZZZZZZZZZZZZZzzzzzzzzzzzzzzzzzz',
     87                      compiled_fs.GetFromFile('apps/fakedir/file.html').Get())
     88 
     89   def testPopulateFromFileListing(self):
     90     def strip_ext(_, files):
     91       return [os.path.splitext(f)[0] for f in files]
     92     compiled_fs = _GetTestCompiledFsCreator()(strip_ext, CompiledFileSystemTest)
     93     expected_top_listing = [
     94       '404',
     95       'apps/a11y',
     96       'apps/about_apps',
     97       'apps/deepdir/deeper/deepest',
     98       'apps/deepdir/deepfile',
     99       'apps/fakedir/file',
    100       'extensions/activeTab',
    101       'extensions/alarms'
    102     ]
    103     self.assertEqual(expected_top_listing,
    104                      sorted(compiled_fs.GetFromFileListing('').Get()))
    105     expected_apps_listing = [
    106       'a11y',
    107       'about_apps',
    108       'deepdir/deeper/deepest',
    109       'deepdir/deepfile',
    110       'fakedir/file',
    111     ]
    112     self.assertEqual(expected_apps_listing,
    113                      sorted(compiled_fs.GetFromFileListing('apps/').Get()))
    114     self.assertEqual(['file',],
    115                      compiled_fs.GetFromFileListing('apps/fakedir/').Get())
    116     self.assertEqual(['deeper/deepest', 'deepfile'],
    117                      sorted(compiled_fs.GetFromFileListing(
    118                          'apps/deepdir/').Get()))
    119     self.assertEqual(['deepest'],
    120                      compiled_fs.GetFromFileListing(
    121                          'apps/deepdir/deeper/').Get())
    122 
    123   def testCaching(self):
    124     compiled_fs = _GetTestCompiledFsCreator()(Cache(identity),
    125                                               CompiledFileSystemTest)
    126     self.assertEqual('404.html contents',
    127                      compiled_fs.GetFromFile('404.html').Get())
    128     self.assertEqual(set(('file.html',)),
    129                      set(compiled_fs.GetFromFileListing('apps/fakedir/').Get()))
    130 
    131     compiled_fs._file_system._path_values['404.html'] = 'boom'
    132     compiled_fs._file_system._path_values['apps/fakedir/'] = [
    133         'file.html', 'boom.html']
    134     self.assertEqual('404.html contents',
    135                      compiled_fs.GetFromFile('404.html').Get())
    136     self.assertEqual(set(('file.html',)),
    137                      set(compiled_fs.GetFromFileListing('apps/fakedir/').Get()))
    138 
    139     compiled_fs._file_system.IncrementStat()
    140     self.assertEqual('boom', compiled_fs.GetFromFile('404.html').Get())
    141     self.assertEqual(set(('file.html', 'boom.html')),
    142                      set(compiled_fs.GetFromFileListing('apps/fakedir/').Get()))
    143 
    144   def testFailures(self):
    145     compiled_fs = _GetTestCompiledFsCreator()(identity, CompiledFileSystemTest)
    146     self.assertRaises(FileNotFoundError,
    147                       compiled_fs.GetFromFile('405.html').Get)
    148     # TODO(kalman): would be nice to test this fails since apps/ is a dir.
    149     compiled_fs.GetFromFile('apps')
    150     #self.assertRaises(SomeError, compiled_fs.GetFromFile, 'apps/')
    151     self.assertRaises(FileNotFoundError,
    152                       compiled_fs.GetFromFileListing('nodir/').Get)
    153     # TODO(kalman): likewise, not a FileNotFoundError.
    154     self.assertRaises(FileNotFoundError,
    155                       compiled_fs.GetFromFileListing('404.html/').Get)
    156 
    157   def testCorrectFutureBehaviour(self):
    158     # Tests that the underlying FileSystem's Read Future has had Get() called
    159     # on it before the Future is resolved, but the underlying Future isn't
    160     # resolved until Get is.
    161     mock_fs = MockFileSystem(TestFileSystem(_TEST_DATA))
    162     compiled_fs = CompiledFileSystem.Factory(
    163         ObjectStoreCreator.ForTest()).Create(
    164             mock_fs, lambda path, contents: contents, type(self))
    165 
    166     self.assertTrue(*mock_fs.CheckAndReset())
    167     future = compiled_fs.GetFromFile('404.html')
    168     self.assertTrue(*mock_fs.CheckAndReset(stat_count=1, read_count=1))
    169     future.Get()
    170     self.assertTrue(*mock_fs.CheckAndReset(read_resolve_count=1))
    171 
    172     future = compiled_fs.GetFromFileListing('apps/')
    173     # Current behaviour is to have read=2 and read_resolve=1 because the first
    174     # level is read eagerly, then all of the second is read (in parallel). If
    175     # it weren't eager (and it may be worth experimenting with that) then it'd
    176     # be read=1 and read_resolve=0.
    177     self.assertTrue(*mock_fs.CheckAndReset(stat_count=1,
    178                                            read_count=2,
    179                                            read_resolve_count=1))
    180     future.Get()
    181     # It's doing 1 more level 'deeper' (already read 'fakedir' and 'deepdir'
    182     # though not resolved), so that's 1 more read/resolve + the resolve from
    183     # the first read.
    184     self.assertTrue(*mock_fs.CheckAndReset(read_count=1, read_resolve_count=2))
    185 
    186     # Even though the directory is 1 layer deep the caller has no way of
    187     # determining that ahead of time (though perhaps the API could give some
    188     # kind of clue, if we really cared).
    189     future = compiled_fs.GetFromFileListing('extensions/')
    190     self.assertTrue(*mock_fs.CheckAndReset(stat_count=1,
    191                                            read_count=1,
    192                                            read_resolve_count=1))
    193     future.Get()
    194     self.assertTrue(*mock_fs.CheckAndReset())
    195 
    196     # Similar configuration to the 'apps/' case but deeper.
    197     future = compiled_fs.GetFromFileListing('')
    198     self.assertTrue(*mock_fs.CheckAndReset(stat_count=1,
    199                                            read_count=2,
    200                                            read_resolve_count=1))
    201     future.Get()
    202     self.assertTrue(*mock_fs.CheckAndReset(read_count=2, read_resolve_count=3))
    203 
    204   def testSkipNotFound(self):
    205     mock_fs = MockFileSystem(TestFileSystem(_TEST_DATA))
    206     compiled_fs = CompiledFileSystem.Factory(
    207         ObjectStoreCreator.ForTest()).Create(
    208             mock_fs, Cache(lambda path, contents: contents), type(self))
    209 
    210     future = compiled_fs.GetFromFile('no_file', skip_not_found=True)
    211     # If the file doesn't exist, then the file system is not read.
    212     self.assertTrue(*mock_fs.CheckAndReset(read_count=1, stat_count=1))
    213     self.assertEqual(None, future.Get())
    214     self.assertTrue(*mock_fs.CheckAndReset(read_resolve_count=1))
    215     future = compiled_fs.GetFromFile('no_file', skip_not_found=True)
    216     self.assertTrue(*mock_fs.CheckAndReset(stat_count=1))
    217     self.assertEqual(None, future.Get())
    218     # The result for a non-existent file should still be cached.
    219     self.assertTrue(*mock_fs.CheckAndReset())
    220     future = compiled_fs.GetFromFile('no_file')
    221     self.assertRaises(FileNotFoundError, future.Get)
    222 
    223 
    224 if __name__ == '__main__':
    225   unittest.main()
    226