~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_osutils.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2006-08-17 07:52:09 UTC
  • mfrom: (1910.3.4 trivial)
  • Revision ID: pqm@pqm.ubuntu.com-20060817075209-e85a1f9e05ff8b87
(andrew) Trivial fixes to NotImplemented errors.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2005 by Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
23
23
import sys
24
24
 
25
25
import bzrlib
26
 
from bzrlib import (
27
 
    errors,
28
 
    osutils,
29
 
    win32utils,
30
 
    )
31
26
from bzrlib.errors import BzrBadParameterNotUnicode, InvalidURL
32
 
from bzrlib.osutils import (
33
 
        is_inside_any,
34
 
        is_inside_or_parent_of_any,
35
 
        pathjoin,
36
 
        )
 
27
import bzrlib.osutils as osutils
37
28
from bzrlib.tests import (
38
 
        probe_unicode_in_user_encoding,
39
29
        StringIOWrapper,
40
 
        TestCase,
41
 
        TestCaseInTempDir,
 
30
        TestCase, 
 
31
        TestCaseInTempDir, 
42
32
        TestSkipped,
43
33
        )
44
34
 
45
35
 
46
36
class TestOSUtils(TestCaseInTempDir):
47
37
 
48
 
    def test_contains_whitespace(self):
49
 
        self.failUnless(osutils.contains_whitespace(u' '))
50
 
        self.failUnless(osutils.contains_whitespace(u'hello there'))
51
 
        self.failUnless(osutils.contains_whitespace(u'hellothere\n'))
52
 
        self.failUnless(osutils.contains_whitespace(u'hello\nthere'))
53
 
        self.failUnless(osutils.contains_whitespace(u'hello\rthere'))
54
 
        self.failUnless(osutils.contains_whitespace(u'hello\tthere'))
55
 
 
56
 
        # \xa0 is "Non-breaking-space" which on some python locales thinks it
57
 
        # is whitespace, but we do not.
58
 
        self.failIf(osutils.contains_whitespace(u''))
59
 
        self.failIf(osutils.contains_whitespace(u'hellothere'))
60
 
        self.failIf(osutils.contains_whitespace(u'hello\xa0there'))
61
 
 
62
38
    def test_fancy_rename(self):
63
39
        # This should work everywhere
64
40
        def rename(a, b):
102
78
        self.assertEqual(type(result), str)
103
79
        self.assertContainsRe(result, r'^[a-z0-9]{100}$')
104
80
 
105
 
    def test_is_inside(self):
106
 
        is_inside = osutils.is_inside
107
 
        self.assertTrue(is_inside('src', 'src/foo.c'))
108
 
        self.assertFalse(is_inside('src', 'srccontrol'))
109
 
        self.assertTrue(is_inside('src', 'src/a/a/a/foo.c'))
110
 
        self.assertTrue(is_inside('foo.c', 'foo.c'))
111
 
        self.assertFalse(is_inside('foo.c', ''))
112
 
        self.assertTrue(is_inside('', 'foo.c'))
113
 
 
114
 
    def test_is_inside_any(self):
115
 
        SRC_FOO_C = pathjoin('src', 'foo.c')
116
 
        for dirs, fn in [(['src', 'doc'], SRC_FOO_C),
117
 
                         (['src'], SRC_FOO_C),
118
 
                         (['src'], 'src'),
119
 
                         ]:
120
 
            self.assert_(is_inside_any(dirs, fn))
121
 
        for dirs, fn in [(['src'], 'srccontrol'),
122
 
                         (['src'], 'srccontrol/foo')]:
123
 
            self.assertFalse(is_inside_any(dirs, fn))
124
 
 
125
 
    def test_is_inside_or_parent_of_any(self):
