~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_globbing.py

  • Committer: Alexander Belchenko
  • Date: 2007-01-24 13:03:32 UTC
  • mto: This revision was merged to the branch mainline in revision 2242.
  • Revision ID: bialix@ukr.net-20070124130332-ane2eqz3eqrtm9u1
Use new API for testing

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006 Canonical Ltd
 
2
# -*- coding: utf-8 -*-
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
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
 
 
18
from bzrlib.globbing import (
 
19
    Globster,
 
20
    )
 
21
from bzrlib.tests import (
 
22
    TestCase, 
 
23
    TestCaseInTempDir,
 
24
    )
 
25
 
 
26
 
 
27
class TestGlobster(TestCase):
 
28
 
 
29
    def assertMatch(self, matchset, glob_prefix=None):
 
30
        for glob, positive, negative in matchset:
 
31
            if glob_prefix:
 
32
                glob = glob_prefix + glob
 
33
            globster = Globster([glob])
 
34
            for name in positive:
 
35
                self.failUnless(globster.match(name), repr(
 
36
                    u'name "%s" does not match glob "%s" (re=%s)' %
 
37
                    (name, glob, globster._regex_patterns[0][0].pattern)))
 
38
            for name in negative:
 
39
                self.failIf(globster.match(name), repr(
 
40
                    u'name "%s" does match glob "%s" (re=%s)' %
 
41
                    (name, glob, globster._regex_patterns[0][0].pattern)))
 
42
 
 
43
    def assertMatchBasenameAndFullpath(self, matchset):
 
44
        # test basename matcher
 
45
        self.assertMatch(matchset)
 
46
        # test fullpath matcher
 
47
        self.assertMatch(matchset, glob_prefix='./')
 
48
 
 
49
    def test_char_group_digit(self):
 
50
        self.assertMatchBasenameAndFullpath([
 
51
            # 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.
 
54
            (u'[[:digit:]]',
 
55
             [u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21', u'\xb9'],
 
56
             [u'T', u'q', u' ', u'\u8336', u'.']),
 
57
            (u'[^[:digit:]]',
 
58
             [u'T', u'q', u' ', u'\u8336', u'.'],
 
59
             [u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21', u'\xb9']),
 
60
            ])
 
61
 
 
62
    def test_char_group_space(self):
 
63
        self.assertMatchBasenameAndFullpath([
 
64
            (u'[[:space:]]',
 
65
             [u' ', u'\t', u'\n', u'\xa0', u'\u2000', u'\u2002'],
 
66
             [u'a', u'-', u'\u8336', u'.']),
 
67
            (u'[^[:space:]]',
 
68
             [u'a', u'-', u'\u8336', u'.'],
 
69
             [u' ', u'\t', u'\n', u'\xa0', u'\u2000', u'\u2002']),
 
70
            ])
 
71
 
 
72
    def test_char_group_alnum(self):
 
73
        self.assertMatchBasenameAndFullpath([
 
74
            (u'[[:alnum:]]',
 
75
             [u'a', u'Z', u'\u017e', u'\u8336'],
 
76
             [u':', u'-', u'\u25cf', u'.']),
 
77
            (u'[^[:alnum:]]',
 
78
             [u':', u'-', u'\u25cf', u'.'],
 
79
             [u'a']),
 
80
            ])
 
81
 
 
82
    def test_char_group_ascii(self):
 
83
        self.assertMatchBasenameAndFullpath([
 
84
            (u'[[:ascii:]]',
 
85
             [u'a', u'Q', u'^', u'.'],
 
86
             [u'\xcc', u'\u8336']),
 
87
            (u'[^[:ascii:]]',
 
88
             [u'\xcc', u'\u8336'],
 
89
             [u'a', u'Q', u'^', u'.']),
 
90
            ])
 
91
 
 
92
    def test_char_group_blank(self):
 
93
        self.assertMatchBasenameAndFullpath([
 
94
            (u'[[:blank:]]',
 
95
             [u'\t'],
 
96
             [u'x', u'y', u'z', u'.']),
 
97
            (u'[^[:blank:]]',
 
98
             [u'x', u'y', u'z', u'.'],
 
99
             [u'\t']),
 
100
            ])
 
101
 
 
102
    def test_char_group_cntrl(self):
 
103
        self.assertMatchBasenameAndFullpath([
 
104
            (u'[[:cntrl:]]',
 
105
             [u'\b', u'\t', '\x7f'],
 
106
             [u'a', u'Q', u'\u8336', u'.']),
 
107
            (u'[^[:cntrl:]]',
 
108
             [u'a', u'Q', u'\u8336', u'.'],
 
109
             [u'\b', u'\t', '\x7f']),
 
110
            ])
 
111
 
 
112
    def test_char_group_range(self):
 
113
        self.assertMatchBasenameAndFullpath([
 
114
            (u'[a-z]',
 
115
             [u'a', u'q', u'f'],
 
116
             [u'A', u'Q', u'F']),
 
117
            (ur'[^a-z]',
 
118
             [u'A', u'Q', u'F'],
 
119
             [u'a', u'q', u'f']),
 
120
            (u'[!a-z]foo',
 
121
             [u'Afoo', u'.foo'],
 
122
             [u'afoo', u'ABfoo']),
 
123
            (ur'foo[!a-z]bar',
 
124
             [u'fooAbar', u'foo.bar'],
 
125
             [u'foojbar']),
 
126
            (ur'[\x20-\x30\u8336]',
 
127
             [u'\040', u'\044', u'\u8336'],
 
128
             [u'\x1f']),
 
129
            (ur'[^\x20-\x30\u8336]',
 
130
             [u'\x1f'],
 
131
             [u'\040', u'\044', u'\u8336']),
 
132
            ])
 
133
 
 
134
    def test_regex(self):
 
135
        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'a'],
 
144
             [u'ab', u'aa', u'aaa']),
 
145
            ])
 
