##// END OF EJS Templates
vfs: use 'vfs' module directly in 'test-filecache'...
Pierre-Yves David -
r31251:34d57dda default
parent child Browse files
Show More
@@ -1,247 +1,248 b''
1 1 from __future__ import absolute_import, print_function
2 2 import os
3 3 import subprocess
4 4 import sys
5 5
6 6 if subprocess.call(['python', '%s/hghave' % os.environ['TESTDIR'],
7 7 'cacheable']):
8 8 sys.exit(80)
9 9
10 10 from mercurial import (
11 11 extensions,
12 12 hg,
13 13 scmutil,
14 14 ui as uimod,
15 15 util,
16 vfs as vfsmod,
16 17 )
17 18
18 19 filecache = scmutil.filecache
19 20
20 21 class fakerepo(object):
21 22 def __init__(self):
22 23 self._filecache = {}
23 24
24 25 def join(self, p):
25 26 return p
26 27
27 28 def sjoin(self, p):
28 29 return p
29 30
30 31 @filecache('x', 'y')
31 32 def cached(self):
32 33 print('creating')
33 34 return 'string from function'
34 35
35 36 def invalidate(self):
36 37 for k in self._filecache:
37 38 try:
38 39 delattr(self, k)
39 40 except AttributeError:
40 41 pass
41 42
42 43 def basic(repo):
43 44 print("* neither file exists")
44 45 # calls function
45 46 repo.cached
46 47
47 48 repo.invalidate()
48 49 print("* neither file still exists")
49 50 # uses cache
50 51 repo.cached
51 52
52 53 # create empty file
53 54 f = open('x', 'w')
54 55 f.close()
55 56 repo.invalidate()
56 57 print("* empty file x created")
57 58 # should recreate the object
58 59 repo.cached
59 60
60 61 f = open('x', 'w')
61 62 f.write('a')
62 63 f.close()
63 64 repo.invalidate()
64 65 print("* file x changed size")
65 66 # should recreate the object
66 67 repo.cached
67 68
68 69 repo.invalidate()
69 70 print("* nothing changed with either file")
70 71 # stats file again, reuses object
71 72 repo.cached
72 73
73 74 # atomic replace file, size doesn't change
74 75 # hopefully st_mtime doesn't change as well so this doesn't use the cache
75 76 # because of inode change
76 f = scmutil.vfs('.')('x', 'w', atomictemp=True)
77 f = vfsmod.vfs('.')('x', 'w', atomictemp=True)
77 78 f.write('b')
78 79 f.close()
79 80
80 81 repo.invalidate()
81 82 print("* file x changed inode")
82 83 repo.cached
83 84
84 85 # create empty file y
85 86 f = open('y', 'w')
86 87 f.close()
87 88 repo.invalidate()
88 89 print("* empty file y created")
89 90 # should recreate the object
90 91 repo.cached
91 92
92 93 f = open('y', 'w')
93 94 f.write('A')
94 95 f.close()
95 96 repo.invalidate()
96 97 print("* file y changed size")
97 98 # should recreate the object
98 99 repo.cached
99 100
100 f = scmutil.vfs('.')('y', 'w', atomictemp=True)
101 f = vfsmod.vfs('.')('y', 'w', atomictemp=True)
101 102 f.write('B')
102 103 f.close()
103 104
104 105 repo.invalidate()
105 106 print("* file y changed inode")
106 107 repo.cached
107 108
108 f = scmutil.vfs('.')('x', 'w', atomictemp=True)
109 f = vfsmod.vfs('.')('x', 'w', atomictemp=True)
109 110 f.write('c')
110 111 f.close()
111 f = scmutil.vfs('.')('y', 'w', atomictemp=True)
112 f = vfsmod.vfs('.')('y', 'w', atomictemp=True)
112 113 f.write('C')
113 114 f.close()
114 115
115 116 repo.invalidate()
116 117 print("* both files changed inode")
117 118 repo.cached
118 119
119 120 def fakeuncacheable():
120 121 def wrapcacheable(orig, *args, **kwargs):
121 122 return False
122 123
123 124 def wrapinit(orig, *args, **kwargs):
124 125 pass
125 126
126 127 originit = extensions.wrapfunction(util.cachestat, '__init__', wrapinit)
127 128 origcacheable = extensions.wrapfunction(util.cachestat, 'cacheable',
128 129 wrapcacheable)
129 130
130 131 for fn in ['x', 'y']:
131 132 try:
132 133 os.remove(fn)
133 134 except OSError:
134 135 pass
135 136
136 137 basic(fakerepo())
137 138
138 139 util.cachestat.cacheable = origcacheable
139 140 util.cachestat.__init__ = originit
140 141
141 142 def test_filecache_synced():
142 143 # test old behavior that caused filecached properties to go out of sync
143 144 os.system('hg init && echo a >> a && hg ci -qAm.')
144 145 repo = hg.repository(uimod.ui.load())
145 146 # first rollback clears the filecache, but changelog to stays in __dict__
146 147 repo.rollback()
147 148 repo.commit('.')
148 149 # second rollback comes along and touches the changelog externally
149 150 # (file is moved)
150 151 repo.rollback()
151 152 # but since changelog isn't under the filecache control anymore, we don't
152 153 # see that it changed, and return the old changelog without reconstructing
153 154 # it
154 155 repo.commit('.')
155 156
156 157 def setbeforeget(repo):
157 158 os.remove('x')
158 159 os.remove('y')
159 160 repo.cached = 'string set externally'
160 161 repo.invalidate()
161 162 print("* neither file exists")
162 163 print(repo.cached)
163 164 repo.invalidate()
164 165 f = open('x', 'w')
165 166 f.write('a')
166 167 f.close()
167 168 print("* file x created")
168 169 print(repo.cached)
169 170
170 171 repo.cached = 'string 2 set externally'
171 172 repo.invalidate()
172 173 print("* string set externally again")
173 174 print(repo.cached)
174 175
175 176 repo.invalidate()
176 177 f = open('y', 'w')
177 178 f.write('b')
178 179 f.close()
179 180 print("* file y created")
180 181 print(repo.cached)
181 182
182 183 def antiambiguity():
183 184 filename = 'ambigcheck'
184 185
185 186 # try some times, because reproduction of ambiguity depends on
186 187 # "filesystem time"
187 188 for i in xrange(5):
188 189 fp = open(filename, 'w')
189 190 fp.write('FOO')
190 191 fp.close()
191 192
192 193 oldstat = os.stat(filename)
193 194 if oldstat.st_ctime != oldstat.st_mtime:
194 195 # subsequent changing never causes ambiguity
195 196 continue
196 197
197 198 repetition = 3
198 199
199 200 # repeat changing via checkambigatclosing, to examine whether
200 201 # st_mtime is advanced multiple times as expected
201 202 for i in xrange(repetition):
202 203 # explicit closing
203 fp = scmutil.checkambigatclosing(open(filename, 'a'))
204 fp = vfsmod.checkambigatclosing(open(filename, 'a'))
204 205 fp.write('FOO')
205 206 fp.close()
206 207
207 208 # implicit closing by "with" statement
208 with scmutil.checkambigatclosing(open(filename, 'a')) as fp:
209 with vfsmod.checkambigatclosing(open(filename, 'a')) as fp:
209 210 fp.write('BAR')
210 211
211 212 newstat = os.stat(filename)
212 213 if oldstat.st_ctime != newstat.st_ctime:
213 214 # timestamp ambiguity was naturally avoided while repetition
214 215 continue
215 216
216 217 # st_mtime should be advanced "repetition * 2" times, because
217 218 # all changes occurred at same time (in sec)
218 219 expected = (oldstat.st_mtime + repetition * 2) & 0x7fffffff
219 220 if newstat.st_mtime != expected:
220 221 print("'newstat.st_mtime %s is not %s (as %s + %s * 2)" %
221 222 (newstat.st_mtime, expected, oldstat.st_mtime, repetition))
222 223
223 224 # no more examination is needed regardless of result
224 225 break
225 226 else:
226 227 # This platform seems too slow to examine anti-ambiguity
227 228 # of file timestamp (or test happened to be executed at
228 229 # bad timing). Exit silently in this case, because running
229 230 # on other faster platforms can detect problems
230 231 pass
231 232
232 233 print('basic:')
233 234 print()
234 235 basic(fakerepo())
235 236 print()
236 237 print('fakeuncacheable:')
237 238 print()
238 239 fakeuncacheable()
239 240 test_filecache_synced()
240 241 print()
241 242 print('setbeforeget:')
242 243 print()
243 244 setbeforeget(fakerepo())
244 245 print()
245 246 print('antiambiguity:')
246 247 print()
247 248 antiambiguity()
General Comments 0
You need to be logged in to leave comments. Login now