test-linelog.py
173 lines
| 6.7 KiB
| text/x-python
|
PythonLexer
/ tests / test-linelog.py
Augie Fackler
|
r38831 | from __future__ import absolute_import, print_function | ||
import difflib | ||||
import random | ||||
import unittest | ||||
from mercurial import linelog | ||||
maxlinenum = 0xffffff | ||||
maxb1 = 0xffffff | ||||
maxdeltaa = 10 | ||||
maxdeltab = 10 | ||||
def _genedits(seed, endrev): | ||||
lines = [] | ||||
random.seed(seed) | ||||
rev = 0 | ||||
for rev in range(0, endrev): | ||||
n = len(lines) | ||||
a1 = random.randint(0, n) | ||||
a2 = random.randint(a1, min(n, a1 + maxdeltaa)) | ||||
b1 = random.randint(0, maxb1) | ||||
b2 = random.randint(b1, b1 + maxdeltab) | ||||
blines = [(rev, idx) for idx in range(b1, b2)] | ||||
lines[a1:a2] = blines | ||||
yield lines, rev, a1, a2, b1, b2 | ||||
class linelogtests(unittest.TestCase): | ||||
def testlinelogencodedecode(self): | ||||
program = [linelog._eof(0, 0), | ||||
linelog._jge(41, 42), | ||||
linelog._jump(0, 43), | ||||
linelog._eof(0, 0), | ||||
linelog._jl(44, 45), | ||||
linelog._line(46, 47), | ||||
] | ||||
ll = linelog.linelog(program, maxrev=100) | ||||
enc = ll.encode() | ||||
# round-trips okay | ||||
self.assertEqual(linelog.linelog.fromdata(enc)._program, ll._program) | ||||
self.assertEqual(linelog.linelog.fromdata(enc), ll) | ||||
# This encoding matches the encoding used by hg-experimental's | ||||
# linelog file, or is supposed to if it doesn't. | ||||
Augie Fackler
|
r38845 | self.assertEqual(enc, (b'\x00\x00\x01\x90\x00\x00\x00\x06' | ||
b'\x00\x00\x00\xa4\x00\x00\x00*' | ||||
b'\x00\x00\x00\x00\x00\x00\x00+' | ||||
b'\x00\x00\x00\x00\x00\x00\x00\x00' | ||||
b'\x00\x00\x00\xb1\x00\x00\x00-' | ||||
b'\x00\x00\x00\xba\x00\x00\x00/')) | ||||
Augie Fackler
|
r38831 | |||
def testsimpleedits(self): | ||||
ll = linelog.linelog() | ||||
# Initial revision: add lines 0, 1, and 2 | ||||
ll.replacelines(1, 0, 0, 0, 3) | ||||
self.assertEqual([(l.rev, l.linenum) for l in ll.annotate(1)], | ||||
[(1, 0), | ||||
(1, 1), | ||||
(1, 2), | ||||
]) | ||||
# Replace line 1 with a new line | ||||
ll.replacelines(2, 1, 2, 1, 2) | ||||
self.assertEqual([(l.rev, l.linenum) for l in ll.annotate(2)], | ||||
[(1, 0), | ||||
(2, 1), | ||||
(1, 2), | ||||
]) | ||||
# delete a line out of 2 | ||||
ll.replacelines(3, 1, 2, 0, 0) | ||||
self.assertEqual([(l.rev, l.linenum) for l in ll.annotate(3)], | ||||
[(1, 0), | ||||
(1, 2), | ||||
]) | ||||
# annotation of 1 is unchanged | ||||
self.assertEqual([(l.rev, l.linenum) for l in ll.annotate(1)], | ||||
[(1, 0), | ||||
(1, 1), | ||||
(1, 2), | ||||
]) | ||||
ll.annotate(3) # set internal state to revision 3 | ||||
start = ll.getoffset(0) | ||||
end = ll.getoffset(1) | ||||
self.assertEqual(ll.getalllines(start, end), [ | ||||
(1, 0), | ||||
(2, 1), | ||||
(1, 1), | ||||
]) | ||||
self.assertEqual(ll.getalllines(), [ | ||||
(1, 0), | ||||
(2, 1), | ||||
(1, 1), | ||||
(1, 2), | ||||
]) | ||||
def testparseclinelogfile(self): | ||||
# This data is what the replacements in testsimpleedits | ||||
# produce when fed to the original linelog.c implementation. | ||||
Augie Fackler
|
r38845 | data = (b'\x00\x00\x00\x0c\x00\x00\x00\x0f' | ||
b'\x00\x00\x00\x00\x00\x00\x00\x02' | ||||
b'\x00\x00\x00\x05\x00\x00\x00\x06' | ||||
b'\x00\x00\x00\x06\x00\x00\x00\x00' | ||||
b'\x00\x00\x00\x00\x00\x00\x00\x07' | ||||
b'\x00\x00\x00\x06\x00\x00\x00\x02' | ||||
b'\x00\x00\x00\x00\x00\x00\x00\x00' | ||||
b'\x00\x00\x00\t\x00\x00\x00\t' | ||||
b'\x00\x00\x00\x00\x00\x00\x00\x0c' | ||||
b'\x00\x00\x00\x08\x00\x00\x00\x05' | ||||
b'\x00\x00\x00\x06\x00\x00\x00\x01' | ||||
b'\x00\x00\x00\x00\x00\x00\x00\x05' | ||||
b'\x00\x00\x00\x0c\x00\x00\x00\x05' | ||||
b'\x00\x00\x00\n\x00\x00\x00\x01' | ||||
b'\x00\x00\x00\x00\x00\x00\x00\t') | ||||
Augie Fackler
|
r38831 | llc = linelog.linelog.fromdata(data) | ||
self.assertEqual([(l.rev, l.linenum) for l in llc.annotate(1)], | ||||
[(1, 0), | ||||
(1, 1), | ||||
(1, 2), | ||||
]) | ||||
self.assertEqual([(l.rev, l.linenum) for l in llc.annotate(2)], | ||||
[(1, 0), | ||||
(2, 1), | ||||
(1, 2), | ||||
]) | ||||
self.assertEqual([(l.rev, l.linenum) for l in llc.annotate(3)], | ||||
[(1, 0), | ||||
(1, 2), | ||||
]) | ||||
# Check we emit the same bytecode. | ||||
ll = linelog.linelog() | ||||
# Initial revision: add lines 0, 1, and 2 | ||||
ll.replacelines(1, 0, 0, 0, 3) | ||||
# Replace line 1 with a new line | ||||
ll.replacelines(2, 1, 2, 1, 2) | ||||
# delete a line out of 2 | ||||
ll.replacelines(3, 1, 2, 0, 0) | ||||
diff = '\n ' + '\n '.join(difflib.unified_diff( | ||||
ll.debugstr().splitlines(), llc.debugstr().splitlines(), | ||||
'python', 'c', lineterm='')) | ||||
self.assertEqual(ll._program, llc._program, 'Program mismatch: ' + diff) | ||||
# Done as a secondary step so we get a better result if the | ||||
# program is where the mismatch is. | ||||
self.assertEqual(ll, llc) | ||||
self.assertEqual(ll.encode(), data) | ||||
def testanothersimplecase(self): | ||||
ll = linelog.linelog() | ||||
ll.replacelines(3, 0, 0, 0, 2) | ||||
ll.replacelines(4, 0, 2, 0, 0) | ||||
self.assertEqual([(l.rev, l.linenum) for l in ll.annotate(4)], | ||||
[]) | ||||
self.assertEqual([(l.rev, l.linenum) for l in ll.annotate(3)], | ||||
[(3, 0), (3, 1)]) | ||||
# rev 2 is empty because contents were only ever introduced in rev 3 | ||||
self.assertEqual([(l.rev, l.linenum) for l in ll.annotate(2)], | ||||
[]) | ||||
def testrandomedits(self): | ||||
# Inspired by original linelog tests. | ||||
seed = random.random() | ||||
numrevs = 2000 | ||||
ll = linelog.linelog() | ||||
# Populate linelog | ||||
for lines, rev, a1, a2, b1, b2 in _genedits(seed, numrevs): | ||||
ll.replacelines(rev, a1, a2, b1, b2) | ||||
ar = ll.annotate(rev) | ||||
self.assertEqual(ll.annotateresult, lines) | ||||
# Verify we can get back these states by annotating each rev | ||||
for lines, rev, a1, a2, b1, b2 in _genedits(seed, numrevs): | ||||
ar = ll.annotate(rev) | ||||
self.assertEqual([(l.rev, l.linenum) for l in ar], lines) | ||||
if __name__ == '__main__': | ||||
import silenttestrunner | ||||
silenttestrunner.main(__name__) | ||||