tests/test-filecache.py
changeset 43076 2372284d9457
parent 40424 7caf632e30c3
child 45834 e01ea8325859
equal deleted inserted replaced
43075:57875cf423c9 43076:2372284d9457
     2 import os
     2 import os
     3 import stat
     3 import stat
     4 import subprocess
     4 import subprocess
     5 import sys
     5 import sys
     6 
     6 
     7 if subprocess.call(['python', '%s/hghave' % os.environ['TESTDIR'],
     7 if subprocess.call(
     8                     'cacheable']):
     8     ['python', '%s/hghave' % os.environ['TESTDIR'], 'cacheable']
       
     9 ):
     9     sys.exit(80)
    10     sys.exit(80)
    10 
    11 
    11 print_ = print
    12 print_ = print
       
    13 
       
    14 
    12 def print(*args, **kwargs):
    15 def print(*args, **kwargs):
    13     """print() wrapper that flushes stdout buffers to avoid py3 buffer issues
    16     """print() wrapper that flushes stdout buffers to avoid py3 buffer issues
    14 
    17 
    15     We could also just write directly to sys.stdout.buffer the way the
    18     We could also just write directly to sys.stdout.buffer the way the
    16     ui object will, but this was easier for porting the test.
    19     ui object will, but this was easier for porting the test.
    17     """
    20     """
    18     print_(*args, **kwargs)
    21     print_(*args, **kwargs)
    19     sys.stdout.flush()
    22     sys.stdout.flush()
       
    23 
    20 
    24 
    21 from mercurial import (
    25 from mercurial import (
    22     extensions,
    26     extensions,
    23     hg,
    27     hg,
    24     localrepo,
    28     localrepo,
    29 )
    33 )
    30 
    34 
    31 if pycompat.ispy3:
    35 if pycompat.ispy3:
    32     xrange = range
    36     xrange = range
    33 
    37 
       
    38 
    34 class fakerepo(object):
    39 class fakerepo(object):
    35     def __init__(self):
    40     def __init__(self):
    36         self._filecache = {}
    41         self._filecache = {}
    37 
    42 
    38     class fakevfs(object):
    43     class fakevfs(object):
    39 
       
    40         def join(self, p):
    44         def join(self, p):
    41             return p
    45             return p
    42 
    46 
    43     vfs = fakevfs()
    47     vfs = fakevfs()
    44 
    48 
    58             try:
    62             try:
    59                 delattr(self, pycompat.sysstr(k))
    63                 delattr(self, pycompat.sysstr(k))
    60             except AttributeError:
    64             except AttributeError:
    61                 pass
    65                 pass
    62 
    66 
       
    67 
    63 def basic(repo):
    68 def basic(repo):
    64     print("* neither file exists")
    69     print("* neither file exists")
    65     # calls function
    70     # calls function
    66     repo.cached
    71     repo.cached
    67 
    72 
   135 
   140 
   136     repo.invalidate()
   141     repo.invalidate()
   137     print("* both files changed inode")
   142     print("* both files changed inode")
   138     repo.cached
   143     repo.cached
   139 
   144 
       
   145 
   140 def fakeuncacheable():
   146 def fakeuncacheable():
   141     def wrapcacheable(orig, *args, **kwargs):
   147     def wrapcacheable(orig, *args, **kwargs):
   142         return False
   148         return False
   143 
   149 
   144     def wrapinit(orig, *args, **kwargs):
   150     def wrapinit(orig, *args, **kwargs):
   145         pass
   151         pass
   146 
   152 
   147     originit = extensions.wrapfunction(util.cachestat, '__init__', wrapinit)
   153     originit = extensions.wrapfunction(util.cachestat, '__init__', wrapinit)
   148     origcacheable = extensions.wrapfunction(util.cachestat, 'cacheable',
   154     origcacheable = extensions.wrapfunction(
   149                                             wrapcacheable)
   155         util.cachestat, 'cacheable', wrapcacheable
       
   156     )
   150 
   157 
   151     for fn in ['x', 'y']:
   158     for fn in ['x', 'y']:
   152         try:
   159         try:
   153             os.remove(fn)
   160             os.remove(fn)
   154         except OSError:
   161         except OSError:
   156 
   163 
   157     basic(fakerepo())
   164     basic(fakerepo())
   158 
   165 
   159     util.cachestat.cacheable = origcacheable
   166     util.cachestat.cacheable = origcacheable
   160     util.cachestat.__init__ = originit
   167     util.cachestat.__init__ = originit
       
   168 
   161 
   169 
   162 def test_filecache_synced():
   170 def test_filecache_synced():
   163     # test old behavior that caused filecached properties to go out of sync
   171     # test old behavior that caused filecached properties to go out of sync
   164     os.system('hg init && echo a >> a && hg ci -qAm.')
   172     os.system('hg init && echo a >> a && hg ci -qAm.')
   165     repo = hg.repository(uimod.ui.load())
   173     repo = hg.repository(uimod.ui.load())
   172     # but since changelog isn't under the filecache control anymore, we don't
   180     # but since changelog isn't under the filecache control anymore, we don't
   173     # see that it changed, and return the old changelog without reconstructing
   181     # see that it changed, and return the old changelog without reconstructing
   174     # it
   182     # it
   175     repo.commit(b'.')
   183     repo.commit(b'.')
   176 
   184 
       
   185 
   177 def setbeforeget(repo):
   186 def setbeforeget(repo):
   178     os.remove('x')
   187     os.remove('x')
   179     os.remove('y')
   188     os.remove('y')
   180     repo.__class__.cached.set(repo, 'string set externally')
   189     repo.__class__.cached.set(repo, 'string set externally')
   181     repo.invalidate()
   190     repo.invalidate()
   197     f = open('y', 'w')
   206     f = open('y', 'w')
   198     f.write('b')
   207     f.write('b')
   199     f.close()
   208     f.close()
   200     print("* file y created")
   209     print("* file y created")
   201     print(repo.cached)
   210     print(repo.cached)
       
   211 
   202 
   212 
   203 def antiambiguity():
   213 def antiambiguity():
   204     filename = 'ambigcheck'
   214     filename = 'ambigcheck'
   205 
   215 
   206     # try some times, because reproduction of ambiguity depends on
   216     # try some times, because reproduction of ambiguity depends on
   234             # timestamp ambiguity was naturally avoided while repetition
   244             # timestamp ambiguity was naturally avoided while repetition
   235             continue
   245             continue
   236 
   246 
   237         # st_mtime should be advanced "repetition * 2" times, because
   247         # st_mtime should be advanced "repetition * 2" times, because
   238         # all changes occurred at same time (in sec)
   248         # all changes occurred at same time (in sec)
   239         expected = (oldstat[stat.ST_MTIME] + repetition * 2) & 0x7fffffff
   249         expected = (oldstat[stat.ST_MTIME] + repetition * 2) & 0x7FFFFFFF
   240         if newstat[stat.ST_MTIME] != expected:
   250         if newstat[stat.ST_MTIME] != expected:
   241             print("'newstat[stat.ST_MTIME] %s is not %s (as %s + %s * 2)" %
   251             print(
   242                   (newstat[stat.ST_MTIME], expected,
   252                 "'newstat[stat.ST_MTIME] %s is not %s (as %s + %s * 2)"
   243                    oldstat[stat.ST_MTIME], repetition))
   253                 % (
       
   254                     newstat[stat.ST_MTIME],
       
   255                     expected,
       
   256                     oldstat[stat.ST_MTIME],
       
   257                     repetition,
       
   258                 )
       
   259             )
   244 
   260 
   245         # no more examination is needed regardless of result
   261         # no more examination is needed regardless of result
   246         break
   262         break
   247     else:
   263     else:
   248         # This platform seems too slow to examine anti-ambiguity
   264         # This platform seems too slow to examine anti-ambiguity
   249         # of file timestamp (or test happened to be executed at
   265         # of file timestamp (or test happened to be executed at
   250         # bad timing). Exit silently in this case, because running
   266         # bad timing). Exit silently in this case, because running
   251         # on other faster platforms can detect problems
   267         # on other faster platforms can detect problems
   252         pass
   268         pass
   253 
   269 
       
   270 
   254 print('basic:')
   271 print('basic:')
   255 print()
   272 print()
   256 basic(fakerepo())
   273 basic(fakerepo())
   257 print()
   274 print()
   258 print('fakeuncacheable:')
   275 print('fakeuncacheable:')