/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2095.3.1 by Martin Pool
Tests shouldn't assume os.listdir returns sorted results
1
# Copyright (C) 2005, 2006 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,
29
    )
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
30
from bzrlib.errors import BzrBadParameterNotUnicode, InvalidURL
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.
31
from bzrlib.tests import (
32
        StringIOWrapper,
33
        TestCase, 
34
        TestCaseInTempDir, 
35
        TestSkipped,
36
        )
1532 by Robert Collins
Merge in John Meinels integration branch.
37
1185.31.47 by John Arbash Meinel
Added a fancy footwork rename to osutils, made SftpTransport use it.
38
39
class TestOSUtils(TestCaseInTempDir):
40
41
    def test_fancy_rename(self):
42
        # This should work everywhere
43
        def rename(a, b):
44
            osutils.fancy_rename(a, b,
45
                    rename_func=os.rename,
46
                    unlink_func=os.unlink)
47
48
        open('a', 'wb').write('something in a\n')
49
        rename('a', 'b')
50
        self.failIfExists('a')
51
        self.failUnlessExists('b')
52
        self.check_file_contents('b', 'something in a\n')
53
54
        open('a', 'wb').write('new something in a\n')
55
        rename('b', 'a')
56
57
        self.check_file_contents('a', 'something in a\n')
58
59
    def test_rename(self):
60
        # Rename should be semi-atomic on all platforms
61
        open('a', 'wb').write('something in a\n')
62
        osutils.rename('a', 'b')
63
        self.failIfExists('a')
64
        self.failUnlessExists('b')
65
        self.check_file_contents('b', 'something in a\n')
66
67
        open('a', 'wb').write('new something in a\n')
68
        osutils.rename('b', 'a')
69
70
        self.check_file_contents('a', 'something in a\n')
71
72
    # TODO: test fancy_rename using a MemoryTransport
73
1553.5.5 by Martin Pool
New utility routine rand_chars
74
    def test_01_rand_chars_empty(self):
75
        result = osutils.rand_chars(0)
76
        self.assertEqual(result, '')
77
78
    def test_02_rand_chars_100(self):
79
        result = osutils.rand_chars(100)
80
        self.assertEqual(len(result), 100)
81
        self.assertEqual(type(result), str)
82
        self.assertContainsRe(result, r'^[a-z0-9]{100}$')
83
1996.3.14 by John Arbash Meinel
lazy_import osutils and sign_my_commits
84
    def test_is_inside(self):
85
        is_inside = osutils.is_inside
86
        self.assertTrue(is_inside('src', 'src/foo.c'))
87
        self.assertFalse(is_inside('src', 'srccontrol'))
88
        self.assertTrue(is_inside('src', 'src/a/a/a/foo.c'))
89
        self.assertTrue(is_inside('foo.c', 'foo.c'))
90
        self.assertFalse(is_inside('foo.c', ''))
91
        self.assertTrue(is_inside('', 'foo.c'))
1534.3.1 by Robert Collins
* bzrlib.osutils.safe_unicode now exists to provide parameter coercion
92
1692.7.6 by Martin Pool
[patch] force deletion of trees containing readonly files (alexander)
93
    def test_rmtree(self):
94
        # Check to remove tree with read-only files/dirs
95
        os.mkdir('dir')
96
        f = file('dir/file', 'w')
97
        f.write('spam')
98
        f.close()
99
        # would like to also try making the directory readonly, but at the
100
        # moment python shutil.rmtree doesn't handle that properly - it would
101
        # need to chmod the directory before removing things inside it - deferred
102
        # for now -- mbp 20060505
103
        # osutils.make_readonly('dir')
104
        osutils.make_readonly('dir/file')
105
106
        osutils.rmtree('dir')
107
108
        self.failIfExists('dir/file')
109
        self.failIfExists('dir')
110
1732.1.10 by John Arbash Meinel
Updated version of file_kind. Rather than multiple function calls, one mask + dictionary lookup
111
    def test_file_kind(self):
112
        self.build_tree(['file', 'dir/'])
113
        self.assertEquals('file', osutils.file_kind('file'))
114
        self.assertEquals('directory', osutils.file_kind('dir/'))
115
        if osutils.has_symlinks():
116
            os.symlink('symlink', 'symlink')
117
            self.assertEquals('symlink', osutils.file_kind('symlink'))
1732.1.28 by John Arbash Meinel
Add tests for fancy file types.
118
        
