~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-04-23 08:51:52 UTC
  • mfrom: (5131.2.6 support_OO_flag)
  • mto: This revision was merged to the branch mainline in revision 5179.
  • Revision ID: v.ladeuil+lp@free.fr-20100423085152-uoewc1vnkwqhw0pj
Manually assign docstrings to command objects, so that they work with python -OO

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007 Canonical Ltd
 
1
# Copyright (C) 2007-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
17
17
import os
18
18
import sys
19
19
 
20
 
from bzrlib import osutils
21
 
from bzrlib.tests import TestCase, TestCaseInTempDir, TestSkipped, Feature
 
20
from bzrlib import (
 
21
    osutils,
 
22
    tests,
 
23
    win32utils,
 
24
    )
 
25
from bzrlib.tests import (
 
26
    Feature,
 
27
    TestCase,
 
28
    TestCaseInTempDir,
 
29
    TestSkipped,
 
30
    UnicodeFilenameFeature,
 
31
    )
22
32
from bzrlib.win32utils import glob_expand, get_app_path
23
 
from bzrlib import win32utils
24
 
 
25
 
 
26
 
# Features
27
 
# --------
28
 
 
29
 
class _NeedsGlobExpansionFeature(Feature):
 
33
 
 
34
 
 
35
class _BackslashDirSeparatorFeature(tests.Feature):
30
36
 
31
37
    def _probe(self):
32
 
        return sys.platform == 'win32'
 
38
        try:
 
39
            os.lstat(os.getcwd() + '\\')
 
40
        except OSError:
 
41
            return False
 
42
        else:
 
43
            return True
33
44
 
34
45
    def feature_name(self):
35
 
        return 'Internally performed glob expansion'
 
46
        return "Filesystem treats '\\' as a directory separator."
36
47
 
37
 
NeedsGlobExpansionFeature = _NeedsGlobExpansionFeature()
 
48
BackslashDirSeparatorFeature = _BackslashDirSeparatorFeature()
38
49
 
39
50
 
40
51
class _RequiredModuleFeature(Feature):
61
72
# Tests
62
73
# -----
63
74
 
64
 
class TestNeedsGlobExpansionFeature(TestCase):
65
 
 
66
 
    def test_available(self):
67
 
        self.assertEqual(sys.platform == 'win32',
68
 
                         NeedsGlobExpansionFeature.available())
69
 
 
70
 
    def test_str(self):
71
 
        self.assertTrue("performed" in str(NeedsGlobExpansionFeature))
72
 
 
73
 
 
74
75
class TestWin32UtilsGlobExpand(TestCaseInTempDir):
75
76
 
76
 
    _test_needs_features = [NeedsGlobExpansionFeature]
 
77
    _test_needs_features = []
77
78
 
78
79
    def test_empty_tree(self):
79
80
        self.build_tree([])
83
84
            [['*'], ['*']],
84
85
            [['a', 'a'], ['a', 'a']]])
85
86
 
86
 
    def test_tree_ascii(self):
87
 
        """Checks the glob expansion and path separation char
88
 
        normalization"""
 
87
    def build_ascii_tree(self):
