##// END OF EJS Templates
revlog: subclass the new `repository.iverifyproblem` Protocol class...
revlog: subclass the new `repository.iverifyproblem` Protocol class This is the same transformation as 3a90a6fd710d did for dirstate, but the CamelCase naming was already cleaned up here. We shouldn't have to explicitly subclass, but I'm doing so to test the interplay of regular attributes and the `attrs` class. Also, PyCharm has a nifty feature that puts a jump point in the gutter to navigate back and forth between the base class and subclasses (and override functions and base class functions) when there's an explicit subclassing. Additionally, PyCharm will immediately flag signature mismatches without a 40m pytype run.

File last commit:

r49730:6000f5b2 default
r53365:4ef6dbc2 default
Show More
test-linelog.py
238 lines | 7.5 KiB | text/x-python | PythonLexer
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831 import difflib
import random
import unittest
from mercurial import linelog
Augie Fackler
formatting: blacken the codebase...
r43346 vecratio = 3 # number of replacelines / number of replacelines_vec
maxlinenum = 0xFFFFFF
maxb1 = 0xFFFFFF
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831 maxdeltaa = 10
maxdeltab = 10
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831 def _genedits(seed, endrev):
lines = []
random.seed(seed)
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)
Augie Fackler
linelog: add replacelines_vec for fastannotate...
r38960 usevec = not bool(random.randint(0, vecratio))
if usevec:
Augie Fackler
formatting: blacken the codebase...
r43346 blines = [
(random.randint(0, rev), random.randint(0, maxlinenum))
for _ in range(b1, b2)
]
Augie Fackler
linelog: add replacelines_vec for fastannotate...
r38960 else:
blines = [(rev, bidx) for bidx in range(b1, b2)]
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831 lines[a1:a2] = blines
Augie Fackler
linelog: add replacelines_vec for fastannotate...
r38960 yield lines, rev, a1, a2, b1, b2, blines, usevec
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831 class linelogtests(unittest.TestCase):
def testlinelogencodedecode(self):
Augie Fackler
formatting: blacken the codebase...
r43346 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),
]
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831 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
formatting: blacken the codebase...
r43346 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
linelog: add a Python implementation of the linelog datastructure...
r38831
def testsimpleedits(self):
ll = linelog.linelog()
# Initial revision: add lines 0, 1, and 2
ll.replacelines(1, 0, 0, 0, 3)
Augie Fackler
formatting: blacken the codebase...
r43346 self.assertEqual(
[(l.rev, l.linenum) for l in ll.annotate(1)],
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 [
(1, 0),
(1, 1),
(1, 2),
],
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831 # Replace line 1 with a new line
ll.replacelines(2, 1, 2, 1, 2)
Augie Fackler
formatting: blacken the codebase...
r43346 self.assertEqual(
[(l.rev, l.linenum) for l in ll.annotate(2)],
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 [
(1, 0),
(2, 1),
(1, 2),
],
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831 # delete a line out of 2
ll.replacelines(3, 1, 2, 0, 0)
Augie Fackler
formatting: blacken the codebase...
r43346 self.assertEqual(
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 [(l.rev, l.linenum) for l in ll.annotate(3)],
[
(1, 0),
(1, 2),
],
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831 # annotation of 1 is unchanged
Augie Fackler
formatting: blacken the codebase...
r43346 self.assertEqual(
[(l.rev, l.linenum) for l in ll.annotate(1)],
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 [
(1, 0),
(1, 1),
(1, 2),
],
Augie Fackler
formatting: blacken the codebase...
r43346 )
ll.annotate(3) # set internal state to revision 3
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831 start = ll.getoffset(0)
end = ll.getoffset(1)
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 self.assertEqual(
ll.getalllines(start, end),
[
(1, 0),
(2, 1),
(1, 1),
],
)
self.assertEqual(
ll.getalllines(),
[
(1, 0),
(2, 1),
(1, 1),
(1, 2),
],
)
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831
def testparseclinelogfile(self):
# This data is what the replacements in testsimpleedits
# produce when fed to the original linelog.c implementation.
Augie Fackler
formatting: blacken the codebase...
r43346 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
linelog: add a Python implementation of the linelog datastructure...
r38831 llc = linelog.linelog.fromdata(data)
Augie Fackler
formatting: blacken the codebase...
r43346 self.assertEqual(
[(l.rev, l.linenum) for l in llc.annotate(1)],
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 [
(1, 0),
(1, 1),
(1, 2),
],
Augie Fackler
formatting: blacken the codebase...
r43346 )
self.assertEqual(
[(l.rev, l.linenum) for l in llc.annotate(2)],
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 [
(1, 0),
(2, 1),
(1, 2),
],
Augie Fackler
formatting: blacken the codebase...
r43346 )
self.assertEqual(
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 [(l.rev, l.linenum) for l in llc.annotate(3)],
[
(1, 0),
(1, 2),
],
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831 # 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)
Augie Fackler
formatting: blacken the codebase...
r43346 diff = '\n ' + '\n '.join(
difflib.unified_diff(
ll.debugstr().splitlines(),
llc.debugstr().splitlines(),
'python',
'c',
lineterm='',
)
)
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831 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)
Augie Fackler
formatting: blacken the codebase...
r43346 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)]
)
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831 # rev 2 is empty because contents were only ever introduced in rev 3
Augie Fackler
formatting: blacken the codebase...
r43346 self.assertEqual([(l.rev, l.linenum) for l in ll.annotate(2)], [])
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831
def testrandomedits(self):
# Inspired by original linelog tests.
seed = random.random()
numrevs = 2000
ll = linelog.linelog()
# Populate linelog
Augie Fackler
linelog: add replacelines_vec for fastannotate...
r38960 for lines, rev, a1, a2, b1, b2, blines, usevec in _genedits(
Augie Fackler
formatting: blacken the codebase...
r43346 seed, numrevs
):
Augie Fackler
linelog: add replacelines_vec for fastannotate...
r38960 if usevec:
ll.replacelines_vec(rev, a1, a2, blines)
else:
ll.replacelines(rev, a1, a2, b1, b2)
Matt Harbison
tests: drop unused local variable assignments in linelog...
r44444 ll.annotate(rev)
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831 self.assertEqual(ll.annotateresult, lines)
# Verify we can get back these states by annotating each rev
Augie Fackler
linelog: add replacelines_vec for fastannotate...
r38960 for lines, rev, a1, a2, b1, b2, blines, usevec in _genedits(
Augie Fackler
formatting: blacken the codebase...
r43346 seed, numrevs
):
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831 ar = ll.annotate(rev)
self.assertEqual([(l.rev, l.linenum) for l in ar], lines)
Jun Wu
linelog: fix infinite loop vulnerability...
r38970 def testinfinitebadprogram(self):
ll = linelog.linelog.fromdata(
b'\x00\x00\x00\x00\x00\x00\x00\x02' # header
b'\x00\x00\x00\x00\x00\x00\x00\x01' # JUMP to self
)
with self.assertRaises(linelog.LineLogError):
# should not be an infinite loop and raise
ll.annotate(1)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831 if __name__ == '__main__':
import silenttestrunner
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
linelog: add a Python implementation of the linelog datastructure...
r38831 silenttestrunner.main(__name__)