119
        # TODO: jam 20060529 Test a block device
120
        try:
121
            os.lstat('/dev/null')
122
        except OSError, e:
123
            if e.errno not in (errno.ENOENT,):
124
                raise
125
        else:
126
            self.assertEquals('chardev', osutils.file_kind('/dev/null'))
127
128
        mkfifo = getattr(os, 'mkfifo', None)
129
        if mkfifo:
130
            mkfifo('fifo')
131
            try:
132
                self.assertEquals('fifo', osutils.file_kind('fifo'))
133
            finally:
134
                os.remove('fifo')
135
136
        AF_UNIX = getattr(socket, 'AF_UNIX', None)
137
        if AF_UNIX:
138
            s = socket.socket(AF_UNIX)
139
            s.bind('socket')
140
            try:
141
                self.assertEquals('socket', osutils.file_kind('socket'))
142
            finally:
143
                os.remove('socket')
1732.1.10 by John Arbash Meinel
Updated version of file_kind. Rather than multiple function calls, one mask + dictionary lookup
144
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
145
    def test_get_umask(self):
146
        if sys.platform == 'win32':
147
            # umask always returns '0', no way to set it
148
            self.assertEqual(0, osutils.get_umask())
149
            return
150
151
        orig_umask = osutils.get_umask()
152
        try:
153
            os.umask(0222)
154
            self.assertEqual(0222, osutils.get_umask())
155
            os.umask(0022)
156
            self.assertEqual(0022, osutils.get_umask())
157
            os.umask(0002)
158
            self.assertEqual(0002, osutils.get_umask())
159
            os.umask(0027)
160
            self.assertEqual(0027, osutils.get_umask())
161
        finally:
162
            os.umask(orig_umask)
163
1957.1.15 by John Arbash Meinel
Review feedback from Robert
164
    def assertFormatedDelta(self, expected, seconds):
165
        """Assert osutils.format_delta formats as expected"""
166
        actual = osutils.format_delta(seconds)
167
        self.assertEqual(expected, actual)
168
1957.1.4 by John Arbash Meinel
create a helper for formatting a time delta
169
    def test_format_delta(self):
1957.1.15 by John Arbash Meinel
Review feedback from Robert
170
        self.assertFormatedDelta('0 seconds ago', 0)
171
        self.assertFormatedDelta('1 second ago', 1)
172
        self.assertFormatedDelta('10 seconds ago', 10)
173
        self.assertFormatedDelta('59 seconds ago', 59)
174
        self.assertFormatedDelta('89 seconds ago', 89)
175
        self.assertFormatedDelta('1 minute, 30 seconds ago', 90)
176
        self.assertFormatedDelta('3 minutes, 0 seconds ago', 180)
177
        self.assertFormatedDelta('3 minutes, 1 second ago', 181)
178
        self.assertFormatedDelta('10 minutes, 15 seconds ago', 615)
179
        self.assertFormatedDelta('30 minutes, 59 seconds ago', 1859)
180
        self.assertFormatedDelta('31 minutes, 0 seconds ago', 1860)
181
        self.assertFormatedDelta('60 minutes, 0 seconds ago', 3600)
182
        self.assertFormatedDelta('89 minutes, 59 seconds ago', 5399)
183
        self.assertFormatedDelta('1 hour, 30 minutes ago', 5400)
184
        self.assertFormatedDelta('2 hours, 30 minutes ago', 9017)
185
        self.assertFormatedDelta('10 hours, 0 minutes ago', 36000)
186
        self.assertFormatedDelta('24 hours, 0 minutes ago', 86400)
187
        self.assertFormatedDelta('35 hours, 59 minutes ago', 129599)
188
        self.assertFormatedDelta('36 hours, 0 minutes ago', 129600)
189
        self.assertFormatedDelta('36 hours, 0 minutes ago', 129601)
190
        self.assertFormatedDelta('36 hours, 1 minute ago', 129660)
191
        self.assertFormatedDelta('36 hours, 1 minute ago', 129661)
192
        self.assertFormatedDelta('84 hours, 10 minutes ago', 303002)
1957.1.4 by John Arbash Meinel
create a helper for formatting a time delta
193
194
        # We handle when time steps the wrong direction because computers
195
        # don't have synchronized clocks.
1957.1.15 by John Arbash Meinel
Review feedback from Robert
196
        self.assertFormatedDelta('84 hours, 10 minutes in the future', -303002)
197
        self.assertFormatedDelta('1 second in the future', -1)
