~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_win32utils.py

  • Committer: Robert Collins
  • Date: 2009-07-07 04:32:13 UTC
  • mto: This revision was merged to the branch mainline in revision 4524.
  • Revision ID: robertc@robertcollins.net-20090707043213-4hjjhgr40iq7gk2d
More informative assertions in xml serialisation.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2007 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
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
 
16
 
 
17
import os
 
18
import sys
 
19
 
 
20
from bzrlib import osutils
 
21
from bzrlib.tests import TestCase, TestCaseInTempDir, TestSkipped, Feature
 
22
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
 
 
39
 
 
40
class _RequiredModuleFeature(Feature):
 
41
 
 
42
    def __init__(self, mod_name):
 
43
        self.mod_name = mod_name
 
44
        super(_RequiredModuleFeature, self).__init__()
 
45
 
 
46
    def _probe(self):
 
47
        try:
 
48
            __import__(self.mod_name)
 
49
            return True
 
50
        except ImportError:
 
51
            return False
 
52
 
 
53
    def feature_name(self):
 
54
        return self.mod_name
 
55
 
 
56
Win32RegistryFeature = _RequiredModuleFeature('_winreg')
 
57
CtypesFeature = _RequiredModuleFeature('ctypes')
 
58
Win32comShellFeature = _RequiredModuleFeature('win32com.shell')
 
59
 
 
60
 
 
61
# Tests
 
62
# -----
 
63
 
 
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
class TestWin32UtilsGlobExpand(TestCaseInTempDir):
 
75
 
 
76
    _test_needs_features = [NeedsGlobExpansionFeature]
 
77
 
 
78
    def test_empty_tree(self):
 
79
        self.build_tree([])
 
80
        self._run_testset([
 
81
            [['a'], ['a']],
 
82
            [['?'], ['?']],
 
83
            [['*'], ['*']],
 
84
            [['a', 'a'], ['a', 'a']]])
 
85
 
 
86
    def test_tree_ascii(self):
 
87
        """Checks the glob expansion and path separation char
 
88
        normalization"""
 
89
        self.build_tree(['a', 'a1', 'a2', 'a11', 'a.1',
 
90
                         'b', 'b1', 'b2', 'b3',
 
91
                         'c/', 'c/c1', 'c/c2',
 
92
                         'd/', 'd/d1', 'd/d2', 'd/e/', 'd/e/e1'])
 
