/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2729.2.4 by Martin Pool
move some osutils-related tests from test_inv to test_osutils
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
1185.31.47 by John Arbash Meinel
Added a fancy footwork rename to osutils, made SftpTransport use it.
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
17
"""Tests for the osutils wrapper."""
1185.31.47 by John Arbash Meinel
Added a fancy footwork rename to osutils, made SftpTransport use it.
18
1732.1.28 by John Arbash Meinel
Add tests for fancy file types.
19
import errno
1185.31.47 by John Arbash Meinel
Added a fancy footwork rename to osutils, made SftpTransport use it.
20
import os
1732.1.28 by John Arbash Meinel
Add tests for fancy file types.
21
import socket
22
import stat
1185.31.47 by John Arbash Meinel
Added a fancy footwork rename to osutils, made SftpTransport use it.
23
import sys
24
25
import bzrlib
1996.3.14 by John Arbash Meinel
lazy_import osutils and sign_my_commits
26
from bzrlib import (
27
    errors,
28
    osutils,
2279.4.1 by Alexander Belchenko
Reimplementation of ntpath.abspath in Python for Windows98: unicode safe, UNC path safe
29
    win32utils,
1996.3.14 by John Arbash Meinel
lazy_import osutils and sign_my_commits
30
    )
1685.1.9 by John Arbash Meinel
Updated LocalTransport so that it's base is now a URL rather than a local path. This helps consistency with all other functions. To do so, I added local_abspath() which returns the local path, and local_path_to/from_url
31
from bzrlib.errors import BzrBadParameterNotUnicode, InvalidURL
2729.2.4 by Martin Pool
move some osutils-related tests from test_inv to test_osutils
32
from bzrlib.osutils import (
33
        is_inside_any,
34
        is_inside_or_parent_of_any,
35
        pathjoin,
36
        )
1711.4.10 by John Arbash Meinel
Pull out sys.stdout.encoding handling into a separate function so it can be tested, and used elsewhere.
37
from bzrlib.tests import (
38
        StringIOWrapper,
2729.2.4 by Martin Pool
move some osutils-related tests from test_inv to test_osutils
39
        TestCase,
40
        TestCaseInTempDir,
1711.4.10 by John Arbash Meinel
Pull out sys.stdout.encoding handling into a separate function so it can be tested, and used elsewhere.
41
        TestSkipped,
42
        )
1532 by Robert Collins
Merge in John Meinels integration branch.
43
1185.31.47 by John Arbash Meinel
Added a fancy footwork rename to osutils, made SftpTransport use it.
44
45
class TestOSUtils(TestCaseInTempDir):
46
2249.2.1 by John Arbash Meinel
(John Arbash Meinel) hard-code the whitespace chars to avoid problems in some locales.
47
    def test_contains_whitespace(self):
48
        self.failUnless(osutils.contains_whitespace(u' '))
49
        self.failUnless(osutils.contains_whitespace(u'hello there'))
50
        self.failUnless(osutils.contains_whitespace(u'hellothere\n'))
51
        self.failUnless(osutils.contains_whitespace(u'hello\nthere'))
52
        self.failUnless(osutils.contains_whitespace(u'hello\rthere'))
53
        self.failUnless(osutils.contains_whitespace(u'hello\tthere'))
54
55
        # \xa0 is "Non-breaking-space" which on some python locales thinks it
56
        # is whitespace, but we do not.
57
        self.failIf(osutils.contains_whitespace(u''))
58
        self.failIf(osutils.contains_whitespace(u'hellothere'))
59
        self.failIf(osutils.contains_whitespace(u'hello\xa0there'))
60
1185.31.47 by John Arbash Meinel
Added a fancy footwork rename to osutils, made SftpTransport use it.
61
    def test_fancy_rename(self):
62
        # This should work everywhere
63
        def rename(a, b):
64
            osutils.fancy_rename(a, b,
65
                    rename_func=os.rename,
66
                    unlink_func=os.unlink)
67
68
        open('a', 'wb').write('something in a\n')
69
        rename('a', 'b')
70
        self.failIfExists('a')
71
        self.failUnlessExists('b')
72
        self.check_file_contents('b', 'something in a\n')
73
74
        open('a', 'wb').write('new something in a\n')
75
        rename('b', 'a')
76
77
        self.check_file_contents('a', 'something in a\n')
78
79
    def test_rename(self):
80
        # Rename should be semi-atomic on all platforms
81
        open('a', 'wb').write('something in a\n')
82
        osutils.rename('a', 'b')
83
        self.failIfExists('a')
84
        self.failUnlessExists('b')
85
        self.check_file_contents('b', 'something in a\n')
86
87
        open('a', 'wb').write('new something in a\n')
88
        osutils.rename('b', 'a')
89
90
        self.check_file_contents('a', 'something in a\n')
91
92
    # TODO: test fancy_rename using a MemoryTransport
93
1553.5.5 by Martin Pool
New utility routine rand_chars
94
    def test_01_rand_chars_empty(self):
95
        result = osutils.rand_chars(0)
96
        self.assertEqual(result, '')
97
98
    def test_02_rand_chars_100(self):
99
        result = osutils.rand_chars(100)
100
        self.assertEqual(len(result), 100)
101
        self.assertEqual(type(result), str)
102
        self.assertContainsRe(result, r'^[a-z0-9]{100}$')
103
1996.3.14 by John Arbash Meinel
lazy_import osutils and sign_my_commits
104
    def test_is_inside(self):
105
        is_inside = osutils.is_inside
106
        self.assertTrue(is_inside('src', 'src/foo.c'))
107
        self.assertFalse(is_inside('src', 'srccontrol'))
108
        self.assertTrue(is_inside('src', 'src/a/a/a/foo.c'))
109
        self.assertTrue(is_inside('foo.c', 'foo.c'))
110
        self.assertFalse(is_inside('foo.c', ''))
111
        self.assertTrue(is_inside('', 'foo.c'))
1534.3.1 by Robert Collins
* bzrlib.osutils.safe_unicode now exists to provide parameter coercion
112
2729.2.4 by Martin Pool
move some osutils-related tests from test_inv to test_osutils
113
    def test_is_inside_any(self):
114
        SRC_FOO_C = pathjoin('src', 'foo.c')
115
        for dirs, fn in [(['src', 'doc'], SRC_FOO_C),
116
                         (['src'], SRC_FOO_C),
117
                         (['src'], 'src'),
118
                         ]:
119
            self.assert_(is_inside_any(dirs, fn))
120
        for dirs, fn in [(['src'], 'srccontrol'),
121
                         (['src'], 'srccontrol/foo')]:
122
            self.assertFalse(is_inside_any(dirs, fn))
123
124
    def test_is_inside_or_parent_of_any(self):
125
        for dirs, fn in [(['src', 'doc'], 'src/foo.c'),
126
                         (['src'], 'src/foo.c'),
127
                         (['src/bar.c'], 'src'),
128
                         (['src/bar.c', 'bla/foo.c'], 'src'),
129
                         (['src'], 'src'),
130
                         ]:
