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