89
88
        self.build_tree(['a', 'a1', 'a2', 'a11', 'a.1',
90
89
                         'b', 'b1', 'b2', 'b3',
91
90
                         'c/', 'c/c1', 'c/c2',
92
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()
93
102
        self._run_testset([
94
103
            # no wildcards
95
104
            [[u'a'], [u'a']],
96
105
            [[u'a', u'a' ], [u'a', u'a']],
97
 
            [[u'A'], [u'A']],
98
106
 
99
107
            [[u'd'], [u'd']],
100
108
            [[u'd/'], [u'd/']],
101
 
            [[u'd\\'], [u'd/']],
102
109
 
103
110
            # wildcards
104
111
            [[u'a*'], [u'a', u'a1', u'a2', u'a11', u'a.1']],
106
113
            [[u'a?'], [u'a1', u'a2']],
107
114
            [[u'a??'], [u'a11', u'a.1']],
108
115
            [[u'b[1-2]'], [u'b1', u'b2']],
109
 
            [[u'A?'], [u'a1', u'a2']],
110
116
 
111
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/']],
112
128
            [[u'd\\*'], [u'd/d1', u'd/d2', u'd/e']],
113
129
            [[u'?\\*'], [u'c/c1', u'c/c2', u'd/d1', u'd/d2', u'd/e']],
114
130
            [[u'*\\*'], [u'c/c1', u'c/c2', u'd/d1', u'd/d2', u'd/e']],
115
 
            [[u'*/'], [u'c/', u'd/']],
116
 
            [[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
            ])
117
141
 
118
142
    def test_tree_unicode(self):
119
143
        """Checks behaviour with non-ascii filenames"""
120
 
        self.build_tree([u'\u1234', u'\u1234\u1234', u'\u1235/', u'\u1235/\u1235'])
 
144
        self.build_unicode_tree()
121
145
        self._run_testset([
122
146
            # no wildcards
123
147
            [[u'\u1234'], [u'\u1234']],
133
157
 
134
158
            [[u'\u1235/?'], [u'\u1235/\u1235']],
135
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']],
136
173
            [[u'\u1235\\?'], [u'\u1235/\u1235']],
137
174
            [[u'\u1235\\*'], [u'\u1235/\u1235']],
138
 
            [[u'?/'], [u'\u1235/']],
139
 
            [[u'*/'], [u'\u1235/']],
140
175
            [[u'?\\'], [u'\u1235/']],
141
176
            [[u'*\\'], [u'\u1235/']],
142
 
            [[u'?/?'], [u'\u1235/\u1235']],
143
 
            [[u'*/*'], [u'\u1235/\u1235']],
144
177
            [[u'?\\?'], [u'\u1235/\u1235']],
145
 
            [[u'*\\*'], [u'\u1235/\u1235']]])
 
178
            [[u'*\\*'], [u'\u1235/\u1235']],
 
179
            ])
146
180
 
147
181
    def _run_testset(self, testset):
148
182
        for pattern, expected in testset:
164
198
            self.assertEquals('iexplore.exe', b.lower())
165
199
            self.assertNotEquals('', d)
166
200
 
 
201
    def test_wordpad(self):
 
202
        # typical windows users should have wordpad in the system
 
203
        # but there is problem: its path has the format REG_EXPAND_SZ
 
204
        # so naive attempt to get the path is not working
 
205
        for a in ('wordpad', 'wordpad.exe'):
 
206
            p = get_app_path(a)
 
207
            d, b = os.path.split(p)
 
208
            self.assertEquals('wordpad.exe', b.lower())
 
209
            self.assertNotEquals('', d)
 
210
 
167
211
    def test_not_existing(self):
168
212
        p = get_app_path('not-existing')
169
213
        self.assertEquals('not-existing', p)
222
266
        super(TestLocationsPywin32, self).setUp()
223
267
        # We perform the exact same tests after disabling the use of ctypes.
224
268
        # This causes the implementation to fall back to pywin32.
225
 
        self.old_ctypes = win32utils.has_ctypes
226
 
        win32utils.has_ctypes = False
227
 
        self.addCleanup(self.restoreCtypes)
228
 
 
229
 
    def restoreCtypes(self):
230
 
        win32utils.has_ctypes = self.old_ctypes
 
269
        self.overrideAttr(win32utils, 'has_ctypes', False)
 
270
        # FIXME: this should be done by parametrization -- vila 100123
 
271
 
 
272
 
 
273
class TestSetHidden(TestCaseInTempDir):
 
274
 
 
275
    def test_unicode_dir(self):
 
276
        # we should handle unicode paths without errors
 
277
        self.requireFeature(UnicodeFilenameFeature)
 
278
        os.mkdir(u'\u1234')
 
279
        win32utils.set_file_attr_hidden(u'\u1234')
 
280
 
 
281
    def test_dot_bzr_in_unicode_dir(self):
 
282
        # we should not raise traceback if we try to set hidden attribute
 
283
        # on .bzr directory below unicode path
 
284
        self.requireFeature(UnicodeFilenameFeature)
 
285
        os.makedirs(u'\u1234\\.bzr')
 
286
        path = osutils.abspath(u'\u1234\\.bzr')
 
287
        win32utils.set_file_attr_hidden(path)
 
288
 
 
289
 
 
290
 
 
291
 
 
292
class Test_CommandLineToArgv(tests.TestCaseInTempDir):
 
293
 
 
294
    def assertCommandLine(self, expected, line, single_quotes_allowed=False):
 
295
        # Strictly speaking we should respect parameter order versus glob
 
296
        # expansions, but it's not really worth the effort here
 
297
        argv = win32utils._command_line_to_argv(line,
 
298
                single_quotes_allowed=single_quotes_allowed)
 
299
        self.assertEqual(expected, sorted(argv))
 
300
 
 
301
    def test_glob_paths(self):
 
302
        self.build_tree(['a/', 'a/b.c', 'a/c.c', 'a/c.h'])
 
303
        self.assertCommandLine([u'a/b.c', u'a/c.c'], 'a/*.c')
 
304
        self.build_tree(['b/', 'b/b.c', 'b/d.c', 'b/d.h'])
 
305
        self.assertCommandLine([u'a/b.c', u'b/b.c'], '*/b.c')
 
306
        self.assertCommandLine([u'a/b.c', u'a/c.c', u'b/b.c', u'b/d.c'],
 
307
                               '*/*.c')
 
308
        # Bash style, just pass through the argument if nothing matches
 
309
        self.assertCommandLine([u'*/*.qqq'], '*/*.qqq')
 
310
 
 
311
    def test_quoted_globs(self):
 
312
        self.build_tree(['a/', 'a/b.c', 'a/c.c', 'a/c.h'])
 
313
        self.assertCommandLine([u'a/*.c'], '"a/*.c"')
 
314
        self.assertCommandLine([u"'a/*.c'"], "'a/*.c'")
 
315
        self.assertCommandLine([u'a/*.c'], "'a/*.c'",
 
316
            single_quotes_allowed=True)
 
317
 
 
318
    def test_slashes_changed(self):
 
319
        # Quoting doesn't change the supplied args
 
320
        self.assertCommandLine([u'a\\*.c'], '"a\\*.c"')
 
321
        self.assertCommandLine([u'a\\*.c'], "'a\\*.c'",
 
322
            single_quotes_allowed=True)
 
323
        # Expands the glob, but nothing matches, swaps slashes
 
324
        self.assertCommandLine([u'a/*.c'], 'a\\*.c')
 
325
        self.assertCommandLine([u'a/?.c'], 'a\\?.c')
 
326
        # No glob, doesn't touch slashes
 
327
        self.assertCommandLine([u'a\\foo.c'], 'a\\foo.c')
 
328
 
 
329
    def test_single_quote_support(self):
 
330
        self.assertCommandLine(["add", "let's-do-it.txt"],
 
331
            "add let's-do-it.txt")
 
332
        self.assertCommandLine(["add", "lets do it.txt"],
 
333
            "add 'lets do it.txt'", single_quotes_allowed=True)
 
334
 
 
335
    def test_case_insensitive_globs(self):
 
336
        self.requireFeature(tests.CaseInsCasePresFilenameFeature)
 
337
        self.build_tree(['a/', 'a/b.c', 'a/c.c', 'a/c.h'])
 
338
        self.assertCommandLine([u'A/b.c'], 'A/B*')
 
339
 
 
340
    def test_backslashes(self):
 
341
        self.requireFeature(BackslashDirSeparatorFeature)
 
342
        self.build_tree(['a/', 'a/b.c', 'a/c.c', 'a/c.h'])
 
343
        self.assertCommandLine([u'a/b.c'], 'a\\b*')