131
            self.assert_(is_inside_or_parent_of_any(dirs, fn))
132
            
133
        for dirs, fn in [(['src'], 'srccontrol'),
134
                         (['srccontrol/foo.c'], 'src'),
135
                         (['src'], 'srccontrol/foo')]:
136
            self.assertFalse(is_inside_or_parent_of_any(dirs, fn))
137
1692.7.6 by Martin Pool
[patch] force deletion of trees containing readonly files (alexander)
138
    def test_rmtree(self):
139
        # Check to remove tree with read-only files/dirs
140
        os.mkdir('dir')
141
        f = file('dir/file', 'w')
142
        f.write('spam')
143
        f.close()
144
        # would like to also try making the directory readonly, but at the
145
        # moment python shutil.rmtree doesn't handle that properly - it would
146
        # need to chmod the directory before removing things inside it - deferred
147
        # for now -- mbp 20060505
148
        # osutils.make_readonly('dir')
149
        osutils.make_readonly('dir/file')
150
151
        osutils.rmtree('dir')
152
153
        self.failIfExists('dir/file')
154
        self.failIfExists('dir')
155
1732.1.10 by John Arbash Meinel
Updated version of file_kind. Rather than multiple function calls, one mask + dictionary lookup
156
    def test_file_kind(self):
157
        self.build_tree(['file', 'dir/'])
158
        self.assertEquals('file', osutils.file_kind('file'))
159
        self.assertEquals('directory', osutils.file_kind('dir/'))
160
        if osutils.has_symlinks():
161
            os.symlink('symlink', 'symlink')
162
            self.assertEquals('symlink', osutils.file_kind('symlink'))
1732.1.28 by John Arbash Meinel
Add tests for fancy file types.
163
        
164
        # TODO: jam 20060529 Test a block device
165
        try:
166
            os.lstat('/dev/null')
167
        except OSError, e:
168
            if e.errno not in (errno.ENOENT,):
169
                raise
170
        else:
171
            self.assertEquals('chardev', osutils.file_kind('/dev/null'))
172
173
        mkfifo = getattr(os, 'mkfifo', None)
174
        if mkfifo:
175
            mkfifo('fifo')
176
            try:
177
                self.assertEquals('fifo', osutils.file_kind('fifo'))
178
            finally:
179
                os.remove('fifo')
180
181
        AF_UNIX = getattr(socket, 'AF_UNIX', None)
182
        if AF_UNIX:
183
            s = socket.socket(AF_UNIX)
184
            s.bind('socket')
185
            try:
186
                self.assertEquals('socket', osutils.file_kind('socket'))
187
            finally:
188
                os.remove('socket')
1732.1.10 by John Arbash Meinel
Updated version of file_kind. Rather than multiple function calls, one mask + dictionary lookup
189
1551.10.27 by Aaron Bentley
Add a kind marker for subtrees
190
    def test_kind_marker(self):
191
        self.assertEqual(osutils.kind_marker('file'), '')
192
        self.assertEqual(osutils.kind_marker('directory'), '/')
193
        self.assertEqual(osutils.kind_marker('symlink'), '@')
1551.10.28 by Aaron Bentley
change kind marker to '+'
194
        self.assertEqual(osutils.kind_marker('tree-reference'), '+')
1551.10.27 by Aaron Bentley
Add a kind marker for subtrees
195
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
196
    def test_get_umask(self):
197
        if sys.platform == 'win32':
198
            # umask always returns '0', no way to set it
199
            self.assertEqual(0, osutils.get_umask())
200
            return
201
202
        orig_umask = osutils.get_umask()
203
        try:
204
            os.umask(0222)
205
            self.assertEqual(0222, osutils.get_umask())
206
            os.umask(0022)
207
            self.assertEqual(0022, osutils.get_umask())
208
            os.umask(0002)
209
            self.assertEqual(0002, osutils.get_umask())
210
            os.umask(0027)
211
            self.assertEqual(0027, osutils.get_umask())
212
        finally:
213
            os.umask(orig_umask)
214
1957.1.15 by John Arbash Meinel
Review feedback from Robert
215
    def assertFormatedDelta(self, expected, seconds):
216
        """Assert osutils.format_delta formats as expected"""
217
        actual = osutils.format_delta(seconds)
218
        self.assertEqual(expected, actual)
219
1957.1.4 by John Arbash Meinel
create a helper for formatting a time delta
220
    def test_format_delta(self):
1957.1.15 by John Arbash Meinel
Review feedback from Robert
221
        self.assertFormatedDelta('0 seconds ago', 0)
222
        self.assertFormatedDelta('1 second ago', 1)
223
        self.assertFormatedDelta('10 seconds ago', 10)
224
        self.assertFormatedDelta('59 seconds ago', 59)
225
        self.assertFormatedDelta('89 seconds ago', 89)
226
        self.assertFormatedDelta('1 minute, 30 seconds ago', 90)
227
        self.assertFormatedDelta('3 minutes, 0 seconds ago', 180)
228
        self.assertFormatedDelta('3 minutes, 1 second ago', 181)
229
        self.assertFormatedDelta('10 minutes, 15 seconds ago', 615)
230
        self.assertFormatedDelta('30 minutes, 59 seconds ago', 1859)
231
        self.assertFormatedDelta('31 minutes, 0 seconds ago', 1860)
232
        self.assertFormatedDelta('60 minutes, 0 seconds ago', 3600)
233
        self.assertFormatedDelta('89 minutes, 59 seconds ago', 5399)
234
        self.assertFormatedDelta('1 hour, 30 minutes ago', 5400)
235
        self.assertFormatedDelta('2 hours, 30 minutes ago', 9017)
236
        self.assertFormatedDelta('10 hours, 0 minutes ago', 36000)
237
        self.assertFormatedDelta('24 hours, 0 minutes ago', 86400)
238
        self.assertFormatedDelta('35 hours, 59 minutes ago', 129599)
239
        self.assertFormatedDelta('36 hours, 0 minutes ago', 129600)
240
        self.assertFormatedDelta('36 hours, 0 minutes ago', 129601)
241
        self.assertFormatedDelta('36 hours, 1 minute ago', 129660)
242
        self.assertFormatedDelta('36 hours, 1 minute ago', 129661)
243
        self.assertFormatedDelta('84 hours, 10 minutes ago', 303002)
1957.1.4 by John Arbash Meinel
create a helper for formatting a time delta
244
245
        # We handle when time steps the wrong direction because computers
246
        # don't have synchronized clocks.
1957.1.15 by John Arbash Meinel
Review feedback from Robert
247
        self.assertFormatedDelta('84 hours, 10 minutes in the future', -303002)
248
        self.assertFormatedDelta('1 second in the future', -1)
249
        self.assertFormatedDelta('2 seconds in the future', -2)
1957.1.4 by John Arbash Meinel
create a helper for formatting a time delta
250
2091.3.7 by Aaron Bentley
Rename real_parent to dereferenced_path
251
    def test_dereference_path(self):