198
        self.assertFormatedDelta('2 seconds in the future', -2)
1957.1.4 by John Arbash Meinel
create a helper for formatting a time delta
199
2091.3.7 by Aaron Bentley
Rename real_parent to dereferenced_path
200
    def test_dereference_path(self):
2091.3.6 by Aaron Bentley
Add symlink test guards
201
        if not osutils.has_symlinks():
202
            raise TestSkipped('Symlinks are not supported on this platform')
2091.3.5 by Aaron Bentley
Move realpath functionality into osutils
203
        cwd = osutils.realpath('.')
204
        os.mkdir('bar')
205
        bar_path = osutils.pathjoin(cwd, 'bar')
206
        # Using './' to avoid bug #1213894 (first path component not
207
        # dereferenced) in Python 2.4.1 and earlier
208
        self.assertEqual(bar_path, osutils.realpath('./bar'))
209
        os.symlink('bar', 'foo')
210
        self.assertEqual(bar_path, osutils.realpath('./foo'))
211
        
212
        # Does not dereference terminal symlinks
213
        foo_path = osutils.pathjoin(cwd, 'foo')
2091.3.7 by Aaron Bentley
Rename real_parent to dereferenced_path
214
        self.assertEqual(foo_path, osutils.dereference_path('./foo'))
2091.3.5 by Aaron Bentley
Move realpath functionality into osutils
215
216
        # Dereferences parent symlinks
217
        os.mkdir('bar/baz')
218
        baz_path = osutils.pathjoin(bar_path, 'baz')
2091.3.7 by Aaron Bentley
Rename real_parent to dereferenced_path
219
        self.assertEqual(baz_path, osutils.dereference_path('./foo/baz'))
2091.3.5 by Aaron Bentley
Move realpath functionality into osutils
220
221
        # Dereferences parent symlinks that are the first path element
2091.3.7 by Aaron Bentley
Rename real_parent to dereferenced_path
222
        self.assertEqual(baz_path, osutils.dereference_path('foo/baz'))
2091.3.5 by Aaron Bentley
Move realpath functionality into osutils
223
224
        # Dereferences parent symlinks in absolute paths
225
        foo_baz_path = osutils.pathjoin(foo_path, 'baz')
2091.3.7 by Aaron Bentley
Rename real_parent to dereferenced_path
226
        self.assertEqual(baz_path, osutils.dereference_path(foo_baz_path))
2091.3.5 by Aaron Bentley
Move realpath functionality into osutils
227
1692.7.6 by Martin Pool
[patch] force deletion of trees containing readonly files (alexander)
228
1534.3.1 by Robert Collins
* bzrlib.osutils.safe_unicode now exists to provide parameter coercion
229
class TestSafeUnicode(TestCase):
230
231
    def test_from_ascii_string(self):
232
        self.assertEqual(u'foobar', osutils.safe_unicode('foobar'))
233
1534.3.2 by Robert Collins
An extra test for John.
234
    def test_from_unicode_string_ascii_contents(self):
1534.3.1 by Robert Collins
* bzrlib.osutils.safe_unicode now exists to provide parameter coercion
235
        self.assertEqual(u'bargam', osutils.safe_unicode(u'bargam'))
236
1534.3.2 by Robert Collins
An extra test for John.
237
    def test_from_unicode_string_unicode_contents(self):
238
        self.assertEqual(u'bargam\xae', osutils.safe_unicode(u'bargam\xae'))
239
1534.3.1 by Robert Collins
* bzrlib.osutils.safe_unicode now exists to provide parameter coercion
240
    def test_from_utf8_string(self):
241
        self.assertEqual(u'foo\xae', osutils.safe_unicode('foo\xc2\xae'))
242
243
    def test_bad_utf8_string(self):
1185.65.29 by Robert Collins
Implement final review suggestions.
244
        self.assertRaises(BzrBadParameterNotUnicode,
245
                          osutils.safe_unicode,
246
                          '\xbb\xbb')
1666.1.6 by Robert Collins
Make knit the default format.
247
248
2249.5.8 by John Arbash Meinel
Add osutils.safe_utf8 and safe_revision_id for the new revision_id work.
249
class TestSafeUtf8(TestCase):
250
251
    def test_from_ascii_string(self):
252
        f = 'foobar'
253
        self.assertEqual('foobar', osutils.safe_utf8(f))
254
255
    def test_from_unicode_string_ascii_contents(self):
