1
# Copyright (C) 2005, 2006 Canonical Ltd
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.
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.
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
17
"""Tests for the osutils wrapper."""
31
from bzrlib.errors import BzrBadParameterNotUnicode, InvalidURL
32
from bzrlib.tests import (
40
class TestOSUtils(TestCaseInTempDir):
42
def test_contains_whitespace(self):
43
self.failUnless(osutils.contains_whitespace(u' '))
44
self.failUnless(osutils.contains_whitespace(u'hello there'))
45
self.failUnless(osutils.contains_whitespace(u'hellothere\n'))
46
self.failUnless(osutils.contains_whitespace(u'hello\nthere'))
47
self.failUnless(osutils.contains_whitespace(u'hello\rthere'))
48
self.failUnless(osutils.contains_whitespace(u'hello\tthere'))
50
# \xa0 is "Non-breaking-space" which on some python locales thinks it
51
# is whitespace, but we do not.
52
self.failIf(osutils.contains_whitespace(u''))
53
self.failIf(osutils.contains_whitespace(u'hellothere'))
54
self.failIf(osutils.contains_whitespace(u'hello\xa0there'))
56
def test_fancy_rename(self):
57
# This should work everywhere
59
osutils.fancy_rename(a, b,
60
rename_func=os.rename,
61
unlink_func=os.unlink)
63
open('a', 'wb').write('something in a\n')
65
self.failIfExists('a')
66
self.failUnlessExists('b')
67
self.check_file_contents('b', 'something in a\n')
69
open('a', 'wb').write('new something in a\n')
72
self.check_file_contents('a', 'something in a\n')
74
def test_rename(self):
75
# Rename should be semi-atomic on all platforms
76
open('a', 'wb').write('something in a\n')
77
osutils.rename('a', 'b')
78
self.failIfExists('a')
79
self.failUnlessExists('b')
80
self.check_file_contents('b', 'something in a\n')
82
open('a', 'wb').write('new something in a\n')
83
osutils.rename('b', 'a')
85
self.check_file_contents('a', 'something in a\n')
87
# TODO: test fancy_rename using a MemoryTransport
89
def test_01_rand_chars_empty(self):
90
result = osutils.rand_chars(0)
91
self.assertEqual(result, '')
93
def test_02_rand_chars_100(self):
94
result = osutils.rand_chars(100)
95
self.assertEqual(len(result), 100)
96
self.assertEqual(type(result), str)
97
self.assertContainsRe(result, r'^[a-z0-9]{100}$')
99
def test_is_inside(self):
100
is_inside = osutils.is_inside
101
self.assertTrue(is_inside('src', 'src/foo.c'))
102
self.assertFalse(is_inside('src', 'srccontrol'))
103
self.assertTrue(is_inside('src', 'src/a/a/a/foo.c'))
104
self.assertTrue(is_inside('foo.c', 'foo.c'))
105
self.assertFalse(is_inside('foo.c', ''))
106
self.assertTrue(is_inside('', 'foo.c'))
108
def test_rmtree(self):
109
# Check to remove tree with read-only files/dirs
111
f = file('dir/file', 'w')
114
# would like to also try making the directory readonly, but at the
115
# moment python shutil.rmtree doesn't handle that properly - it would
116
# need to chmod the directory before removing things inside it - deferred
117
# for now -- mbp 20060505
118
# osutils.make_readonly('dir')
119
osutils.make_readonly('dir/file')
121
osutils.rmtree('dir')
123
self.failIfExists('dir/file')
124
self.failIfExists('dir')
126
def test_file_kind(self):
127
self.build_tree(['file', 'dir/'])
128
self.assertEquals('file', osutils.file_kind('file'))
129
self.assertEquals('directory', osutils.file_kind('dir/'))
130
if osutils.has_symlinks():
131
os.symlink('symlink', 'symlink')
132
self.assertEquals('symlink', osutils.file_kind('symlink'))
134
# TODO: jam 20060529 Test a block device
136
os.lstat('/dev/null')
138
if e.errno not in (errno.ENOENT,):
141
self.assertEquals('chardev', osutils.file_kind('/dev/null'))
143
mkfifo = getattr(os, 'mkfifo', None)
147
self.assertEquals('fifo', osutils.file_kind('fifo'))
151
AF_UNIX = getattr(socket, 'AF_UNIX', None)
153
s = socket.socket(AF_UNIX)
156
self.assertEquals('socket', osutils.file_kind('socket'))
160
def test_kind_marker(self):
161
self.assertEqual(osutils.kind_marker('file'), '')
162
self.assertEqual(osutils.kind_marker('directory'), '/')
163
self.assertEqual(osutils.kind_marker('symlink'), '@')
164
self.assertEqual(osutils.kind_marker('tree-reference'), '+')
166
def test_get_umask(self):
167
if sys.platform == 'win32':
168
# umask always returns '0', no way to set it
169
self.assertEqual(0, osutils.get_umask())
172
orig_umask = osutils.get_umask()
175
self.assertEqual(0222, osutils.get_umask())
177
self.assertEqual(0022, osutils.get_umask())
179
self.assertEqual(0002, osutils.get_umask())
181
self.assertEqual(0027, osutils.get_umask())
185
def assertFormatedDelta(self, expected, seconds):
186
"""Assert osutils.format_delta formats as expected"""
187
actual = osutils.format_delta(seconds)
188
self.assertEqual(expected, actual)
190
def test_format_delta(self):
191
self.assertFormatedDelta('0 seconds ago', 0)
192
self.assertFormatedDelta('1 second ago', 1)
193
self.assertFormatedDelta('10 seconds ago', 10)
194
self.assertFormatedDelta('59 seconds ago', 59)
195
self.assertFormatedDelta('89 seconds ago', 89)
196
self.assertFormatedDelta('1 minute, 30 seconds ago', 90)
197
self.assertFormatedDelta('3 minutes, 0 seconds ago', 180)
198
self.assertFormatedDelta('3 minutes, 1 second ago', 181)
199
self.assertFormatedDelta('10 minutes, 15 seconds ago', 615)
200
self.assertFormatedDelta('30 minutes, 59 seconds ago', 1859)
201
self.assertFormatedDelta('31 minutes, 0 seconds ago', 1860)
202
self.assertFormatedDelta('60 minutes, 0 seconds ago', 3600)
203
self.assertFormatedDelta('89 minutes, 59 seconds ago', 5399)
204
self.assertFormatedDelta('1 hour, 30 minutes ago', 5400)
205
self.assertFormatedDelta('2 hours, 30 minutes ago', 9017)
206
self.assertFormatedDelta('10 hours, 0 minutes ago', 36000)
207
self.assertFormatedDelta('24 hours, 0 minutes ago', 86400)
208
self.assertFormatedDelta('35 hours, 59 minutes ago', 129599)
209
self.assertFormatedDelta('36 hours, 0 minutes ago', 129600)
210
self.assertFormatedDelta('36 hours, 0 minutes ago', 129601)
211
self.assertFormatedDelta('36 hours, 1 minute ago', 129660)
212
self.assertFormatedDelta('36 hours, 1 minute ago', 129661)
213
self.assertFormatedDelta('84 hours, 10 minutes ago', 303002)
215
# We handle when time steps the wrong direction because computers
216
# don't have synchronized clocks.
217
self.assertFormatedDelta('84 hours, 10 minutes in the future', -303002)
218
self.assertFormatedDelta('1 second in the future', -1)
219
self.assertFormatedDelta('2 seconds in the future', -2)
221
def test_dereference_path(self):
222
if not osutils.has_symlinks():
223
raise TestSkipped('Symlinks are not supported on this platform')
224
cwd = osutils.realpath('.')
226
bar_path = osutils.pathjoin(cwd, 'bar')
227
# Using './' to avoid bug #1213894 (first path component not
228
# dereferenced) in Python 2.4.1 and earlier
229
self.assertEqual(bar_path, osutils.realpath('./bar'))
230
os.symlink('bar', 'foo')
231
self.assertEqual(bar_path, osutils.realpath('./foo'))
233
# Does not dereference terminal symlinks
234
foo_path = osutils.pathjoin(cwd, 'foo')
235
self.assertEqual(foo_path, osutils.dereference_path('./foo'))
237
# Dereferences parent symlinks
239
baz_path = osutils.pathjoin(bar_path, 'baz')
240
self.assertEqual(baz_path, osutils.dereference_path('./foo/baz'))
242
# Dereferences parent symlinks that are the first path element
243
self.assertEqual(baz_path, osutils.dereference_path('foo/baz'))
245
# Dereferences parent symlinks in absolute paths
246
foo_baz_path = osutils.pathjoin(foo_path, 'baz')
247
self.assertEqual(baz_path, osutils.dereference_path(foo_baz_path))
250
def test_kind_marker(self):
251
self.assertEqual("", osutils.kind_marker("file"))
252
self.assertEqual("/", osutils.kind_marker(osutils._directory_kind))
253
self.assertEqual("@", osutils.kind_marker("symlink"))
254
self.assertRaises(errors.BzrError, osutils.kind_marker, "unknown")
257
class TestSafeUnicode(TestCase):
259
def test_from_ascii_string(self):
260
self.assertEqual(u'foobar', osutils.safe_unicode('foobar'))
262
def test_from_unicode_string_ascii_contents(self):
263
self.assertEqual(u'bargam', osutils.safe_unicode(u'bargam'))
265
def test_from_unicode_string_unicode_contents(self):
266
self.assertEqual(u'bargam\xae', osutils.safe_unicode(u'bargam\xae'))
268
def test_from_utf8_string(self):
269
self.assertEqual(u'foo\xae', osutils.safe_unicode('foo\xc2\xae'))
271
def test_bad_utf8_string(self):
272
self.assertRaises(BzrBadParameterNotUnicode,
273
osutils.safe_unicode,
277
class TestSafeUtf8(TestCase):
279
def test_from_ascii_string(self):
281
self.assertEqual('foobar', osutils.safe_utf8(f))
283
def test_from_unicode_string_ascii_contents(self):
284
self.assertEqual('bargam', osutils.safe_utf8(u'bargam'))
286
def test_from_unicode_string_unicode_contents(self):
287
self.assertEqual('bargam\xc2\xae', osutils.safe_utf8(u'bargam\xae'))
289
def test_from_utf8_string(self):
290
self.assertEqual('foo\xc2\xae', osutils.safe_utf8('foo\xc2\xae'))
292
def test_bad_utf8_string(self):
293
self.assertRaises(BzrBadParameterNotUnicode,
294
osutils.safe_utf8, '\xbb\xbb')
297
class TestSafeRevisionId(TestCase):
299
def test_from_ascii_string(self):
300
self.assertEqual('foobar', osutils.safe_revision_id('foobar'))
302
def test_from_unicode_string_ascii_contents(self):
303
self.assertEqual('bargam',
304
osutils.safe_revision_id(u'bargam', warn=False))
306
def test_from_unicode_deprecated(self):
307
self.assertEqual('bargam',
308
self.callDeprecated([osutils._revision_id_warning],
309
osutils.safe_revision_id, u'bargam'))
311
def test_from_unicode_string_unicode_contents(self):
312
self.assertEqual('bargam\xc2\xae',
313
osutils.safe_revision_id(u'bargam\xae', warn=False))
315
def test_from_utf8_string(self):
316
self.assertEqual('foo\xc2\xae',
317
osutils.safe_revision_id('foo\xc2\xae'))
320
"""Currently, None is a valid revision_id"""
321
self.assertEqual(None, osutils.safe_revision_id(None))
324
class TestSafeFileId(TestCase):
326
def test_from_ascii_string(self):
327
self.assertEqual('foobar', osutils.safe_file_id('foobar'))
329
def test_from_unicode_string_ascii_contents(self):
330
self.assertEqual('bargam', osutils.safe_file_id(u'bargam', warn=False))
332
def test_from_unicode_deprecated(self):
333
self.assertEqual('bargam',
334
self.callDeprecated([osutils._file_id_warning],
335
osutils.safe_file_id, u'bargam'))
337
def test_from_unicode_string_unicode_contents(self):
338
self.assertEqual('bargam\xc2\xae',
339
osutils.safe_file_id(u'bargam\xae', warn=False))
341
def test_from_utf8_string(self):
342
self.assertEqual('foo\xc2\xae',
343
osutils.safe_file_id('foo\xc2\xae'))
346
"""Currently, None is a valid revision_id"""
347
self.assertEqual(None, osutils.safe_file_id(None))
350
class TestWin32Funcs(TestCase):
351
"""Test that the _win32 versions of os utilities return appropriate paths."""
353
def test_abspath(self):
354
self.assertEqual('C:/foo', osutils._win32_abspath('C:\\foo'))
355
self.assertEqual('C:/foo', osutils._win32_abspath('C:/foo'))
356
self.assertEqual('//HOST/path', osutils._win32_abspath(r'\\HOST\path'))
357
self.assertEqual('//HOST/path', osutils._win32_abspath('//HOST/path'))
359
def test_realpath(self):
360
self.assertEqual('C:/foo', osutils._win32_realpath('C:\\foo'))
361
self.assertEqual('C:/foo', osutils._win32_realpath('C:/foo'))
363
def test_pathjoin(self):
364
self.assertEqual('path/to/foo', osutils._win32_pathjoin('path', 'to', 'foo'))
365
self.assertEqual('C:/foo', osutils._win32_pathjoin('path\\to', 'C:\\foo'))
366
self.assertEqual('C:/foo', osutils._win32_pathjoin('path/to', 'C:/foo'))
367
self.assertEqual('path/to/foo', osutils._win32_pathjoin('path/to/', 'foo'))
368
self.assertEqual('/foo', osutils._win32_pathjoin('C:/path/to/', '/foo'))
369
self.assertEqual('/foo', osutils._win32_pathjoin('C:\\path\\to\\', '\\foo'))
371
def test_normpath(self):
372
self.assertEqual('path/to/foo', osutils._win32_normpath(r'path\\from\..\to\.\foo'))
373
self.assertEqual('path/to/foo', osutils._win32_normpath('path//from/../to/./foo'))
375
def test_getcwd(self):
376
cwd = osutils._win32_getcwd()
377
os_cwd = os.getcwdu()
378
self.assertEqual(os_cwd[1:].replace('\\', '/'), cwd[1:])
379
# win32 is inconsistent whether it returns lower or upper case
380
# and even if it was consistent the user might type the other
381
# so we force it to uppercase
382
# running python.exe under cmd.exe return capital C:\\
383
# running win32 python inside a cygwin shell returns lowercase
384
self.assertEqual(os_cwd[0].upper(), cwd[0])
386
def test_fixdrive(self):
387
self.assertEqual('H:/foo', osutils._win32_fixdrive('h:/foo'))
388
self.assertEqual('H:/foo', osutils._win32_fixdrive('H:/foo'))
389
self.assertEqual('C:\\foo', osutils._win32_fixdrive('c:\\foo'))
391
def test_win98_abspath(self):
393
self.assertEqual('C:/foo', osutils._win98_abspath('C:\\foo'))
394
self.assertEqual('C:/foo', osutils._win98_abspath('C:/foo'))
396
self.assertEqual('//HOST/path', osutils._win98_abspath(r'\\HOST\path'))
397
self.assertEqual('//HOST/path', osutils._win98_abspath('//HOST/path'))
399
cwd = osutils.getcwd().rstrip('/')
400
drive = osutils._nt_splitdrive(cwd)[0]
401
self.assertEqual(cwd+'/path', osutils._win98_abspath('path'))
402
self.assertEqual(drive+'/path', osutils._win98_abspath('/path'))
405
self.assertEqual(cwd+'/'+u, osutils._win98_abspath(u))
408
class TestWin32FuncsDirs(TestCaseInTempDir):
409
"""Test win32 functions that create files."""
411
def test_getcwd(self):
412
if win32utils.winver == 'Windows 98':
413
raise TestSkipped('Windows 98 cannot handle unicode filenames')
414
# Make sure getcwd can handle unicode filenames
418
raise TestSkipped("Unable to create Unicode filename")
421
# TODO: jam 20060427 This will probably fail on Mac OSX because
422
# it will change the normalization of B\xe5gfors
423
# Consider using a different unicode character, or make
424
# osutils.getcwd() renormalize the path.
425
self.assertEndsWith(osutils._win32_getcwd(), u'mu-\xb5')
427
def test_mkdtemp(self):
428
tmpdir = osutils._win32_mkdtemp(dir='.')
429
self.assertFalse('\\' in tmpdir)
431
def test_rename(self):
439
osutils._win32_rename('b', 'a')
440
self.failUnlessExists('a')
441
self.failIfExists('b')
442
self.assertFileEqual('baz\n', 'a')
444
def test_rename_missing_file(self):
450
osutils._win32_rename('b', 'a')
451
except (IOError, OSError), e:
452
self.assertEqual(errno.ENOENT, e.errno)
453
self.assertFileEqual('foo\n', 'a')
455
def test_rename_missing_dir(self):
458
osutils._win32_rename('b', 'a')
459
except (IOError, OSError), e:
460
self.assertEqual(errno.ENOENT, e.errno)
462
def test_rename_current_dir(self):
465
# You can't rename the working directory
466
# doing rename non-existant . usually
467
# just raises ENOENT, since non-existant
470
osutils._win32_rename('b', '.')
471
except (IOError, OSError), e:
472
self.assertEqual(errno.ENOENT, e.errno)
474
def test_splitpath(self):
475
def check(expected, path):
476
self.assertEqual(expected, osutils.splitpath(path))
479
check(['a', 'b'], 'a/b')
480
check(['a', 'b'], 'a/./b')
481
check(['a', '.b'], 'a/.b')
482
check(['a', '.b'], 'a\\.b')
484
self.assertRaises(errors.BzrError, osutils.splitpath, 'a/../b')
487
class TestMacFuncsDirs(TestCaseInTempDir):
488
"""Test mac special functions that require directories."""
490
def test_getcwd(self):
491
# On Mac, this will actually create Ba\u030agfors
492
# but chdir will still work, because it accepts both paths
494
os.mkdir(u'B\xe5gfors')
496
raise TestSkipped("Unable to create Unicode filename")
498
os.chdir(u'B\xe5gfors')
499
self.assertEndsWith(osutils._mac_getcwd(), u'B\xe5gfors')
501
def test_getcwd_nonnorm(self):
502
# Test that _mac_getcwd() will normalize this path
504
os.mkdir(u'Ba\u030agfors')
506
raise TestSkipped("Unable to create Unicode filename")
508
os.chdir(u'Ba\u030agfors')
509
self.assertEndsWith(osutils._mac_getcwd(), u'B\xe5gfors')
512
class TestSplitLines(TestCase):
514
def test_split_unicode(self):
515
self.assertEqual([u'foo\n', u'bar\xae'],
516
osutils.split_lines(u'foo\nbar\xae'))
517
self.assertEqual([u'foo\n', u'bar\xae\n'],
518
osutils.split_lines(u'foo\nbar\xae\n'))
520
def test_split_with_carriage_returns(self):
521
self.assertEqual(['foo\rbar\n'],
522
osutils.split_lines('foo\rbar\n'))
525
class TestWalkDirs(TestCaseInTempDir):
527
def test_walkdirs(self):
536
self.build_tree(tree)
537
expected_dirblocks = [
539
[('0file', '0file', 'file'),
540
('1dir', '1dir', 'directory'),
541
('2file', '2file', 'file'),
545
[('1dir/0file', '0file', 'file'),
546
('1dir/1dir', '1dir', 'directory'),
549
(('1dir/1dir', './1dir/1dir'),
556
for dirdetail, dirblock in osutils.walkdirs('.'):
557
if len(dirblock) and dirblock[0][1] == '.bzr':
558
# this tests the filtering of selected paths
561
result.append((dirdetail, dirblock))
563
self.assertTrue(found_bzrdir)
564
self.assertEqual(expected_dirblocks,
565
[(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
566
# you can search a subdir only, with a supplied prefix.
568
for dirblock in osutils.walkdirs('./1dir', '1dir'):
569
result.append(dirblock)
570
self.assertEqual(expected_dirblocks[1:],
571
[(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
573
def test__walkdirs_utf8(self):
582
self.build_tree(tree)
583
expected_dirblocks = [
585
[('0file', '0file', 'file'),
586
('1dir', '1dir', 'directory'),
587
('2file', '2file', 'file'),
591
[('1dir/0file', '0file', 'file'),
592
('1dir/1dir', '1dir', 'directory'),
595
(('1dir/1dir', './1dir/1dir'),
602
for dirdetail, dirblock in osutils._walkdirs_utf8('.'):
603
if len(dirblock) and dirblock[0][1] == '.bzr':
604
# this tests the filtering of selected paths
607
result.append((dirdetail, dirblock))
609
self.assertTrue(found_bzrdir)
610
self.assertEqual(expected_dirblocks,
611
[(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
612
# you can search a subdir only, with a supplied prefix.
614
for dirblock in osutils.walkdirs('./1dir', '1dir'):
615
result.append(dirblock)
616
self.assertEqual(expected_dirblocks[1:],
617
[(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
619
def _filter_out_stat(self, result):
620
"""Filter out the stat value from the walkdirs result"""
621
for dirdetail, dirblock in result:
623
for info in dirblock:
624
# Ignore info[3] which is the stat
625
new_dirblock.append((info[0], info[1], info[2], info[4]))
626
dirblock[:] = new_dirblock
628
def test_unicode_walkdirs(self):
629
"""Walkdirs should always return unicode paths."""
630
name0 = u'0file-\xb6'
631
name1 = u'1dir-\u062c\u0648'
632
name2 = u'2file-\u0633'
637
name1 + '/' + name1 + '/',
641
self.build_tree(tree)
643
raise TestSkipped('Could not represent Unicode chars'
644
' in current encoding.')
645
expected_dirblocks = [
647
[(name0, name0, 'file', './' + name0),
648
(name1, name1, 'directory', './' + name1),
649
(name2, name2, 'file', './' + name2),
652
((name1, './' + name1),
653
[(name1 + '/' + name0, name0, 'file', './' + name1
655
(name1 + '/' + name1, name1, 'directory', './' + name1
659
((name1 + '/' + name1, './' + name1 + '/' + name1),
664
result = list(osutils.walkdirs('.'))
665
self._filter_out_stat(result)
666
self.assertEqual(expected_dirblocks, result)
667
result = list(osutils.walkdirs(u'./'+name1, name1))
668
self._filter_out_stat(result)
669
self.assertEqual(expected_dirblocks[1:], result)
671
def test_unicode__walkdirs_utf8(self):
672
"""Walkdirs_utf8 should always return utf8 paths.
674
The abspath portion might be in unicode or utf-8
676
name0 = u'0file-\xb6'
677
name1 = u'1dir-\u062c\u0648'
678
name2 = u'2file-\u0633'
683
name1 + '/' + name1 + '/',
687
self.build_tree(tree)
689
raise TestSkipped('Could not represent Unicode chars'
690
' in current encoding.')
691
name0 = name0.encode('utf8')
692
name1 = name1.encode('utf8')
693
name2 = name2.encode('utf8')
695
expected_dirblocks = [
697
[(name0, name0, 'file', './' + name0),
698
(name1, name1, 'directory', './' + name1),
699
(name2, name2, 'file', './' + name2),
702
((name1, './' + name1),
703
[(name1 + '/' + name0, name0, 'file', './' + name1
705
(name1 + '/' + name1, name1, 'directory', './' + name1
709
((name1 + '/' + name1, './' + name1 + '/' + name1),
715
# For ease in testing, if walkdirs_utf8 returns Unicode, assert that
716
# all abspaths are Unicode, and encode them back into utf8.
717
for dirdetail, dirblock in osutils._walkdirs_utf8('.'):
718
self.assertIsInstance(dirdetail[0], str)
719
if isinstance(dirdetail[1], unicode):
720
dirdetail = (dirdetail[0], dirdetail[1].encode('utf8'))
721
dirblock = [list(info) for info in dirblock]
722
for info in dirblock:
723
self.assertIsInstance(info[4], unicode)
724
info[4] = info[4].encode('utf8')
726
for info in dirblock:
727
self.assertIsInstance(info[0], str)
728
self.assertIsInstance(info[1], str)
729
self.assertIsInstance(info[4], str)
730
# Remove the stat information
731
new_dirblock.append((info[0], info[1], info[2], info[4]))
732
result.append((dirdetail, new_dirblock))
733
self.assertEqual(expected_dirblocks, result)
735
def test_unicode__walkdirs_unicode_to_utf8(self):
736
"""walkdirs_unicode_to_utf8 should be a safe fallback everywhere
738
The abspath portion should be in unicode
740
name0u = u'0file-\xb6'
741
name1u = u'1dir-\u062c\u0648'
742
name2u = u'2file-\u0633'
746
name1u + '/' + name0u,
747
name1u + '/' + name1u + '/',
751
self.build_tree(tree)
753
raise TestSkipped('Could not represent Unicode chars'
754
' in current encoding.')
755
name0 = name0u.encode('utf8')
756
name1 = name1u.encode('utf8')
757
name2 = name2u.encode('utf8')
759
# All of the abspaths should be in unicode, all of the relative paths
761
expected_dirblocks = [
763
[(name0, name0, 'file', './' + name0u),
764
(name1, name1, 'directory', './' + name1u),
765
(name2, name2, 'file', './' + name2u),
768
((name1, './' + name1u),
769
[(name1 + '/' + name0, name0, 'file', './' + name1u
771
(name1 + '/' + name1, name1, 'directory', './' + name1u
775
((name1 + '/' + name1, './' + name1u + '/' + name1u),
780
result = list(osutils._walkdirs_unicode_to_utf8('.'))
781
self._filter_out_stat(result)
782
self.assertEqual(expected_dirblocks, result)
784
def assertPathCompare(self, path_less, path_greater):
785
"""check that path_less and path_greater compare correctly."""
786
self.assertEqual(0, osutils.compare_paths_prefix_order(
787
path_less, path_less))
788
self.assertEqual(0, osutils.compare_paths_prefix_order(
789
path_greater, path_greater))
790
self.assertEqual(-1, osutils.compare_paths_prefix_order(
791
path_less, path_greater))
792
self.assertEqual(1, osutils.compare_paths_prefix_order(
793
path_greater, path_less))
795
def test_compare_paths_prefix_order(self):
796
# root before all else
797
self.assertPathCompare("/", "/a")
799
self.assertPathCompare("/a", "/b")
800
self.assertPathCompare("/b", "/z")
801
# high dirs before lower.
802
self.assertPathCompare("/z", "/a/a")
803
# except if the deeper dir should be output first
804
self.assertPathCompare("/a/b/c", "/d/g")
805
# lexical betwen dirs of the same height
806
self.assertPathCompare("/a/z", "/z/z")
807
self.assertPathCompare("/a/c/z", "/a/d/e")
809
# this should also be consistent for no leading / paths
810
# root before all else
811
self.assertPathCompare("", "a")
813
self.assertPathCompare("a", "b")
814
self.assertPathCompare("b", "z")
815
# high dirs before lower.
816
self.assertPathCompare("z", "a/a")
817
# except if the deeper dir should be output first
818
self.assertPathCompare("a/b/c", "d/g")
819
# lexical betwen dirs of the same height
820
self.assertPathCompare("a/z", "z/z")
821
self.assertPathCompare("a/c/z", "a/d/e")
823
def test_path_prefix_sorting(self):
824
"""Doing a sort on path prefix should match our sample data."""
855
sorted(original_paths, key=osutils.path_prefix_key))
856
# using the comparison routine shoudl work too:
859
sorted(original_paths, cmp=osutils.compare_paths_prefix_order))
862
class TestCopyTree(TestCaseInTempDir):
864
def test_copy_basic_tree(self):
865
self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
866
osutils.copy_tree('source', 'target')
867
self.assertEqual(['a', 'b'], sorted(os.listdir('target')))
868
self.assertEqual(['c'], os.listdir('target/b'))
870
def test_copy_tree_target_exists(self):
871
self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c',
873
osutils.copy_tree('source', 'target')
874
self.assertEqual(['a', 'b'], sorted(os.listdir('target')))
875
self.assertEqual(['c'], os.listdir('target/b'))
877
def test_copy_tree_symlinks(self):
878
if not osutils.has_symlinks():
880
self.build_tree(['source/'])
881
os.symlink('a/generic/path', 'source/lnk')
882
osutils.copy_tree('source', 'target')
883
self.assertEqual(['lnk'], os.listdir('target'))
884
self.assertEqual('a/generic/path', os.readlink('target/lnk'))
886
def test_copy_tree_handlers(self):
889
def file_handler(from_path, to_path):
890
processed_files.append(('f', from_path, to_path))
891
def dir_handler(from_path, to_path):
892
processed_files.append(('d', from_path, to_path))
893
def link_handler(from_path, to_path):
894
processed_links.append((from_path, to_path))
895
handlers = {'file':file_handler,
896
'directory':dir_handler,
897
'symlink':link_handler,
900
self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
901
if osutils.has_symlinks():
902
os.symlink('a/generic/path', 'source/lnk')
903
osutils.copy_tree('source', 'target', handlers=handlers)
905
self.assertEqual([('d', 'source', 'target'),
906
('f', 'source/a', 'target/a'),
907
('d', 'source/b', 'target/b'),
908
('f', 'source/b/c', 'target/b/c'),
910
self.failIfExists('target')
911
if osutils.has_symlinks():
912
self.assertEqual([('source/lnk', 'target/lnk')], processed_links)
915
#class TestTerminalEncoding has been moved to test_osutils_encodings.py
916
# [bialix] 2006/12/26
919
class TestSetUnsetEnv(TestCase):
920
"""Test updating the environment"""
923
super(TestSetUnsetEnv, self).setUp()
925
self.assertEqual(None, os.environ.get('BZR_TEST_ENV_VAR'),
926
'Environment was not cleaned up properly.'
927
' Variable BZR_TEST_ENV_VAR should not exist.')
929
if 'BZR_TEST_ENV_VAR' in os.environ:
930
del os.environ['BZR_TEST_ENV_VAR']
932
self.addCleanup(cleanup)
935
"""Test that we can set an env variable"""
936
old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'foo')
937
self.assertEqual(None, old)
938
self.assertEqual('foo', os.environ.get('BZR_TEST_ENV_VAR'))
940
def test_double_set(self):
941
"""Test that we get the old value out"""
942
osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'foo')
943
old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'bar')
944
self.assertEqual('foo', old)
945
self.assertEqual('bar', os.environ.get('BZR_TEST_ENV_VAR'))
947
def test_unicode(self):
948
"""Environment can only contain plain strings
950
So Unicode strings must be encoded.
952
# Try a few different characters, to see if we can get
953
# one that will be valid in the user_encoding
954
possible_vals = [u'm\xb5', u'\xe1', u'\u0410']
955
for uni_val in possible_vals:
957
env_val = uni_val.encode(bzrlib.user_encoding)
958
except UnicodeEncodeError:
959
# Try a different character
964
raise TestSkipped('Cannot find a unicode character that works in'
965
' encoding %s' % (bzrlib.user_encoding,))
967
old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', uni_val)
968
self.assertEqual(env_val, os.environ.get('BZR_TEST_ENV_VAR'))
970
def test_unset(self):
971
"""Test that passing None will remove the env var"""
972
osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'foo')
973
old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', None)
974
self.assertEqual('foo', old)
975
self.assertEqual(None, os.environ.get('BZR_TEST_ENV_VAR'))
976
self.failIf('BZR_TEST_ENV_VAR' in os.environ)
979
class TestLocalTimeOffset(TestCase):
981
def test_local_time_offset(self):
982
"""Test that local_time_offset() returns a sane value."""
983
offset = osutils.local_time_offset()
984
self.assertTrue(isinstance(offset, int))
985
# Test that the offset is no more than a eighteen hours in
987
# Time zone handling is system specific, so it is difficult to
988
# do more specific tests, but a value outside of this range is
990
eighteen_hours = 18 * 3600
991
self.assertTrue(-eighteen_hours < offset < eighteen_hours)
993
def test_local_time_offset_with_timestamp(self):
994
"""Test that local_time_offset() works with a timestamp."""
995
offset = osutils.local_time_offset(1000000000.1234567)
996
self.assertTrue(isinstance(offset, int))
997
eighteen_hours = 18 * 3600
998
self.assertTrue(-eighteen_hours < offset < eighteen_hours)