2091.3.6 by Aaron Bentley
Add symlink test guards
252
        if not osutils.has_symlinks():
253
            raise TestSkipped('Symlinks are not supported on this platform')
2091.3.5 by Aaron Bentley
Move realpath functionality into osutils
254
        cwd = osutils.realpath('.')
255
        os.mkdir('bar')
256
        bar_path = osutils.pathjoin(cwd, 'bar')
257
        # Using './' to avoid bug #1213894 (first path component not
258
        # dereferenced) in Python 2.4.1 and earlier
259
        self.assertEqual(bar_path, osutils.realpath('./bar'))
260
        os.symlink('bar', 'foo')
261
        self.assertEqual(bar_path, osutils.realpath('./foo'))
262
        
263
        # Does not dereference terminal symlinks
264
        foo_path = osutils.pathjoin(cwd, 'foo')
2091.3.7 by Aaron Bentley
Rename real_parent to dereferenced_path
265
        self.assertEqual(foo_path, osutils.dereference_path('./foo'))
2091.3.5 by Aaron Bentley
Move realpath functionality into osutils
266
267
        # Dereferences parent symlinks
268
        os.mkdir('bar/baz')
269
        baz_path = osutils.pathjoin(bar_path, 'baz')
2091.3.7 by Aaron Bentley
Rename real_parent to dereferenced_path
270
        self.assertEqual(baz_path, osutils.dereference_path('./foo/baz'))
2091.3.5 by Aaron Bentley
Move realpath functionality into osutils
271
272
        # Dereferences parent symlinks that are the first path element
2091.3.7 by Aaron Bentley
Rename real_parent to dereferenced_path
273
        self.assertEqual(baz_path, osutils.dereference_path('foo/baz'))
2091.3.5 by Aaron Bentley
Move realpath functionality into osutils
274
275
        # Dereferences parent symlinks in absolute paths
276
        foo_baz_path = osutils.pathjoin(foo_path, 'baz')
2091.3.7 by Aaron Bentley
Rename real_parent to dereferenced_path
277
        self.assertEqual(baz_path, osutils.dereference_path(foo_baz_path))
2091.3.5 by Aaron Bentley
Move realpath functionality into osutils
278
1692.7.6 by Martin Pool
[patch] force deletion of trees containing readonly files (alexander)
279
2568.1.1 by John Arbash Meinel
(Elliot Murphy) Use os.lstat rather than os.stat for osutils.make_readonly/make_writeable
280
    def test_changing_access(self):
281
        f = file('file', 'w')
282
        f.write('monkey')
283
        f.close()
284
285
        # Make a file readonly
286
        osutils.make_readonly('file')
287
        mode = osutils.lstat('file').st_mode
288
        self.assertEqual(mode, mode & 0777555)
289
290
        # Make a file writable
291
        osutils.make_writable('file')
292
        mode = osutils.lstat('file').st_mode
293
        self.assertEqual(mode, mode | 0200)
294
295
        if osutils.has_symlinks():
296
            # should not error when handed a symlink
297
            os.symlink('nonexistent', 'dangling')
298
            osutils.make_readonly('dangling')
299
            osutils.make_writable('dangling')
300
301
2324.2.1 by Dmitry Vasiliev
kind_marker() optimization
302
    def test_kind_marker(self):
303
        self.assertEqual("", osutils.kind_marker("file"))
304
        self.assertEqual("/", osutils.kind_marker(osutils._directory_kind))
305
        self.assertEqual("@", osutils.kind_marker("symlink"))
306
        self.assertRaises(errors.BzrError, osutils.kind_marker, "unknown")
307
308
1534.3.1 by Robert Collins
* bzrlib.osutils.safe_unicode now exists to provide parameter coercion
309
class TestSafeUnicode(TestCase):
310
311
    def test_from_ascii_string(self):
312
        self.assertEqual(u'foobar', osutils.safe_unicode('foobar'))
313
1534.3.2 by Robert Collins
An extra test for John.
314
    def test_from_unicode_string_ascii_contents(self):
1534.3.1 by Robert Collins
* bzrlib.osutils.safe_unicode now exists to provide parameter coercion
315
        self.assertEqual(u'bargam', osutils.safe_unicode(u'bargam'))
316
1534.3.2 by Robert Collins
An extra test for John.
317
    def test_from_unicode_string_unicode_contents(self):
318
        self.assertEqual(u'bargam\xae', osutils.safe_unicode(u'bargam\xae'))
319
1534.3.1 by Robert Collins
* bzrlib.osutils.safe_unicode now exists to provide parameter coercion
320
    def test_from_utf8_string(self):
321
        self.assertEqual(u'foo\xae', osutils.safe_unicode('foo\xc2\xae'))
322
323
    def test_bad_utf8_string(self):
1185.65.29 by Robert Collins
Implement final review suggestions.
324
        self.assertRaises(BzrBadParameterNotUnicode,
325
                          osutils.safe_unicode,
326
                          '\xbb\xbb')
1666.1.6 by Robert Collins
Make knit the default format.
327
328
2249.5.8 by John Arbash Meinel
Add osutils.safe_utf8 and safe_revision_id for the new revision_id work.
329
class TestSafeUtf8(TestCase):
330
331
    def test_from_ascii_string(self):
332
        f = 'foobar'
333
        self.assertEqual('foobar', osutils.safe_utf8(f))
334
335
    def test_from_unicode_string_ascii_contents(self):
336
        self.assertEqual('bargam', osutils.safe_utf8(u'bargam'))
337
338
    def test_from_unicode_string_unicode_contents(self):
339
        self.assertEqual('bargam\xc2\xae', osutils.safe_utf8(u'bargam\xae'))
340
341
    def test_from_utf8_string(self):
342
        self.assertEqual('foo\xc2\xae', osutils.safe_utf8('foo\xc2\xae'))
343
344
    def test_bad_utf8_string(self):
345
        self.assertRaises(BzrBadParameterNotUnicode,
346
                          osutils.safe_utf8, '\xbb\xbb')
347
348
349
class TestSafeRevisionId(TestCase):
350
351
    def test_from_ascii_string(self):
2309.4.4 by John Arbash Meinel
Change what warnings are raised, and add tests that they are used.
352
        self.assertEqual('foobar', osutils.safe_revision_id('foobar'))
2249.5.8 by John Arbash Meinel
Add osutils.safe_utf8 and safe_revision_id for the new revision_id work.
353
354
    def test_from_unicode_string_ascii_contents(self):
2309.4.4 by John Arbash Meinel
Change what warnings are raised, and add tests that they are used.
355
        self.assertEqual('bargam',
356
                         osutils.safe_revision_id(u'bargam', warn=False))
357
358
    def test_from_unicode_deprecated(self):
359
        self.assertEqual('bargam',
360
            self.callDeprecated([osutils._revision_id_warning],
361
                                osutils.safe_revision_id, u'bargam'))
2249.5.8 by John Arbash Meinel
Add osutils.safe_utf8 and safe_revision_id for the new revision_id work.
362
363
    def test_from_unicode_string_unicode_contents(self):