126
 
        for dirs, fn in [(['src', 'doc'], 'src/foo.c'),
127
 
                         (['src'], 'src/foo.c'),
128
 
                         (['src/bar.c'], 'src'),
129
 
                         (['src/bar.c', 'bla/foo.c'], 'src'),
130
 
                         (['src'], 'src'),
131
 
                         ]:
132
 
            self.assert_(is_inside_or_parent_of_any(dirs, fn))
133
 
            
134
 
        for dirs, fn in [(['src'], 'srccontrol'),
135
 
                         (['srccontrol/foo.c'], 'src'),
136
 
                         (['src'], 'srccontrol/foo')]:
137
 
            self.assertFalse(is_inside_or_parent_of_any(dirs, fn))
138
81
 
139
82
    def test_rmtree(self):
140
83
        # Check to remove tree with read-only files/dirs
188
131
            finally:
189
132
                os.remove('socket')
190
133
 
191
 
    def test_kind_marker(self):
192
 
        self.assertEqual(osutils.kind_marker('file'), '')
193
 
        self.assertEqual(osutils.kind_marker('directory'), '/')
194
 
        self.assertEqual(osutils.kind_marker('symlink'), '@')
195
 
        self.assertEqual(osutils.kind_marker('tree-reference'), '+')
196
 
 
197
134
    def test_get_umask(self):
198
135
        if sys.platform == 'win32':
199
136
            # umask always returns '0', no way to set it
213
150
        finally:
214
151
            os.umask(orig_umask)
215
152
 
216
 
    def assertFormatedDelta(self, expected, seconds):
217
 
        """Assert osutils.format_delta formats as expected"""
218
 
        actual = osutils.format_delta(seconds)
219
 
        self.assertEqual(expected, actual)
220
 
 
221
 
    def test_format_delta(self):
222
 
        self.assertFormatedDelta('0 seconds ago', 0)
223
 
        self.assertFormatedDelta('1 second ago', 1)
224
 
        self.assertFormatedDelta('10 seconds ago', 10)
225
 
        self.assertFormatedDelta('59 seconds ago', 59)
226
 
        self.assertFormatedDelta('89 seconds ago', 89)
227
 
        self.assertFormatedDelta('1 minute, 30 seconds ago', 90)
228
 
        self.assertFormatedDelta('3 minutes, 0 seconds ago', 180)
229
 
        self.assertFormatedDelta('3 minutes, 1 second ago', 181)
230
 
        self.assertFormatedDelta('10 minutes, 15 seconds ago', 615)
231
 
        self.assertFormatedDelta('30 minutes, 59 seconds ago', 1859)
232
 
        self.assertFormatedDelta('31 minutes, 0 seconds ago', 1860)
233
 
        self.assertFormatedDelta('60 minutes, 0 seconds ago', 3600)
234
 
        self.assertFormatedDelta('89 minutes, 59 seconds ago', 5399)
235
 
        self.assertFormatedDelta('1 hour, 30 minutes ago', 5400)
236
 
        self.assertFormatedDelta('2 hours, 30 minutes ago', 9017)
237
 
        self.assertFormatedDelta('10 hours, 0 minutes ago', 36000)
238
 
        self.assertFormatedDelta('24 hours, 0 minutes ago', 86400)
239
 
        self.assertFormatedDelta('35 hours, 59 minutes ago', 129599)
240
 
        self.assertFormatedDelta('36 hours, 0 minutes ago', 129600)
241
 
        self.assertFormatedDelta('36 hours, 0 minutes ago', 129601)
242
 
        self.assertFormatedDelta('36 hours, 1 minute ago', 129660)
243
 
        self.assertFormatedDelta('36 hours, 1 minute ago', 129661)
244
 
        self.assertFormatedDelta('84 hours, 10 minutes ago', 303002)
245
 
 
246
 
        # We handle when time steps the wrong direction because computers
247
 
        # don't have synchronized clocks.
248
 
        self.assertFormatedDelta('84 hours, 10 minutes in the future', -303002)
