]> arthur.barton.de Git - bup.git/commitdiff
cache_notice: import randrange; use del not pop(); add tests
authorRob Browning <rlb@defaultvalue.org>
Sun, 6 May 2018 15:56:50 +0000 (10:56 -0500)
committerRob Browning <rlb@defaultvalue.org>
Sun, 6 May 2018 15:57:37 +0000 (10:57 -0500)
Signed-off-by: Rob Browning <rlb@defaultvalue.org>
Tested-by: Rob Browning <rlb@defaultvalue.org>
lib/bup/t/tvfs.py
lib/bup/vfs.py

index 0af42fbb784745088d7f6f510888f8914ecf75c1..d8670a71b774f5d35ff0e8eb4f6f24e26c759f7d 100644 (file)
@@ -22,16 +22,50 @@ bup_tmp = os.path.realpath('../../../t/tmp')
 bup_path = top_dir + '/bup'
 start_dir = os.getcwd()
 
+def ex(cmd, **kwargs):
+    print(shstr(cmd), file=stderr)
+    return exc(cmd, **kwargs)
+
+@wvtest
+def test_cache_behavior():
+    orig_max = vfs._cache_max_items
+    try:
+        vfs._cache_max_items = 2
+        vfs.clear_cache()
+        wvpasseq({}, vfs._cache)
+        wvpasseq([], vfs._cache_keys)
+        wvfail(vfs._cache_keys)
+        wvexcept(AssertionError, vfs.cache_notice, 'x', 1)
+        key_0 = b'\0' * 20
+        key_1 = b'\1' * 20
+        key_2 = b'\2' * 20
+        vfs.cache_notice(key_0, 'something')
+        wvpasseq({key_0 : 'something'}, vfs._cache)
+        wvpasseq([key_0], vfs._cache_keys)
+        vfs.cache_notice(key_1, 'something else')
+        wvpasseq({key_0 : 'something', key_1 : 'something else'}, vfs._cache)
+        wvpasseq(frozenset([key_0, key_1]), frozenset(vfs._cache_keys))
+        vfs.cache_notice(key_2, 'and also')
+        wvpasseq(2, len(vfs._cache))
+        wvpass(frozenset(vfs._cache.iteritems())
+               < frozenset({key_0 : 'something',
+                            key_1 : 'something else',
+                            key_2 : 'and also'}.iteritems()))
+        wvpasseq(2, len(vfs._cache_keys))
+        wvpass(frozenset(vfs._cache_keys) < frozenset([key_0, key_1, key_2]))
+        vfs.clear_cache()
+        wvpasseq({}, vfs._cache)
+        wvpasseq([], vfs._cache_keys)
+    finally:
+        vfs._cache_max_items = orig_max
+        vfs.clear_cache()
+
 ## The clear_cache() calls below are to make sure that the test starts
 ## from a known state since at the moment the cache entry for a given
 ## item (like a commit) can change.  For example, its meta value might
 ## be promoted from a mode to a Metadata instance once the tree it
 ## refers to is traversed.
 
-def ex(cmd, **kwargs):
-    print(shstr(cmd), file=stderr)
-    return exc(cmd, **kwargs)
-
 TreeDictValue = namedtuple('TreeDictValue', ('name', 'oid', 'meta'))
 
 def tree_items(repo, oid):
index 14293dc202e8fb50172d8e1f03a9e29ecabcfba8..0ac31a99d103afd0cefa91359819ae24c711ed6a 100644 (file)
@@ -49,6 +49,7 @@ from __future__ import absolute_import, print_function
 from collections import namedtuple
 from errno import ELOOP, ENOENT, ENOTDIR
 from itertools import chain, dropwhile, groupby, izip, tee
+from random import randrange
 from stat import S_IFDIR, S_IFLNK, S_IFREG, S_ISDIR, S_ISLNK, S_ISREG
 from time import localtime, strftime
 import exceptions, re, sys
@@ -273,13 +274,15 @@ def cache_notice(key, value):
     assert is_valid_cache_key(key)
     if key in _cache:
         return
-    _cache[key] = value
     if len(_cache) < _cache_max_items:
+        _cache_keys.append(key)
+        _cache[key] = value
         return
-    victim_i = random.randrange(0, len(_cache_keys))
+    victim_i = randrange(0, len(_cache_keys))
     victim = _cache_keys[victim_i]
+    del _cache[victim]
     _cache_keys[victim_i] = key
-    _cache.pop(victim)
+    _cache[key] = value
 
 
 def cache_get_commit_item(oid, need_meta=True):