364
        self.assertEqual('bargam\xc2\xae',
2309.4.4 by John Arbash Meinel
Change what warnings are raised, and add tests that they are used.
365
                         osutils.safe_revision_id(u'bargam\xae', warn=False))
2249.5.8 by John Arbash Meinel
Add osutils.safe_utf8 and safe_revision_id for the new revision_id work.
366
367
    def test_from_utf8_string(self):
368
        self.assertEqual('foo\xc2\xae',
369
                         osutils.safe_revision_id('foo\xc2\xae'))
370
2249.5.9 by John Arbash Meinel
Update WorkingTree to use safe_revision_id when appropriate
371
    def test_none(self):
372
        """Currently, None is a valid revision_id"""
373
        self.assertEqual(None, osutils.safe_revision_id(None))
374
2249.5.8 by John Arbash Meinel
Add osutils.safe_utf8 and safe_revision_id for the new revision_id work.
375
2294.1.4 by John Arbash Meinel
Add safe_file_id as a helper in osutils.
376
class TestSafeFileId(TestCase):
377
378
    def test_from_ascii_string(self):
2309.4.4 by John Arbash Meinel
Change what warnings are raised, and add tests that they are used.
379
        self.assertEqual('foobar', osutils.safe_file_id('foobar'))
2294.1.4 by John Arbash Meinel
Add safe_file_id as a helper in osutils.
380
381
    def test_from_unicode_string_ascii_contents(self):
2309.4.4 by John Arbash Meinel
Change what warnings are raised, and add tests that they are used.
382
        self.assertEqual('bargam', osutils.safe_file_id(u'bargam', warn=False))
383
384
    def test_from_unicode_deprecated(self):
385
        self.assertEqual('bargam',
386
            self.callDeprecated([osutils._file_id_warning],
387
                                osutils.safe_file_id, u'bargam'))
2294.1.4 by John Arbash Meinel
Add safe_file_id as a helper in osutils.
388
389
    def test_from_unicode_string_unicode_contents(self):
390
        self.assertEqual('bargam\xc2\xae',
2309.4.4 by John Arbash Meinel
Change what warnings are raised, and add tests that they are used.
391
                         osutils.safe_file_id(u'bargam\xae', warn=False))
2294.1.4 by John Arbash Meinel
Add safe_file_id as a helper in osutils.
392
393
    def test_from_utf8_string(self):
394
        self.assertEqual('foo\xc2\xae',
395
                         osutils.safe_file_id('foo\xc2\xae'))
396
397
    def test_none(self):
398
        """Currently, None is a valid revision_id"""
399
        self.assertEqual(None, osutils.safe_file_id(None))
400
401
1685.1.31 by John Arbash Meinel
Adding tests for the rest of the _win32 functions.
402
class TestWin32Funcs(TestCase):
403
    """Test that the _win32 versions of os utilities return appropriate paths."""
404
405
    def test_abspath(self):
406
        self.assertEqual('C:/foo', osutils._win32_abspath('C:\\foo'))
407
        self.assertEqual('C:/foo', osutils._win32_abspath('C:/foo'))
2279.4.1 by Alexander Belchenko
Reimplementation of ntpath.abspath in Python for Windows98: unicode safe, UNC path safe
408
        self.assertEqual('//HOST/path', osutils._win32_abspath(r'\\HOST\path'))
409
        self.assertEqual('//HOST/path', osutils._win32_abspath('//HOST/path'))
1685.1.31 by John Arbash Meinel
Adding tests for the rest of the _win32 functions.
410
411
    def test_realpath(self):
412
        self.assertEqual('C:/foo', osutils._win32_realpath('C:\\foo'))
413
        self.assertEqual('C:/foo', osutils._win32_realpath('C:/foo'))
414
415
    def test_pathjoin(self):
416
        self.assertEqual('path/to/foo', osutils._win32_pathjoin('path', 'to', 'foo'))
417
        self.assertEqual('C:/foo', osutils._win32_pathjoin('path\\to', 'C:\\foo'))
418
        self.assertEqual('C:/foo', osutils._win32_pathjoin('path/to', 'C:/foo'))
419
        self.assertEqual('path/to/foo', osutils._win32_pathjoin('path/to/', 'foo'))
420
        self.assertEqual('/foo', osutils._win32_pathjoin('C:/path/to/', '/foo'))
421
        self.assertEqual('/foo', osutils._win32_pathjoin('C:\\path\\to\\', '\\foo'))
422
423
    def test_normpath(self):
424
        self.assertEqual('path/to/foo', osutils._win32_normpath(r'path\\from\..\to\.\foo'))
425
        self.assertEqual('path/to/foo', osutils._win32_normpath('path//from/../to/./foo'))
426
427
    def test_getcwd(self):
1711.5.2 by John Arbash Meinel
win32 likes to return lowercase drive letters sometimes, and uppercase at other times. normalize this
428
        cwd = osutils._win32_getcwd()
429
        os_cwd = os.getcwdu()
430
        self.assertEqual(os_cwd[1:].replace('\\', '/'), cwd[1:])
431
        # win32 is inconsistent whether it returns lower or upper case
432
        # and even if it was consistent the user might type the other
433
        # so we force it to uppercase
434
        # running python.exe under cmd.exe return capital C:\\
435
        # running win32 python inside a cygwin shell returns lowercase
436
        self.assertEqual(os_cwd[0].upper(), cwd[0])
437
438
    def test_fixdrive(self):
439
        self.assertEqual('H:/foo', osutils._win32_fixdrive('h:/foo'))
440
        self.assertEqual('H:/foo', osutils._win32_fixdrive('H:/foo'))
441
        self.assertEqual('C:\\foo', osutils._win32_fixdrive('c:\\foo'))
1685.1.31 by John Arbash Meinel
Adding tests for the rest of the _win32 functions.
442
2279.4.1 by Alexander Belchenko
Reimplementation of ntpath.abspath in Python for Windows98: unicode safe, UNC path safe
443
    def test_win98_abspath(self):
444
        # absolute path
445
        self.assertEqual('C:/foo', osutils._win98_abspath('C:\\foo'))
446
        self.assertEqual('C:/foo', osutils._win98_abspath('C:/foo'))
447
        # UNC path
448
        self.assertEqual('//HOST/path', osutils._win98_abspath(r'\\HOST\path'))
449
        self.assertEqual('//HOST/path', osutils._win98_abspath('//HOST/path'))
450
        # relative path
451
        cwd = osutils.getcwd().rstrip('/')
452
        drive = osutils._nt_splitdrive(cwd)[0]
453
        self.assertEqual(cwd+'/path', osutils._win98_abspath('path'))
454
        self.assertEqual(drive+'/path', osutils._win98_abspath('/path'))
455
        # unicode path
456
        u = u'\u1234'
457
        self.assertEqual(cwd+'/'+u, osutils._win98_abspath(u))