93
        self._run_testset([
 
94
            # no wildcards
 
95
            [[u'a'], [u'a']],
 
96
            [[u'a', u'a' ], [u'a', u'a']],
 
97
            [[u'A'], [u'A']],
 
98
 
 
99
            [[u'd'], [u'd']],
 
100
            [[u'd/'], [u'd/']],
 
101
            [[u'd\\'], [u'd/']],
 
102
 
 
103
            # wildcards
 
104
            [[u'a*'], [u'a', u'a1', u'a2', u'a11', u'a.1']],
 
105
            [[u'?'], [u'a', u'b', u'c', u'd']],
 
106
            [[u'a?'], [u'a1', u'a2']],
 
107
            [[u'a??'], [u'a11', u'a.1']],
 
108
            [[u'b[1-2]'], [u'b1', u'b2']],
 
109
            [[u'A?'], [u'a1', u'a2']],
 
110
 
 
111
            [[u'd/*'], [u'd/d1', u'd/d2', u'd/e']],
 
112
            [[u'd\\*'], [u'd/d1', u'd/d2', u'd/e']],
 
113
            [[u'?\\*'], [u'c/c1', u'c/c2', u'd/d1', u'd/d2', u'd/e']],
 
114
            [[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/']]])
 
117
 
 
118
    def test_tree_unicode(self):
 
119
        """Checks behaviour with non-ascii filenames"""
 
120
        self.build_tree([u'\u1234', u'\u1234\u1234', u'\u1235/', u'\u1235/\u1235'])
 
121
        self._run_testset([
 
122
            # no wildcards
 
123
            [[u'\u1234'], [u'\u1234']],
 
124
            [[u'\u1235'], [u'\u1235']],
 
125
 
 
126
            [[u'\u1235/'], [u'\u1235/']],
 
127
            [[u'\u1235/\u1235'], [u'\u1235/\u1235']],
 
128
 
 
129
            # wildcards
 
130
            [[u'?'], [u'\u1234', u'\u1235']],
 
131
            [[u'*'], [u'\u1234', u'\u1234\u1234', u'\u1235']],
 
132
            [[u'\u1234*'], [u'\u1234', u'\u1234\u1234']],
 
133
 
 
134
            [[u'\u1235/?'], [u'\u1235/\u1235']],
 
135
            [[u'\u1235/*'], [u'\u1235/\u1235']],
 
136
            [[u'\u1235\\?'], [u'\u1235/\u1235']],
 
137
            [[u'\u1235\\*'], [u'\u1235/\u1235']],
 
138
            [[u'?/'], [u'\u1235/']],
 
139
            [[u'*/'], [u'\u1235/']],
 
140
            [[u'?\\'], [u'\u1235/']],
 
141
            [[u'*\\'], [u'\u1235/']],
 
142
            [[u'?/?'], [u'\u1235/\u1235']],
 
143
            [[u'*/*'], [u'\u1235/\u1235']],
 
144
            [[u'?\\?'], [u'\u1235/\u1235']],
 
145
            [[u'*\\*'], [u'\u1235/\u1235']]])
 
146
 
 
147
    def _run_testset(self, testset):
 
148
        for pattern, expected in testset:
 
149
            result = glob_expand(pattern)
 
150
            expected.sort()
 
151
            result.sort()
 
152
            self.assertEqual(expected, result, 'pattern %s' % pattern)
 
153
 
 
154
 
 
155
class TestAppPaths(TestCase):
 
156
 
 
157
    _test_needs_features = [Win32RegistryFeature]
 
158
 
 
159
    def test_iexplore(self):
 
160
        # typical windows users should have IE installed
 
161
        for a in ('iexplore', 'iexplore.exe'):
 
162
            p = get_app_path(a)
 
163
            d, b = os.path.split(p)
 
164
            self.assertEquals('iexplore.exe', b.lower())
 
165
            self.assertNotEquals('', d)
 
166
 
 
167
    def test_wordpad(self):
 
168
        # typical windows users should have wordpad in the system
 
169
        # but there is problem: its path has the format REG_EXPAND_SZ
 
170
        # so naive attempt to get the path is not working
 
171
        for a in ('wordpad', 'wordpad.exe'):
 
172
            p = get_app_path(a)
 
173
            d, b = os.path.split(p)
 
174
            self.assertEquals('wordpad.exe', b.lower())
 
175
            self.assertNotEquals('', d)
 
176
 
 
177
    def test_not_existing(self):
 
178
        p = get_app_path('not-existing')
 
179
        self.assertEquals('not-existing', p)
 
180
 
 
181
 
 
182
class TestLocationsCtypes(TestCase):
 
183
 
 
184
    _test_needs_features = [CtypesFeature]
 
185
 
 
186
    def assertPathsEqual(self, p1, p2):
 
187
        # TODO: The env var values in particular might return the "short"
 
188
        # version (ie, "C:\DOCUME~1\...").  Its even possible the returned
 
189
        # values will differ only by case - handle these situations as we
 
190
        # come across them.
 
191
        self.assertEquals(p1, p2)
 
192
 
 
193
    def test_appdata_not_using_environment(self):
 
194
        # Test that we aren't falling back to the environment
 
195
        first = win32utils.get_appdata_location()
 
196
        self._captureVar("APPDATA", None)
 
197
        self.assertPathsEqual(first, win32utils.get_appdata_location())
 
198
 
 
199
    def test_appdata_matches_environment(self):
 
200
        # Typically the APPDATA environment variable will match
 
201
        # get_appdata_location
 
202
        # XXX - See bug 262874, which asserts the correct encoding is 'mbcs',
 
203
        encoding = osutils.get_user_encoding()
 
204
        env_val = os.environ.get("APPDATA", None)
 
205
        if not env_val:
 
206
            raise TestSkipped("No APPDATA environment variable exists")
 
207
        self.assertPathsEqual(win32utils.get_appdata_location(),
 
208
                              env_val.decode(encoding))
 
209
 
 
210
    def test_local_appdata_not_using_environment(self):
 
211
        # Test that we aren't falling back to the environment
 
212
        first = win32utils.get_local_appdata_location()
 
213
        self._captureVar("LOCALAPPDATA", None)
 
214
        self.assertPathsEqual(first, win32utils.get_local_appdata_location())
 
215
 
 
216
    def test_local_appdata_matches_environment(self):
 
217
        # LOCALAPPDATA typically only exists on Vista, so we only attempt to
 
218
        # compare when it exists.
 
219
        lad = win32utils.get_local_appdata_location()
 
220
        env = os.environ.get("LOCALAPPDATA")
 
221
        if env:
 
222
            # XXX - See bug 262874, which asserts the correct encoding is 'mbcs'
 
223
            encoding = osutils.get_user_encoding()
 
224
            self.assertPathsEqual(lad, env.decode(encoding))
 
225
 
 
226
 
 
227
class TestLocationsPywin32(TestLocationsCtypes):
 
228
 
 
229
    _test_needs_features = [Win32comShellFeature]
 
230
 
 
231
    def setUp(self):
 
232
        super(TestLocationsPywin32, self).setUp()
 
233
        # We perform the exact same tests after disabling the use of ctypes.
 
234
        # This causes the implementation to fall back to pywin32.
 
235
        self.old_ctypes = win32utils.has_ctypes
 
236
        win32utils.has_ctypes = False
 
237
        self.addCleanup(self.restoreCtypes)
 
238
 
 
239
    def restoreCtypes(self):
 
240
        win32utils.has_ctypes = self.old_ctypes