comparison tests/bruterebase.py @ 33708:71b77b61ed60

test-rebase: add a brute force test Rebase is becoming more complex and it looks like a good idea to try some brute force enumeration to cover cases that are hard to find manually. Using brute force to generate repos in different shapes and enumerating the rebase source and destination would generate too many cases that takes too long to compute. This patch limits the "brute force" to only the "rebase source" part. Repo and destination are still manual. The added test cases are crafted manually to reveal some behaviors that are not covered by other tests: - "revlog index out of range" crash - after rebase, p1 == p2, p2 != null - "nothing to merge" abort In the future we might want to add more tests here. For now I'm more interested in revealing interesting behaviors in a minified way. I tried some more complex cases but didn't find other interesting behaviors. Differential Revision: https://phab.mercurial-scm.org/D262
author Jun Wu <quark@fb.com>
date Sun, 06 Aug 2017 11:40:53 -0700
parents
children bab82c43c065
comparison
equal deleted inserted replaced
33707:36d216dcae6a 33708:71b77b61ed60
1 # bruterebase.py - brute force rebase testing
2 #
3 # Copyright 2017 Facebook, Inc.
4 #
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
7
8 from __future__ import absolute_import
9
10 from mercurial import (
11 error,
12 registrar,
13 revsetlang,
14 )
15
16 from hgext import rebase
17
18 cmdtable = {}
19 command = registrar.command(cmdtable)
20
21 @command('debugbruterebase')
22 def debugbruterebase(ui, repo, source, dest):
23 """for every non-empty subset of source, run rebase -r subset -d dest
24
25 Print one line summary for each subset. Assume obsstore is enabled.
26 """
27 srevs = list(repo.revs(source))
28
29 with repo.wlock(), repo.lock():
30 repolen = len(repo)
31 cl = repo.changelog
32
33 def getdesc(rev):
34 result = cl.changelogrevision(rev).description
35 if rev >= repolen:
36 result += "'"
37 return result
38
39 for i in xrange(1, 2 ** len(srevs)):
40 subset = [rev for j, rev in enumerate(srevs) if i & (1 << j) != 0]
41 spec = revsetlang.formatspec('%ld', subset)
42 tr = repo.transaction('rebase')
43 tr.report = lambda x: 0 # hide "transaction abort"
44
45 ui.pushbuffer()
46 try:
47 rebase.rebase(ui, repo, dest=dest, rev=[spec])
48 except error.Abort as ex:
49 summary = 'ABORT: %s' % ex
50 except Exception as ex:
51 summary = 'CRASH: %s' % ex
52 else:
53 # short summary about new nodes
54 cl = repo.changelog
55 descs = []
56 for rev in xrange(repolen, len(repo)):
57 desc = '%s:' % getdesc(rev)
58 for prev in cl.parentrevs(rev):
59 if prev > -1:
60 desc += getdesc(prev)
61 descs.append(desc)
62 descs.sort()
63 summary = ' '.join(descs)
64 ui.popbuffer()
65 repo.vfs.tryunlink('rebasestate')
66
67 subsetdesc = ''.join(getdesc(rev) for rev in subset)
68 ui.write(('%s: %s\n') % (subsetdesc.rjust(len(srevs)), summary))
69 tr.abort()