~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_globbing.py

  • Committer: Patch Queue Manager
  • Date: 2014-02-12 18:22:22 UTC
  • mfrom: (6589.2.1 trunk)
  • Revision ID: pqm@pqm.ubuntu.com-20140212182222-beouo25gaf1cny76
(vila) The XDG Base Directory Specification uses the XDG_CACHE_HOME,
 not XDG_CACHE_DIR. (Andrew Starr-Bochicchio)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006 Canonical Ltd
 
1
# Copyright (C) 2006-2011 Canonical Ltd
2
2
# -*- coding: utf-8 -*-
3
3
#
4
4
# This program is free software; you can redistribute it and/or modify
13
13
#
14
14
# You should have received a copy of the GNU General Public License
15
15
# along with this program; if not, write to the Free Software
16
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 
 
 
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
17
 
 
18
import re
 
19
 
 
20
from bzrlib import errors
18
21
from bzrlib.globbing import (
19
22
    Globster,
 
23
    ExceptionGlobster,
 
24
    _OrderedGlobster,
 
25
    normalize_pattern
20
26
    )
21
27
from bzrlib.tests import (
22
 
    TestCase, 
23
 
    TestCaseInTempDir,
 
28
    TestCase,
24
29
    )
25
30
 
26
31
 
32
37
                glob = glob_prefix + glob
33
38
            globster = Globster([glob])
34
39
            for name in positive:
