~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_win32utils.py

  • Committer: Vincent Ladeuil
  • Date: 2010-01-25 15:55:48 UTC
  • mto: (4985.1.4 add-attr-cleanup)
  • mto: This revision was merged to the branch mainline in revision 4988.
  • Revision ID: v.ladeuil+lp@free.fr-20100125155548-0l352pujvt5bzl5e
Deploy addAttrCleanup on the whole test suite.

Several use case worth mentioning:

- setting a module or any other object attribute is the majority
by far. In some cases the setting itself is deferred but most of
the time we want to set at the same time we add the cleanup.

- there multiple occurrences of protecting hooks or ui factory
which are now useless (the test framework takes care of that now),

- there was some lambda uses that can now be avoided.

That first cleanup already simplifies things a lot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
import os
18
18
import sys
19
19
 
20
 
from bzrlib import osutils
 
20
from bzrlib import (
 
21
    osutils,
 
22
    tests,
 
23
    win32utils,
 
24
    )
21
25
from bzrlib.tests import (
22
26
    Feature,
23
27
    TestCase,
26
30
    UnicodeFilenameFeature,
27
31
    )
28
32
from bzrlib.win32utils import glob_expand, get_app_path
29
 
from bzrlib import win32utils
30
 
 
31
 
 
32
 
# Features
33
 
# --------
34
 
 
35
 
class _NeedsGlobExpansionFeature(Feature):
 
33
 
 
34
 
 
35
class _BackslashDirSeparatorFeature(tests.Feature):
36
36
 
37
37
    def _probe(self):
38
 
        return sys.platform == 'win32'
 
38
        try:
 
39
            os.lstat(os.getcwd() + '\\')
 
40
        except OSError:
 
41
            return False
 
42
        else:
 
43
            return True
39
44
 
40
45
    def feature_name(self):
41
 
        return 'Internally performed glob expansion'
 
46
        return "Filesystem treats '\\' as a directory separator."
42
47
 
43
 
NeedsGlobExpansionFeature = _NeedsGlobExpansionFeature()
 
48
BackslashDirSeparatorFeature = _BackslashDirSeparatorFeature()
44
49
 
45
50
 
46
51
class _RequiredModuleFeature(Feature):
67
72
# Tests
68
73
# -----
69
74
 
70
 
class TestNeedsGlobExpansionFeature(TestCase):
71
 
 
72
 
    def test_available(self):
73
 
        self.assertEqual(sys.platform == 'win32',
74
 
                         NeedsGlobExpansionFeature.available())
75
 
 
76
 
    def test_str(self):
77
 
        self.assertTrue("performed" in str(NeedsGlobExpansionFeature))
78
 
 
79
 
 
80
75
class TestWin32UtilsGlobExpand(TestCaseInTempDir):
81
76
 
82
 
    _test_needs_features = [NeedsGlobExpansionFeature]
 
77
    _test_needs_features = []
83
78
 
84
79
    def test_empty_tree(self):
85
80
        self.build_tree([])
89
84
            [['*'], ['*']],
90
85
            [['a', 'a'], ['a', 'a']]])
91
86
 
92
 
    def test_tree_ascii(self):
93
 
        """Checks the glob expansion and path separation char
94
 
        normalization"""
 
87
    def build_ascii_tree(self):
95
88
        self.build_tree(['a', 'a1', 'a2', 'a11', 'a.1',
96
89
                         'b', 'b1', 'b2', 'b3',
97
90
                         'c/', 'c/c1', 'c/c2',
98
91
                         'd/', 'd/d1', 'd/d2', 'd/e/', 'd/e/e1'])
 
92
 
 
93
    def build_unicode_tree(self):
 
94
        self.requireFeature(UnicodeFilenameFeature)
 
95
        self.build_tree([u'\u1234', u'\u1234\u1234', u'\u1235/',
 
96
                         u'\u1235/\u1235'])
 
97
 
 
98
    def test_tree_ascii(self):
 
99
        """Checks the glob expansion and path separation char
 
100
        normalization"""
 