256
        self.assertEqual('bargam', osutils.safe_utf8(u'bargam'))
257
258
    def test_from_unicode_string_unicode_contents(self):
259
        self.assertEqual('bargam\xc2\xae', osutils.safe_utf8(u'bargam\xae'))
260
261
    def test_from_utf8_string(self):
262
        self.assertEqual('foo\xc2\xae', osutils.safe_utf8('foo\xc2\xae'))
263
264
    def test_bad_utf8_string(self):
265
        self.assertRaises(BzrBadParameterNotUnicode,
266
                          osutils.safe_utf8, '\xbb\xbb')
267
268
269
class TestSafeRevisionId(TestCase):
270
271
    def test_from_ascii_string(self):
272
        f = 'foobar'
273
        self.assertEqual('foobar', osutils.safe_revision_id(f))
274
        self.assertIs(osutils.safe_utf8(f), f)
275
276
    def test_from_unicode_string_ascii_contents(self):
277
        self.assertEqual('bargam', osutils.safe_revision_id(u'bargam'))
278
279
    def test_from_unicode_string_unicode_contents(self):
280
        self.assertEqual('bargam\xc2\xae',
281
                         osutils.safe_revision_id(u'bargam\xae'))
282
283
    def test_from_utf8_string(self):
284
        self.assertEqual('foo\xc2\xae',
285
                         osutils.safe_revision_id('foo\xc2\xae'))
286
287
    def test_bad_utf8_string(self):
288
        # This check may eventually go away
289
        self.assertRaises(BzrBadParameterNotUnicode,
290
                          osutils.safe_utf8, '\xbb\xbb')
291
2249.5.9 by John Arbash Meinel
Update WorkingTree to use safe_revision_id when appropriate
292
    def test_none(self):
293
        """Currently, None is a valid revision_id"""
294
        self.assertEqual(None, osutils.safe_revision_id(None))
295
2249.5.8 by John Arbash Meinel
Add osutils.safe_utf8 and safe_revision_id for the new revision_id work.
296
1685.1.31 by John Arbash Meinel
Adding tests for the rest of the _win32 functions.
297
class TestWin32Funcs(TestCase):
298
    """Test that the _win32 versions of os utilities return appropriate paths."""
299
300
    def test_abspath(self):
301
        self.assertEqual('C:/foo', osutils._win32_abspath('C:\\foo'))
302
        self.assertEqual('C:/foo', osutils._win32_abspath('C:/foo'))
303
304
    def test_realpath(self):
305
        self.assertEqual('C:/foo', osutils._win32_realpath('C:\\foo'))
306
        self.assertEqual('C:/foo', osutils._win32_realpath('C:/foo'))
307
308
    def test_pathjoin(self):
309
        self.assertEqual('path/to/foo', osutils._win32_pathjoin('path', 'to', 'foo'))
310
        self.assertEqual('C:/foo', osutils._win32_pathjoin('path\\to', 'C:\\foo'))
311
        self.assertEqual('C:/foo', osutils._win32_pathjoin('path/to', 'C:/foo'))
312
        self.assertEqual('path/to/foo', osutils._win32_pathjoin('path/to/', 'foo'))
313
        self.assertEqual('/foo', osutils._win32_pathjoin('C:/path/to/', '/foo'))
314
        self.assertEqual('/foo', osutils._win32_pathjoin('C:\\path\\to\\', '\\foo'))
315
316
    def test_normpath(self):
317
        self.assertEqual('path/to/foo', osutils._win32_normpath(r'path\\from\..\to\.\foo'))
318
        self.assertEqual('path/to/foo', osutils._win32_normpath('path//from/../to/./foo'))
319
320
    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
321
        cwd = osutils._win32_getcwd()
322
        os_cwd = os.getcwdu()
323
        self.assertEqual(os_cwd[1:].replace('\\', '/'), cwd[1:])
324
        # win32 is inconsistent whether it returns lower or upper case
325
        # and even if it was consistent the user might type the other
326
        # so we force it to uppercase
327
        # running python.exe under cmd.exe return capital C:\\
328
        # running win32 python inside a cygwin shell returns lowercase
329
        self.assertEqual(os_cwd[0].upper(), cwd[0])
330
331
    def test_fixdrive(self):
332
        self.assertEqual('H:/foo', osutils._win32_fixdrive('h:/foo'))
333
        self.assertEqual('H:/foo', osutils._win32_fixdrive('H:/foo'))
