Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: chrome/common/extensions/docs/server2/mock_file_system.py

Issue 151883009: Docserver: Make MockFileSystem not iterate over the entire file system as part (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # Copyright 2013 The Chromium Authors. All rights reserved. 1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import posixpath
6
5 from file_system import FileSystem, FileNotFoundError 7 from file_system import FileSystem, FileNotFoundError
6 from future import Gettable, Future 8 from future import Gettable, Future
7 from test_file_system import TestFileSystem 9 from test_file_system import _List, _StatTracker, TestFileSystem
10
8 11
9 class MockFileSystem(FileSystem): 12 class MockFileSystem(FileSystem):
10 '''Wraps FileSystems to add a selection of mock behaviour: 13 '''Wraps FileSystems to add a selection of mock behaviour:
11
12 - asserting how often Stat/Read calls are being made to it. 14 - asserting how often Stat/Read calls are being made to it.
13 - primitive changes/versioning via applying object "diffs", mapping paths to 15 - primitive changes/versioning via applying object "diffs", mapping paths to
14 new content (similar to how TestFileSystem works). 16 new content (similar to how TestFileSystem works).
15 ''' 17 '''
16 def __init__(self, file_system): 18 def __init__(self, file_system):
17 self._file_system = file_system 19 self._file_system = file_system
18 # Updates are modelled are stored as TestFileSystems because they've 20 # Updates are stored as TestFileSystems because it already implements a
19 # implemented a bunch of logic to interpret paths into dictionaries. 21 # bunch of logic to intepret paths into dictionaries.
20 self._updates = [] 22 self._updates = []
23 self._stat_tracker = _StatTracker()
21 self._read_count = 0 24 self._read_count = 0
22 self._read_resolve_count = 0 25 self._read_resolve_count = 0
23 self._stat_count = 0 26 self._stat_count = 0
24 27
25 @staticmethod 28 @staticmethod
26 def Create(file_system, updates): 29 def Create(file_system, updates):
27 mock_file_system = MockFileSystem(file_system) 30 mock_file_system = MockFileSystem(file_system)
28 for update in updates: 31 for update in updates:
29 mock_file_system.Update(update) 32 mock_file_system.Update(update)
30 return mock_file_system 33 return mock_file_system
31 34
32 # 35 #
33 # FileSystem implementation. 36 # FileSystem implementation.
34 # 37 #
35 38
36 def Read(self, paths): 39 def Read(self, paths):
37 '''Reads |paths| from |_file_system|, then applies the most recent update 40 '''Reads |paths| from |_file_system|, then applies the most recent update
38 from |_updates|, if any. 41 from |_updates|, if any.
39 ''' 42 '''
40 self._read_count += 1 43 self._read_count += 1
41 future_result = self._file_system.Read(paths) 44 future_result = self._file_system.Read(paths)
42 def resolve(): 45 def resolve():
43 self._read_resolve_count += 1 46 self._read_resolve_count += 1
44 result = future_result.Get() 47 result = future_result.Get()
45 for path in result.iterkeys(): 48 for path in result.iterkeys():
46 _, update = self._GetMostRecentUpdate(path) 49 update = self._GetMostRecentUpdate(path)
47 if update is not None: 50 if update is not None:
48 result[path] = update 51 result[path] = update
49 return result 52 return result
50 return Future(delegate=Gettable(resolve)) 53 return Future(delegate=Gettable(resolve))
51 54
52 def Refresh(self): 55 def Refresh(self):
53 return self._file_system.Refresh() 56 return self._file_system.Refresh()
54 57
55 def _GetMostRecentUpdate(self, path): 58 def _GetMostRecentUpdate(self, path):
56 for revision, update in reversed(list(enumerate(self._updates))): 59 '''Returns the latest update for the file at |path|, or None if |path|
60 has never been updated.
61 '''
62 for update in reversed(self._updates):
57 try: 63 try:
58 return (revision + 1, update.ReadSingle(path).Get()) 64 return update.ReadSingle(path).Get()
59 except FileNotFoundError: 65 except FileNotFoundError:
60 pass 66 pass
61 return (0, None) 67 return None
62 68
63 def Stat(self, path): 69 def Stat(self, path):
64 self._stat_count += 1 70 self._stat_count += 1
65 return self._StatImpl(path)
66 71
67 def _StatImpl(self, path): 72 # This only supports numeric stat values since we need to add to it. In
68 result = self._file_system.Stat(path) 73 # reality the logic here could just be to randomly mutate the stat values
69 result.version = self._UpdateStat(result.version, path) 74 # every time there's an Update but that's less meaningful for testing.
70 child_versions = result.child_versions 75 def stradd(a, b):
71 if child_versions is not None: 76 return str(int(a) + b)
72 for child_path in child_versions.iterkeys():
73 child_versions[child_path] = self._UpdateStat(
74 child_versions[child_path],
75 '%s%s' % (path, child_path))
76 return result
77 77
78 def _UpdateStat(self, version, path): 78 stat = self._file_system.Stat(path)
79 if not path.endswith('/'): 79 stat.version = stradd(stat.version, self._stat_tracker.GetVersion(path))
80 return str(int(version) + self._GetMostRecentUpdate(path)[0]) 80 if stat.child_versions:
81 # Bleh, it's a directory, need to recursively search all the children. 81 for child_path, child_version in stat.child_versions.iteritems():
82 child_paths = self._file_system.ReadSingle(path).Get() 82 stat.child_versions[child_path] = stradd(
83 if not child_paths: 83 stat.child_versions[child_path],
84 return version 84 self._stat_tracker.GetVersion(posixpath.join(path, child_path)))
85 return str(max([int(version)] + 85
86 [int(self._StatImpl('%s%s' % (path, child_path)).version) 86 return stat
87 for child_path in child_paths]))
88 87
89 def GetIdentity(self): 88 def GetIdentity(self):
90 return self._file_system.GetIdentity() 89 return self._file_system.GetIdentity()
91 90
92 def __str__(self): 91 def __str__(self):
93 return repr(self) 92 return repr(self)
94 93
95 def __repr__(self): 94 def __repr__(self):
96 return 'MockFileSystem(read_count=%s, stat_count=%s, updates=%s)' % ( 95 return 'MockFileSystem(read_count=%s, stat_count=%s, updates=%s)' % (
97 self._read_count, self._stat_count, len(self._updates)) 96 self._read_count, self._stat_count, len(self._updates))
(...skipping 21 matching lines...) Expand all
119 finally: 118 finally:
120 self.Reset() 119 self.Reset()
121 120
122 def Reset(self): 121 def Reset(self):
123 self._read_count = 0 122 self._read_count = 0
124 self._read_resolve_count = 0 123 self._read_resolve_count = 0
125 self._stat_count = 0 124 self._stat_count = 0
126 125
127 def Update(self, update): 126 def Update(self, update):
128 self._updates.append(TestFileSystem(update)) 127 self._updates.append(TestFileSystem(update))
128 for path in _List(update).iterkeys():
129 # Any files (not directories) which changed are now at the version
130 # derived from |_updates|.
131 if path != '' and not path.endswith('/'):
132 self._stat_tracker.SetVersion(path, len(self._updates))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698