101
        self.build_ascii_tree()
99
102
        self._run_testset([
100
103
            # no wildcards
101
104
            [[u'a'], [u'a']],
102
105
            [[u'a', u'a' ], [u'a', u'a']],
103
 
            [[u'A'], [u'A']],
104
106
 
105
107
            [[u'd'], [u'd']],
106
108
            [[u'd/'], [u'd/']],
107
 
            [[u'd\\'], [u'd/']],
108
109
 
109
110
            # wildcards
110
111
            [[u'a*'], [u'a', u'a1', u'a2', u'a11', u'a.1']],
112
113
            [[u'a?'], [u'a1', u'a2']],
113
114
            [[u'a??'], [u'a11', u'a.1']],
114
115
            [[u'b[1-2]'], [u'b1', u'b2']],
115
 
            [[u'A?'], [u'a1', u'a2']],
116
116
 
117
117
            [[u'd/*'], [u'd/d1', u'd/d2', u'd/e']],
 
118
            [[u'?/*'], [u'c/c1', u'c/c2', u'd/d1', u'd/d2', u'd/e']],
 
119
            [[u'*/*'], [u'c/c1', u'c/c2', u'd/d1', u'd/d2', u'd/e']],
 
120
            [[u'*/'], [u'c/', u'd/']],
 
121
            ])
 
122
 
 
123
    def test_backslash_globbing(self):
 
124
        self.requireFeature(BackslashDirSeparatorFeature)
 
125
        self.build_ascii_tree()
 
126
        self._run_testset([
 
127
            [[u'd\\'], [u'd/']],
118
128
            [[u'd\\*'], [u'd/d1', u'd/d2', u'd/e']],
119
129
            [[u'?\\*'], [u'c/c1', u'c/c2', u'd/d1', u'd/d2', u'd/e']],
120
130
            [[u'*\\*'], [u'c/c1', u'c/c2', u'd/d1', u'd/d2', u'd/e']],
121
 
            [[u'*/'], [u'c/', u'd/']],
122
 
            [[u'*\\'], [u'c/', u'd/']]])
 
131
            [[u'*\\'], [u'c/', u'd/']],
 
132
            ])
 
133
 
 
134
    def test_case_insensitive_globbing(self):
 
135
        self.requireFeature(tests.CaseInsCasePresFilenameFeature)
 
136
        self.build_ascii_tree()
 
137
        self._run_testset([
 
138
            [[u'A'], [u'A']],
 
139
            [[u'A?'], [u'a1', u'a2']],
 
140
            ])
123
141
 
124
142
    def test_tree_unicode(self):
125
143
        """Checks behaviour with non-ascii filenames"""
126
 
        self.build_tree([u'\u1234', u'\u1234\u1234', u'\u1235/', u'\u1235/\u1235'])
 
144
        self.build_unicode_tree()
127
145
        self._run_testset([
128
146
            # no wildcards
129
147
            [[u'\u1234'], [u'\u1234']],
139
157
 
140
158
            [[u'\u1235/?'], [u'\u1235/\u1235']],
141
159
            [[u'\u1235/*'], [u'\u1235/\u1235']],
 
160
            [[u'?/'], [u'\u1235/']],
 
161
            [[u'*/'], [u'\u1235/']],
 
162
            [[u'?/?'], [u'\u1235/\u1235']],
 
163
            [[u'*/*'], [u'\u1235/\u1235']],
 
164
            ])
 
165
 
 
166
    def test_unicode_backslashes(self):
 
167
        self.requireFeature(BackslashDirSeparatorFeature)
 
168
        self.build_unicode_tree()
 