249
 
        self.assertFormatedDelta('1 second in the future', -1)
250
 
        self.assertFormatedDelta('2 seconds in the future', -2)
251
 
 
252
 
    def test_dereference_path(self):
253
 
        if not osutils.has_symlinks():
254
 
            raise TestSkipped('Symlinks are not supported on this platform')
255
 
        cwd = osutils.realpath('.')
256
 
        os.mkdir('bar')
257
 
        bar_path = osutils.pathjoin(cwd, 'bar')
258
 
        # Using './' to avoid bug #1213894 (first path component not
259
 
        # dereferenced) in Python 2.4.1 and earlier
260
 
        self.assertEqual(bar_path, osutils.realpath('./bar'))
261
 
        os.symlink('bar', 'foo')
262
 
        self.assertEqual(bar_path, osutils.realpath('./foo'))
263
 
        
264
 
        # Does not dereference terminal symlinks
265
 
        foo_path = osutils.pathjoin(cwd, 'foo')
266
 
        self.assertEqual(foo_path, osutils.dereference_path('./foo'))
267
 
 
268
 
        # Dereferences parent symlinks
269
 
        os.mkdir('bar/baz')
270
 
        baz_path = osutils.pathjoin(bar_path, 'baz')
271
 
        self.assertEqual(baz_path, osutils.dereference_path('./foo/baz'))
272
 
 
273
 
        # Dereferences parent symlinks that are the first path element
274
 
        self.assertEqual(baz_path, osutils.dereference_path('foo/baz'))
275
 
 
276
 
        # Dereferences parent symlinks in absolute paths
277
 
        foo_baz_path = osutils.pathjoin(foo_path, 'baz')
278
 
        self.assertEqual(baz_path, osutils.dereference_path(foo_baz_path))
279
 
 
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
 
    def test_kind_marker(self):
302
 
        self.assertEqual("", osutils.kind_marker("file"))
303
 
        self.assertEqual("/", osutils.kind_marker(osutils._directory_kind))
304
 
        self.assertEqual("@", osutils.kind_marker("symlink"))
305
 
        self.assertRaises(errors.BzrError, osutils.kind_marker, "unknown")
306
 
 
307
153
 
308
154
class TestSafeUnicode(TestCase):
309
155
 
325
171
                          '\xbb\xbb')
326
172
 
327
173
 
328
 
class TestSafeUtf8(TestCase):
329
 
 
330
 
    def test_from_ascii_string(self):
331
 
        f = 'foobar'
332
 
        self.assertEqual('foobar', osutils.safe_utf8(f))
333
 
 
334
 
    def test_from_unicode_string_ascii_contents(self):
335
 
        self.assertEqual('bargam', osutils.safe_utf8(u'bargam'))
336
 
 
337
 
    def test_from_unicode_string_unicode_contents(self):
338
 
        self.assertEqual('bargam\xc2\xae', osutils.safe_utf8(u'bargam\xae'))
339
 
 
340
 
    def test_from_utf8_string(self):
341
 
        self.assertEqual('foo\xc2\xae', osutils.safe_utf8('foo\xc2\xae'))
342
 
 
343
 
    def test_bad_utf8_string(self):
344
 
        self.assertRaises(BzrBadParameterNotUnicode,
345
 
                          osutils.safe_utf8, '\xbb\xbb')
346
 
 
347
 
 
348
 
class TestSafeRevisionId(TestCase):
349
 
 
350
 
    def test_from_ascii_string(self):
351
 
        # this shouldn't give a warning because it's getting an ascii string
352
 
        self.assertEqual('foobar', osutils.safe_revision_id('foobar'))
353
 
 
354
 
    def test_from_unicode_string_ascii_contents(self):
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'))
362
 
 
363
 
    def test_from_unicode_string_unicode_contents(self):
364
 
        self.assertEqual('bargam\xc2\xae',
365
 
                         osutils.safe_revision_id(u'bargam\xae', warn=False))