458
1685.1.31 by John Arbash Meinel
Adding tests for the rest of the _win32 functions.
459
460
class TestWin32FuncsDirs(TestCaseInTempDir):
461
    """Test win32 functions that create files."""
462
    
463
    def test_getcwd(self):
2279.4.1 by Alexander Belchenko
Reimplementation of ntpath.abspath in Python for Windows98: unicode safe, UNC path safe
464
        if win32utils.winver == 'Windows 98':
465
            raise TestSkipped('Windows 98 cannot handle unicode filenames')
1685.1.31 by John Arbash Meinel
Adding tests for the rest of the _win32 functions.
466
        # Make sure getcwd can handle unicode filenames
467
        try:
1830.3.9 by John Arbash Meinel
Use a directory name that doesn't get messed up on Mac for getcwd() test.
468
            os.mkdir(u'mu-\xb5')
1685.1.31 by John Arbash Meinel
Adding tests for the rest of the _win32 functions.
469
        except UnicodeError:
470
            raise TestSkipped("Unable to create Unicode filename")
471
1830.3.9 by John Arbash Meinel
Use a directory name that doesn't get messed up on Mac for getcwd() test.
472
        os.chdir(u'mu-\xb5')
1685.1.31 by John Arbash Meinel
Adding tests for the rest of the _win32 functions.
473
        # TODO: jam 20060427 This will probably fail on Mac OSX because
474
        #       it will change the normalization of B\xe5gfors
475
        #       Consider using a different unicode character, or make
476
        #       osutils.getcwd() renormalize the path.
1830.3.9 by John Arbash Meinel
Use a directory name that doesn't get messed up on Mac for getcwd() test.
477
        self.assertEndsWith(osutils._win32_getcwd(), u'mu-\xb5')
1685.1.31 by John Arbash Meinel
Adding tests for the rest of the _win32 functions.
478
479
    def test_mkdtemp(self):
480
        tmpdir = osutils._win32_mkdtemp(dir='.')
481
        self.assertFalse('\\' in tmpdir)
482
483
    def test_rename(self):
484
        a = open('a', 'wb')
485
        a.write('foo\n')
486
        a.close()
487
        b = open('b', 'wb')
488
        b.write('baz\n')
489
        b.close()
490
491
        osutils._win32_rename('b', 'a')
492
        self.failUnlessExists('a')
493
        self.failIfExists('b')
494
        self.assertFileEqual('baz\n', 'a')
495
1711.7.6 by John Arbash Meinel
Change _win32_rename() so that it raises ENOENT *before* it tries any renaming.
496
    def test_rename_missing_file(self):
497
        a = open('a', 'wb')
498
        a.write('foo\n')
499
        a.close()
500
501
        try:
502
            osutils._win32_rename('b', 'a')
503
        except (IOError, OSError), e:
504
            self.assertEqual(errno.ENOENT, e.errno)
505
        self.assertFileEqual('foo\n', 'a')
506
507
    def test_rename_missing_dir(self):
508
        os.mkdir('a')
509
        try:
510
            osutils._win32_rename('b', 'a')
511
        except (IOError, OSError), e:
512
            self.assertEqual(errno.ENOENT, e.errno)
513
514
    def test_rename_current_dir(self):
515
        os.mkdir('a')
516
        os.chdir('a')
517
        # You can't rename the working directory
518
        # doing rename non-existant . usually
519
        # just raises ENOENT, since non-existant
520
        # doesn't exist.
521
        try:
522
            osutils._win32_rename('b', '.')
523
        except (IOError, OSError), e:
524
            self.assertEqual(errno.ENOENT, e.errno)
525
1996.3.14 by John Arbash Meinel
lazy_import osutils and sign_my_commits
526
    def test_splitpath(self):
527
        def check(expected, path):
528
            self.assertEqual(expected, osutils.splitpath(path))
529
530
        check(['a'], 'a')
531
        check(['a', 'b'], 'a/b')
532
        check(['a', 'b'], 'a/./b')
533
        check(['a', '.b'], 'a/.b')
534
        check(['a', '.b'], 'a\\.b')
535
536
        self.assertRaises(errors.BzrError, osutils.splitpath, 'a/../b')
537
1685.1.31 by John Arbash Meinel
Adding tests for the rest of the _win32 functions.
538
1830.3.11 by John Arbash Meinel
Create a mac version of 'getcwd()' which normalizes the path.
539
class TestMacFuncsDirs(TestCaseInTempDir):
540
    """Test mac special functions that require directories."""
541
542
    def test_getcwd(self):
543
        # On Mac, this will actually create Ba\u030agfors
544
        # but chdir will still work, because it accepts both paths
545
        try:
546
            os.mkdir(u'B\xe5gfors')
547
        except UnicodeError:
548
            raise TestSkipped("Unable to create Unicode filename")
549
550
        os.chdir(u'B\xe5gfors')
551
        self.assertEndsWith(osutils._mac_getcwd(), u'B\xe5gfors')
552
553
    def test_getcwd_nonnorm(self):
554
        # Test that _mac_getcwd() will normalize this path
555
        try:
556
            os.mkdir(u'Ba\u030agfors')
557
        except UnicodeError:
558
            raise TestSkipped("Unable to create Unicode filename")
559
560
        os.chdir(u'Ba\u030agfors')
561
        self.assertEndsWith(osutils._mac_getcwd(), u'B\xe5gfors')
562
1996.3.14 by John Arbash Meinel
lazy_import osutils and sign_my_commits
563
1666.1.6 by Robert Collins
Make knit the default format.
564
class TestSplitLines(TestCase):
565
566
    def test_split_unicode(self):
567
        self.assertEqual([u'foo\n', u'bar\xae'],
568
                         osutils.split_lines(u'foo\nbar\xae'))
569
        self.assertEqual([u'foo\n', u'bar\xae\n'],
570
                         osutils.split_lines(u'foo\nbar\xae\n'))
571
572
    def test_split_with_carriage_returns(self):
573
        self.assertEqual(['foo\rbar\n'],
574
                         osutils.split_lines('foo\rbar\n'))
1753.1.1 by Robert Collins
(rbc, jam, mbp)Add bzrlib.osutils.walkdirs, an optimised walk-and-stat routine.
575
576
577
class TestWalkDirs(TestCaseInTempDir):
578
579
    def test_walkdirs(self):
580
        tree = [
581
            '.bzr',
582
            '0file',
583
            '1dir/',
584
            '1dir/0file',
585
            '1dir/1dir/',
586
            '2file'
587
            ]
588
        self.build_tree(tree)
589
        expected_dirblocks = [
1897.1.1 by Robert Collins
Add some useful summary data to osutils.walkdirs output.
590
                (('', '.'),
591
                 [('0file', '0file', 'file'),
592
                  ('1dir', '1dir', 'directory'),
593
                  ('2file', '2file', 'file'),
594
                 ]
595
                ),
596
                (('1dir', './1dir'),
597
                 [('1dir/0file', '0file', 'file'),
598
                  ('1dir/1dir', '1dir', 'directory'),
599
                 ]
600
                ),
601
                (('1dir/1dir', './1dir/1dir'),
602
                 [
603
                 ]
604
                ),
1753.1.1 by Robert Collins
(rbc, jam, mbp)Add bzrlib.osutils.walkdirs, an optimised walk-and-stat routine.
605
            ]