169
        self._run_testset([
 
170
            # no wildcards
 
171
            [[u'\u1235\\'], [u'\u1235/']],
 
172
            [[u'\u1235\\\u1235'], [u'\u1235/\u1235']],
142
173
            [[u'\u1235\\?'], [u'\u1235/\u1235']],
143
174
            [[u'\u1235\\*'], [u'\u1235/\u1235']],
144
 
            [[u'?/'], [u'\u1235/']],
145
 
            [[u'*/'], [u'\u1235/']],
146
175
            [[u'?\\'], [u'\u1235/']],
147
176
            [[u'*\\'], [u'\u1235/']],
148
 
            [[u'?/?'], [u'\u1235/\u1235']],
149
 
            [[u'*/*'], [u'\u1235/\u1235']],
150
177
            [[u'?\\?'], [u'\u1235/\u1235']],
151
 
            [[u'*\\*'], [u'\u1235/\u1235']]])
 
178
            [[u'*\\*'], [u'\u1235/\u1235']],
 
179
            ])
152
180
 
153
181
    def _run_testset(self, testset):
154
182
        for pattern, expected in testset:
236
264
 
237
265
    def setUp(self):
238
266
        super(TestLocationsPywin32, self).setUp()
 
267
        self.addAttrCleanup(win32utils, 'has_ctypes')
239
268
        # We perform the exact same tests after disabling the use of ctypes.
240
269
        # This causes the implementation to fall back to pywin32.
241
 
        self.old_ctypes = win32utils.has_ctypes
 
270
        # FIXME: this smells parametrization -- vila 100123
242
271
        win32utils.has_ctypes = False
243
 
        self.addCleanup(self.restoreCtypes)
244
 
 
245
 
    def restoreCtypes(self):
246
 
        win32utils.has_ctypes = self.old_ctypes
247
272
 
248
273
 
249
274
class TestSetHidden(TestCaseInTempDir):
261
286
        os.makedirs(u'\u1234\\.bzr')
262
287
        path = osutils.abspath(u'\u1234\\.bzr')
263
288
        win32utils.set_file_attr_hidden(path)
 
289
 
 
290
 
 
291
 
 
292
class TestUnicodeShlex(tests.TestCase):
 
293
 
 
294
    def assertAsTokens(self, expected, line):
 
295
        s = win32utils.UnicodeShlex(line)
 
296
        self.assertEqual(expected, list(s))
 
297
 
 
298
    def test_simple(self):
 
299
        self.assertAsTokens([(False, u'foo'), (False, u'bar'), (False, u'baz')],
 
300
                            u'foo bar baz')
 
301
 
 
302
    def test_ignore_multiple_spaces(self):
 
303
        self.assertAsTokens([(False, u'foo'), (False, u'bar')], u'foo  bar')
 
304
 
 
305
    def test_ignore_leading_space(self):
 
306
        self.assertAsTokens([(False, u'foo'), (False, u'bar')], u'  foo bar')
 
307
 
 
308
    def test_ignore_trailing_space(self):
 
309
        self.assertAsTokens([(False, u'foo'), (False, u'bar')], u'foo bar  ')
 
310
 
 
311
    def test_posix_quotations(self):
 
312
        self.assertAsTokens([(True, u'foo bar')], u'"foo bar"')
 
313
        self.assertAsTokens([(False, u"'fo''o"), (False, u"b''ar'")],
 
314
            u"'fo''o b''ar'")
 
315
        self.assertAsTokens([(True, u'foo bar')], u'"fo""o b""ar"')
 
316
        self.assertAsTokens([(True, u"fo'o"), (True, u"b'ar")],
 
317
            u'"fo"\'o b\'"ar"')
 
318
 
 
319
    def test_nested_quotations(self):
 
320
        self.assertAsTokens([(True, u'foo"" bar')], u"\"foo\\\"\\\" bar\"")
 
321
        self.assertAsTokens([(True, u'foo\'\' bar')], u"\"foo'' bar\"")
 
322
 
 
323
    def test_empty_result(self):
 
324
        self.assertAsTokens([], u'')
 
325
        self.assertAsTokens([], u'    ')
 
326
 
 
327
    def test_quoted_empty(self):
 
328
        self.assertAsTokens([(True, '')], u'""')
 
329
        self.assertAsTokens([(False, u"''")], u"''")
 
