Mercurial > hg
changeset 38953:987d3a4b989f
match: add tests for visitdir functionality
There are a few cases that we could have done better with some additional logic;
I tried to annotate these when I noticed them, but may have missed some. The
tests are not exhaustive; there are certainly some patterns that I didn't test
well, and many that I didn't test at all.
The primary motivation was to get coverage on visitdir so that I can cover
identical cases in a similar method I'm working on, to make sure that this new
method behaves the same (or better).
Differential Revision: https://phab.mercurial-scm.org/D4128
author | spectral <spectral@google.com> |
---|---|
date | Sun, 05 Aug 2018 18:31:19 -0700 |
parents | 0e58c5b20745 |
children | 5a7df82de142 |
files | tests/test-match.py |
diffstat | 1 files changed, 429 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/tests/test-match.py Mon Jul 23 22:51:53 2018 -0700 +++ b/tests/test-match.py Sun Aug 05 18:31:19 2018 -0700 @@ -6,8 +6,23 @@ from mercurial import ( match as matchmod, + util, ) +class BaseMatcherTests(unittest.TestCase): + + def testVisitdir(self): + m = matchmod.basematcher('', '') + self.assertTrue(m.visitdir('.')) + self.assertTrue(m.visitdir('dir')) + +class AlwaysMatcherTests(unittest.TestCase): + + def testVisitdir(self): + m = matchmod.alwaysmatcher('', '') + self.assertEqual(m.visitdir('.'), 'all') + self.assertEqual(m.visitdir('dir'), 'all') + class NeverMatcherTests(unittest.TestCase): def testVisitdir(self): @@ -15,5 +30,419 @@ self.assertFalse(m.visitdir('.')) self.assertFalse(m.visitdir('dir')) +class PredicateMatcherTests(unittest.TestCase): + # predicatematcher does not currently define either of these methods, so + # this is equivalent to BaseMatcherTests. + + def testVisitdir(self): + m = matchmod.predicatematcher('', '', lambda *a: False) + self.assertTrue(m.visitdir('.')) + self.assertTrue(m.visitdir('dir')) + +class PatternMatcherTests(unittest.TestCase): + + def testVisitdirPrefix(self): + m = matchmod.match('x', '', patterns=['path:dir/subdir']) + assert isinstance(m, matchmod.patternmatcher) + self.assertTrue(m.visitdir('.')) + self.assertTrue(m.visitdir('dir')) + self.assertEqual(m.visitdir('dir/subdir'), 'all') + # OPT: This should probably be 'all' if its parent is? + self.assertTrue(m.visitdir('dir/subdir/x')) + self.assertFalse(m.visitdir('folder')) + + def testVisitdirRootfilesin(self): + m = matchmod.match('x', '', patterns=['rootfilesin:dir/subdir']) + assert isinstance(m, matchmod.patternmatcher) + self.assertTrue(m.visitdir('.')) + self.assertFalse(m.visitdir('dir/subdir/x')) + self.assertFalse(m.visitdir('folder')) + # FIXME: These should probably be True. + self.assertFalse(m.visitdir('dir')) + self.assertFalse(m.visitdir('dir/subdir')) + + def testVisitdirGlob(self): + m = matchmod.match('x', '', patterns=['glob:dir/z*']) + assert isinstance(m, matchmod.patternmatcher) + self.assertTrue(m.visitdir('.')) + self.assertTrue(m.visitdir('dir')) + self.assertFalse(m.visitdir('folder')) + # OPT: these should probably be False. + self.assertTrue(m.visitdir('dir/subdir')) + self.assertTrue(m.visitdir('dir/subdir/x')) + +class IncludeMatcherTests(unittest.TestCase): + + def testVisitdirPrefix(self): + m = matchmod.match('x', '', include=['path:dir/subdir']) + assert isinstance(m, matchmod.includematcher) + self.assertTrue(m.visitdir('.')) + self.assertTrue(m.visitdir('dir')) + self.assertEqual(m.visitdir('dir/subdir'), 'all') + # OPT: This should probably be 'all' if its parent is? + self.assertTrue(m.visitdir('dir/subdir/x')) + self.assertFalse(m.visitdir('folder')) + + def testVisitdirRootfilesin(self): + m = matchmod.match('x', '', include=['rootfilesin:dir/subdir']) + assert isinstance(m, matchmod.includematcher) + self.assertTrue(m.visitdir('.')) + self.assertTrue(m.visitdir('dir')) + self.assertTrue(m.visitdir('dir/subdir')) + self.assertFalse(m.visitdir('dir/subdir/x')) + self.assertFalse(m.visitdir('folder')) + + def testVisitdirGlob(self): + m = matchmod.match('x', '', include=['glob:dir/z*']) + assert isinstance(m, matchmod.includematcher) + self.assertTrue(m.visitdir('.')) + self.assertTrue(m.visitdir('dir')) + self.assertFalse(m.visitdir('folder')) + # OPT: these should probably be False. + self.assertTrue(m.visitdir('dir/subdir')) + self.assertTrue(m.visitdir('dir/subdir/x')) + +class ExactMatcherTests(unittest.TestCase): + + def testVisitdir(self): + m = matchmod.match('x', '', patterns=['dir/subdir/foo.txt'], exact=True) + assert isinstance(m, matchmod.exactmatcher) + self.assertTrue(m.visitdir('.')) + self.assertTrue(m.visitdir('dir')) + self.assertTrue(m.visitdir('dir/subdir')) + self.assertFalse(m.visitdir('dir/subdir/foo.txt')) + self.assertFalse(m.visitdir('dir/foo')) + self.assertFalse(m.visitdir('dir/subdir/x')) + self.assertFalse(m.visitdir('folder')) + +class DifferenceMatcherTests(unittest.TestCase): + + def testVisitdirM2always(self): + m1 = matchmod.alwaysmatcher('', '') + m2 = matchmod.alwaysmatcher('', '') + dm = matchmod.differencematcher(m1, m2) + # dm should be equivalent to a nevermatcher. + self.assertFalse(dm.visitdir('.')) + self.assertFalse(dm.visitdir('dir')) + self.assertFalse(dm.visitdir('dir/subdir')) + self.assertFalse(dm.visitdir('dir/subdir/z')) + self.assertFalse(dm.visitdir('dir/foo')) + self.assertFalse(dm.visitdir('dir/subdir/x')) + self.assertFalse(dm.visitdir('folder')) + + def testVisitdirM2never(self): + m1 = matchmod.alwaysmatcher('', '') + m2 = matchmod.nevermatcher('', '') + dm = matchmod.differencematcher(m1, m2) + # dm should be equivalent to a alwaysmatcher. OPT: if m2 is a + # nevermatcher, we could return 'all' for these. + # + # We're testing Equal-to-True instead of just 'assertTrue' since + # assertTrue does NOT verify that it's a bool, just that it's truthy. + # While we may want to eventually make these return 'all', they should + # not currently do so. + self.assertEqual(dm.visitdir('.'), True) + self.assertEqual(dm.visitdir('dir'), True) + self.assertEqual(dm.visitdir('dir/subdir'), True) + self.assertEqual(dm.visitdir('dir/subdir/z'), True) + self.assertEqual(dm.visitdir('dir/foo'), True) + self.assertEqual(dm.visitdir('dir/subdir/x'), True) + self.assertEqual(dm.visitdir('folder'), True) + + def testVisitdirM2SubdirPrefix(self): + m1 = matchmod.alwaysmatcher('', '') + m2 = matchmod.match('', '', patterns=['path:dir/subdir']) + dm = matchmod.differencematcher(m1, m2) + self.assertEqual(dm.visitdir('.'), True) + self.assertEqual(dm.visitdir('dir'), True) + self.assertFalse(dm.visitdir('dir/subdir')) + # OPT: We should probably return False for these; we don't because + # patternmatcher.visitdir() (our m2) doesn't return 'all' for subdirs of + # an 'all' pattern, just True. + self.assertEqual(dm.visitdir('dir/subdir/z'), True) + self.assertEqual(dm.visitdir('dir/subdir/x'), True) + # OPT: We could return 'all' for these. + self.assertEqual(dm.visitdir('dir/foo'), True) + self.assertEqual(dm.visitdir('folder'), True) + + # We're using includematcher instead of patterns because it behaves slightly + # better (giving narrower results) than patternmatcher. + def testVisitdirIncludeIncludfe(self): + m1 = matchmod.match('', '', include=['path:dir/subdir']) + m2 = matchmod.match('', '', include=['rootfilesin:dir']) + dm = matchmod.differencematcher(m1, m2) + self.assertEqual(dm.visitdir('.'), True) + self.assertEqual(dm.visitdir('dir'), True) + self.assertEqual(dm.visitdir('dir/subdir'), True) + self.assertFalse(dm.visitdir('dir/foo')) + self.assertFalse(dm.visitdir('folder')) + # OPT: We should probably return False for these; we don't because + # patternmatcher.visitdir() (our m2) doesn't return 'all' for subdirs of + # an 'all' pattern, just True. + self.assertEqual(dm.visitdir('dir/subdir/z'), True) + self.assertEqual(dm.visitdir('dir/subdir/x'), True) + +class IntersectionMatcherTests(unittest.TestCase): + + def testVisitdirM2always(self): + m1 = matchmod.alwaysmatcher('', '') + m2 = matchmod.alwaysmatcher('', '') + im = matchmod.intersectmatchers(m1, m2) + # im should be equivalent to a alwaysmatcher. + self.assertEqual(im.visitdir('.'), 'all') + self.assertEqual(im.visitdir('dir'), 'all') + self.assertEqual(im.visitdir('dir/subdir'), 'all') + self.assertEqual(im.visitdir('dir/subdir/z'), 'all') + self.assertEqual(im.visitdir('dir/foo'), 'all') + self.assertEqual(im.visitdir('dir/subdir/x'), 'all') + self.assertEqual(im.visitdir('folder'), 'all') + + def testVisitdirM2never(self): + m1 = matchmod.alwaysmatcher('', '') + m2 = matchmod.nevermatcher('', '') + im = matchmod.intersectmatchers(m1, m2) + # im should be equivalent to a nevermatcher. + self.assertFalse(im.visitdir('.')) + self.assertFalse(im.visitdir('dir')) + self.assertFalse(im.visitdir('dir/subdir')) + self.assertFalse(im.visitdir('dir/subdir/z')) + self.assertFalse(im.visitdir('dir/foo')) + self.assertFalse(im.visitdir('dir/subdir/x')) + self.assertFalse(im.visitdir('folder')) + + def testVisitdirM2SubdirPrefix(self): + m1 = matchmod.alwaysmatcher('', '') + m2 = matchmod.match('', '', patterns=['path:dir/subdir']) + im = matchmod.intersectmatchers(m1, m2) + self.assertEqual(im.visitdir('.'), True) + self.assertEqual(im.visitdir('dir'), True) + self.assertEqual(im.visitdir('dir/subdir'), 'all') + self.assertFalse(im.visitdir('dir/foo')) + self.assertFalse(im.visitdir('folder')) + # OPT: We should probably return 'all' for these; we don't because + # patternmatcher.visitdir() (our m2) doesn't return 'all' for subdirs of + # an 'all' pattern, just True. + self.assertEqual(im.visitdir('dir/subdir/z'), True) + self.assertEqual(im.visitdir('dir/subdir/x'), True) + + # We're using includematcher instead of patterns because it behaves slightly + # better (giving narrower results) than patternmatcher. + def testVisitdirIncludeIncludfe(self): + m1 = matchmod.match('', '', include=['path:dir/subdir']) + m2 = matchmod.match('', '', include=['rootfilesin:dir']) + im = matchmod.intersectmatchers(m1, m2) + self.assertEqual(im.visitdir('.'), True) + self.assertEqual(im.visitdir('dir'), True) + self.assertFalse(im.visitdir('dir/subdir')) + self.assertFalse(im.visitdir('dir/foo')) + self.assertFalse(im.visitdir('folder')) + self.assertFalse(im.visitdir('dir/subdir/z')) + self.assertFalse(im.visitdir('dir/subdir/x')) + + # We're using includematcher instead of patterns because it behaves slightly + # better (giving narrower results) than patternmatcher. + def testVisitdirIncludeInclude2(self): + m1 = matchmod.match('', '', include=['path:dir/subdir']) + m2 = matchmod.match('', '', include=['path:folder']) + im = matchmod.intersectmatchers(m1, m2) + # FIXME: is True correct here? + self.assertEqual(im.visitdir('.'), True) + self.assertFalse(im.visitdir('dir')) + self.assertFalse(im.visitdir('dir/subdir')) + self.assertFalse(im.visitdir('dir/foo')) + self.assertFalse(im.visitdir('folder')) + self.assertFalse(im.visitdir('dir/subdir/z')) + self.assertFalse(im.visitdir('dir/subdir/x')) + + # We're using includematcher instead of patterns because it behaves slightly + # better (giving narrower results) than patternmatcher. + def testVisitdirIncludeInclude3(self): + m1 = matchmod.match('', '', include=['path:dir/subdir/x']) + m2 = matchmod.match('', '', include=['path:dir/subdir']) + im = matchmod.intersectmatchers(m1, m2) + self.assertEqual(im.visitdir('.'), True) + self.assertEqual(im.visitdir('dir'), True) + self.assertEqual(im.visitdir('dir/subdir'), True) + self.assertFalse(im.visitdir('dir/foo')) + self.assertFalse(im.visitdir('folder')) + self.assertFalse(im.visitdir('dir/subdir/z')) + # OPT: this should probably be 'all' not True. + self.assertEqual(im.visitdir('dir/subdir/x'), True) + + # We're using includematcher instead of patterns because it behaves slightly + # better (giving narrower results) than patternmatcher. + def testVisitdirIncludeInclude4(self): + m1 = matchmod.match('', '', include=['path:dir/subdir/x']) + m2 = matchmod.match('', '', include=['path:dir/subdir/z']) + im = matchmod.intersectmatchers(m1, m2) + # OPT: these next three could probably be False as well. + self.assertEqual(im.visitdir('.'), True) + self.assertEqual(im.visitdir('dir'), True) + self.assertEqual(im.visitdir('dir/subdir'), True) + self.assertFalse(im.visitdir('dir/foo')) + self.assertFalse(im.visitdir('folder')) + self.assertFalse(im.visitdir('dir/subdir/z')) + self.assertFalse(im.visitdir('dir/subdir/x')) + +class UnionMatcherTests(unittest.TestCase): + + def testVisitdirM2always(self): + m1 = matchmod.alwaysmatcher('', '') + m2 = matchmod.alwaysmatcher('', '') + um = matchmod.unionmatcher([m1, m2]) + # um should be equivalent to a alwaysmatcher. + self.assertEqual(um.visitdir('.'), 'all') + self.assertEqual(um.visitdir('dir'), 'all') + self.assertEqual(um.visitdir('dir/subdir'), 'all') + self.assertEqual(um.visitdir('dir/subdir/z'), 'all') + self.assertEqual(um.visitdir('dir/foo'), 'all') + self.assertEqual(um.visitdir('dir/subdir/x'), 'all') + self.assertEqual(um.visitdir('folder'), 'all') + + def testVisitdirM1never(self): + m1 = matchmod.nevermatcher('', '') + m2 = matchmod.alwaysmatcher('', '') + um = matchmod.unionmatcher([m1, m2]) + # um should be equivalent to a alwaysmatcher. + self.assertEqual(um.visitdir('.'), 'all') + self.assertEqual(um.visitdir('dir'), 'all') + self.assertEqual(um.visitdir('dir/subdir'), 'all') + self.assertEqual(um.visitdir('dir/subdir/z'), 'all') + self.assertEqual(um.visitdir('dir/foo'), 'all') + self.assertEqual(um.visitdir('dir/subdir/x'), 'all') + self.assertEqual(um.visitdir('folder'), 'all') + + def testVisitdirM2never(self): + m1 = matchmod.alwaysmatcher('', '') + m2 = matchmod.nevermatcher('', '') + um = matchmod.unionmatcher([m1, m2]) + # um should be equivalent to a alwaysmatcher. + self.assertEqual(um.visitdir('.'), 'all') + self.assertEqual(um.visitdir('dir'), 'all') + self.assertEqual(um.visitdir('dir/subdir'), 'all') + self.assertEqual(um.visitdir('dir/subdir/z'), 'all') + self.assertEqual(um.visitdir('dir/foo'), 'all') + self.assertEqual(um.visitdir('dir/subdir/x'), 'all') + self.assertEqual(um.visitdir('folder'), 'all') + + def testVisitdirM2SubdirPrefix(self): + m1 = matchmod.alwaysmatcher('', '') + m2 = matchmod.match('', '', patterns=['path:dir/subdir']) + um = matchmod.unionmatcher([m1, m2]) + self.assertEqual(um.visitdir('.'), 'all') + self.assertEqual(um.visitdir('dir'), 'all') + self.assertEqual(um.visitdir('dir/subdir'), 'all') + self.assertEqual(um.visitdir('dir/foo'), 'all') + self.assertEqual(um.visitdir('folder'), 'all') + self.assertEqual(um.visitdir('dir/subdir/z'), 'all') + self.assertEqual(um.visitdir('dir/subdir/x'), 'all') + + # We're using includematcher instead of patterns because it behaves slightly + # better (giving narrower results) than patternmatcher. + def testVisitdirIncludeIncludfe(self): + m1 = matchmod.match('', '', include=['path:dir/subdir']) + m2 = matchmod.match('', '', include=['rootfilesin:dir']) + um = matchmod.unionmatcher([m1, m2]) + self.assertEqual(um.visitdir('.'), True) + self.assertEqual(um.visitdir('dir'), True) + self.assertEqual(um.visitdir('dir/subdir'), 'all') + self.assertFalse(um.visitdir('dir/foo')) + self.assertFalse(um.visitdir('folder')) + # OPT: These two should probably be 'all' not True. + self.assertEqual(um.visitdir('dir/subdir/z'), True) + self.assertEqual(um.visitdir('dir/subdir/x'), True) + + # We're using includematcher instead of patterns because it behaves slightly + # better (giving narrower results) than patternmatcher. + def testVisitdirIncludeInclude2(self): + m1 = matchmod.match('', '', include=['path:dir/subdir']) + m2 = matchmod.match('', '', include=['path:folder']) + um = matchmod.unionmatcher([m1, m2]) + self.assertEqual(um.visitdir('.'), True) + self.assertEqual(um.visitdir('dir'), True) + self.assertEqual(um.visitdir('dir/subdir'), 'all') + self.assertFalse(um.visitdir('dir/foo')) + self.assertEqual(um.visitdir('folder'), 'all') + # OPT: These should probably be 'all' not True. + self.assertEqual(um.visitdir('dir/subdir/z'), True) + self.assertEqual(um.visitdir('dir/subdir/x'), True) + + # We're using includematcher instead of patterns because it behaves slightly + # better (giving narrower results) than patternmatcher. + def testVisitdirIncludeInclude3(self): + m1 = matchmod.match('', '', include=['path:dir/subdir/x']) + m2 = matchmod.match('', '', include=['path:dir/subdir']) + um = matchmod.unionmatcher([m1, m2]) + self.assertEqual(um.visitdir('.'), True) + self.assertEqual(um.visitdir('dir'), True) + self.assertEqual(um.visitdir('dir/subdir'), 'all') + self.assertFalse(um.visitdir('dir/foo')) + self.assertFalse(um.visitdir('folder')) + self.assertEqual(um.visitdir('dir/subdir/x'), 'all') + # OPT: this should probably be 'all' not True. + self.assertEqual(um.visitdir('dir/subdir/z'), True) + + # We're using includematcher instead of patterns because it behaves slightly + # better (giving narrower results) than patternmatcher. + def testVisitdirIncludeInclude4(self): + m1 = matchmod.match('', '', include=['path:dir/subdir/x']) + m2 = matchmod.match('', '', include=['path:dir/subdir/z']) + um = matchmod.unionmatcher([m1, m2]) + # OPT: these next three could probably be False as well. + self.assertEqual(um.visitdir('.'), True) + self.assertEqual(um.visitdir('dir'), True) + self.assertEqual(um.visitdir('dir/subdir'), True) + self.assertFalse(um.visitdir('dir/foo')) + self.assertFalse(um.visitdir('folder')) + self.assertEqual(um.visitdir('dir/subdir/z'), 'all') + self.assertEqual(um.visitdir('dir/subdir/x'), 'all') + +class SubdirMatcherTests(unittest.TestCase): + + def testVisitdir(self): + m = matchmod.match('', '', include=['path:dir/subdir']) + sm = matchmod.subdirmatcher('dir', m) + + self.assertEqual(sm.visitdir('.'), True) + self.assertEqual(sm.visitdir('subdir'), 'all') + # OPT: These next two should probably be 'all' not True. + self.assertEqual(sm.visitdir('subdir/x'), True) + self.assertEqual(sm.visitdir('subdir/z'), True) + self.assertFalse(sm.visitdir('foo')) + +class PrefixdirMatcherTests(unittest.TestCase): + + def testVisitdir(self): + m = matchmod.match(util.localpath('root/d'), 'e/f', + ['../a.txt', 'b.txt']) + pm = matchmod.prefixdirmatcher('root', 'd/e/f', 'd', m) + + # `m` elides 'd' because it's part of the root, and the rest of the + # patterns are relative. + self.assertEqual(bool(m('a.txt')), False) + self.assertEqual(bool(m('b.txt')), False) + self.assertEqual(bool(m('e/a.txt')), True) + self.assertEqual(bool(m('e/b.txt')), False) + self.assertEqual(bool(m('e/f/b.txt')), True) + + # The prefix matcher re-adds 'd' to the paths, so they need to be + # specified when using the prefixdirmatcher. + self.assertEqual(bool(pm('a.txt')), False) + self.assertEqual(bool(pm('b.txt')), False) + self.assertEqual(bool(pm('d/e/a.txt')), True) + self.assertEqual(bool(pm('d/e/b.txt')), False) + self.assertEqual(bool(pm('d/e/f/b.txt')), True) + + self.assertEqual(m.visitdir('.'), True) + self.assertEqual(m.visitdir('e'), True) + self.assertEqual(m.visitdir('e/f'), True) + self.assertEqual(m.visitdir('e/f/g'), False) + + self.assertEqual(pm.visitdir('.'), True) + self.assertEqual(pm.visitdir('d'), True) + self.assertEqual(pm.visitdir('d/e'), True) + self.assertEqual(pm.visitdir('d/e/f'), True) + self.assertEqual(pm.visitdir('d/e/f/g'), False) + if __name__ == '__main__': silenttestrunner.main(__name__)