146
 
 
147
    def test_question_mark(self):
 
148
        self.assertMatch([
 
149
            (u'?foo',
 
150
             [u'xfoo', u'bar/xfoo', u'bar/\u8336foo', u'.foo', u'bar/.foo'],
 
151
             [u'bar/foo', u'foo']),
 
152
            (u'foo?bar',
 
153
             [u'fooxbar', u'foo.bar', u'foo\u8336bar', u'qyzzy/foo.bar'],
 
154
             [u'foo/bar']),
 
155
            (u'foo/?bar',
 
156
             [u'foo/xbar', u'foo/\u8336bar', u'foo/.bar'],
 
157
             [u'foo/bar', u'bar/foo/xbar']),
 
158
            ])
 
159
 
 
160
    def test_asterisk(self):
 
161
        self.assertMatch([
 
162
            (u'x*x',
 
163
             [u'xx', u'x.x', u'x\u8336..x', u'\u8336/x.x', u'x.y.x'],
 
164
             [u'x/x', u'bar/x/bar/x', u'bax/abaxab']),
 
165
            (u'foo/*x',
 
166
             [u'foo/x', u'foo/bax', u'foo/a.x', u'foo/.x', u'foo/.q.x'],
 
167
             [u'foo/bar/bax']),
 
168
            (u'*/*x',
 
169
             [u'\u8336/x', u'foo/x', u'foo/bax', u'x/a.x', u'.foo/x', 
 
170
              u'\u8336/.x', u'foo/.q.x'],
 
171
             [u'foo/bar/bax']),
 
172
            (u'f*',
 
173
             [u'foo', u'foo.bar'],
 
174
             [u'.foo', u'foo/bar', u'foo/.bar']),
 
175
            (u'*bar',
 
176
             [u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar', 
 
177
              u'foo/foobar', u'foo/f.bar', u'.bar', u'foo/.bar'],
 
178
             []),
 
179
            ])
 
180
 
 
181
    def test_double_asterisk(self):
 
