/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_win32utils.py

  • Committer: Martin Pool
  • Date: 2007-10-03 08:06:44 UTC
  • mto: This revision was merged to the branch mainline in revision 2901.
  • Revision ID: mbp@sourcefrog.net-20071003080644-oivy0gkg98sex0ed
Avoid internal error tracebacks on failure to lock on readonly transport (#129701).

Add new LockFailed, which doesn't imply that we failed to get it because of
contention.  Raise this if we fail to create the pending or lock directories
because of Transport errors.

UnlockableTransport is not an internal error.

ReadOnlyLockError has a message which didn't match its name or usage; it's now
deprecated and callers are updated to use LockFailed which is more appropriate.

Add zero_ninetytwo deprecation symbol.

Unify assertMatchesRe with TestCase.assertContainsRe.

When the constructor is deprecated, just say that the class is deprecated, not
the __init__ method - this works better with applyDeprecated in tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2010 Canonical Ltd
 
1
# Copyright (C) 2007 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
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
import os
18
18
import sys
19
19
 
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
 
    )
 
20
from bzrlib import osutils
 
21
from bzrlib.tests import TestCase, TestCaseInTempDir, Feature
32
22
from bzrlib.win32utils import glob_expand, get_app_path
33
23
 
34
24
 
35
 
class _BackslashDirSeparatorFeature(tests.Feature):
 
25
# Features
 
26
# --------
 
27
 
 
28
class _NeedsGlobExpansionFeature(Feature):
36
29
 
37
30
    def _probe(self):
38
 
        try:
39
 
            os.lstat(os.getcwd() + '\\')
40
 
        except OSError:
41
 
            return False
42
 
        else:
43
 
            return True
 
31
        return sys.platform == 'win32'
44
32
 
45
33
    def feature_name(self):
46
 
        return "Filesystem treats '\\' as a directory separator."
47
 
 
48
 
BackslashDirSeparatorFeature = _BackslashDirSeparatorFeature()
49
 
 
50
 
 
51
 
class _RequiredModuleFeature(Feature):
52
 
 
53
 
    def __init__(self, mod_name):
54
 
        self.mod_name = mod_name
55
 
        super(_RequiredModuleFeature, self).__init__()
 
34
        return 'Internally performed glob expansion'
 
35
 
 
36
NeedsGlobExpansionFeature = _NeedsGlobExpansionFeature()
 
37
 
 
38
 
 
39
class _Win32RegistryFeature(Feature):
56
40
 
57
41
    def _probe(self):
58
42
        try:
59
 
            __import__(self.mod_name)
 
43
            import _winreg
60
44
            return True
61
45
        except ImportError:
62
46
            return False
63
47
 
64
48
    def feature_name(self):
65
 
        return self.mod_name
 
49
        return '_winreg'
66
50
 
67
 
Win32RegistryFeature = _RequiredModuleFeature('_winreg')
68
 
CtypesFeature = _RequiredModuleFeature('ctypes')
69
 
Win32comShellFeature = _RequiredModuleFeature('win32com.shell')
 
51
Win32RegistryFeature = _Win32RegistryFeature()
70
52
 
71
53
 
72
54
# Tests
73
55
# -----
74
56
 
 
57
class TestNeedsGlobExpansionFeature(TestCase):
 
58
    
 
59
    def test_available(self):
 
60
        self.assertEqual(sys.platform == 'win32', 
 
61
                         NeedsGlobExpansionFeature.available())
 
62
        
 
63
    def test_str(self):
 
64
        self.assertTrue("performed" in str(NeedsGlobExpansionFeature))
 
65
 
 
66
 
75
67
class TestWin32UtilsGlobExpand(TestCaseInTempDir):
76
68
 
77
 
    _test_needs_features = []
78
 
 
 
69
    _test_needs_features = [NeedsGlobExpansionFeature]
 
70
   
79
71
    def test_empty_tree(self):
80
72
        self.build_tree([])