334
        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.
335
336
337
class TestWin32FuncsDirs(TestCaseInTempDir):
338
    """Test win32 functions that create files."""
339
    
340
    def test_getcwd(self):
341
        # Make sure getcwd can handle unicode filenames
342
        try:
1830.3.9 by John Arbash Meinel
Use a directory name that doesn't get messed up on Mac for getcwd() test.
343
            os.mkdir(u'mu-\xb5')
1685.1.31 by John Arbash Meinel
Adding tests for the rest of the _win32 functions.
344
        except UnicodeError:
345
            raise TestSkipped("Unable to create Unicode filename")
346
1830.3.9 by John Arbash Meinel
Use a directory name that doesn't get messed up on Mac for getcwd() test.
347
        os.chdir(u'mu-\xb5')
1685.1.31 by John Arbash Meinel
Adding tests for the rest of the _win32 functions.
348
        # TODO: jam 20060427 This will probably fail on Mac OSX because
349
        #       it will change the normalization of B\xe5gfors
350
        #       Consider using a different unicode character, or make
351
        #       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.
352
        self.assertEndsWith(osutils._win32_getcwd(), u'mu-\xb5')
1685.1.31 by John Arbash Meinel
Adding tests for the rest of the _win32 functions.
353
354
    def test_mkdtemp(self):
355
        tmpdir = osutils._win32_mkdtemp(dir='.')
356
        self.assertFalse('\\' in tmpdir)
357
358
    def test_rename(self):
359
        a = open('a', 'wb')
360
        a.write('foo\n')
361
        a.close()
362
        b = open('b', 'wb')
363
        b.write('baz\n')
364
        b.close()
365
366
        osutils._win32_rename('b', 'a')
367
        self.failUnlessExists('a')
368
        self.failIfExists('b')
369
        self.assertFileEqual('baz\n', 'a')
370
1711.7.6 by John Arbash Meinel
Change _win32_rename() so that it raises ENOENT *before* it tries any renaming.
371
    def test_rename_missing_file(self):
372
        a = open('a', 'wb')
373
        a.write('foo\n')
374
        a.close()
375
376
        try:
377
            osutils._win32_rename('b', 'a')
378
        except (IOError, OSError), e:
379
            self.assertEqual(errno.ENOENT, e.errno)
380
        self.assertFileEqual('foo\n', 'a')
381
382
    def test_rename_missing_dir(self):
383
        os.mkdir('a')
384
        try:
385
            osutils._win32_rename('b', 'a')
386
        except (IOError, OSError), e:
387
            self.assertEqual(errno.ENOENT, e.errno)
388
389
    def test_rename_current_dir(self):
390
        os.mkdir('a')
391
        os.chdir('a')
392
        # You can't rename the working directory
393
        # doing rename non-existant . usually
394
        # just raises ENOENT, since non-existant
395
        # doesn't exist.
396
        try:
397
            osutils._win32_rename('b', '.')
398
        except (IOError, OSError), e:
399
            self.assertEqual(errno.ENOENT, e.errno)
400
1996.3.14 by John Arbash Meinel
lazy_import osutils and sign_my_commits
401
    def test_splitpath(self):
402
        def check(expected, path):
403
            self.assertEqual(expected, osutils.splitpath(path))
404
405
        check(['a'], 'a')
406
        check(['a', 'b'], 'a/b')
407
        check(['a', 'b'], 'a/./b')
408
        check(['a', '.b'], 'a/.b')
409
        check(['a', '.b'], 'a\\.b')
410
411
        self.assertRaises(errors.BzrError, osutils.splitpath, 'a/../b')
412
1685.1.31 by John Arbash Meinel
Adding tests for the rest of the _win32 functions.
413
1830.3.11 by John Arbash Meinel
Create a mac version of 'getcwd()' which normalizes the path.
414
class TestMacFuncsDirs(TestCaseInTempDir):
415
    """Test mac special functions that require directories."""
416
417
    def test_getcwd(self):
418
        # On Mac, this will actually create Ba\u030agfors
419
        # but chdir will still work, because it accepts both paths
420
        try:
421
            os.mkdir(u'B\xe5gfors')
422
        except UnicodeError:
423
            raise TestSkipped("Unable to create Unicode filename")
424
425
        os.chdir(u'B\xe5gfors')
426
        self.assertEndsWith(osutils._mac_getcwd(), u'B\xe5gfors')
427
428
    def test_getcwd_nonnorm(self):