366
 
 
367
 
    def test_from_utf8_string(self):
368
 
        self.assertEqual('foo\xc2\xae',
369
 
                         osutils.safe_revision_id('foo\xc2\xae'))
370
 
 
371
 
    def test_none(self):
372
 
        """Currently, None is a valid revision_id"""
373
 
        self.assertEqual(None, osutils.safe_revision_id(None))
374
 
 
375
 
 
376
 
class TestSafeFileId(TestCase):
377
 
 
378
 
    def test_from_ascii_string(self):
379
 
        self.assertEqual('foobar', osutils.safe_file_id('foobar'))
380
 
 
381
 
    def test_from_unicode_string_ascii_contents(self):
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'))
388
 
 
389
 
    def test_from_unicode_string_unicode_contents(self):
390
 
        self.assertEqual('bargam\xc2\xae',
391
 
                         osutils.safe_file_id(u'bargam\xae', warn=False))
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
 
 
402
174
class TestWin32Funcs(TestCase):
403
175
    """Test that the _win32 versions of os utilities return appropriate paths."""
404
176
 
405
177
    def test_abspath(self):
406
178
        self.assertEqual('C:/foo', osutils._win32_abspath('C:\\foo'))
407
179
        self.assertEqual('C:/foo', osutils._win32_abspath('C:/foo'))
408
 
        self.assertEqual('//HOST/path', osutils._win32_abspath(r'\\HOST\path'))
409
 
        self.assertEqual('//HOST/path', osutils._win32_abspath('//HOST/path'))
410
180
 
411
181
    def test_realpath(self):
412
182
        self.assertEqual('C:/foo', osutils._win32_realpath('C:\\foo'))
440
210
        self.assertEqual('H:/foo', osutils._win32_fixdrive('H:/foo'))
441
211
        self.assertEqual('C:\\foo', osutils._win32_fixdrive('c:\\foo'))
442
212
 
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
 
 
459
213
 
460
214
class TestWin32FuncsDirs(TestCaseInTempDir):
461
215
    """Test win32 functions that create files."""
462
216
    
463
217
    def test_getcwd(self):
464
 
        if win32utils.winver == 'Windows 98':
465
 
            raise TestSkipped('Windows 98 cannot handle unicode filenames')
466
218
        # Make sure getcwd can handle unicode filenames
467
219
        try:
468
220
            os.mkdir(u'mu-\xb5')
476
228
        #       osutils.getcwd() renormalize the path.
477
229
        self.assertEndsWith(osutils._win32_getcwd(), u'mu-\xb5')
478
230
 
479
 
    def test_minimum_path_selection(self):
480
 
        self.assertEqual(set(),
481
 
            osutils.minimum_path_selection([]))
482
 
        self.assertEqual(set(['a', 'b']),
483
 
            osutils.minimum_path_selection(['a', 'b']))
484
 
        self.assertEqual(set(['a/', 'b']),
485
 
            osutils.minimum_path_selection(['a/', 'b']))
486
 
        self.assertEqual(set(['a/', 'b']),
487
 
            osutils.minimum_path_selection(['a/c', 'a/', 'b']))
488
 
 
489
231
    def test_mkdtemp(self):
490
232
        tmpdir = osutils._win32_mkdtemp(dir='.')
491
233
        self.assertFalse('\\' in tmpdir)
533
275
        except (IOError, OSError), e:
534
276
            self.assertEqual(errno.ENOENT, e.errno)
535
277
 
536
 
    def test_splitpath(self):
537
 
        def check(expected, path):
538
 
            self.assertEqual(expected, osutils.splitpath(path))
539
 
 
540
 
        check(['a'], 'a')
541
 
        check(['a', 'b'], 'a/b')
542
 
        check(['a', 'b'], 'a/./b')
543
 
        check(['a', '.b'], 'a/.b')
