~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_win32utils.py

  • Committer: Ian Clatworthy
  • Date: 2010-05-26 04:26:59 UTC
  • mto: (5255.2.1 integration)
  • mto: This revision was merged to the branch mainline in revision 5256.
  • Revision ID: ian.clatworthy@canonical.com-20100526042659-2e3p4qdjr0sby0bt
Fix PDF generation of User Reference

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
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
 
17
"""Tests for win32utils."""
 
18
 
17
19
import os
18
20
import sys
19
21
 
20
 
from bzrlib import osutils
21
 
from bzrlib.tests import TestCase, TestCaseInTempDir, TestSkipped, Feature
 
22
from bzrlib import (
 
23
    osutils,
 
24
    tests,
 
25
    win32utils,
 
26
    )
 
27
from bzrlib.tests import (
 
28
    Feature,
 
29
    TestCase,
 
30
    TestCaseInTempDir,
 
31
    TestSkipped,
 
32
    UnicodeFilenameFeature,
 
33
    )
 
34
from bzrlib.tests.features import backslashdir_feature
22
35
from bzrlib.win32utils import glob_expand, get_app_path
23
 
from bzrlib import win32utils
24
 
 
25
 
 
26
 
# Features
27
 
# --------
28
 
 
29
 
class _NeedsGlobExpansionFeature(Feature):
30
 
 
31
 
    def _probe(self):
32
 
        return sys.platform == 'win32'
33
 
 
34
 
    def feature_name(self):
35
 
        return 'Internally performed glob expansion'
36
 
 
37
 
NeedsGlobExpansionFeature = _NeedsGlobExpansionFeature()
38
36
 
39
37
 
40
38
class _RequiredModuleFeature(Feature):
61
59
# Tests
62
60
# -----
63
61
 
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
62
class TestWin32UtilsGlobExpand(TestCaseInTempDir):
75
63
 
76
 
    _test_needs_features = [NeedsGlobExpansionFeature]
 
64
    _test_needs_features = []
77
65
 
78
66
    def test_empty_tree(self):
79
67
        self.build_tree([])
83
71
            [['*'], ['*']],
84
72
            [['a', 'a'], ['a', 'a']]])
85
73
 
86
 
    def test_tree_ascii(self):
87
 
        """Checks the glob expansion and path separation char
88
 
        normalization"""
 
74
    def build_ascii_tree(self):
89
75
        self.build_tree(['a', 'a1', 'a2', 'a11', 'a.1',
90
76
                         'b', 'b1', 'b2', 'b3',
91
77
                         'c/', 'c/c1', 'c/c2',
92
78
                         'd/', 'd/d1', 'd/d2', 'd/e/', 'd/e/e1'])
 
79
 
 
80
    def build_unicode_tree(self):
 
81
        self.requireFeature(UnicodeFilenameFeature)
 
82
        self.build_tree([u'\u1234', u'\u1234\u1234', u'\u1235/',
 
83
                         u'\u1235/\u1235'])
 
84
 
 
85
    def test_tree_ascii(self):
 
86
        """Checks the glob expansion and path separation char
 
87
        normalization"""
 
88
        self.build_ascii_tree()
93
89
        self._run_testset([
94
90
            # no wildcards
95
91
            [[u'a'], [u'a']],
96
92
            [[u'a', u'a' ], [u'a', u'a']],
97
 
            [[u'A'], [u'A']],
98
93
 
99
94
            [[u'd'], [u'd']],
100
95
            [[u'd/'], [u'd/']],
101
 
            [[u'd\\'], [u'd/']],
102
96
 
103
97
            # wildcards
104
98
            [[u'a*'], [u'a', u'a1', u'a2', u'a11', u'a.1']],
106
100
            [[u'a?'], [u'a1', u'a2']],
107
101
            [[u'a??'], [u'a11', u'a.1']],
108
102
            [[u'b[1-2]'], [u'b1', u'b2']],
109
 
            [[u'A?'], [u'a1', u'a2']],
110
103
 
111
104
            [[u'd/*'], [u'd/d1', u'd/d2', u'd/e']],
 
105
            [[u'?/*'], [u'c/c1', u'c/c2', u'd/d1', u'd/d2', u'd/e']],
 
106
            [[u'*/*'], [u'c/c1', u'c/c2', u'd/d1', u'd/d2', u'd/e']],
 
107
            [[u'*/'], [u'c/', u'd/']],
 
108
            ])
 
