~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_osutils.py

  • Committer: John Arbash Meinel
  • Date: 2006-10-11 00:23:23 UTC
  • mfrom: (2070 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2071.
  • Revision ID: john@arbash-meinel.com-20061011002323-82ba88c293d7caff
[merge] bzr.dev 2070

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 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
26
26
from bzrlib import (
27
27
    errors,
28
28
    osutils,
29
 
    win32utils,
30
29
    )
31
30
from bzrlib.errors import BzrBadParameterNotUnicode, InvalidURL
32
31
from bzrlib.tests import (
39
38
 
40
39
class TestOSUtils(TestCaseInTempDir):
41
40
 
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'))
49
 
 
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'))
55
 
 
56
41
    def test_fancy_rename(self):
57
42
        # This should work everywhere
58
43
        def rename(a, b):
212
197
        self.assertFormatedDelta('1 second in the future', -1)
213
198
        self.assertFormatedDelta('2 seconds in the future', -2)
214
199
 
215
 
    def test_dereference_path(self):
216
 
        if not osutils.has_symlinks():
217
 
            raise TestSkipped('Symlinks are not supported on this platform')
218
 
        cwd = osutils.realpath('.')
219
 
        os.mkdir('bar')
220
 
        bar_path = osutils.pathjoin(cwd, 'bar')
221
 
        # Using './' to avoid bug #1213894 (first path component not
222
 
        # dereferenced) in Python 2.4.1 and earlier
223
 
        self.assertEqual(bar_path, osutils.realpath('./bar'))
224
 
        os.symlink('bar', 'foo')
225
 
        self.assertEqual(bar_path, osutils.realpath('./foo'))
226
 
        
227
 
        # Does not dereference terminal symlinks
228
 
        foo_path = osutils.pathjoin(cwd, 'foo')
229
 
        self.assertEqual(foo_path, osutils.dereference_path('./foo'))
230
 
 
231
 
        # Dereferences parent symlinks
232
 
        os.mkdir('bar/baz')
233
 
        baz_path = osutils.pathjoin(bar_path, 'baz')
234
 
        self.assertEqual(baz_path, osutils.dereference_path('./foo/baz'))
235
 
 
236
 
        # Dereferences parent symlinks that are the first path element
237
 
        self.assertEqual(baz_path, osutils.dereference_path('foo/baz'))
238
 
 
239
 
        # Dereferences parent symlinks in absolute paths
240
 
        foo_baz_path = osutils.pathjoin(foo_path, 'baz')
241
 
        self.assertEqual(baz_path, osutils.dereference_path(foo_baz_path))
242
 
 
243
200
 
244
201
class TestSafeUnicode(TestCase):
245
202
 
261
218
                          '\xbb\xbb')
262
219
 
263
220
 
264
 
class TestSafeUtf8(TestCase):
265
 
 
266
 
    def test_from_ascii_string(self):
267
 
        f = 'foobar'
268
 
        self.assertEqual('foobar', osutils.safe_utf8(f))
269
 
 
270
 
    def test_from_unicode_string_ascii_contents(self):
271
 
        self.assertEqual('bargam', osutils.safe_utf8(u'bargam'))
272
 
 
273
 
    def test_from_unicode_string_unicode_contents(self):
274
 
        self.assertEqual('bargam\xc2\xae', osutils.safe_utf8(u'bargam\xae'))
275
 
 
276
 
    def test_from_utf8_string(self):
277
 
        self.assertEqual('foo\xc2\xae', osutils.safe_utf8('foo\xc2\xae'))
278
 
 
279
 
    def test_bad_utf8_string(self):
280
 
        self.assertRaises(BzrBadParameterNotUnicode,
281
 
                          osutils.safe_utf8, '\xbb\xbb')
282
 
 
283
 
 
284
 
class TestSafeRevisionId(TestCase):
285
 
 
286
 
    def test_from_ascii_string(self):
287
 
        self.assertEqual('foobar', osutils.safe_revision_id('foobar'))
288
 
 
289
 
    def test_from_unicode_string_ascii_contents(self):
290
 
        self.assertEqual('bargam',
291
 
                         osutils.safe_revision_id(u'bargam', warn=False))
292
 
 
293
 
    def test_from_unicode_deprecated(self):
294
 
        self.assertEqual('bargam',
295
 
            self.callDeprecated([osutils._revision_id_warning],
296
 
                                osutils.safe_revision_id, u'bargam'))
297
 
 
298
 
    def test_from_unicode_string_unicode_contents(self):
299
 
        self.assertEqual('bargam\xc2\xae',
300
 
                         osutils.safe_revision_id(u'bargam\xae', warn=False))
301
 
 
302
 
    def test_from_utf8_string(self):
303
 
        self.assertEqual('foo\xc2\xae',
304
 
                         osutils.safe_revision_id('foo\xc2\xae'))
305
 
 
306
 
    def test_none(self):
307
 
        """Currently, None is a valid revision_id"""
308
 
        self.assertEqual(None, osutils.safe_revision_id(None))
309
 
 
310
 
 
311
 
class TestSafeFileId(TestCase):
312
 
 
313
 
    def test_from_ascii_string(self):
314
 
        self.assertEqual('foobar', osutils.safe_file_id('foobar'))
315
 
 
316
 
    def test_from_unicode_string_ascii_contents(self):
317
 
        self.assertEqual('bargam', osutils.safe_file_id(u'bargam', warn=False))
318
 
 
319
 
    def test_from_unicode_deprecated(self):
320
 
        self.assertEqual('bargam',
321
 
            self.callDeprecated([osutils._file_id_warning],
322
 
                                osutils.safe_file_id, u'bargam'))
323
 
 
324
 
    def test_from_unicode_string_unicode_contents(self):
325
 
        self.assertEqual('bargam\xc2\xae',
326
 
                         osutils.safe_file_id(u'bargam\xae', warn=False))
327
 
 
328
 
    def test_from_utf8_string(self):
329
 
        self.assertEqual('foo\xc2\xae',
330
 
                         osutils.safe_file_id('foo\xc2\xae'))
331
 
 
332
 
    def test_none(self):
333
 
        """Currently, None is a valid revision_id"""
334
 
        self.assertEqual(None, osutils.safe_file_id(None))
335
 
 
336
 
 
337
221
class TestWin32Funcs(TestCase):
338
222
    """Test that the _win32 versions of os utilities return appropriate paths."""
339
223
 
340
224
    def test_abspath(self):
341
225
        self.assertEqual('C:/foo', osutils._win32_abspath('C:\\foo'))
342
226
        self.assertEqual('C:/foo', osutils._win32_abspath('C:/foo'))
343
 
        self.assertEqual('//HOST/path', osutils._win32_abspath(r'\\HOST\path'))
344
 
        self.assertEqual('//HOST/path', osutils._win32_abspath('//HOST/path'))
345
227
 
346
228
    def test_realpath(self):
347
229
        self.assertEqual('C:/foo', osutils._win32_realpath('C:\\foo'))
375
257
        self.assertEqual('H:/foo', osutils._win32_fixdrive('H:/foo'))
376
258
        self.assertEqual('C:\\foo', osutils._win32_fixdrive('c:\\foo'))
377
259
 
378
 
    def test_win98_abspath(self):
379
 
        # absolute path
380
 
        self.assertEqual('C:/foo', osutils._win98_abspath('C:\\foo'))
381
 
        self.assertEqual('C:/foo', osutils._win98_abspath('C:/foo'))
382
 
        # UNC path
383
 
        self.assertEqual('//HOST/path', osutils._win98_abspath(r'\\HOST\path'))
384
 
        self.assertEqual('//HOST/path', osutils._win98_abspath('//HOST/path'))
385
 
        # relative path
386
 
        cwd = osutils.getcwd().rstrip('/')
387
 
        drive = osutils._nt_splitdrive(cwd)[0]
388
 
        self.assertEqual(cwd+'/path', osutils._win98_abspath('path'))
389
 
        self.assertEqual(drive+'/path', osutils._win98_abspath('/path'))
390
 
        # unicode path
391
 
        u = u'\u1234'
392
 
        self.assertEqual(cwd+'/'+u, osutils._win98_abspath(u))
393
 
 
394
260
 
395
261
class TestWin32FuncsDirs(TestCaseInTempDir):
396
262
    """Test win32 functions that create files."""
397
263
    
398
264
    def test_getcwd(self):
399
 
        if win32utils.winver == 'Windows 98':
400
 
            raise TestSkipped('Windows 98 cannot handle unicode filenames')
401
265
        # Make sure getcwd can handle unicode filenames
402
266
        try:
403
267
            os.mkdir(u'mu-\xb5')
557
421
        self.assertEqual(expected_dirblocks[1:],
558
422
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
559
423
 
560
 
    def test__walkdirs_utf8(self):
561
 
        tree = [
562
 
            '.bzr',
563
 
            '0file',
564
 
            '1dir/',
565
 
            '1dir/0file',
566
 
            '1dir/1dir/',
567
 
            '2file'
568
 
            ]
569
 
        self.build_tree(tree)
570
 
        expected_dirblocks = [
571
 
                (('', '.'),
572
 
                 [('0file', '0file', 'file'),
573
 
                  ('1dir', '1dir', 'directory'),
574
 
                  ('2file', '2file', 'file'),
575
 
                 ]
576
 
                ),
577
 
                (('1dir', './1dir'),
578
 
                 [('1dir/0file', '0file', 'file'),
579
 
                  ('1dir/1dir', '1dir', 'directory'),
580
 
                 ]
581
 
                ),
582
 
                (('1dir/1dir', './1dir/1dir'),
583
 
                 [
584
 
                 ]
585
 
                ),
586
 
            ]
587
 
        result = []
588
 
        found_bzrdir = False
589
 
        for dirdetail, dirblock in osutils._walkdirs_utf8('.'):
590
 
            if len(dirblock) and dirblock[0][1] == '.bzr':
591
 
                # this tests the filtering of selected paths
592
 
                found_bzrdir = True
593
 
                del dirblock[0]
594
 
            result.append((dirdetail, dirblock))
595
 
 
596
 
        self.assertTrue(found_bzrdir)
597
 
        self.assertEqual(expected_dirblocks,
598
 
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
599
 
        # you can search a subdir only, with a supplied prefix.
600
 
        result = []
601
 
        for dirblock in osutils.walkdirs('./1dir', '1dir'):
602
 
            result.append(dirblock)
603
 
        self.assertEqual(expected_dirblocks[1:],
604
 
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
605
 
 
606
 
    def _filter_out_stat(self, result):
607
 
        """Filter out the stat value from the walkdirs result"""
608
 
        for dirdetail, dirblock in result:
609
 
            new_dirblock = []
610
 
            for info in dirblock:
611
 
                # Ignore info[3] which is the stat
612
 
                new_dirblock.append((info[0], info[1], info[2], info[4]))
613
 
            dirblock[:] = new_dirblock
614
 
 
615
 
    def test_unicode_walkdirs(self):
616
 
        """Walkdirs should always return unicode paths."""
617
 
        name0 = u'0file-\xb6'
618
 
        name1 = u'1dir-\u062c\u0648'
619
 
        name2 = u'2file-\u0633'
620
 
        tree = [
621
 
            name0,
622
 
            name1 + '/',
623
 
            name1 + '/' + name0,
624
 
            name1 + '/' + name1 + '/',
625
 
            name2,
626
 
            ]
627
 
        try:
628
 
            self.build_tree(tree)
629
 
        except UnicodeError:
630
 
            raise TestSkipped('Could not represent Unicode chars'
631
 
                              ' in current encoding.')
632
 
        expected_dirblocks = [
633
 
                ((u'', u'.'),
634
 
                 [(name0, name0, 'file', './' + name0),
635
 
                  (name1, name1, 'directory', './' + name1),
636
 
                  (name2, name2, 'file', './' + name2),
637
 
                 ]
638
 
                ),
639
 
                ((name1, './' + name1),
640
 
                 [(name1 + '/' + name0, name0, 'file', './' + name1
641
 
                                                        + '/' + name0),
642
 
                  (name1 + '/' + name1, name1, 'directory', './' + name1
643
 
                                                            + '/' + name1),
644
 
                 ]
645
 
                ),
646
 
                ((name1 + '/' + name1, './' + name1 + '/' + name1),
647
 
                 [
648
 
                 ]
649
 
                ),
650
 
            ]
651
 
        result = list(osutils.walkdirs('.'))
652
 
        self._filter_out_stat(result)
653
 
        self.assertEqual(expected_dirblocks, result)
654
 
        result = list(osutils.walkdirs(u'./'+name1, name1))
655
 
        self._filter_out_stat(result)
656
 
        self.assertEqual(expected_dirblocks[1:], result)
657
 
 
658
 
    def test_unicode__walkdirs_utf8(self):
659
 
        """Walkdirs_utf8 should always return utf8 paths.
660
 
 
661
 
        The abspath portion might be in unicode or utf-8
662
 
        """
663
 
        name0 = u'0file-\xb6'
664
 
        name1 = u'1dir-\u062c\u0648'
665
 
        name2 = u'2file-\u0633'
666
 
        tree = [
667
 
            name0,
668
 
            name1 + '/',
669
 
            name1 + '/' + name0,
670
 
            name1 + '/' + name1 + '/',
671
 
            name2,
672
 
            ]
673
 
        try:
674
 
            self.build_tree(tree)
675
 
        except UnicodeError:
676
 
            raise TestSkipped('Could not represent Unicode chars'
677
 
                              ' in current encoding.')
678
 
        name0 = name0.encode('utf8')
679
 
        name1 = name1.encode('utf8')
680
 
        name2 = name2.encode('utf8')
681
 
 
682
 
        expected_dirblocks = [
683
 
                (('', '.'),
684
 
                 [(name0, name0, 'file', './' + name0),
685
 
                  (name1, name1, 'directory', './' + name1),
686
 
                  (name2, name2, 'file', './' + name2),
687
 
                 ]
688
 
                ),
689
 
                ((name1, './' + name1),
690
 
                 [(name1 + '/' + name0, name0, 'file', './' + name1
691
 
                                                        + '/' + name0),
692
 
                  (name1 + '/' + name1, name1, 'directory', './' + name1
693
 
                                                            + '/' + name1),
694
 
                 ]
695
 
                ),
696
 
                ((name1 + '/' + name1, './' + name1 + '/' + name1),
697
 
                 [
698
 
                 ]
699
 
                ),
700
 
            ]
701
 
        result = []
702
 
        # For ease in testing, if walkdirs_utf8 returns Unicode, assert that
703
 
        # all abspaths are Unicode, and encode them back into utf8.
704
 
        for dirdetail, dirblock in osutils._walkdirs_utf8('.'):
705
 
            self.assertIsInstance(dirdetail[0], str)
706
 
            if isinstance(dirdetail[1], unicode):
707
 
                dirdetail[1] = dirdetail[1].encode('utf8')
708
 
                for info in dirblock:
709
 
                    self.assertIsInstance(info[4], unicode)
710
 
                    info[4] = info[4].encode('utf8')
711
 
            new_dirblock = []
712
 
            for info in dirblock:
713
 
                self.assertIsInstance(info[0], str)
714
 
                self.assertIsInstance(info[1], str)
715
 
                self.assertIsInstance(info[4], str)
716
 
                # Remove the stat information
717
 
                new_dirblock.append((info[0], info[1], info[2], info[4]))
718
 
            result.append((dirdetail, new_dirblock))
719
 
        self.assertEqual(expected_dirblocks, result)
720
 
 
721
 
    def test_unicode__walkdirs_unicode_to_utf8(self):
722
 
        """walkdirs_unicode_to_utf8 should be a safe fallback everywhere
723
 
 
724
 
        The abspath portion should be in unicode
725
 
        """
726
 
        name0u = u'0file-\xb6'
727
 
        name1u = u'1dir-\u062c\u0648'
728
 
        name2u = u'2file-\u0633'
729
 
        tree = [
730
 
            name0u,
731
 
            name1u + '/',
732
 
            name1u + '/' + name0u,
733
 
            name1u + '/' + name1u + '/',
734
 
            name2u,
735
 
            ]
736
 
        try:
737
 
            self.build_tree(tree)
738
 
        except UnicodeError:
739
 
            raise TestSkipped('Could not represent Unicode chars'
740
 
                              ' in current encoding.')
741
 
        name0 = name0u.encode('utf8')
742
 
        name1 = name1u.encode('utf8')
743
 
        name2 = name2u.encode('utf8')
744
 
 
745
 
        # All of the abspaths should be in unicode, all of the relative paths
746
 
        # should be in utf8
747
 
        expected_dirblocks = [
748
 
                (('', '.'),
749
 
                 [(name0, name0, 'file', './' + name0u),
750
 
                  (name1, name1, 'directory', './' + name1u),
751
 
                  (name2, name2, 'file', './' + name2u),
752
 
                 ]
753
 
                ),
754
 
                ((name1, './' + name1u),
755
 
                 [(name1 + '/' + name0, name0, 'file', './' + name1u
756
 
                                                        + '/' + name0u),
757
 
                  (name1 + '/' + name1, name1, 'directory', './' + name1u
758
 
                                                            + '/' + name1u),
759
 
                 ]
760
 
                ),
761
 
                ((name1 + '/' + name1, './' + name1u + '/' + name1u),
762
 
                 [
763
 
                 ]
764
 
                ),
765
 
            ]
766
 
        result = list(osutils._walkdirs_unicode_to_utf8('.'))
767
 
        self._filter_out_stat(result)
768
 
        self.assertEqual(expected_dirblocks, result)
769
 
 
770
424
    def assertPathCompare(self, path_less, path_greater):
771
425
        """check that path_less and path_greater compare correctly."""
772
426
        self.assertEqual(0, osutils.compare_paths_prefix_order(
850
504
    def test_copy_basic_tree(self):
851
505
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
852
506
        osutils.copy_tree('source', 'target')
853
 
        self.assertEqual(['a', 'b'], sorted(os.listdir('target')))
 
507
        self.assertEqual(['a', 'b'], os.listdir('target'))
854
508
        self.assertEqual(['c'], os.listdir('target/b'))
855
509
 
856
510
    def test_copy_tree_target_exists(self):
857
511
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c',
858
512
                         'target/'])
859
513
        osutils.copy_tree('source', 'target')
860
 
        self.assertEqual(['a', 'b'], sorted(os.listdir('target')))
 
514
        self.assertEqual(['a', 'b'], os.listdir('target'))
861
515
        self.assertEqual(['c'], os.listdir('target/b'))
862
516
 
863
517
    def test_copy_tree_symlinks(self):
898
552
            self.assertEqual([('source/lnk', 'target/lnk')], processed_links)
899
553
 
900
554
 
901
 
#class TestTerminalEncoding has been moved to test_osutils_encodings.py
902
 
# [bialix] 2006/12/26
 
555
class TestTerminalEncoding(TestCase):
 
556
    """Test the auto-detection of proper terminal encoding."""
 
557
 
 
558
    def setUp(self):
 
559
        self._stdout = sys.stdout
 
560
        self._stderr = sys.stderr
 
561
        self._stdin = sys.stdin
 
562
        self._user_encoding = bzrlib.user_encoding
 
563
 
 
564
        self.addCleanup(self._reset)
 
565
 
 
566
        sys.stdout = StringIOWrapper()
 
567
        sys.stdout.encoding = 'stdout_encoding'
 
568
        sys.stderr = StringIOWrapper()
 
569
        sys.stderr.encoding = 'stderr_encoding'
 
570
        sys.stdin = StringIOWrapper()
 
571
        sys.stdin.encoding = 'stdin_encoding'
 
572
        bzrlib.user_encoding = 'user_encoding'
 
573
 
 
574
    def _reset(self):
 
575
        sys.stdout = self._stdout
 
576
        sys.stderr = self._stderr
 
577
        sys.stdin = self._stdin
 
578
        bzrlib.user_encoding = self._user_encoding
 
579
 
 
580
    def test_get_terminal_encoding(self):
 
581
        # first preference is stdout encoding
 
582
        self.assertEqual('stdout_encoding', osutils.get_terminal_encoding())
 
583
 
 
584
        sys.stdout.encoding = None
 
585
        # if sys.stdout is None, fall back to sys.stdin
 
586
        self.assertEqual('stdin_encoding', osutils.get_terminal_encoding())
 
587
 
 
588
        sys.stdin.encoding = None
 
589
        # and in the worst case, use bzrlib.user_encoding
 
590
        self.assertEqual('user_encoding', osutils.get_terminal_encoding())
903
591
 
904
592
 
905
593
class TestSetUnsetEnv(TestCase):
961
649
        self.assertEqual(None, os.environ.get('BZR_TEST_ENV_VAR'))
962
650
        self.failIf('BZR_TEST_ENV_VAR' in os.environ)
963
651
 
964
 
 
965
 
class TestLocalTimeOffset(TestCase):
966
 
 
967
 
    def test_local_time_offset(self):
968
 
        """Test that local_time_offset() returns a sane value."""
969
 
        offset = osutils.local_time_offset()
970
 
        self.assertTrue(isinstance(offset, int))
971
 
        # Test that the offset is no more than a eighteen hours in
972
 
        # either direction.
973
 
        # Time zone handling is system specific, so it is difficult to
974
 
        # do more specific tests, but a value outside of this range is
975
 
        # probably wrong.
976
 
        eighteen_hours = 18 * 3600
977
 
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)
978
 
 
979
 
    def test_local_time_offset_with_timestamp(self):
980
 
        """Test that local_time_offset() works with a timestamp."""
981
 
        offset = osutils.local_time_offset(1000000000.1234567)
982
 
        self.assertTrue(isinstance(offset, int))
983
 
        eighteen_hours = 18 * 3600
984
 
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)