[PATCH 1 of 7 V4] test-revset: show how inconsistent the ordering of compound expressions is
Martin von Zweigbergk
martinvonz at google.com
Thu Jun 23 12:07:29 EDT 2016
I've queued this to start with. Thanks!
On Thu, Jun 23, 2016 at 8:59 AM, Yuya Nishihara <yuya at tcha.org> wrote:
> # HG changeset patch
> # User Yuya Nishihara <yuya at tcha.org>
> # Date 1466600545 -32400
> # Wed Jun 22 22:02:25 2016 +0900
> # Node ID 8ae1910bc804846ea065854aea7896e3c46cde05
> # Parent aa1d56003872cba207d908706da059141dd901a5
> test-revset: show how inconsistent the ordering of compound expressions is
>
> This adds mostly broken tests that will be fixed by subsequent patches. We
> generally don't do that, but this patch series would be hard to review
> without a set of broken tests.
>
> Note that some tests pass thanks to the reordering problem in optimize().
> For instance, '2:0 & _intlist(0 1 2)' doesn't fail because it is rewritten
> as '_intlist(0 1 2) & 2:0'.
>
> diff --git a/tests/test-revset.t b/tests/test-revset.t
> --- a/tests/test-revset.t
> +++ b/tests/test-revset.t
> @@ -31,6 +31,46 @@
> > hg log --template '{rev}\n' -r "$1"
> > }
>
> +extension to build '_intlist()' and '_hexlist()', which is necessary because
> +these predicates use '\0' as a separator:
> +
> + $ cat <<EOF > debugrevlistspec.py
> + > from __future__ import absolute_import
> + > from mercurial import (
> + > cmdutil,
> + > node as nodemod,
> + > revset,
> + > )
> + > cmdtable = {}
> + > command = cmdutil.command(cmdtable)
> + > @command('debugrevlistspec',
> + > [('', 'optimize', None, 'print parsed tree after optimizing'),
> + > ('', 'bin', None, 'unhexlify arguments')])
> + > def debugrevlistspec(ui, repo, fmt, *args, **opts):
> + > if opts['bin']:
> + > args = map(nodemod.bin, args)
> + > expr = revset.formatspec(fmt, list(args))
> + > if ui.verbose:
> + > tree = revset.parse(expr, lookup=repo.__contains__)
> + > ui.note(revset.prettyformat(tree), "\n")
> + > if opts["optimize"]:
> + > opttree = revset.optimize(tree)
> + > ui.note("* optimized:\n", revset.prettyformat(opttree), "\n")
> + > func = revset.match(ui, expr, repo)
> + > revs = func(repo)
> + > if ui.verbose:
> + > ui.note("* set:\n", revset.prettyformatset(revs), "\n")
> + > for c in revs:
> + > ui.write("%s\n" % c)
> + > EOF
> + $ cat <<EOF >> $HGRCPATH
> + > [extensions]
> + > debugrevlistspec = $TESTTMP/debugrevlistspec.py
> + > EOF
> + $ trylist() {
> + > hg debugrevlistspec --debug "$@"
> + > }
> +
> $ hg init repo
> $ cd repo
>
> @@ -901,6 +941,10 @@ Test working-directory revision
> Test order of revisions in compound expression
> ----------------------------------------------
>
> +The general rule is that only the outermost (= leftmost) predicate can
> +enforce its ordering requirement. The other predicates should take the
> +ordering defined by it.
> +
> 'A & B' should follow the order of 'A':
>
> $ log '2:0 & 0::2'
> @@ -908,6 +952,432 @@ Test order of revisions in compound expr
> 1
> 0
>
> + 'head()' combines sets in wrong order:
> +
> + $ log '2:0 & head()'
> + 0
> + 1
> + 2
> + BROKEN: should be '2 1 0'
> +
> + 'a + b', which is optimized to '_list(a b)', should take the ordering of
> + the left expression:
> +
> + $ try --optimize '2:0 & (0 + 1 + 2)'
> + (and
> + (range
> + ('symbol', '2')
> + ('symbol', '0'))
> + (group
> + (or
> + ('symbol', '0')
> + ('symbol', '1')
> + ('symbol', '2'))))
> + * optimized:
> + (and
> + (range
> + ('symbol', '2')
> + ('symbol', '0'))
> + (func
> + ('symbol', '_list')
> + ('string', '0\x001\x002')))
> + * set:
> + <baseset [0, 1, 2]>
> + 0
> + 1
> + 2
> + BROKEN: should be '2 1 0'
> +
> + 'A + B' should take the ordering of the left expression:
> +
> + $ try --optimize '2:0 & (0:1 + 2)'
> + (and
> + (range
> + ('symbol', '2')
> + ('symbol', '0'))
> + (group
> + (or
> + (range
> + ('symbol', '0')
> + ('symbol', '1'))
> + ('symbol', '2'))))
> + * optimized:
> + (and
> + (range
> + ('symbol', '2')
> + ('symbol', '0'))
> + (or
> + (range
> + ('symbol', '0')
> + ('symbol', '1'))
> + ('symbol', '2')))
> + * set:
> + <addset
> + <filteredset
> + <spanset+ 0:1>,
> + <spanset- 0:2>>,
> + <baseset [2]>>
> + 0
> + 1
> + 2
> + BROKEN: should be '2 1 0'
> +
> + '_intlist(a b)' should behave like 'a + b':
> +
> + $ trylist --optimize '2:0 & %ld' 0 1 2
> + (and
> + (range
> + ('symbol', '2')
> + ('symbol', '0'))
> + (func
> + ('symbol', '_intlist')
> + ('string', '0\x001\x002')))
> + * optimized:
> + (and
> + (func
> + ('symbol', '_intlist')
> + ('string', '0\x001\x002'))
> + (range
> + ('symbol', '2')
> + ('symbol', '0')))
> + * set:
> + <filteredset
> + <spanset- 0:2>,
> + <baseset [0, 1, 2]>>
> + 2
> + 1
> + 0
> +
> + $ trylist --optimize '%ld & 2:0' 0 2 1
> + (and
> + (func
> + ('symbol', '_intlist')
> + ('string', '0\x002\x001'))
> + (range
> + ('symbol', '2')
> + ('symbol', '0')))
> + * optimized:
> + (and
> + (func
> + ('symbol', '_intlist')
> + ('string', '0\x002\x001'))
> + (range
> + ('symbol', '2')
> + ('symbol', '0')))
> + * set:
> + <filteredset
> + <spanset- 0:2>,
> + <baseset [0, 2, 1]>>
> + 2
> + 1
> + 0
> + BROKEN: should be '0 2 1'
> +
> + '_hexlist(a b)' should behave like 'a + b':
> +
> + $ trylist --optimize --bin '2:0 & %ln' `hg log -T '{node} ' -r0:2`
> + (and
> + (range
> + ('symbol', '2')
> + ('symbol', '0'))
> + (func
> + ('symbol', '_hexlist')
> + ('string', '*'))) (glob)
> + * optimized:
> + (and
> + (range
> + ('symbol', '2')
> + ('symbol', '0'))
> + (func
> + ('symbol', '_hexlist')
> + ('string', '*'))) (glob)
> + * set:
> + <baseset [0, 1, 2]>
> + 0
> + 1
> + 2
> + BROKEN: should be '2 1 0'
> +
> + $ trylist --optimize --bin '%ln & 2:0' `hg log -T '{node} ' -r0+2+1`
> + (and
> + (func
> + ('symbol', '_hexlist')
> + ('string', '*')) (glob)
> + (range
> + ('symbol', '2')
> + ('symbol', '0')))
> + * optimized:
> + (and
> + (range
> + ('symbol', '2')
> + ('symbol', '0'))
> + (func
> + ('symbol', '_hexlist')
> + ('string', '*'))) (glob)
> + * set:
> + <baseset [0, 2, 1]>
> + 0
> + 2
> + 1
> +
> + 'present()' should do nothing other than suppressing an error:
> +
> + $ try --optimize '2:0 & present(0 + 1 + 2)'
> + (and
> + (range
> + ('symbol', '2')
> + ('symbol', '0'))
> + (func
> + ('symbol', 'present')
> + (or
> + ('symbol', '0')
> + ('symbol', '1')
> + ('symbol', '2'))))
> + * optimized:
> + (and
> + (range
> + ('symbol', '2')
> + ('symbol', '0'))
> + (func
> + ('symbol', 'present')
> + (func
> + ('symbol', '_list')
> + ('string', '0\x001\x002'))))
> + * set:
> + <baseset [0, 1, 2]>
> + 0
> + 1
> + 2
> + BROKEN: should be '2 1 0'
> +
> + 'reverse()' should take effect only if it is the outermost expression:
> +
> + $ try --optimize '0:2 & reverse(all())'
> + (and
> + (range
> + ('symbol', '0')
> + ('symbol', '2'))
> + (func
> + ('symbol', 'reverse')
> + (func
> + ('symbol', 'all')
> + None)))
> + * optimized:
> + (and
> + (range
> + ('symbol', '0')
> + ('symbol', '2'))
> + (func
> + ('symbol', 'reverse')
> + (func
> + ('symbol', 'all')
> + None)))
> + * set:
> + <filteredset
> + <spanset- 0:2>,
> + <spanset+ 0:9>>
> + 2
> + 1
> + 0
> + BROKEN: should be '0 1 2'
> +
> + 'sort()' should take effect only if it is the outermost expression:
> +
> + $ try --optimize '0:2 & sort(all(), -rev)'
> + (and
> + (range
> + ('symbol', '0')
> + ('symbol', '2'))
> + (func
> + ('symbol', 'sort')
> + (list
> + (func
> + ('symbol', 'all')
> + None)
> + (negate
> + ('symbol', 'rev')))))
> + * optimized:
> + (and
> + (range
> + ('symbol', '0')
> + ('symbol', '2'))
> + (func
> + ('symbol', 'sort')
> + (list
> + (func
> + ('symbol', 'all')
> + None)
> + ('string', '-rev'))))
> + * set:
> + <filteredset
> + <spanset- 0:2>,
> + <spanset+ 0:9>>
> + 2
> + 1
> + 0
> + BROKEN: should be '0 1 2'
> +
> + for 'A & f(B)', 'B' should not be affected by the order of 'A':
> +
> + $ try --optimize '2:0 & first(1 + 0 + 2)'
> + (and
> + (range
> + ('symbol', '2')
> + ('symbol', '0'))
> + (func
> + ('symbol', 'first')
> + (or
> + ('symbol', '1')
> + ('symbol', '0')
> + ('symbol', '2'))))
> + * optimized:
> + (and
> + (range
> + ('symbol', '2')
> + ('symbol', '0'))
> + (func
> + ('symbol', 'first')
> + (func
> + ('symbol', '_list')
> + ('string', '1\x000\x002'))))
> + * set:
> + <baseset
> + <limit n=1, offset=0,
> + <spanset- 0:2>,
> + <baseset [1, 0, 2]>>>
> + 1
> +
> + $ try --optimize '2:0 & not last(0 + 2 + 1)'
> + (and
> + (range
> + ('symbol', '2')
> + ('symbol', '0'))
> + (not
> + (func
> + ('symbol', 'last')
> + (or
> + ('symbol', '0')
> + ('symbol', '2')
> + ('symbol', '1')))))
> + * optimized:
> + (difference
> + (range
> + ('symbol', '2')
> + ('symbol', '0'))
> + (func
> + ('symbol', 'last')
> + (func
> + ('symbol', '_list')
> + ('string', '0\x002\x001'))))
> + * set:
> + <filteredset
> + <spanset- 0:2>,
> + <not
> + <baseset
> + <last n=1,
> + <fullreposet+ 0:9>,
> + <baseset [1, 2, 0]>>>>>
> + 2
> + 0
> +
> + for 'A & (op)(B)', 'B' should not be affected by the order of 'A':
> +
> + $ try --optimize '2:0 & (1 + 0 + 2):(0 + 2 + 1)'
> + (and
> + (range
> + ('symbol', '2')
> + ('symbol', '0'))
> + (range
> + (group
> + (or
> + ('symbol', '1')
> + ('symbol', '0')
> + ('symbol', '2')))
> + (group
> + (or
> + ('symbol', '0')
> + ('symbol', '2')
> + ('symbol', '1')))))
> + * optimized:
> + (and
> + (range
> + ('symbol', '2')
> + ('symbol', '0'))
> + (range
> + (func
> + ('symbol', '_list')
> + ('string', '1\x000\x002'))
> + (func
> + ('symbol', '_list')
> + ('string', '0\x002\x001'))))
> + * set:
> + <filteredset
> + <baseset [1]>,
> + <spanset- 0:2>>
> + 1
> +
> + 'A & B' can be rewritten as 'B & A' by weight, but the ordering rule should
> + be determined before the optimization (i.e. 'B' should take the ordering of
> + 'A'):
> +
> + $ try --optimize 'contains("glob:*") & (2 + 0 + 1)'
> + (and
> + (func
> + ('symbol', 'contains')
> + ('string', 'glob:*'))
> + (group
> + (or
> + ('symbol', '2')
> + ('symbol', '0')
> + ('symbol', '1'))))
> + * optimized:
> + (and
> + (func
> + ('symbol', '_list')
> + ('string', '2\x000\x001'))
> + (func
> + ('symbol', 'contains')
> + ('string', 'glob:*')))
> + * set:
> + <filteredset
> + <baseset [2, 0, 1]>,
> + <contains 'glob:*'>>
> + 2
> + 0
> + 1
> + BROKEN: should be '0 1 2'
> +
> + $ try --optimize 'reverse(contains("glob:*")) & (0 + 2 + 1)'
> + (and
> + (func
> + ('symbol', 'reverse')
> + (func
> + ('symbol', 'contains')
> + ('string', 'glob:*')))
> + (group
> + (or
> + ('symbol', '0')
> + ('symbol', '2')
> + ('symbol', '1'))))
> + * optimized:
> + (and
> + (func
> + ('symbol', '_list')
> + ('string', '0\x002\x001'))
> + (func
> + ('symbol', 'reverse')
> + (func
> + ('symbol', 'contains')
> + ('string', 'glob:*'))))
> + * set:
> + <filteredset
> + <baseset [1, 2, 0]>,
> + <contains 'glob:*'>>
> + 1
> + 2
> + 0
> + BROKEN: should be '2 1 0'
> +
> test sort revset
> --------------------------------------------
>
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
More information about the Mercurial-devel
mailing list