[PATCH 4 of 7] revlog: add test to check raw processing is sane

Jun Wu quark at fb.com
Tue Mar 28 03:49:05 EDT 2017


# HG changeset patch
# User Jun Wu <quark at fb.com>
# Date 1490677106 25200
#      Mon Mar 27 21:58:26 2017 -0700
# Node ID a9d87712bec99abe109c155948ee4b7f1f5ec208
# Parent  d557aaee6ada70bf51fcc9d4d05d07a54d8f2d4e
# Available At https://bitbucket.org/quark-zju/hg-draft
#              hg pull https://bitbucket.org/quark-zju/hg-draft -r a9d87712bec9
revlog: add test to check raw processing is sane

This test fails in various ways, if any of the previous 3 patches is
missing.

Note: I was first putting the test at the first patch. Then found it got
too much churn with the fixes, and the test file diff is not that obvious
explaining what happened. So I've decided to put the test after behavior
fix, before performance fix.

diff --git a/tests/test-revlog-raw.py b/tests/test-revlog-raw.py
new file mode 100644
--- /dev/null
+++ b/tests/test-revlog-raw.py
@@ -0,0 +1,121 @@
+# test revlog interaction about raw data (flagprocessor)
+
+from __future__ import absolute_import, print_function
+
+from mercurial import (
+    encoding,
+    extensions,
+    node,
+    revlog,
+    transaction,
+    vfs,
+)
+
+# TESTTMP is optional - so the test can run outside run-tests.py
+tvfs = vfs.vfs(encoding.environ.get('TESTTMP', b'/tmp'))
+
+# format utilities
+def rightpad(data, length):
+    return (data + b' ' * length)[:length]
+
+def normalize(data):
+    data = data.replace(b'LINEPREFIX_', b'').replace(b'\n', b'')
+    return rightpad(data, 7)
+
+# register a revlog processor for EXTSTORED
+def readprocessor(self, text):
+    return text[2:], True
+
+def writeprocessor(self, text):
+    return b'+\n' + text, False
+
+def rawprocessor(self, text):
+    # do not check hash
+    return False
+
+revlog.addflagprocessor(revlog.REVIDX_EXTSTORED,
+                        (readprocessor, writeprocessor, rawprocessor))
+
+# replace revlog.hash so the test is sensitive to anything that goes wrong
+def _hash(orig, text, p1, p2):
+    r = orig(text, p1, p2)
+    print('  # %s = hash(%s, %s)'
+          % (node.short(r), node.short(p1), normalize(text).strip()))
+    return r
+
+extensions.wrapfunction(revlog, 'hash', _hash)
+
+# writing revlog requires a transaction
+def report(msg):
+    print('transaction: %s' % msg.strip())
+
+tr = transaction.transaction(report, tvfs, {'plain': tvfs}, b'journal')
+
+def newrevlog(name='foo.i'):
+    return revlog.revlog(tvfs, 'foo.i')
+
+rl = newrevlog()
+
+# We are going to construct something like:
+# rev 0: delta-base
+# rev 1: delta against rev 0, with special flag
+# rev 2: delta against rev 1, without special flag
+
+def appendrev(rlog, data, flags=revlog.REVIDX_DEFAULT_FLAGS):
+    nextrev = len(rlog)
+    p1 = rlog.node(nextrev - 1)
+    p2 = node.nullid
+    try:
+        n = rl.addrevision(data, tr, nextrev, p1, p2, flags=flags)
+        print(b'Appended rev %d as %s' % (nextrev, node.short(n)))
+    except Exception as ex:
+        print(b'Failed to append rev %d: %s' % (nextrev, ex))
+
+# revision 0
+data = b''.join(b'LINEPREFIX_%d\n' % i for i in range(5))
+appendrev(rl, data)
+
+# revision 1
+data = data.replace(b'3\n', b'T\n3\n')
+appendrev(rl, data, flags=revlog.REVIDX_EXTSTORED)
+
+# revision 2
+data = data.replace(b'1\n', b'').replace('4\n', '5')
+appendrev(rl, data)
+
+tr.close()
+
+# examine content of the revlog
+print(b'\nREV RAW DATA    CACHE BEFORE -> AFTER')
+
+def describecache(rlog):
+    if rlog._cache is None:
+        cache = b'None'
+    else:
+        n, r, text = rlog._cache
+        cache = b'%d %s' % (r, normalize(text))
+    return rightpad(cache, 9)
+
+def printrev(rlog, rev, raw):
+    cachebefore = describecache(rlog)
+    try:
+        data = rlog.revision(rev, raw=raw)
+    except Exception:
+        data = b'Error'
+    cacheafter = describecache(rlog).strip()
+    print(b'%3d %s   %s %s       %s'
+          % (rev, raw and 'y' or ' ', normalize(data), cachebefore, cacheafter))
+
+for revorder in [[1, 2], [2, 1]]:
+    for raworder in [[True], [False], [True, False], [False, True]]:
+        rlog = newrevlog()
+        for rev in revorder:
+            for raw in raworder:
+                printrev(rlog, rev, raw)
+        print()
+
+# when run outside run-tests.py, clean-ups are needed
+if 'TESTTMP' not in encoding.environ:
+    rl = None
+    tvfs.tryunlink('foo.i')
+    tvfs.tryunlink('foo.d')
diff --git a/tests/test-revlog-raw.py.out b/tests/test-revlog-raw.py.out
new file mode 100644
--- /dev/null
+++ b/tests/test-revlog-raw.py.out
@@ -0,0 +1,58 @@
+  # ea4d2d9efcc9 = hash(000000000000, 01234)
+  # ea4d2d9efcc9 = hash(000000000000, 01234)
+Appended rev 0 as ea4d2d9efcc9
+  # 7bc003d2bcd3 = hash(ea4d2d9efcc9, 012T34)
+Appended rev 1 as 7bc003d2bcd3
+  # 3338e2e7da35 = hash(7bc003d2bcd3, 02T35)
+  # 3338e2e7da35 = hash(7bc003d2bcd3, 02T35)
+Appended rev 2 as 3338e2e7da35
+
+REV RAW DATA    CACHE BEFORE -> AFTER
+  1 y   +012T34 None            1 +012T34
+  # 3338e2e7da35 = hash(7bc003d2bcd3, 02T35)
+  2 y   02T35   1 +012T34       2 02T35
+
+  # 7bc003d2bcd3 = hash(ea4d2d9efcc9, 012T34)
+  1     012T34  None            1 +012T34
+  # 3338e2e7da35 = hash(7bc003d2bcd3, 02T35)
+  2     02T35   1 +012T34       2 02T35
+
+  1 y   +012T34 None            1 +012T34
+  # 7bc003d2bcd3 = hash(ea4d2d9efcc9, 012T34)
+  1     012T34  1 +012T34       1 +012T34
+  # 3338e2e7da35 = hash(7bc003d2bcd3, 02T35)
+  2 y   02T35   1 +012T34       2 02T35
+  # 3338e2e7da35 = hash(7bc003d2bcd3, 02T35)
+  2     02T35   2 02T35         2 02T35
+
+  # 7bc003d2bcd3 = hash(ea4d2d9efcc9, 012T34)
+  1     012T34  None            1 +012T34
+  1 y   +012T34 1 +012T34       1 +012T34
+  # 3338e2e7da35 = hash(7bc003d2bcd3, 02T35)
+  2     02T35   1 +012T34       2 02T35
+  2 y   02T35   2 02T35         2 02T35
+
+  # 3338e2e7da35 = hash(7bc003d2bcd3, 02T35)
+  2 y   02T35   None            2 02T35
+  1 y   +012T34 2 02T35         1 +012T34
+
+  # 3338e2e7da35 = hash(7bc003d2bcd3, 02T35)
+  2     02T35   None            2 02T35
+  # 7bc003d2bcd3 = hash(ea4d2d9efcc9, 012T34)
+  1     012T34  2 02T35         1 +012T34
+
+  # 3338e2e7da35 = hash(7bc003d2bcd3, 02T35)
+  2 y   02T35   None            2 02T35
+  # 3338e2e7da35 = hash(7bc003d2bcd3, 02T35)
+  2     02T35   2 02T35         2 02T35
+  1 y   +012T34 2 02T35         1 +012T34
+  # 7bc003d2bcd3 = hash(ea4d2d9efcc9, 012T34)
+  1     012T34  1 +012T34       1 +012T34
+
+  # 3338e2e7da35 = hash(7bc003d2bcd3, 02T35)
+  2     02T35   None            2 02T35
+  2 y   02T35   2 02T35         2 02T35
+  # 7bc003d2bcd3 = hash(ea4d2d9efcc9, 012T34)
+  1     012T34  2 02T35         1 +012T34
+  1 y   +012T34 1 +012T34       1 +012T34
+


More information about the Mercurial-devel mailing list