test-absorb-filefixupstate.py
232 lines
| 6.5 KiB
| text/x-python
|
PythonLexer
/ tests / test-absorb-filefixupstate.py
Augie Fackler
|
r38953 | import itertools | ||
Augie Fackler
|
r39024 | from mercurial import pycompat | ||
Augie Fackler
|
r38953 | from hgext import absorb | ||
Augie Fackler
|
r43346 | |||
Gregory Szorc
|
r49801 | class simplefctx: | ||
Augie Fackler
|
r38953 | def __init__(self, content): | ||
self.content = content | ||||
def data(self): | ||||
return self.content | ||||
Augie Fackler
|
r43346 | |||
Augie Fackler
|
r38953 | def insertreturns(x): | ||
# insert "\n"s after each single char | ||||
Augie Fackler
|
r39024 | if isinstance(x, bytes): | ||
return b''.join(ch + b'\n' for ch in pycompat.bytestr(x)) | ||||
Augie Fackler
|
r38953 | else: | ||
Augie Fackler
|
r39024 | return pycompat.maplist(insertreturns, x) | ||
Augie Fackler
|
r38953 | |||
Augie Fackler
|
r43346 | |||
Augie Fackler
|
r38953 | def removereturns(x): | ||
# the revert of "insertreturns" | ||||
Augie Fackler
|
r39024 | if isinstance(x, bytes): | ||
return x.replace(b'\n', b'') | ||||
Augie Fackler
|
r38953 | else: | ||
Augie Fackler
|
r39024 | return pycompat.maplist(removereturns, x) | ||
Augie Fackler
|
r38953 | |||
Augie Fackler
|
r43346 | |||
Augie Fackler
|
r38953 | def assertlistequal(lhs, rhs, decorator=lambda x: x): | ||
if lhs != rhs: | ||||
Augie Fackler
|
r43346 | raise RuntimeError( | ||
'mismatch:\n actual: %r\n expected: %r' | ||||
% tuple(map(decorator, [lhs, rhs])) | ||||
) | ||||
Augie Fackler
|
r38953 | |||
def testfilefixup(oldcontents, workingcopy, expectedcontents, fixups=None): | ||||
"""([str], str, [str], [(rev, a1, a2, b1, b2)]?) -> None | ||||
workingcopy is a string, of which every character denotes a single line. | ||||
oldcontents, expectedcontents are lists of strings, every character of | ||||
every string denots a single line. | ||||
if fixups is not None, it's the expected fixups list and will be checked. | ||||
""" | ||||
expectedcontents = insertreturns(expectedcontents) | ||||
oldcontents = insertreturns(oldcontents) | ||||
workingcopy = insertreturns(workingcopy) | ||||
Augie Fackler
|
r43346 | state = absorb.filefixupstate( | ||
pycompat.maplist(simplefctx, oldcontents), 'path' | ||||
) | ||||
Augie Fackler
|
r38953 | state.diffwith(simplefctx(workingcopy)) | ||
if fixups is not None: | ||||
assertlistequal(state.fixups, fixups) | ||||
state.apply() | ||||
assertlistequal(state.finalcontents, expectedcontents, removereturns) | ||||
Augie Fackler
|
r43346 | |||
Augie Fackler
|
r38953 | def buildcontents(linesrevs): | ||
# linesrevs: [(linecontent : str, revs : [int])] | ||||
revs = set(itertools.chain(*[revs for line, revs in linesrevs])) | ||||
Augie Fackler
|
r39024 | return [b''] + [ | ||
Augie Fackler
|
r43346 | b''.join([l for l, rs in linesrevs if r in rs]) for r in sorted(revs) | ||
Augie Fackler
|
r38953 | ] | ||
Augie Fackler
|
r43346 | |||
Augie Fackler
|
r38953 | # input case 0: one single commit | ||
Augie Fackler
|
r39024 | case0 = [b'', b'11'] | ||
Augie Fackler
|
r38953 | |||
# replace a single chunk | ||||
Augie Fackler
|
r39024 | testfilefixup(case0, b'', [b'', b'']) | ||
testfilefixup(case0, b'2', [b'', b'2']) | ||||
testfilefixup(case0, b'22', [b'', b'22']) | ||||
testfilefixup(case0, b'222', [b'', b'222']) | ||||
Augie Fackler
|
r38953 | |||
# input case 1: 3 lines, each commit adds one line | ||||
Augie Fackler
|
r46554 | case1 = buildcontents( | ||
[ | ||||
(b'1', [1, 2, 3]), | ||||
(b'2', [2, 3]), | ||||
(b'3', [3]), | ||||
] | ||||
) | ||||
Augie Fackler
|
r38953 | |||
# 1:1 line mapping | ||||
Augie Fackler
|
r39024 | testfilefixup(case1, b'123', case1) | ||
testfilefixup(case1, b'12c', [b'', b'1', b'12', b'12c']) | ||||
testfilefixup(case1, b'1b3', [b'', b'1', b'1b', b'1b3']) | ||||
testfilefixup(case1, b'1bc', [b'', b'1', b'1b', b'1bc']) | ||||
testfilefixup(case1, b'a23', [b'', b'a', b'a2', b'a23']) | ||||
testfilefixup(case1, b'a2c', [b'', b'a', b'a2', b'a2c']) | ||||
testfilefixup(case1, b'ab3', [b'', b'a', b'ab', b'ab3']) | ||||
testfilefixup(case1, b'abc', [b'', b'a', b'ab', b'abc']) | ||||
Augie Fackler
|
r38953 | |||
# non 1:1 edits | ||||
Augie Fackler
|
r39024 | testfilefixup(case1, b'abcd', case1) | ||
testfilefixup(case1, b'ab', case1) | ||||
Augie Fackler
|
r38953 | |||
# deletion | ||||
Augie Fackler
|
r43346 | testfilefixup(case1, b'', [b'', b'', b'', b'']) | ||
testfilefixup(case1, b'1', [b'', b'1', b'1', b'1']) | ||||
testfilefixup(case1, b'2', [b'', b'', b'2', b'2']) | ||||
testfilefixup(case1, b'3', [b'', b'', b'', b'3']) | ||||
Augie Fackler
|
r39024 | testfilefixup(case1, b'13', [b'', b'1', b'1', b'13']) | ||
Augie Fackler
|
r38953 | |||
# replaces | ||||
Augie Fackler
|
r39024 | testfilefixup(case1, b'1bb3', [b'', b'1', b'1bb', b'1bb3']) | ||
Augie Fackler
|
r38953 | |||
# (confusing) replaces | ||||
Augie Fackler
|
r39024 | testfilefixup(case1, b'1bbb', case1) | ||
testfilefixup(case1, b'bbbb', case1) | ||||
testfilefixup(case1, b'bbb3', case1) | ||||
testfilefixup(case1, b'1b', case1) | ||||
testfilefixup(case1, b'bb', case1) | ||||
testfilefixup(case1, b'b3', case1) | ||||
Augie Fackler
|
r38953 | |||
# insertions at the beginning and the end | ||||
Augie Fackler
|
r39024 | testfilefixup(case1, b'123c', [b'', b'1', b'12', b'123c']) | ||
testfilefixup(case1, b'a123', [b'', b'a1', b'a12', b'a123']) | ||||
Augie Fackler
|
r38953 | |||
# (confusing) insertions | ||||
Augie Fackler
|
r39024 | testfilefixup(case1, b'1a23', case1) | ||
testfilefixup(case1, b'12b3', case1) | ||||
Augie Fackler
|
r38953 | |||
# input case 2: delete in the middle | ||||
Augie Fackler
|
r46554 | case2 = buildcontents( | ||
[ | ||||
(b'11', [1, 2]), | ||||
(b'22', [1]), | ||||
(b'33', [1, 2]), | ||||
] | ||||
) | ||||
Augie Fackler
|
r38953 | |||
# deletion (optimize code should make it 2 chunks) | ||||
Augie Fackler
|
r43346 | testfilefixup( | ||
case2, b'', [b'', b'22', b''], fixups=[(4, 0, 2, 0, 0), (4, 2, 4, 0, 0)] | ||||
) | ||||
Augie Fackler
|
r38953 | |||
# 1:1 line mapping | ||||
Augie Fackler
|
r39024 | testfilefixup(case2, b'aaaa', [b'', b'aa22aa', b'aaaa']) | ||
Augie Fackler
|
r38953 | |||
# non 1:1 edits | ||||
# note: unlike case0, the chunk is not "continuous" and no edit allowed | ||||
Augie Fackler
|
r39024 | testfilefixup(case2, b'aaa', case2) | ||
Augie Fackler
|
r38953 | |||
# input case 3: rev 3 reverts rev 2 | ||||
Augie Fackler
|
r46554 | case3 = buildcontents( | ||
[ | ||||
(b'1', [1, 2, 3]), | ||||
(b'2', [2]), | ||||
(b'3', [1, 2, 3]), | ||||
] | ||||
) | ||||
Augie Fackler
|
r38953 | |||
# 1:1 line mapping | ||||
Augie Fackler
|
r39024 | testfilefixup(case3, b'13', case3) | ||
testfilefixup(case3, b'1b', [b'', b'1b', b'12b', b'1b']) | ||||
testfilefixup(case3, b'a3', [b'', b'a3', b'a23', b'a3']) | ||||
testfilefixup(case3, b'ab', [b'', b'ab', b'a2b', b'ab']) | ||||
Augie Fackler
|
r38953 | |||
# non 1:1 edits | ||||
Augie Fackler
|
r39024 | testfilefixup(case3, b'a', case3) | ||
testfilefixup(case3, b'abc', case3) | ||||
Augie Fackler
|
r38953 | |||
# deletion | ||||
Augie Fackler
|
r39024 | testfilefixup(case3, b'', [b'', b'', b'2', b'']) | ||
Augie Fackler
|
r38953 | |||
# insertion | ||||
Augie Fackler
|
r39024 | testfilefixup(case3, b'a13c', [b'', b'a13c', b'a123c', b'a13c']) | ||
Augie Fackler
|
r38953 | |||
# input case 4: a slightly complex case | ||||
Augie Fackler
|
r43346 | case4 = buildcontents( | ||
[ | ||||
(b'1', [1, 2, 3]), | ||||
(b'2', [2, 3]), | ||||
Augie Fackler
|
r46554 | ( | ||
b'3', | ||||
[ | ||||
1, | ||||
2, | ||||
], | ||||
), | ||||
Augie Fackler
|
r43346 | (b'4', [1, 3]), | ||
(b'5', [3]), | ||||
(b'6', [2, 3]), | ||||
(b'7', [2]), | ||||
(b'8', [2, 3]), | ||||
(b'9', [3]), | ||||
] | ||||
) | ||||
Augie Fackler
|
r38953 | |||
Augie Fackler
|
r39024 | testfilefixup(case4, b'1245689', case4) | ||
testfilefixup(case4, b'1a2456bbb', case4) | ||||
testfilefixup(case4, b'1abc5689', case4) | ||||
testfilefixup(case4, b'1ab5689', [b'', b'134', b'1a3678', b'1ab5689']) | ||||
testfilefixup(case4, b'aa2bcd8ee', [b'', b'aa34', b'aa23d78', b'aa2bcd8ee']) | ||||
Augie Fackler
|
r43346 | testfilefixup(case4, b'aa2bcdd8ee', [b'', b'aa34', b'aa23678', b'aa24568ee']) | ||
Augie Fackler
|
r39024 | testfilefixup(case4, b'aaaaaa', case4) | ||
testfilefixup(case4, b'aa258b', [b'', b'aa34', b'aa2378', b'aa258b']) | ||||
testfilefixup(case4, b'25bb', [b'', b'34', b'23678', b'25689']) | ||||
testfilefixup(case4, b'27', [b'', b'34', b'23678', b'245689']) | ||||
testfilefixup(case4, b'28', [b'', b'34', b'2378', b'28']) | ||||
testfilefixup(case4, b'', [b'', b'34', b'37', b'']) | ||||
Augie Fackler
|
r38953 | |||
# input case 5: replace a small chunk which is near a deleted line | ||||
Augie Fackler
|
r46554 | case5 = buildcontents( | ||
[ | ||||
(b'12', [1, 2]), | ||||
(b'3', [1]), | ||||
(b'4', [1, 2]), | ||||
] | ||||
) | ||||
Augie Fackler
|
r38953 | |||
Augie Fackler
|
r39024 | testfilefixup(case5, b'1cd4', [b'', b'1cd34', b'1cd4']) | ||
Augie Fackler
|
r38953 | |||
# input case 6: base "changeset" is immutable | ||||
Augie Fackler
|
r39024 | case6 = [b'1357', b'0125678'] | ||
Augie Fackler
|
r38953 | |||
Augie Fackler
|
r39024 | testfilefixup(case6, b'0125678', case6) | ||
testfilefixup(case6, b'0a25678', case6) | ||||
testfilefixup(case6, b'0a256b8', case6) | ||||
testfilefixup(case6, b'abcdefg', [b'1357', b'a1c5e7g']) | ||||
testfilefixup(case6, b'abcdef', case6) | ||||
testfilefixup(case6, b'', [b'1357', b'157']) | ||||
testfilefixup(case6, b'0123456789', [b'1357', b'0123456789']) | ||||
Augie Fackler
|
r38953 | |||
# input case 7: change an empty file | ||||
Augie Fackler
|
r39024 | case7 = [b''] | ||
Augie Fackler
|
r38953 | |||
Augie Fackler
|
r39024 | testfilefixup(case7, b'1', case7) | ||