544
 
        check(['a', '.b'], 'a\\.b')
545
 
 
546
 
        self.assertRaises(errors.BzrError, osutils.splitpath, 'a/../b')
547
 
 
548
278
 
549
279
class TestMacFuncsDirs(TestCaseInTempDir):
550
280
    """Test mac special functions that require directories."""
570
300
        os.chdir(u'Ba\u030agfors')
571
301
        self.assertEndsWith(osutils._mac_getcwd(), u'B\xe5gfors')
572
302
 
573
 
 
574
303
class TestSplitLines(TestCase):
575
304
 
576
305
    def test_split_unicode(self):
632
361
        self.assertEqual(expected_dirblocks[1:],
633
362
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
634
363
 
635
 
    def test__walkdirs_utf8(self):
636
 
        tree = [
637
 
            '.bzr',
638
 
            '0file',
639
 
            '1dir/',
640
 
            '1dir/0file',
641
 
            '1dir/1dir/',
642
 
            '2file'
643
 
            ]
644
 
        self.build_tree(tree)
645
 
        expected_dirblocks = [
646
 
                (('', '.'),
647
 
                 [('0file', '0file', 'file'),
648
 
                  ('1dir', '1dir', 'directory'),
649
 
                  ('2file', '2file', 'file'),
650
 
                 ]
651
 
                ),
652
 
                (('1dir', './1dir'),
653
 
                 [('1dir/0file', '0file', 'file'),
654
 
                  ('1dir/1dir', '1dir', 'directory'),
655
 
                 ]
656
 
                ),
657
 
                (('1dir/1dir', './1dir/1dir'),
658
 
                 [
659
 
                 ]
660
 
                ),
661
 
            ]
662
 
        result = []
663
 
        found_bzrdir = False
664
 
        for dirdetail, dirblock in osutils._walkdirs_utf8('.'):
665
 
            if len(dirblock) and dirblock[0][1] == '.bzr':
666
 
                # this tests the filtering of selected paths
667
 
                found_bzrdir = True
668
 
                del dirblock[0]
669
 
            result.append((dirdetail, dirblock))
670
 
 
671
 
        self.assertTrue(found_bzrdir)
672
 
        self.assertEqual(expected_dirblocks,
673
 
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
674
 
        # you can search a subdir only, with a supplied prefix.
675
 
        result = []
676
 
        for dirblock in osutils.walkdirs('./1dir', '1dir'):
677
 
            result.append(dirblock)
678
 
        self.assertEqual(expected_dirblocks[1:],
679
 
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
680
 
 
681
 
    def _filter_out_stat(self, result):
682
 
        """Filter out the stat value from the walkdirs result"""
683
 
        for dirdetail, dirblock in result:
684
 
            new_dirblock = []
685
 
            for info in dirblock:
686
 
                # Ignore info[3] which is the stat
687
 
                new_dirblock.append((info[0], info[1], info[2], info[4]))
688
 
            dirblock[:] = new_dirblock
689
 
 
690
 
    def test_unicode_walkdirs(self):
691
 
        """Walkdirs should always return unicode paths."""
692
 
        name0 = u'0file-\xb6'
693
 
        name1 = u'1dir-\u062c\u0648'
694
 
        name2 = u'2file-\u0633'
695
 
        tree = [
696
 
            name0,
697
 
            name1 + '/',
698
 
            name1 + '/' + name0,
699
 
            name1 + '/' + name1 + '/',
700
 
            name2,
701
 
            ]
702
 
        try:
703
 
            self.build_tree(tree)
704
 
        except UnicodeError:
705
 
            raise TestSkipped('Could not represent Unicode chars'
706
 
                              ' in current encoding.')
707
 
        expected_dirblocks = [
708
 
                ((u'', u'.'),
709
 
                 [(name0, name0, 'file', './' + name0),
710
 
                  (name1, name1, 'directory', './' + name1),
711
 
                  (name2, name2, 'file', './' + name2),
712
 
                 ]
713
 
                ),
714
 
                ((name1, './' + name1),
715
 
                 [(name1 + '/' + name0, name0, 'file', './' + name1
716
 
                                                        + '/' + name0),
717
 
                  (name1 + '/' + name1, name1, 'directory', './' + name1
718
 
                                                            + '/' + name1),
719
 
                 ]
720
 
                ),
721
 
                ((name1 + '/' + name1, './' + name1 + '/' + name1),
722
 
                 [
723
 
                 ]
724
 
                ),
725
 
            ]
726
 
        result = list(osutils.walkdirs('.'))
727
 
        self._filter_out_stat(result)
728
 
        self.assertEqual(expected_dirblocks, result)
729
 
        result = list(osutils.walkdirs(u'./'+name1, name1))
730
 
        self._filter_out_stat(result)
731
 
        self.assertEqual(expected_dirblocks[1:], result)
732
 
 
733
 
    def test_unicode__walkdirs_utf8(self):
734
 
        """Walkdirs_utf8 should always return utf8 paths.
735
 
 
736
 
        The abspath portion might be in unicode or utf-8
737
 
        """
738
 
        name0 = u'0file-\xb6'
739
 
        name1 = u'1dir-\u062c\u0648'
740
 
        name2 = u'2file-\u0633'
741
 
        tree = [
742
 
            name0,
743
 
            name1 + '/',
744
 
            name1 + '/' + name0,
745
 
            name1 + '/' + name1 + '/',
746
 
            name2,
747
 
            ]
748
 
        try:
749
 
            self.build_tree(tree)
750
 
        except UnicodeError:
751
 
            raise TestSkipped('Could not represent Unicode chars'
752
 
                              ' in current encoding.')
753
 
        name0 = name0.encode('utf8')
754
 
        name1 = name1.encode('utf8')
755
 
        name2 = name2.encode('utf8')
756
 
 
757
 
        expected_dirblocks = [
758
 
                (('', '.'),
759
 
                 [(name0, name0, 'file', './' + name0),
760
 
                  (name1, name1, 'directory', './' + name1),
761
 
                  (name2, name2, 'file', './' + name2),
762
 
                 ]
763
 
                ),
764
 
                ((name1, './' + name1),
765
 
                 [(name1 + '/' + name0, name0, 'file', './' + name1
766
 
                                                        + '/' + name0),
767
 
                  (name1 + '/' + name1, name1, 'directory', './' + name1
768
 
                                                            + '/' + name1),
769
 
                 ]
770
 
                ),
771
 
                ((name1 + '/' + name1, './' + name1 + '/' + name1),
772
 
                 [
773
 
                 ]
774
 
                ),
775
 
            ]
776
 
        result = []
777
 
        # For ease in testing, if walkdirs_utf8 returns Unicode, assert that
778
 
        # all abspaths are Unicode, and encode them back into utf8.
779
 
        for dirdetail, dirblock in osutils._walkdirs_utf8('.'):
780
 
            self.assertIsInstance(dirdetail[0], str)
781
 
            if isinstance(dirdetail[1], unicode):
782
 
                dirdetail = (dirdetail[0], dirdetail[1].encode('utf8'))
783
 
                dirblock = [list(info) for info in dirblock]
784
 
                for info in dirblock:
785
 
                    self.assertIsInstance(info[4], unicode)
786
 
                    info[4] = info[4].encode('utf8')
787
 
            new_dirblock = []
788
 
            for info in dirblock:
789
 
                self.assertIsInstance(info[0], str)
790
 
                self.assertIsInstance(info[1], str)
791
 
                self.assertIsInstance(info[4], str)
792
 
                # Remove the stat information
793
 
                new_dirblock.append((info[0], info[1], info[2], info[4]))
794
 
            result.append((dirdetail, new_dirblock))
795
 
        self.assertEqual(expected_dirblocks, result)
796
 
 
797
 
    def test_unicode__walkdirs_unicode_to_utf8(self):
798
 
        """walkdirs_unicode_to_utf8 should be a safe fallback everywhere
799
 
 
800
 
        The abspath portion should be in unicode
801
 
        """
802
 
        name0u = u'0file-\xb6'
803
 
        name1u = u'1dir-\u062c\u0648'
804
 
        name2u = u'2file-\u0633'
805
 
        tree = [
806
 
            name0u,
807
 
            name1u + '/',
808
 
            name1u + '/' + name0u,
809
 
            name1u + '/' + name1u + '/',
810
 
            name2u,
811
 
            ]
812
 
        try:
813
 
            self.build_tree(tree)
814
 
        except UnicodeError:
815
 
            raise TestSkipped('Could not represent Unicode chars'
816
 
                              ' in current encoding.')
817
 
        name0 = name0u.encode('utf8')
818
 
        name1 = name1u.encode('utf8')
819
 
        name2 = name2u.encode('utf8')
820
 
 
821
 
        # All of the abspaths should be in unicode, all of the relative paths
822
 
        # should be in utf8
823
 
        expected_dirblocks = [
824
 
                (('', '.'),
825
 
                 [(name0, name0, 'file', './' + name0u),
826
 
                  (name1, name1, 'directory', './' + name1u),
827
 
                  (name2, name2, 'file', './' + name2u),
828
 
                 ]
829
 
                ),
830
 
                ((name1, './' + name1u),
831
 
                 [(name1 + '/' + name0, name0, 'file', './' + name1u
832
 
                                                        + '/' + name0u),
833
 
                  (name1 + '/' + name1, name1, 'directory', './' + name1u
834
 
                                                            + '/' + name1u),
835
 
                 ]
836
 
                ),
837
 
                ((name1 + '/' + name1, './' + name1u + '/' + name1u),
838
 
                 [
839
 
                 ]
840
 
                ),
841
 
            ]
842
 
        result = list(osutils._walkdirs_unicode_to_utf8('.'))
843
 
        self._filter_out_stat(result)
844
 
        self.assertEqual(expected_dirblocks, result)
845
 
 
846
364
    def assertPathCompare(self, path_less, path_greater):
847
365
        """check that path_less and path_greater compare correctly."""
848
366
        self.assertEqual(0, osutils.compare_paths_prefix_order(
926
444
    def test_copy_basic_tree(self):
927
445
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
928
446
        osutils.copy_tree('source', 'target')
929
 
        self.assertEqual(['a', 'b'], sorted(os.listdir('target')))
 
447
        self.assertEqual(['a', 'b'], os.listdir('target'))
930
448
        self.assertEqual(['c'], os.listdir('target/b'))
931
449
 
932
450
    def test_copy_tree_target_exists(self):
933
451
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c',
934
452
                         'target/'])
935
453
        osutils.copy_tree('source', 'target')
936
 
        self.assertEqual(['a', 'b'], sorted(os.listdir('target')))
 
454
        self.assertEqual(['a', 'b'], os.listdir('target'))
937
455
        self.assertEqual(['c'], os.listdir('target/b'))
938
456
 
939
457
    def test_copy_tree_symlinks(self):
974
492
            self.assertEqual([('source/lnk', 'target/lnk')], processed_links)
975
493
 
976
494
 
977
 
#class TestTerminalEncoding has been moved to test_osutils_encodings.py
978
 
# [bialix] 2006/12/26
979
 
 
980
 
 
981
 
class TestSetUnsetEnv(TestCase):
982
 
    """Test updating the environment"""
 
495
class TestTerminalEncoding(TestCase):
 
496
    """Test the auto-detection of proper terminal encoding."""
983
497
 
984
498
    def setUp(self):
985
 
        super(TestSetUnsetEnv, self).setUp()
986
 
 
987
 
        self.assertEqual(None, os.environ.get('BZR_TEST_ENV_VAR'),
988
 
                         'Environment was not cleaned up properly.'
989
 
                         ' Variable BZR_TEST_ENV_VAR should not exist.')
990
 
        def cleanup():
991
 
            if 'BZR_TEST_ENV_VAR' in os.environ:
992
 
                del os.environ['BZR_TEST_ENV_VAR']
993
 
 
994
 
        self.addCleanup(cleanup)
995
 
 
996
 
    def test_set(self):
997
 
        """Test that we can set an env variable"""
998
 
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'foo')
999
 
        self.assertEqual(None, old)
1000
 
        self.assertEqual('foo', os.environ.get('BZR_TEST_ENV_VAR'))
1001
 
 
1002
 
    def test_double_set(self):
1003
 
        """Test that we get the old value out"""
1004
 
        osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'foo')
1005
 
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'bar')
1006
 
        self.assertEqual('foo', old)