330
 
 
331
    def test_unicode_chars(self):
 
332
        self.assertAsTokens([(False, u'f\xb5\xee'), (False, u'\u1234\u3456')],
 
333
                             u'f\xb5\xee \u1234\u3456')
 
334
 
 
335
    def test_newline_in_quoted_section(self):
 
336
        self.assertAsTokens([(True, u'foo\nbar\nbaz\n')], u'"foo\nbar\nbaz\n"')
 
337
 
 
338
    def test_escape_chars(self):
 
339
        self.assertAsTokens([(False, u'foo\\bar')], u'foo\\bar')
 
340
 
 
341
    def test_escape_quote(self):
 
342
        self.assertAsTokens([(True, u'foo"bar')], u'"foo\\"bar"')
 
343
 
 
344
    def test_double_escape(self):
 
345
        self.assertAsTokens([(True, u'foo\\bar')], u'"foo\\\\bar"')
 
346
        self.assertAsTokens([(False, u'foo\\\\bar')], u"foo\\\\bar")
 
347
 
 
348
 
 
349
class Test_CommandLineToArgv(tests.TestCaseInTempDir):
 
350
 
 
351
    def assertCommandLine(self, expected, line):
 
352
        # Strictly speaking we should respect parameter order versus glob
 
353
        # expansions, but it's not really worth the effort here
 
354
        self.assertEqual(expected,
 
355
                         sorted(win32utils._command_line_to_argv(line)))
 
356
 
 
357
    def test_glob_paths(self):
 
358
        self.build_tree(['a/', 'a/b.c', 'a/c.c', 'a/c.h'])
 
359
        self.assertCommandLine([u'a/b.c', u'a/c.c'], 'a/*.c')
 
360
        self.build_tree(['b/', 'b/b.c', 'b/d.c', 'b/d.h'])
 
361
        self.assertCommandLine([u'a/b.c', u'b/b.c'], '*/b.c')
 
362
        self.assertCommandLine([u'a/b.c', u'a/c.c', u'b/b.c', u'b/d.c'],
 
363
                               '*/*.c')
 
364
        # Bash style, just pass through the argument if nothing matches
 
365
        self.assertCommandLine([u'*/*.qqq'], '*/*.qqq')
 
366
 
 
367
    def test_quoted_globs(self):
 
368
        self.build_tree(['a/', 'a/b.c', 'a/c.c', 'a/c.h'])
 
369
        self.assertCommandLine([u'a/*.c'], '"a/*.c"')
 
370
        self.assertCommandLine([u"'a/*.c'"], "'a/*.c'")
 
371
 
 
372
    def test_slashes_changed(self):
 
373
        # Quoting doesn't change the supplied args
 
374
        self.assertCommandLine([u'a\\*.c'], '"a\\*.c"')
 
375
        # Expands the glob, but nothing matches, swaps slashes
 
376
        self.assertCommandLine([u'a/*.c'], 'a\\*.c')
 
377
        self.assertCommandLine([u'a/?.c'], 'a\\?.c')
 
378
        # No glob, doesn't touch slashes
 
379
        self.assertCommandLine([u'a\\foo.c'], 'a\\foo.c')
 
380
 
 
381
    def test_no_single_quote_supported(self):
 
382
        self.assertCommandLine(["add", "let's-do-it.txt"],
 
383
            "add let's-do-it.txt")
 
384
 
 
385
    def test_case_insensitive_globs(self):
 
386
        self.requireFeature(tests.CaseInsCasePresFilenameFeature)
 
387
        self.build_tree(['a/', 'a/b.c', 'a/c.c', 'a/c.h'])
 
388
        self.assertCommandLine([u'A/b.c'], 'A/B*')
 
389
 
 
390
    def test_backslashes(self):
 
391
        self.requireFeature(BackslashDirSeparatorFeature)
 
392
        self.build_tree(['a/', 'a/b.c', 'a/c.c', 'a/c.h'])
 
393
        self.assertCommandLine([u'a/b.c'], 'a\\b*')