429
        # Test that _mac_getcwd() will normalize this path
430
        try:
431
            os.mkdir(u'Ba\u030agfors')
432
        except UnicodeError:
433
            raise TestSkipped("Unable to create Unicode filename")
434
435
        os.chdir(u'Ba\u030agfors')
436
        self.assertEndsWith(osutils._mac_getcwd(), u'B\xe5gfors')
437
1996.3.14 by John Arbash Meinel
lazy_import osutils and sign_my_commits
438
1666.1.6 by Robert Collins
Make knit the default format.
439
class TestSplitLines(TestCase):
440
441
    def test_split_unicode(self):
442
        self.assertEqual([u'foo\n', u'bar\xae'],
443
                         osutils.split_lines(u'foo\nbar\xae'))
444
        self.assertEqual([u'foo\n', u'bar\xae\n'],
445
                         osutils.split_lines(u'foo\nbar\xae\n'))
446
447
    def test_split_with_carriage_returns(self):
448
        self.assertEqual(['foo\rbar\n'],
449
                         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.
450
451
452
class TestWalkDirs(TestCaseInTempDir):
453
454
    def test_walkdirs(self):
455
        tree = [
456
            '.bzr',
457
            '0file',
458
            '1dir/',
459
            '1dir/0file',
460
            '1dir/1dir/',
461
            '2file'
462
            ]
463
        self.build_tree(tree)
464
        expected_dirblocks = [
1897.1.1 by Robert Collins
Add some useful summary data to osutils.walkdirs output.
465
                (('', '.'),
466
                 [('0file', '0file', 'file'),
467
                  ('1dir', '1dir', 'directory'),
468
                  ('2file', '2file', 'file'),
469
                 ]
470
                ),
471
                (('1dir', './1dir'),
472
                 [('1dir/0file', '0file', 'file'),
473
                  ('1dir/1dir', '1dir', 'directory'),
474
                 ]
475
                ),
476
                (('1dir/1dir', './1dir/1dir'),
477
                 [
478
                 ]
479
                ),
1753.1.1 by Robert Collins
(rbc, jam, mbp)Add bzrlib.osutils.walkdirs, an optimised walk-and-stat routine.
480
            ]
481
        result = []
482
        found_bzrdir = False
1897.1.1 by Robert Collins
Add some useful summary data to osutils.walkdirs output.
483
        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.
484
            if len(dirblock) and dirblock[0][1] == '.bzr':
485
                # this tests the filtering of selected paths
486
                found_bzrdir = True
487
                del dirblock[0]
1897.1.1 by Robert Collins
Add some useful summary data to osutils.walkdirs output.
488
            result.append((dirdetail, dirblock))
1753.1.1 by Robert Collins
(rbc, jam, mbp)Add bzrlib.osutils.walkdirs, an optimised walk-and-stat routine.
489
490
        self.assertTrue(found_bzrdir)
491
        self.assertEqual(expected_dirblocks,
1897.1.1 by Robert Collins
Add some useful summary data to osutils.walkdirs output.
492
            [(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.
493
        # you can search a subdir only, with a supplied prefix.
494
        result = []
1897.1.1 by Robert Collins
Add some useful summary data to osutils.walkdirs output.
495
        for dirblock in osutils.walkdirs('./1dir', '1dir'):
1757.2.8 by Robert Collins
Teach walkdirs to walk a subdir of a tree.
496
            result.append(dirblock)
497
        self.assertEqual(expected_dirblocks[1:],
1897.1.1 by Robert Collins
Add some useful summary data to osutils.walkdirs output.
498
            [(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.
499
1773.3.1 by Robert Collins
Add path_prefix_key and compare_paths_prefix_order utility functions.
500
    def assertPathCompare(self, path_less, path_greater):
501
        """check that path_less and path_greater compare correctly."""
502
        self.assertEqual(0, osutils.compare_paths_prefix_order(
503
            path_less, path_less))
504
        self.assertEqual(0, osutils.compare_paths_prefix_order(
505
            path_greater, path_greater))
506
        self.assertEqual(-1, osutils.compare_paths_prefix_order(
507
            path_less, path_greater))
508
        self.assertEqual(1, osutils.compare_paths_prefix_order(
509
            path_greater, path_less))
510
511
    def test_compare_paths_prefix_order(self):
512
        # root before all else
513
        self.assertPathCompare("/", "/a")
514
        # alpha within a dir
515
        self.assertPathCompare("/a", "/b")
516
        self.assertPathCompare("/b", "/z")
517
        # high dirs before lower.
518
        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.
519
        # except if the deeper dir should be output first
520
        self.assertPathCompare("/a/b/c", "/d/g")
1773.3.1 by Robert Collins
Add path_prefix_key and compare_paths_prefix_order utility functions.
521
        # lexical betwen dirs of the same height
522
        self.assertPathCompare("/a/z", "/z/z")
523
        self.assertPathCompare("/a/c/z", "/a/d/e")
524
525
        # this should also be consistent for no leading / paths
526
        # root before all else
527
        self.assertPathCompare("", "a")
528
        # alpha within a dir
529
        self.assertPathCompare("a", "b")
530
        self.assertPathCompare("b", "z")
531
        # high dirs before lower.
532
        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.
533
        # except if the deeper dir should be output first
534
        self.assertPathCompare("a/b/c", "d/g")
1773.3.1 by Robert Collins
Add path_prefix_key and compare_paths_prefix_order utility functions.
535
        # lexical betwen dirs of the same height
536
        self.assertPathCompare("a/z", "z/z")
537
        self.assertPathCompare("a/c/z", "a/d/e")
538
1773.3.3 by Robert Collins
Add new tests John Meinel asked for.
539
    def test_path_prefix_sorting(self):
540
        """Doing a sort on path prefix should match our sample data."""
541
        original_paths = [
542
            'a',
543
            'a/b',
544
            'a/b/c',
545
            'b',
546
            'b/c',
547
            'd',
548
            'd/e',
549
            'd/e/f',
550
            'd/f',
551
            'd/g',
552
            'g',
553
            ]
554
555
        dir_sorted_paths = [
556
            'a',
557
            'b',
558
            'd',
559
            'g',
560
            'a/b',
561
            'a/b/c',
562
            'b/c',
563
            'd/e',
564
            'd/f',
565
            'd/g',
566
            'd/e/f',
567
            ]
568
569
        self.assertEqual(
570
            dir_sorted_paths,
571
            sorted(original_paths, key=osutils.path_prefix_key))
572
        # using the comparison routine shoudl work too:
573
        self.assertEqual(
574
            dir_sorted_paths,
575
            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.
576
577
1907.3.1 by John Arbash Meinel
create a copy_tree wrapper around walkdirs()
578
class TestCopyTree(TestCaseInTempDir):
579
    
580
    def test_copy_basic_tree(self):
581
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
582
        osutils.copy_tree('source', 'target')
2095.3.1 by Martin Pool
Tests shouldn't assume os.listdir returns sorted results
583
        self.assertEqual(['a', 'b'], sorted(os.listdir('target')))
1907.3.1 by John Arbash Meinel
create a copy_tree wrapper around walkdirs()
584
        self.assertEqual(['c'], os.listdir('target/b'))
585
586
    def test_copy_tree_target_exists(self):
587
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c',
588
                         'target/'])
589
        osutils.copy_tree('source', 'target')
2095.3.1 by Martin Pool
Tests shouldn't assume os.listdir returns sorted results
590
        self.assertEqual(['a', 'b'], sorted(os.listdir('target')))
1907.3.1 by John Arbash Meinel
create a copy_tree wrapper around walkdirs()
591
        self.assertEqual(['c'], os.listdir('target/b'))
592
1907.3.2 by John Arbash Meinel
Updated the copy_tree function to allow overriding functionality.
593
    def test_copy_tree_symlinks(self):
594
        if not osutils.has_symlinks():
595
            return
596
        self.build_tree(['source/'])
597
        os.symlink('a/generic/path', 'source/lnk')
598
        osutils.copy_tree('source', 'target')
599
        self.assertEqual(['lnk'], os.listdir('target'))
600
        self.assertEqual('a/generic/path', os.readlink('target/lnk'))
601
602
    def test_copy_tree_handlers(self):
603
        processed_files = []
604
        processed_links = []
605
        def file_handler(from_path, to_path):
606
            processed_files.append(('f', from_path, to_path))
607
        def dir_handler(from_path, to_path):
608
            processed_files.append(('d', from_path, to_path))
609
        def link_handler(from_path, to_path):
610
            processed_links.append((from_path, to_path))
611
        handlers = {'file':file_handler,
612
                    'directory':dir_handler,
613
                    'symlink':link_handler,
614
                   }
615
616
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
617
        if osutils.has_symlinks():
618
            os.symlink('a/generic/path', 'source/lnk')
619
        osutils.copy_tree('source', 'target', handlers=handlers)
620
621
        self.assertEqual([('d', 'source', 'target'),
622
                          ('f', 'source/a', 'target/a'),
623
                          ('d', 'source/b', 'target/b'),
624
                          ('f', 'source/b/c', 'target/b/c'),
625
                         ], processed_files)
626
        self.failIfExists('target')
627
        if osutils.has_symlinks():
628
            self.assertEqual([('source/lnk', 'target/lnk')], processed_links)
629
1907.3.1 by John Arbash Meinel
create a copy_tree wrapper around walkdirs()
630
2192.1.2 by Alexander Belchenko
Tests for osutils.get_terminal_encoding()
631
#class TestTerminalEncoding has been moved to test_osutils_encodings.py
632
# [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.
633
1963.1.5 by John Arbash Meinel
Create an osutils helper function for modifying the environment
634
635
class TestSetUnsetEnv(TestCase):
636
    """Test updating the environment"""
637
638
    def setUp(self):
639
        super(TestSetUnsetEnv, self).setUp()
640
641
        self.assertEqual(None, os.environ.get('BZR_TEST_ENV_VAR'),
642
                         'Environment was not cleaned up properly.'
643
                         ' Variable BZR_TEST_ENV_VAR should not exist.')
644
        def cleanup():
645
            if 'BZR_TEST_ENV_VAR' in os.environ:
646
                del os.environ['BZR_TEST_ENV_VAR']
647
648
        self.addCleanup(cleanup)
649
650
    def test_set(self):
651
        """Test that we can set an env variable"""
652
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'foo')
653
        self.assertEqual(None, old)
654
        self.assertEqual('foo', os.environ.get('BZR_TEST_ENV_VAR'))
655
656
    def test_double_set(self):
657
        """Test that we get the old value out"""
658
        osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'foo')
659
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'bar')
660
        self.assertEqual('foo', old)
661
        self.assertEqual('bar', os.environ.get('BZR_TEST_ENV_VAR'))
662
663
    def test_unicode(self):
664
        """Environment can only contain plain strings
665
        
666
        So Unicode strings must be encoded.
667
        """
668
        # Try a few different characters, to see if we can get
669
        # one that will be valid in the user_encoding
670
        possible_vals = [u'm\xb5', u'\xe1', u'\u0410']
671
        for uni_val in possible_vals:
672
            try:
673
                env_val = uni_val.encode(bzrlib.user_encoding)
674
            except UnicodeEncodeError:
675
                # Try a different character
676
                pass
677
            else:
678
                break
679
        else:
680
            raise TestSkipped('Cannot find a unicode character that works in'
681
                              ' encoding %s' % (bzrlib.user_encoding,))
682
683
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', uni_val)
684
        self.assertEqual(env_val, os.environ.get('BZR_TEST_ENV_VAR'))
685
686
    def test_unset(self):
687
        """Test that passing None will remove the env var"""
688
        osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'foo')
689
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', None)
690
        self.assertEqual('foo', old)
691
        self.assertEqual(None, os.environ.get('BZR_TEST_ENV_VAR'))
692
        self.failIf('BZR_TEST_ENV_VAR' in os.environ)
693
2215.6.2 by James Henstridge
add some simple tests for local_time_offset()
694
695
class TestLocalTimeOffset(TestCase):
696
697
    def test_local_time_offset(self):
698
        """Test that local_time_offset() returns a sane value."""
699
        offset = osutils.local_time_offset()
700
        self.assertTrue(isinstance(offset, int))
2215.6.3 by James Henstridge
narrow the range that the local_time_offset() test uses
701
        # Test that the offset is no more than a eighteen hours in
702
        # either direction.
703
        # Time zone handling is system specific, so it is difficult to
704
        # do more specific tests, but a value outside of this range is
705
        # probably wrong.
706
        eighteen_hours = 18 * 3600
707
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)
2215.6.2 by James Henstridge
add some simple tests for local_time_offset()
708
709
    def test_local_time_offset_with_timestamp(self):
710
        """Test that local_time_offset() works with a timestamp."""
711
        offset = osutils.local_time_offset(1000000000.1234567)
712
        self.assertTrue(isinstance(offset, int))
2215.6.3 by James Henstridge
narrow the range that the local_time_offset() test uses
713
        eighteen_hours = 18 * 3600
714
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)