81
73
        self._run_testset([
83
75
            [['?'], ['?']],
84
76
            [['*'], ['*']],
85
77
            [['a', 'a'], ['a', 'a']]])
86
 
 
87
 
    def build_ascii_tree(self):
 
78
        
 
79
    def test_tree_ascii(self):
 
80
        """Checks the glob expansion and path separation char
 
81
        normalization"""
88
82
        self.build_tree(['a', 'a1', 'a2', 'a11', 'a.1',
89
83
                         'b', 'b1', 'b2', 'b3',
90
 
                         'c/', 'c/c1', 'c/c2',
 
84
                         'c/', 'c/c1', 'c/c2', 
91
85
                         '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()
102
86
        self._run_testset([
103
87
            # no wildcards
104
88
            [[u'a'], [u'a']],
105
89
            [[u'a', u'a' ], [u'a', u'a']],
106
 
 
 
90
            [[u'A'], [u'A']],
 
91
                
107
92
            [[u'd'], [u'd']],
108
93
            [[u'd/'], [u'd/']],
109
 
 
 
94
            [[u'd\\'], [u'd/']],
 
95
            
110
96
            # wildcards
111
97
            [[u'a*'], [u'a', u'a1', u'a2', u'a11', u'a.1']],
112
98
            [[u'?'], [u'a', u'b', u'c', u'd']],
113
99
            [[u'a?'], [u'a1', u'a2']],
114
100
            [[u'a??'], [u'a11', u'a.1']],
115
101
            [[u'b[1-2]'], [u'b1', u'b2']],
116
 
 
 
102
            [[u'A?'], [u'a1', u'a2']],
 
103
               
117
104
            [[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/']],
128
105
            [[u'd\\*'], [u'd/d1', u'd/d2', u'd/e']],
129
106
            [[u'?\\*'], [u'c/c1', u'c/c2', u'd/d1', u'd/d2', u'd/e']],
130
107
            [[u'*\\*'], [u'c/c1', u'c/c2', u'd/d1', u'd/d2', u'd/e']],
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
 
            ])
141
 
 
 
108
            [[u'*/'], [u'c/', u'd/']],
 
109
            [[u'*\\'], [u'c/', u'd/']]])
 
110
        
142
111
    def test_tree_unicode(self):
143
112
        """Checks behaviour with non-ascii filenames"""
144
 
        self.build_unicode_tree()
 
113
        self.build_tree([u'\u1234', u'\u1234\u1234', u'\u1235/', u'\u1235/\u1235'])
145
114
        self._run_testset([
146
115
            # no wildcards
147
116
            [[u'\u1234'], [u'\u1234']],
148
117
            [[u'\u1235'], [u'\u1235']],
149
 
 
 
118
         
150
119
            [[u'\u1235/'], [u'\u1235/']],
151
120
            [[u'\u1235/\u1235'], [u'\u1235/\u1235']],
152
 
 
 
121
            
153
122
            # wildcards
154
123
            [[u'?'], [u'\u1234', u'\u1235']],
155
124
            [[u'*'], [u'\u1234', u'\u1234\u1234', u'\u1235']],
156
125
            [[u'\u1234*'], [u'\u1234', u'\u1234\u1234']],
157
 
 
 
126
            
158
127
            [[u'\u1235/?'], [u'\u1235/\u1235']],
159
128
            [[u'\u1235/*'], [u'\u1235/\u1235']],
 
129
            [[u'\u1235\\?'], [u'\u1235/\u1235']],
 
130
            [[u'\u1235\\*'], [u'\u1235/\u1235']],
160
131
            [[u'?/'], [u'\u1235/']],
161
132
            [[u'*/'], [u'\u1235/']],
 
133
            [[u'?\\'], [u'\u1235/']],
 
134
            [[u'*\\'], [u'\u1235/']],
162
135
            [[u'?/?'], [u'\u1235/\u1235']],
163
136
            [[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']],
173
 
            [[u'\u1235\\?'], [u'\u1235/\u1235']],
174
 
            [[u'\u1235\\*'], [u'\u1235/\u1235']],
175
 
            [[u'?\\'], [u'\u1235/']],
176
 
            [[u'*\\'], [u'\u1235/']],
177
137
            [[u'?\\?'], [u'\u1235/\u1235']],
178
 
            [[u'*\\*'], [u'\u1235/\u1235']],
179
 
            ])
 
138
            [[u'*\\*'], [u'\u1235/\u1235']]])
180
139
 
181
140
    def _run_testset(self, testset):
182
141
        for pattern, expected in testset:
195
154
        for a in ('iexplore', 'iexplore.exe'):
196
155
            p = get_app_path(a)
197
156
            d, b = os.path.split(p)
198
 
            self.assertEquals('iexplore.exe', b.lower())
199
 
            self.assertNotEquals('', d)
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())
 
157
            self.assertEquals('iexplore.exe', b)
209
158
            self.assertNotEquals('', d)
210
159
 
211
160
    def test_not_existing(self):
212
161
        p = get_app_path('not-existing')
213
162
        self.assertEquals('not-existing', p)
214
 
 
215
 
 
216
 
class TestLocationsCtypes(TestCase):
217
 
 
218
 
    _test_needs_features = [CtypesFeature]
219
 
 
220
 
    def assertPathsEqual(self, p1, p2):
221
 
        # TODO: The env var values in particular might return the "short"
222
 
        # version (ie, "C:\DOCUME~1\...").  Its even possible the returned
223
 
        # values will differ only by case - handle these situations as we
224
 
        # come across them.
225
 
        self.assertEquals(p1, p2)
226
 
 
227
 
    def test_appdata_not_using_environment(self):
228
 
        # Test that we aren't falling back to the environment
229
 
        first = win32utils.get_appdata_location()
230
 
        self._captureVar("APPDATA", None)
231
 
        self.assertPathsEqual(first, win32utils.get_appdata_location())
232
 
 
233
 
    def test_appdata_matches_environment(self):
234
 
        # Typically the APPDATA environment variable will match
235
 
        # get_appdata_location
236
 
        # XXX - See bug 262874, which asserts the correct encoding is 'mbcs',
237
 
        encoding = osutils.get_user_encoding()
238
 
        env_val = os.environ.get("APPDATA", None)
239
 
        if not env_val:
240
 
            raise TestSkipped("No APPDATA environment variable exists")
241
 
        self.assertPathsEqual(win32utils.get_appdata_location(),
242
 
                              env_val.decode(encoding))
243
 
 
244
 
    def test_local_appdata_not_using_environment(self):
245
 
        # Test that we aren't falling back to the environment
246
 
        first = win32utils.get_local_appdata_location()
247
 
        self._captureVar("LOCALAPPDATA", None)
248
 
        self.assertPathsEqual(first, win32utils.get_local_appdata_location())
249
 
 
250
 
    def test_local_appdata_matches_environment(self):
251
 
        # LOCALAPPDATA typically only exists on Vista, so we only attempt to
252
 
        # compare when it exists.
253
 
        lad = win32utils.get_local_appdata_location()
254
 
        env = os.environ.get("LOCALAPPDATA")
255
 
        if env:
256
 
            # XXX - See bug 262874, which asserts the correct encoding is 'mbcs'
257
 
            encoding = osutils.get_user_encoding()
258
 
            self.assertPathsEqual(lad, env.decode(encoding))
259
 
 
260
 
 
261
 
class TestLocationsPywin32(TestLocationsCtypes):
262
 
 
263
 
    _test_needs_features = [Win32comShellFeature]
264
 
 
265
 
    def setUp(self):
266
 
        super(TestLocationsPywin32, self).setUp()
267
 
        # We perform the exact same tests after disabling the use of ctypes.
268
 
        # This causes the implementation to fall back to pywin32.
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*')