35
 
                self.failUnless(globster.match(name), repr(
 
40
                self.assertTrue(globster.match(name), repr(
36
41
                    u'name "%s" does not match glob "%s" (re=%s)' %
37
42
                    (name, glob, globster._regex_patterns[0][0].pattern)))
38
43
            for name in negative:
39
 
                self.failIf(globster.match(name), repr(
 
44
                self.assertFalse(globster.match(name), repr(
40
45
                    u'name "%s" does match glob "%s" (re=%s)' %
41
46
                    (name, glob, globster._regex_patterns[0][0].pattern)))
42
47
 
49
54
    def test_char_group_digit(self):
50
55
        self.assertMatchBasenameAndFullpath([
51
56
            # The definition of digit this uses includes arabic digits from
52
 
            # non-latin scripts (arabic, indic, etc.) and subscript/superscript
53
 
            # digits, but neither roman numerals nor vulgar fractions.
 
57
            # non-latin scripts (arabic, indic, etc.) but neither roman
 
58
            # numerals nor vulgar fractions. Some characters such as
 
59
            # subscript/superscript digits may or may not match depending on
 
60
            # the Python version used, see: <http://bugs.python.org/issue6561>
54
61
            (u'[[:digit:]]',
55
 
             [u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21', u'\xb9'],
 
62
             [u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21'],
56
63
             [u'T', u'q', u' ', u'\u8336', u'.']),
57
64
            (u'[^[:digit:]]',
58
65
             [u'T', u'q', u' ', u'\u8336', u'.'],
59
 
             [u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21', u'\xb9']),
 
66
             [u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21']),
60
67
            ])
61
68
 
62
69
    def test_char_group_space(self):
114
121
            (u'[a-z]',
115
122
             [u'a', u'q', u'f'],
116
123
             [u'A', u'Q', u'F']),
117
 
            (ur'[^a-z]',
 
124
            (u'[^a-z]',
118
125
             [u'A', u'Q', u'F'],
119
126
             [u'a', u'q', u'f']),
120
127
            (u'[!a-z]foo',
121
128
             [u'Afoo', u'.foo'],
122
129
             [u'afoo', u'ABfoo']),
123
 
            (ur'foo[!a-z]bar',
 
130
            (u'foo[!a-z]bar',
124
131
             [u'fooAbar', u'foo.bar'],
125
132
             [u'foojbar']),
126
 
            (ur'[\x20-\x30\u8336]',
 
133
            (u'[\x20-\x30\u8336]',
127
134
             [u'\040', u'\044', u'\u8336'],
128
135
             [u'\x1f']),
129
 
            (ur'[^\x20-\x30\u8336]',
 
136
            (u'[^\x20-\x30\u8336]',
130
137
             [u'\x1f'],
131
138
             [u'\040', u'\044', u'\u8336']),
132
139
            ])
133
140
 
134
141
    def test_regex(self):
135
142
        self.assertMatch([
136
 
            (ur'RE:(a|b|c+)',
137
 
             [u'a', u'b', u'ccc'],
138
 
             [u'd', u'aa', u'c+', u'-a']),
139
 
            (ur'RE:(?:a|b|c+)',
140
 
             [u'a', u'b', u'ccc'],
141
 
             [u'd', u'aa', u'c+', u'-a']),
142
 
            (ur'RE:(?P<a>.)(?P=a)',
 
143
            (u'RE:(a|b|c+)',
 
144
             [u'a', u'b', u'ccc'],
 
145
             [u'd', u'aa', u'c+', u'-a']),
 
146
            (u'RE:(?:a|b|c+)',
 
147
             [u'a', u'b', u'ccc'],
 
148
             [u'd', u'aa', u'c+', u'-a']),
 
149
            (u'RE:(?P<a>.)(?P=a)',
143
150
             [u'a'],
144
151
             [u'ab', u'aa', u'aaa']),
 
152
            # test we can handle odd numbers of trailing backslashes
 
153
            (u'RE:a\\\\\\',
 
154
             [u'a\\'],
 
155
             [u'a', u'ab', u'aa', u'aaa']),
145
156
            ])
146
157
 
147
158
    def test_question_mark(self):
166
177
             [u'foo/x', u'foo/bax', u'foo/a.x', u'foo/.x', u'foo/.q.x'],
167
178
             [u'foo/bar/bax']),
168
179
            (u'*/*x',
169
 
             [u'\u8336/x', u'foo/x', u'foo/bax', u'x/a.x', u'.foo/x', 
 
180
             [u'\u8336/x', u'foo/x', u'foo/bax', u'x/a.x', u'.foo/x',
170
181
              u'\u8336/.x', u'foo/.q.x'],
171
182
             [u'foo/bar/bax']),
172
183
            (u'f*',
173
184
             [u'foo', u'foo.bar'],
174
185
             [u'.foo', u'foo/bar', u'foo/.bar']),
175
186
            (u'*bar',
176
 
             [u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar', 
 
187
             [u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar',
177
188
              u'foo/foobar', u'foo/f.bar', u'.bar', u'foo/.bar'],
178
189
             []),
179
190
            ])
186
197
             [u'foox', u'foo/bax', u'foo/.x', u'foo/bar/bax']),
187
198
            (u'**/bar',
188
199
             [u'bar', u'foo/bar'],
189
 
             [u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar', 
 
200
             [u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar',
190
201
              u'.bar', u'foo/.bar']),
191
202
            # check that we ignore extra *s, so *** is treated like ** not *.
192
203
            (u'foo/***/x',
194
205
             [u'foox', u'foo/bax', u'foo/.x', u'foo/bar/bax']),
195
206
            (u'***/bar',
196
207
             [u'bar', u'foo/bar'],
197
 
             [u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar', 
 
208
             [u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar',
198
209
              u'.bar', u'foo/.bar']),
199
210
            # the remaining tests check that ** is interpreted as *
200
211
            # unless it is a whole path component
211
222
             [u'foo', u'foo.bar'],
212
223
             [u'.foo', u'foo/bar', u'foo/.bar']),
213
224
            (u'**bar',
214
 
             [u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar', 
 
225
             [u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar',
215
226
              u'foo/foobar', u'foo/f.bar', u'.bar', u'foo/.bar'],
216
227
             []),
217
228
            ])
226
237
             [u'foo/bar', u'foo/.bar', u'x/foo/y']),
227
238
            ])
228
239
 
 
240
    def test_backslash(self):
 
241
        self.assertMatch([
 
242
            (u'.\\foo',
 
243
             [u'foo'],
 
244
             [u'\u8336/foo', u'barfoo', u'x/y/foo']),
 
245
            (u'.\\f*',
 
246
             [u'foo'],
 
247
             [u'foo/bar', u'foo/.bar', u'x/foo/y']),
 
248
            (u'foo\\**\\x',
 
249
             [u'foo/x', u'foo/bar/x'],
 
250
             [u'foox', u'foo/bax', u'foo/.x', u'foo/bar/bax']),
 
251
            ])
 
252
 
 
253
    def test_trailing_slash(self):
 
254
        self.assertMatch([
 
255
            (u'./foo/',
 
256
             [u'foo'],
 
257
             [u'\u8336/foo', u'barfoo', u'x/y/foo']),
 
258
            (u'.\\foo\\',
 
259
             [u'foo'],
 
260
             [u'foo/', u'\u8336/foo', u'barfoo', u'x/y/foo']),
 
261
            ])
 
262
 
229
263
    def test_leading_asterisk_dot(self):
230
264
        self.assertMatch([
231
265
            (u'*.x',
232
 
             [u'foo/bar/baz.x', u'\u8336/Q.x', u'foo.y.x', u'.foo.x', 
 
266
             [u'foo/bar/baz.x', u'\u8336/Q.x', u'foo.y.x', u'.foo.x',
233
267
              u'bar/.foo.x', u'.x',],
234
268
             [u'foo.x.y']),
235
269
            (u'foo/*.bar',
265
299
    def test_large_globset(self):
266
300
        """tests that the globster can handle a large set of patterns.
267
301
 
268
 
        Large is defined as more than supported by python regex groups, 
 
302
        Large is defined as more than supported by python regex groups,
269
303
        i.e. 99.
270
304
        This test assumes the globs are broken into regexs containing 99
271
305
        groups.
278
312
            self.assertEqual(patterns[x],globster.match(filename))
279
313
        self.assertEqual(None,globster.match('foobar.300'))
280
314
 
 
315
    def test_bad_pattern(self):
 
316
        """Ensure that globster handles bad patterns cleanly."""
 
317
        patterns = [u'RE:[', u'/home/foo', u'RE:*.cpp']
 
318
        g = Globster(patterns)
 
319
        e = self.assertRaises(errors.InvalidPattern, g.match, 'filename')
 
320
        self.assertContainsRe(e.msg,
 
321
            "File.*ignore.*contains error.*RE:\[.*RE:\*\.cpp", flags=re.DOTALL)
 
322
 
 
323
 
 
324
class TestExceptionGlobster(TestCase):
 
325
 
 
326
    def test_exclusion_patterns(self):
 
327
        """test that exception patterns are not matched"""
 
328
        patterns = [ u'*', u'!./local', u'!./local/**/*', u'!RE:\.z.*',u'!!./.zcompdump' ]
 
329
        globster = ExceptionGlobster(patterns)
 
330
        self.assertEqual(u'*', globster.match('tmp/foo.txt'))
 
331
        self.assertEqual(None, globster.match('local'))
 
332
        self.assertEqual(None, globster.match('local/bin/wombat'))
 
333
        self.assertEqual(None, globster.match('.zshrc'))
 
334
        self.assertEqual(None, globster.match('.zfunctions/fiddle/flam'))
 
335
        self.assertEqual(u'!!./.zcompdump', globster.match('.zcompdump'))
 
336
 
 
337
    def test_exclusion_order(self):
 
338
        """test that ordering of exclusion patterns does not matter"""
 
339
        patterns = [ u'static/**/*.html', u'!static/**/versionable.html']
 
340
        globster = ExceptionGlobster(patterns)
 
341
        self.assertEqual(u'static/**/*.html', globster.match('static/foo.html'))
 
342
        self.assertEqual(None, globster.match('static/versionable.html'))
 
343
        self.assertEqual(None, globster.match('static/bar/versionable.html'))
 
344
        globster = ExceptionGlobster(reversed(patterns))
 
345
        self.assertEqual(u'static/**/*.html', globster.match('static/foo.html'))
 
346
        self.assertEqual(None, globster.match('static/versionable.html'))
 
347
        self.assertEqual(None, globster.match('static/bar/versionable.html'))
 
348
 
 
349
class TestOrderedGlobster(TestCase):
 
350
 
 
351
    def test_ordered_globs(self):
 
352
        """test that the first match in a list is the one found"""
 
353
        patterns = [ u'*.foo', u'bar.*']
 
354
        globster = _OrderedGlobster(patterns)
 
355
        self.assertEqual(u'*.foo', globster.match('bar.foo'))
 
356
        self.assertEqual(None, globster.match('foo.bar'))
 
357
        globster = _OrderedGlobster(reversed(patterns))
 
358
        self.assertEqual(u'bar.*', globster.match('bar.foo'))
 
359
        self.assertEqual(None, globster.match('foo.bar'))
 
360
 
 
361
 
 
362
class TestNormalizePattern(TestCase):
 
363
 
 
364
    def test_backslashes(self):
 
365
        """tests that backslashes are converted to forward slashes, multiple
 
366
        backslashes are collapsed to single forward slashes and trailing
 
367
        backslashes are removed"""
 
368
        self.assertEqual(u'/', normalize_pattern(u'\\'))
 
369
        self.assertEqual(u'/', normalize_pattern(u'\\\\'))
 
370
        self.assertEqual(u'/foo/bar', normalize_pattern(u'\\foo\\bar'))
 
371
        self.assertEqual(u'foo/bar', normalize_pattern(u'foo\\bar\\'))
 
372
        self.assertEqual(u'/foo/bar', normalize_pattern(u'\\\\foo\\\\bar\\\\'))
 
373
 
 
374
    def test_forward_slashes(self):
 
375
        """tests that multiple foward slashes are collapsed to single forward
 
376
        slashes and trailing forward slashes are removed"""
 
377
        self.assertEqual(u'/', normalize_pattern(u'/'))
 
378
        self.assertEqual(u'/', normalize_pattern(u'//'))
 
379
        self.assertEqual(u'/foo/bar', normalize_pattern(u'/foo/bar'))
 
380
        self.assertEqual(u'foo/bar', normalize_pattern(u'foo/bar/'))
 
381
        self.assertEqual(u'/foo/bar', normalize_pattern(u'//foo//bar//'))
 
382
 
 
383
    def test_mixed_slashes(self):
 
384
        """tests that multiple mixed slashes are collapsed to single forward
 
385
        slashes and trailing mixed slashes are removed"""
 
386
        self.assertEqual(u'/foo/bar', normalize_pattern(u'\\/\\foo//\\///bar/\\\\/'))