606
        result = []
607
        found_bzrdir = False
1897.1.1 by Robert Collins
Add some useful summary data to osutils.walkdirs output.
608
        for dirdetail, dirblock in osutils.walkdirs('.'):
1753.1.1 by Robert Collins
(rbc, jam, mbp)Add bzrlib.osutils.walkdirs, an optimised walk-and-stat routine.
609
            if len(dirblock) and dirblock[0][1] == '.bzr':
610
                # this tests the filtering of selected paths
611
                found_bzrdir = True
612
                del dirblock[0]
1897.1.1 by Robert Collins
Add some useful summary data to osutils.walkdirs output.
613
            result.append((dirdetail, dirblock))
1753.1.1 by Robert Collins
(rbc, jam, mbp)Add bzrlib.osutils.walkdirs, an optimised walk-and-stat routine.
614
615
        self.assertTrue(found_bzrdir)
616
        self.assertEqual(expected_dirblocks,
1897.1.1 by Robert Collins
Add some useful summary data to osutils.walkdirs output.
617
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
1757.2.8 by Robert Collins
Teach walkdirs to walk a subdir of a tree.
618
        # you can search a subdir only, with a supplied prefix.
619
        result = []
1897.1.1 by Robert Collins
Add some useful summary data to osutils.walkdirs output.
620
        for dirblock in osutils.walkdirs('./1dir', '1dir'):
1757.2.8 by Robert Collins
Teach walkdirs to walk a subdir of a tree.
621
            result.append(dirblock)
622
        self.assertEqual(expected_dirblocks[1:],
1897.1.1 by Robert Collins
Add some useful summary data to osutils.walkdirs output.
623
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
1757.2.8 by Robert Collins
Teach walkdirs to walk a subdir of a tree.
624
2255.7.27 by John Arbash Meinel
Add a _walkdirs_utf8 which returns utf8 paths instead of Unicode. Approx 20% faster in walking utf8 filesystems
625
    def test__walkdirs_utf8(self):
626
        tree = [
627
            '.bzr',
628
            '0file',
629
            '1dir/',
630
            '1dir/0file',
631
            '1dir/1dir/',
632
            '2file'
633
            ]
634
        self.build_tree(tree)
635
        expected_dirblocks = [
636
                (('', '.'),
637
                 [('0file', '0file', 'file'),
638
                  ('1dir', '1dir', 'directory'),
639
                  ('2file', '2file', 'file'),
640
                 ]
641
                ),
642
                (('1dir', './1dir'),
643
                 [('1dir/0file', '0file', 'file'),
644
                  ('1dir/1dir', '1dir', 'directory'),
645
                 ]
646
                ),
647
                (('1dir/1dir', './1dir/1dir'),
648
                 [
649
                 ]
650
                ),
651
            ]
652
        result = []
653
        found_bzrdir = False
654
        for dirdetail, dirblock in osutils._walkdirs_utf8('.'):
655
            if len(dirblock) and dirblock[0][1] == '.bzr':
656
                # this tests the filtering of selected paths
657
                found_bzrdir = True
658
                del dirblock[0]
659
            result.append((dirdetail, dirblock))
660
661
        self.assertTrue(found_bzrdir)
662
        self.assertEqual(expected_dirblocks,
663
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
664
        # you can search a subdir only, with a supplied prefix.
665
        result = []
666
        for dirblock in osutils.walkdirs('./1dir', '1dir'):
667
            result.append(dirblock)
668
        self.assertEqual(expected_dirblocks[1:],
669
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
670
2255.7.32 by John Arbash Meinel
Add tests that the walkdirs variants work on unicode paths.
671
    def _filter_out_stat(self, result):
672
        """Filter out the stat value from the walkdirs result"""
673
        for dirdetail, dirblock in result:
674
            new_dirblock = []
675
            for info in dirblock:
676
                # Ignore info[3] which is the stat
677
                new_dirblock.append((info[0], info[1], info[2], info[4]))
678
            dirblock[:] = new_dirblock
679
680
    def test_unicode_walkdirs(self):
681
        """Walkdirs should always return unicode paths."""
682
        name0 = u'0file-\xb6'
683
        name1 = u'1dir-\u062c\u0648'
684
        name2 = u'2file-\u0633'
685
        tree = [
686
            name0,
687
            name1 + '/',
688
            name1 + '/' + name0,
689
            name1 + '/' + name1 + '/',
690
            name2,
691
            ]
692
        try:
693
            self.build_tree(tree)
694
        except UnicodeError:
695
            raise TestSkipped('Could not represent Unicode chars'
696
                              ' in current encoding.')
697
        expected_dirblocks = [
698
                ((u'', u'.'),
699
                 [(name0, name0, 'file', './' + name0),
700
                  (name1, name1, 'directory', './' + name1),
701
                  (name2, name2, 'file', './' + name2),
702
                 ]
703
                ),
704
                ((name1, './' + name1),
705
                 [(name1 + '/' + name0, name0, 'file', './' + name1
706
                                                        + '/' + name0),
707
                  (name1 + '/' + name1, name1, 'directory', './' + name1
708
                                                            + '/' + name1),
709
                 ]
710
                ),
711
                ((name1 + '/' + name1, './' + name1 + '/' + name1),
712
                 [
713
                 ]
714
                ),
715
            ]
716
        result = list(osutils.walkdirs('.'))
717
        self._filter_out_stat(result)
718
        self.assertEqual(expected_dirblocks, result)
719
        result = list(osutils.walkdirs(u'./'+name1, name1))
720
        self._filter_out_stat(result)
721
        self.assertEqual(expected_dirblocks[1:], result)
722
723
    def test_unicode__walkdirs_utf8(self):
724
        """Walkdirs_utf8 should always return utf8 paths.
725
726
        The abspath portion might be in unicode or utf-8
727
        """
728
        name0 = u'0file-\xb6'
729
        name1 = u'1dir-\u062c\u0648'
730
        name2 = u'2file-\u0633'
731
        tree = [
732
            name0,
733
            name1 + '/',
734
            name1 + '/' + name0,
735
            name1 + '/' + name1 + '/',
736
            name2,
737
            ]
738
        try:
739
            self.build_tree(tree)
740
        except UnicodeError:
741
            raise TestSkipped('Could not represent Unicode chars'
742
                              ' in current encoding.')
743
        name0 = name0.encode('utf8')
744
        name1 = name1.encode('utf8')
745
        name2 = name2.encode('utf8')
746
747
        expected_dirblocks = [
748
                (('', '.'),
749
                 [(name0, name0, 'file', './' + name0),
750
                  (name1, name1, 'directory', './' + name1),
751
                  (name2, name2, 'file', './' + name2),
752
                 ]
753
                ),
754
                ((name1, './' + name1),
755
                 [(name1 + '/' + name0, name0, 'file', './' + name1
756
                                                        + '/' + name0),
757
                  (name1 + '/' + name1, name1, 'directory', './' + name1
758
                                                            + '/' + name1),
759
                 ]
760
                ),
761
                ((name1 + '/' + name1, './' + name1 + '/' + name1),
762
                 [
763
                 ]
764
                ),
765
            ]
766
        result = []
767
        # For ease in testing, if walkdirs_utf8 returns Unicode, assert that
768
        # all abspaths are Unicode, and encode them back into utf8.
769
        for dirdetail, dirblock in osutils._walkdirs_utf8('.'):
770
            self.assertIsInstance(dirdetail[0], str)
771
            if isinstance(dirdetail[1], unicode):
2324.2.4 by Dmitry Vasiliev
Fixed test_unicode__walkdirs_utf8 test
772
                dirdetail = (dirdetail[0], dirdetail[1].encode('utf8'))
773
                dirblock = [list(info) for info in dirblock]
2255.7.32 by John Arbash Meinel
Add tests that the walkdirs variants work on unicode paths.
774
                for info in dirblock:
775
                    self.assertIsInstance(info[4], unicode)
776
                    info[4] = info[4].encode('utf8')
777
            new_dirblock = []
778
            for info in dirblock:
779
                self.assertIsInstance(info[0], str)
780
                self.assertIsInstance(info[1], str)
781
                self.assertIsInstance(info[4], str)
782
                # Remove the stat information
783
                new_dirblock.append((info[0], info[1], info[2], info[4]))
784
            result.append((dirdetail, new_dirblock))
785
        self.assertEqual(expected_dirblocks, result)
786
787
    def test_unicode__walkdirs_unicode_to_utf8(self):
788
        """walkdirs_unicode_to_utf8 should be a safe fallback everywhere
789
790
        The abspath portion should be in unicode
791
        """
792
        name0u = u'0file-\xb6'
793
        name1u = u'1dir-\u062c\u0648'
794
        name2u = u'2file-\u0633'
795
        tree = [
796
            name0u,
797
            name1u + '/',
798
            name1u + '/' + name0u,
799
            name1u + '/' + name1u + '/',
800
            name2u,
801
            ]
802
        try:
803
            self.build_tree(tree)
804
        except UnicodeError:
805
            raise TestSkipped('Could not represent Unicode chars'
806
                              ' in current encoding.')
807
        name0 = name0u.encode('utf8')
808
        name1 = name1u.encode('utf8')
809
        name2 = name2u.encode('utf8')
810
811
        # All of the abspaths should be in unicode, all of the relative paths
812
        # should be in utf8
813
        expected_dirblocks = [
814
                (('', '.'),
815
                 [(name0, name0, 'file', './' + name0u),
816
                  (name1, name1, 'directory', './' + name1u),
817
                  (name2, name2, 'file', './' + name2u),
818
                 ]
819
                ),
820
                ((name1, './' + name1u),
821
                 [(name1 + '/' + name0, name0, 'file', './' + name1u
822
                                                        + '/' + name0u),
823
                  (name1 + '/' + name1, name1, 'directory', './' + name1u
824
                                                            + '/' + name1u),
825
                 ]
826
                ),
827
                ((name1 + '/' + name1, './' + name1u + '/' + name1u),
828
                 [
829
                 ]
830
                ),
831
            ]
832
        result = list(osutils._walkdirs_unicode_to_utf8('.'))
833
        self._filter_out_stat(result)
834
        self.assertEqual(expected_dirblocks, result)
835
1773.3.1 by Robert Collins
Add path_prefix_key and compare_paths_prefix_order utility functions.
836
    def assertPathCompare(self, path_less, path_greater):
837
        """check that path_less and path_greater compare correctly."""
838
        self.assertEqual(0, osutils.compare_paths_prefix_order(
839
            path_less, path_less))
840
        self.assertEqual(0, osutils.compare_paths_prefix_order(
841
            path_greater, path_greater))
842
        self.assertEqual(-1, osutils.compare_paths_prefix_order(
843
            path_less, path_greater))
844
        self.assertEqual(1, osutils.compare_paths_prefix_order(
845
            path_greater, path_less))
846
847
    def test_compare_paths_prefix_order(self):
848
        # root before all else
849
        self.assertPathCompare("/", "/a")
850
        # alpha within a dir
851
        self.assertPathCompare("/a", "/b")
852
        self.assertPathCompare("/b", "/z")
853
        # high dirs before lower.
854
        self.assertPathCompare("/z", "/a/a")
1773.3.2 by Robert Collins
New corner case from John Meinel, showing up the need to check the directory lexographically outside of a single tree's root. Fixed.
855
        # except if the deeper dir should be output first
856
        self.assertPathCompare("/a/b/c", "/d/g")
1773.3.1 by Robert Collins
Add path_prefix_key and compare_paths_prefix_order utility functions.
857
        # lexical betwen dirs of the same height
858
        self.assertPathCompare("/a/z", "/z/z")
859
        self.assertPathCompare("/a/c/z", "/a/d/e")
860
861
        # this should also be consistent for no leading / paths
862
        # root before all else
863
        self.assertPathCompare("", "a")
864
        # alpha within a dir
865
        self.assertPathCompare("a", "b")
866
        self.assertPathCompare("b", "z")
867
        # high dirs before lower.
868
        self.assertPathCompare("z", "a/a")
1773.3.2 by Robert Collins
New corner case from John Meinel, showing up the need to check the directory lexographically outside of a single tree's root. Fixed.
869
        # except if the deeper dir should be output first
870
        self.assertPathCompare("a/b/c", "d/g")
1773.3.1 by Robert Collins
Add path_prefix_key and compare_paths_prefix_order utility functions.
871
        # lexical betwen dirs of the same height
872
        self.assertPathCompare("a/z", "z/z")
873
        self.assertPathCompare("a/c/z", "a/d/e")
874
1773.3.3 by Robert Collins
Add new tests John Meinel asked for.
875
    def test_path_prefix_sorting(self):
876
        """Doing a sort on path prefix should match our sample data."""
877
        original_paths = [
878
            'a',
879
            'a/b',
880
            'a/b/c',
881
            'b',
882
            'b/c',
883
            'd',
884
            'd/e',
885
            'd/e/f',
886
            'd/f',
887
            'd/g',
888
            'g',
889
            ]
890
891
        dir_sorted_paths = [
892
            'a',
893
            'b',
894
            'd',
895
            'g',
896
            'a/b',
897
            'a/b/c',
898
            'b/c',
899
            'd/e',
900
            'd/f',
901
            'd/g',
902
            'd/e/f',
903
            ]
904
905
        self.assertEqual(
906
            dir_sorted_paths,
907
            sorted(original_paths, key=osutils.path_prefix_key))
908
        # using the comparison routine shoudl work too:
909
        self.assertEqual(
910
            dir_sorted_paths,
911
            sorted(original_paths, cmp=osutils.compare_paths_prefix_order))
1711.4.10 by John Arbash Meinel
Pull out sys.stdout.encoding handling into a separate function so it can be tested, and used elsewhere.
912
913
1907.3.1 by John Arbash Meinel
create a copy_tree wrapper around walkdirs()
914
class TestCopyTree(TestCaseInTempDir):
915
    
916
    def test_copy_basic_tree(self):
917
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
918
        osutils.copy_tree('source', 'target')
2095.3.1 by Martin Pool
Tests shouldn't assume os.listdir returns sorted results
919
        self.assertEqual(['a', 'b'], sorted(os.listdir('target')))
1907.3.1 by John Arbash Meinel
create a copy_tree wrapper around walkdirs()
920
        self.assertEqual(['c'], os.listdir('target/b'))
921
922
    def test_copy_tree_target_exists(self):
923
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c',
924
                         'target/'])
925
        osutils.copy_tree('source', 'target')
2095.3.1 by Martin Pool
Tests shouldn't assume os.listdir returns sorted results
926
        self.assertEqual(['a', 'b'], sorted(os.listdir('target')))
1907.3.1 by John Arbash Meinel
create a copy_tree wrapper around walkdirs()
927
        self.assertEqual(['c'], os.listdir('target/b'))
928
1907.3.2 by John Arbash Meinel
Updated the copy_tree function to allow overriding functionality.
929
    def test_copy_tree_symlinks(self):
930
        if not osutils.has_symlinks():
931
            return
932
        self.build_tree(['source/'])
933
        os.symlink('a/generic/path', 'source/lnk')
934
        osutils.copy_tree('source', 'target')
935
        self.assertEqual(['lnk'], os.listdir('target'))
936
        self.assertEqual('a/generic/path', os.readlink('target/lnk'))
937
938
    def test_copy_tree_handlers(self):
939
        processed_files = []
940
        processed_links = []
941
        def file_handler(from_path, to_path):
942
            processed_files.append(('f', from_path, to_path))
943
        def dir_handler(from_path, to_path):
944
            processed_files.append(('d', from_path, to_path))
945
        def link_handler(from_path, to_path):
946
            processed_links.append((from_path, to_path))
947
        handlers = {'file':file_handler,
948
                    'directory':dir_handler,
949
                    'symlink':link_handler,
950
                   }
951
952
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
953
        if osutils.has_symlinks():
954
            os.symlink('a/generic/path', 'source/lnk')
955
        osutils.copy_tree('source', 'target', handlers=handlers)
956
957
        self.assertEqual([('d', 'source', 'target'),
958
                          ('f', 'source/a', 'target/a'),
959
                          ('d', 'source/b', 'target/b'),
960
                          ('f', 'source/b/c', 'target/b/c'),
961
                         ], processed_files)
962
        self.failIfExists('target')
963
        if osutils.has_symlinks():
964
            self.assertEqual([('source/lnk', 'target/lnk')], processed_links)
965
1907.3.1 by John Arbash Meinel
create a copy_tree wrapper around walkdirs()
966
2192.1.2 by Alexander Belchenko
Tests for osutils.get_terminal_encoding()
967
#class TestTerminalEncoding has been moved to test_osutils_encodings.py
968
# [bialix] 2006/12/26
1711.4.10 by John Arbash Meinel
Pull out sys.stdout.encoding handling into a separate function so it can be tested, and used elsewhere.
969
1963.1.5 by John Arbash Meinel
Create an osutils helper function for modifying the environment
970
971
class TestSetUnsetEnv(TestCase):
972
    """Test updating the environment"""
973
974
    def setUp(self):
975
        super(TestSetUnsetEnv, self).setUp()
976
977
        self.assertEqual(None, os.environ.get('BZR_TEST_ENV_VAR'),
978
                         'Environment was not cleaned up properly.'
979
                         ' Variable BZR_TEST_ENV_VAR should not exist.')
980
        def cleanup():
981
            if 'BZR_TEST_ENV_VAR' in os.environ:
982
                del os.environ['BZR_TEST_ENV_VAR']
983
984
        self.addCleanup(cleanup)
985
986
    def test_set(self):
987
        """Test that we can set an env variable"""
988
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'foo')
989
        self.assertEqual(None, old)
990
        self.assertEqual('foo', os.environ.get('BZR_TEST_ENV_VAR'))
991
992
    def test_double_set(self):
993
        """Test that we get the old value out"""
994
        osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'foo')
