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