109
 
 
110
    def test_backslash_globbing(self):
 
111
        self.requireFeature(backslashdir_feature)
 
112
        self.build_ascii_tree()
 
113
        self._run_testset([
 
114
            [[u'd\\'], [u'd/']],
112
115
            [[u'd\\*'], [u'd/d1', u'd/d2', u'd/e']],
113
116
            [[u'?\\*'], [u'c/c1', u'c/c2', u'd/d1', u'd/d2', u'd/e']],
114
117
            [[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/']]])
 
118
            [[u'*\\'], [u'c/', u'd/']],
 
119
            ])
 
120
 
 
121
    def test_case_insensitive_globbing(self):
 
122
        self.requireFeature(tests.CaseInsCasePresFilenameFeature)
 
123
        self.build_ascii_tree()
 
124
        self._run_testset([
 
125
            [[u'A'], [u'A']],
 
126
            [[u'A?'], [u'a1', u'a2']],
 
127
            ])
117
128
 
118
129
    def test_tree_unicode(self):
119
130
        """Checks behaviour with non-ascii filenames"""
120
 
        self.build_tree([u'\u1234', u'\u1234\u1234', u'\u1235/', u'\u1235/\u1235'])
 
131
        self.build_unicode_tree()
121
132
        self._run_testset([
122
133
            # no wildcards
123
134
            [[u'\u1234'], [u'\u1234']],
133
144
 
134
145
            [[u'\u1235/?'], [u'\u1235/\u1235']],
135
146
            [[u'\u1235/*'], [u'\u1235/\u1235']],
 
147
            [[u'?/'], [u'\u1235/']],
 
148
            [[u'*/'], [u'\u1235/']],
 
149
            [[u'?/?'], [u'\u1235/\u1235']],
 
150
            [[u'*/*'], [u'\u1235/\u1235']],
 
151
            ])
 
152
 
 
153
    def test_unicode_backslashes(self):
 
154
        self.requireFeature(backslashdir_feature)
 
155
        self.build_unicode_tree()
 
156
        self._run_testset([
 
157
            # no wildcards
 
158
            [[u'\u1235\\'], [u'\u1235/']],
 
159
            [[u'\u1235\\\u1235'], [u'\u1235/\u1235']],
136
160
            [[u'\u1235\\?'], [u'\u1235/\u1235']],
137
161
            [[u'\u1235\\*'], [u'\u1235/\u1235']],
138
 
            [[u'?/'], [u'\u1235/']],
139
 
            [[u'*/'], [u'\u1235/']],
140
162
            [[u'?\\'], [u'\u1235/']],
141
163
            [[u'*\\'], [u'\u1235/']],
142
 
            [[u'?/?'], [u'\u1235/\u1235']],
143
 
            [[u'*/*'], [u'\u1235/\u1235']],
144
164
            [[u'?\\?'], [u'\u1235/\u1235']],
145
 
            [[u'*\\*'], [u'\u1235/\u1235']]])
 
165
            [[u'*\\*'], [u'\u1235/\u1235']],
 
166
            ])
146
167
 
147
168
    def _run_testset(self, testset):
148
169
        for pattern, expected in testset:
164
185
            self.assertEquals('iexplore.exe', b.lower())
165
186
            self.assertNotEquals('', d)
166
187
 
 
188
    def test_wordpad(self):
 
189
        # typical windows users should have wordpad in the system
 
190
        # but there is problem: its path has the format REG_EXPAND_SZ
 
191
        # so naive attempt to get the path is not working
 
192
        for a in ('wordpad', 'wordpad.exe'):
 
193
            p = get_app_path(a)
 
194
            d, b = os.path.split(p)
 
195
            self.assertEquals('wordpad.exe', b.lower())
 
196
            self.assertNotEquals('', d)
 
197
 
167
198
    def test_not_existing(self):
168
199
        p = get_app_path('not-existing')
169
200
        self.assertEquals('not-existing', p)
222
253
        super(TestLocationsPywin32, self).setUp()
223
254
        # We perform the exact same tests after disabling the use of ctypes.
224
255
        # 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
 
256
        self.overrideAttr(win32utils, 'has_ctypes', False)
 
257
        # FIXME: this should be done by parametrization -- vila 100123
 