995
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'bar')
996
        self.assertEqual('foo', old)
997
        self.assertEqual('bar', os.environ.get('BZR_TEST_ENV_VAR'))
998
999
    def test_unicode(self):
1000
        """Environment can only contain plain strings
1001
        
1002
        So Unicode strings must be encoded.
1003
        """
1004
        # Try a few different characters, to see if we can get
1005
        # one that will be valid in the user_encoding
1006
        possible_vals = [u'm\xb5', u'\xe1', u'\u0410']
1007
        for uni_val in possible_vals:
1008
            try:
1009
                env_val = uni_val.encode(bzrlib.user_encoding)
1010
            except UnicodeEncodeError:
1011
                # Try a different character
1012
                pass
1013
            else:
1014
                break
1015
        else:
1016
            raise TestSkipped('Cannot find a unicode character that works in'
1017
                              ' encoding %s' % (bzrlib.user_encoding,))
1018
1019
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', uni_val)
1020
        self.assertEqual(env_val, os.environ.get('BZR_TEST_ENV_VAR'))
1021
1022
    def test_unset(self):
1023
        """Test that passing None will remove the env var"""
1024
        osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'foo')
1025
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', None)
1026
        self.assertEqual('foo', old)
1027
        self.assertEqual(None, os.environ.get('BZR_TEST_ENV_VAR'))