1007
 
        self.assertEqual('bar', os.environ.get('BZR_TEST_ENV_VAR'))
1008
 
 
1009
 
    def test_unicode(self):
1010
 
        """Environment can only contain plain strings
1011
 
        
1012
 
        So Unicode strings must be encoded.
1013
 
        """
1014
 
        uni_val, env_val = probe_unicode_in_user_encoding()
1015
 
        if uni_val is None:
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
 
 
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))
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)
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))
1049
 
        eighteen_hours = 18 * 3600
1050
 
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)
1051
 
 
1052
 
 
1053
 
class TestShaFileByName(TestCaseInTempDir):
1054
 
 
1055
 
    def test_sha_empty(self):
1056
 
        self.build_tree_contents([('foo', '')])
1057
 
        expected_sha = osutils.sha_string('')
1058
 
        self.assertEqual(expected_sha, osutils.sha_file_by_name('foo'))
1059
 
 
1060
 
    def test_sha_mixed_endings(self):
1061
 
        text = 'test\r\nwith\nall\rpossible line endings\r\n'
1062
 
        self.build_tree_contents([('foo', text)])
1063
 
        expected_sha = osutils.sha_string(text)
1064
 
        self.assertEqual(expected_sha, osutils.sha_file_by_name('foo'))
 