182
        self.assertMatch([
 
183
            # expected uses of double asterisk
 
184
            (u'foo/**/x',
 
185
             [u'foo/x', u'foo/bar/x'],
 
186
             [u'foox', u'foo/bax', u'foo/.x', u'foo/bar/bax']),
 
187
            (u'**/bar',
 
188
             [u'bar', u'foo/bar'],
 
189
             [u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar', 
 
190
              u'.bar', u'foo/.bar']),
 
191
            # check that we ignore extra *s, so *** is treated like ** not *.
 
192
            (u'foo/***/x',
 
193
             [u'foo/x', u'foo/bar/x'],
 
194
             [u'foox', u'foo/bax', u'foo/.x', u'foo/bar/bax']),
 
195
            (u'***/bar',
 
196
             [u'bar', u'foo/bar'],
 
197
             [u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar', 
 
198
              u'.bar', u'foo/.bar']),
 
199
            # the remaining tests check that ** is interpreted as *
 
200
            # unless it is a whole path component
 
201
            (u'x**/x',
 
202
             [u'x\u8336/x', u'x/x'],
 
203
             [u'xx', u'x.x', u'bar/x/bar/x', u'x.y.x', u'x/y/x']),
 
204
            (u'x**x',
 
205
             [u'xx', u'x.x', u'x\u8336..x', u'foo/x.x', u'x.y.x'],
 
206
             [u'bar/x/bar/x', u'xfoo/bar/x', u'x/x', u'bax/abaxab']),
 
207
            (u'foo/**x',
 
208
             [u'foo/x', u'foo/bax', u'foo/a.x', u'foo/.x', u'foo/.q.x'],
 
209
             [u'foo/bar/bax']),
 
210
            (u'f**',
 
211
             [u'foo', u'foo.bar'],
 
212
             [u'.foo', u'foo/bar', u'foo/.bar']),
 
213
            (u'**bar',
 
214
             [u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar', 
 
215
              u'foo/foobar', u'foo/f.bar', u'.bar', u'foo/.bar'],
 
216
             []),
 
217
            ])
 
218
 
 
219
    def test_leading_dot_slash(self):
 
220
        self.assertMatch([
 
221
            (u'./foo',
 
222
             [u'foo'],
 
223
             [u'\u8336/foo', u'barfoo', u'x/y/foo']),
 
224
            (u'./f*',
 
225
             [u'foo'],
 
226
             [u'foo/bar', u'foo/.bar', u'x/foo/y']),
 
227
            ])
 
228
 
 
229
    def test_leading_asterisk_dot(self):
 
230
        self.assertMatch([
 
231
            (u'*.x',
 
232
             [u'foo/bar/baz.x', u'\u8336/Q.x', u'foo.y.x', u'.foo.x', 
 
233
              u'bar/.foo.x', u'.x',],
 
234
             [u'foo.x.y']),
 
235
            (u'foo/*.bar',
 
236
             [u'foo/b.bar', u'foo/a.b.bar', u'foo/.bar'],
 
237
             [u'foo/bar']),
 
238
            (u'*.~*',
 
239
             [u'foo.py.~1~', u'.foo.py.~1~'],
 
240
             []),
 
241
            ])
 
242
 
 
243
    def test_end_anchor(self):
 
244
        self.assertMatch([
 
245
            (u'*.333',
 
246
             [u'foo.333'],
 
247
             [u'foo.3']),
 
248
            (u'*.3',
 
249
             [u'foo.3'],
 
250
             [u'foo.333']),
 
251
            ])
 
252
 
 
253
    def test_mixed_globs(self):
 
254
        """tests handling of combinations of path type matches.
 
255
 
 
256
        The types being extension, basename and full path.
 
257
        """
 
258
        patterns = [ u'*.foo', u'.*.swp', u'./*.png']
 
259
        globster = Globster(patterns)
 
260
        self.assertEqual(u'*.foo', globster.match('bar.foo'))
 
261
        self.assertEqual(u'./*.png', globster.match('foo.png'))
 
262
        self.assertEqual(None, globster.match('foo/bar.png'))
 
263
        self.assertEqual(u'.*.swp', globster.match('foo/.bar.py.swp'))
 
264
 
 
265
    def test_large_globset(self):
 
266
        """tests that the globster can handle a large set of patterns.
 
267
 
 
268
        Large is defined as more than supported by python regex groups, 
 
269
        i.e. 99.
 
270
        This test assumes the globs are broken into regexs containing 99
 
271
        groups.
 
272
        """
 
273
        patterns = [ u'*.%03d' % i for i in xrange(0,300) ]
 
274
        globster = Globster(patterns)
 
275
        # test the fence posts
 
276
        for x in (0,98,99,197,198,296,297,299):
 
277
            filename = u'foo.%03d' % x
 
278
            self.assertEqual(patterns[x],globster.match(filename))
 
279
        self.assertEqual(None,globster.match('foobar.300'))
 
280