1028
        self.failIf('BZR_TEST_ENV_VAR' in os.environ)
1029
2215.6.2 by James Henstridge
add some simple tests for local_time_offset()
1030
1031
class TestLocalTimeOffset(TestCase):
1032
1033
    def test_local_time_offset(self):
1034
        """Test that local_time_offset() returns a sane value."""
1035
        offset = osutils.local_time_offset()
1036
        self.assertTrue(isinstance(offset, int))
2215.6.3 by James Henstridge
narrow the range that the local_time_offset() test uses
1037
        # Test that the offset is no more than a eighteen hours in
1038
        # either direction.
1039
        # Time zone handling is system specific, so it is difficult to
1040
        # do more specific tests, but a value outside of this range is
1041
        # probably wrong.
1042
        eighteen_hours = 18 * 3600
1043
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)
2215.6.2 by James Henstridge
add some simple tests for local_time_offset()
1044
1045
    def test_local_time_offset_with_timestamp(self):
1046
        """Test that local_time_offset() works with a timestamp."""
1047
        offset = osutils.local_time_offset(1000000000.1234567)
1048
        self.assertTrue(isinstance(offset, int))
2215.6.3 by James Henstridge
narrow the range that the local_time_offset() test uses
1049
        eighteen_hours = 18 * 3600
1050
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)