499
        self._stdout = sys.stdout
 
500
        self._stderr = sys.stderr
 
501
        self._stdin = sys.stdin
 
502
        self._user_encoding = bzrlib.user_encoding
 
503
 
 
504
        self.addCleanup(self._reset)
 
505
 
 
506
        sys.stdout = StringIOWrapper()
 
507
        sys.stdout.encoding = 'stdout_encoding'
 
508
        sys.stderr = StringIOWrapper()
 
509
        sys.stderr.encoding = 'stderr_encoding'
 
510
        sys.stdin = StringIOWrapper()
 
511
        sys.stdin.encoding = 'stdin_encoding'
 
512
        bzrlib.user_encoding = 'user_encoding'
 
513
 
 
514
    def _reset(self):
 
515
        sys.stdout = self._stdout
 
516
        sys.stderr = self._stderr
 
517
        sys.stdin = self._stdin
 
518
        bzrlib.user_encoding = self._user_encoding
 
519
 
 
520
    def test_get_terminal_encoding(self):
 
521
        # first preference is stdout encoding
 
522
        self.assertEqual('stdout_encoding', osutils.get_terminal_encoding())
 
523
 
 
524
        sys.stdout.encoding = None
 
525
        # if sys.stdout is None, fall back to sys.stdin
 
526
        self.assertEqual('stdin_encoding', osutils.get_terminal_encoding())
 
527
 
 
528
        sys.stdin.encoding = None
 
529
        # and in the worst case, use bzrlib.user_encoding
 
530
        self.assertEqual('user_encoding', osutils.get_terminal_encoding())
 
531