258
 
 
259
 
 
260
class TestSetHidden(TestCaseInTempDir):
 
261
 
 
262
    def test_unicode_dir(self):
 
263
        # we should handle unicode paths without errors
 
264
        self.requireFeature(UnicodeFilenameFeature)
 
265
        os.mkdir(u'\u1234')
 
266
        win32utils.set_file_attr_hidden(u'\u1234')
 
267
 
 
268
    def test_dot_bzr_in_unicode_dir(self):
 
269
        # we should not raise traceback if we try to set hidden attribute
 
270
        # on .bzr directory below unicode path
 
271
        self.requireFeature(UnicodeFilenameFeature)
 
272
        os.makedirs(u'\u1234\\.bzr')
 
273
        path = osutils.abspath(u'\u1234\\.bzr')
 
274
        win32utils.set_file_attr_hidden(path)
 
275
 
 
276
 
 
277
class Test_CommandLineToArgv(tests.TestCaseInTempDir):
 
278
 
 
279
    def assertCommandLine(self, expected, line, single_quotes_allowed=False):
 
280
        # Strictly speaking we should respect parameter order versus glob
 
281
        # expansions, but it's not really worth the effort here
 
282
        argv = win32utils._command_line_to_argv(line,
 
283
                single_quotes_allowed=single_quotes_allowed)
 
284
        self.assertEqual(expected, sorted(argv))
 
285
 
 
286
    def test_glob_paths(self):
 
287
        self.build_tree(['a/', 'a/b.c', 'a/c.c', 'a/c.h'])
 
288
        self.assertCommandLine([u'a/b.c', u'a/c.c'], 'a/*.c')
 
289
        self.build_tree(['b/', 'b/b.c', 'b/d.c', 'b/d.h'])
 
290
        self.assertCommandLine([u'a/b.c', u'b/b.c'], '*/b.c')
 
291
        self.assertCommandLine([u'a/b.c', u'a/c.c', u'b/b.c', u'b/d.c'],
 
292
                               '*/*.c')
 
293
        # Bash style, just pass through the argument if nothing matches
 
294
        self.assertCommandLine([u'*/*.qqq'], '*/*.qqq')
 
295
 
 
296
    def test_quoted_globs(self):
 
297
        self.build_tree(['a/', 'a/b.c', 'a/c.c', 'a/c.h'])
 
298
        self.assertCommandLine([u'a/*.c'], '"a/*.c"')
 
299
        self.assertCommandLine([u"'a/*.c'"], "'a/*.c'")
 
300
        self.assertCommandLine([u'a/*.c'], "'a/*.c'",
 
301
            single_quotes_allowed=True)
 
302
 
 
303
    def test_slashes_changed(self):
 
304
        # Quoting doesn't change the supplied args
 
305
        self.assertCommandLine([u'a\\*.c'], '"a\\*.c"')
 
306
        self.assertCommandLine([u'a\\*.c'], "'a\\*.c'",
 
307
            single_quotes_allowed=True)
 
308
        # Expands the glob, but nothing matches, swaps slashes
 
309
        self.assertCommandLine([u'a/*.c'], 'a\\*.c')
 
310
        self.assertCommandLine([u'a/?.c'], 'a\\?.c')
 
311
        # No glob, doesn't touch slashes
 
312
        self.assertCommandLine([u'a\\foo.c'], 'a\\foo.c')
 
313
 
 
314
    def test_single_quote_support(self):
 
315
        self.assertCommandLine(["add", "let's-do-it.txt"],
 
316
            "add let's-do-it.txt")
 
317
        self.assertCommandLine(["add", "lets do it.txt"],
 
318
            "add 'lets do it.txt'", single_quotes_allowed=True)
 
319
 
 
320
    def test_case_insensitive_globs(self):
 
321
        self.requireFeature(tests.CaseInsCasePresFilenameFeature)
 
322
        self.build_tree(['a/', 'a/b.c', 'a/c.c', 'a/c.h'])
 
323
        self.assertCommandLine([u'A/b.c'], 'A/B*')
 
324
 
 
325
    def test_backslashes(self):
 
326
        self.requireFeature(backslashdir_feature)
 
327
        self.build_tree(['a/', 'a/b.c', 'a/c.c', 'a/c.h'])
 
328
        self.assertCommandLine([u'a/b.c'], 'a\\b*')