~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_osutils.py

  • Committer: Robert Collins
  • Date: 2007-05-07 16:48:14 UTC
  • mto: This revision was merged to the branch mainline in revision 2485.
  • Revision ID: robertc@robertcollins.net-20070507164814-wpagonutf4b5cf8s
Move HACKING to docs/developers/HACKING and adjust Makefile to accomodate this.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
from bzrlib import (
27
27
    errors,
28
28
    osutils,
 
29
    win32utils,
29
30
    )
30
31
from bzrlib.errors import BzrBadParameterNotUnicode, InvalidURL
31
32
from bzrlib.tests import (
38
39
 
39
40
class TestOSUtils(TestCaseInTempDir):
40
41
 
 
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
 
41
56
    def test_fancy_rename(self):
42
57
        # This should work everywhere
43
58
        def rename(a, b):
142
157
            finally:
143
158
                os.remove('socket')
144
159
 
 
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'), '+')
 
165
 
145
166
    def test_get_umask(self):
146
167
        if sys.platform == 'win32':
147
168
            # umask always returns '0', no way to set it
226
247
        self.assertEqual(baz_path, osutils.dereference_path(foo_baz_path))
227
248
 
228
249
 
 
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")
 
255
 
 
256
 
229
257
class TestSafeUnicode(TestCase):
230
258
 
231
259
    def test_from_ascii_string(self):
246
274
                          '\xbb\xbb')
247
275
 
248
276
 
 
277
class TestSafeUtf8(TestCase):
 
278
 
 
279
    def test_from_ascii_string(self):
 
280
        f = 'foobar'
 
281
        self.assertEqual('foobar', osutils.safe_utf8(f))
 
282
 
 
283
    def test_from_unicode_string_ascii_contents(self):
 
284
        self.assertEqual('bargam', osutils.safe_utf8(u'bargam'))
 
285
 
 
286
    def test_from_unicode_string_unicode_contents(self):
 
287
        self.assertEqual('bargam\xc2\xae', osutils.safe_utf8(u'bargam\xae'))
 
288
 
 
289
    def test_from_utf8_string(self):
 
290
        self.assertEqual('foo\xc2\xae', osutils.safe_utf8('foo\xc2\xae'))
 
291
 
 
292
    def test_bad_utf8_string(self):
 
293
        self.assertRaises(BzrBadParameterNotUnicode,
 
294
                          osutils.safe_utf8, '\xbb\xbb')
 
295
 
 
296
 
 
297
class TestSafeRevisionId(TestCase):
 
298
 
 
299
    def test_from_ascii_string(self):
 
300
        self.assertEqual('foobar', osutils.safe_revision_id('foobar'))
 
301
 
 
302
    def test_from_unicode_string_ascii_contents(self):
 
303
        self.assertEqual('bargam',
 
304
                         osutils.safe_revision_id(u'bargam', warn=False))
 
305
 
 
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'))
 
310
 
 
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))
 
314
 
 
315
    def test_from_utf8_string(self):
 
316
        self.assertEqual('foo\xc2\xae',
 
317
                         osutils.safe_revision_id('foo\xc2\xae'))
 
318
 
 
319
    def test_none(self):
 
320
        """Currently, None is a valid revision_id"""
 
321
        self.assertEqual(None, osutils.safe_revision_id(None))
 
322
 
 
323
 
 
324
class TestSafeFileId(TestCase):
 
325
 
 
326
    def test_from_ascii_string(self):
 
327
        self.assertEqual('foobar', osutils.safe_file_id('foobar'))
 
328
 
 
329
    def test_from_unicode_string_ascii_contents(self):
 
330
        self.assertEqual('bargam', osutils.safe_file_id(u'bargam', warn=False))
 
331
 
 
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'))
 
336
 
 
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))
 
340
 
 
341
    def test_from_utf8_string(self):
 
342
        self.assertEqual('foo\xc2\xae',
 
343
                         osutils.safe_file_id('foo\xc2\xae'))
 
344
 
 
345
    def test_none(self):
 
346
        """Currently, None is a valid revision_id"""
 
347
        self.assertEqual(None, osutils.safe_file_id(None))
 
348
 
 
349
 
249
350
class TestWin32Funcs(TestCase):
250
351
    """Test that the _win32 versions of os utilities return appropriate paths."""
251
352
 
252
353
    def test_abspath(self):
253
354
        self.assertEqual('C:/foo', osutils._win32_abspath('C:\\foo'))
254
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'))
255
358
 
256
359
    def test_realpath(self):
257
360
        self.assertEqual('C:/foo', osutils._win32_realpath('C:\\foo'))
285
388
        self.assertEqual('H:/foo', osutils._win32_fixdrive('H:/foo'))
286
389
        self.assertEqual('C:\\foo', osutils._win32_fixdrive('c:\\foo'))
287
390
 
 
391
    def test_win98_abspath(self):
 
392
        # absolute path
 
393
        self.assertEqual('C:/foo', osutils._win98_abspath('C:\\foo'))
 
394
        self.assertEqual('C:/foo', osutils._win98_abspath('C:/foo'))
 
395
        # UNC path
 
396
        self.assertEqual('//HOST/path', osutils._win98_abspath(r'\\HOST\path'))
 
397
        self.assertEqual('//HOST/path', osutils._win98_abspath('//HOST/path'))
 
398
        # relative 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'))
 
403
        # unicode path
 
404
        u = u'\u1234'
 
405
        self.assertEqual(cwd+'/'+u, osutils._win98_abspath(u))
 
406
 
288
407
 
289
408
class TestWin32FuncsDirs(TestCaseInTempDir):
290
409
    """Test win32 functions that create files."""
291
410
    
292
411
    def test_getcwd(self):
 
412
        if win32utils.winver == 'Windows 98':
 
413
            raise TestSkipped('Windows 98 cannot handle unicode filenames')
293
414
        # Make sure getcwd can handle unicode filenames
294
415
        try:
295
416
            os.mkdir(u'mu-\xb5')
449
570
        self.assertEqual(expected_dirblocks[1:],
450
571
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
451
572
 
 
573
    def test__walkdirs_utf8(self):
 
574
        tree = [
 
575
            '.bzr',
 
576
            '0file',
 
577
            '1dir/',
 
578
            '1dir/0file',
 
579
            '1dir/1dir/',
 
580
            '2file'
 
581
            ]
 
582
        self.build_tree(tree)
 
583
        expected_dirblocks = [
 
584
                (('', '.'),
 
585
                 [('0file', '0file', 'file'),
 
586
                  ('1dir', '1dir', 'directory'),
 
587
                  ('2file', '2file', 'file'),
 
588
                 ]
 
589
                ),
 
590
                (('1dir', './1dir'),
 
591
                 [('1dir/0file', '0file', 'file'),
 
592
                  ('1dir/1dir', '1dir', 'directory'),
 
593
                 ]
 
594
                ),
 
595
                (('1dir/1dir', './1dir/1dir'),
 
596
                 [
 
597
                 ]
 
598
                ),
 
599
            ]
 
600
        result = []
 
601
        found_bzrdir = False
 
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
 
605
                found_bzrdir = True
 
606
                del dirblock[0]
 
607
            result.append((dirdetail, dirblock))
 
608
 
 
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.
 
613
        result = []
 
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])
 
618
 
 
619
    def _filter_out_stat(self, result):
 
620
        """Filter out the stat value from the walkdirs result"""
 
621
        for dirdetail, dirblock in result:
 
622
            new_dirblock = []
 
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
 
627
 
 
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'
 
633
        tree = [
 
634
            name0,
 
635
            name1 + '/',
 
636
            name1 + '/' + name0,
 
637
            name1 + '/' + name1 + '/',
 
638
            name2,
 
639
            ]
 
640
        try:
 
641
            self.build_tree(tree)
 
642
        except UnicodeError:
 
643
            raise TestSkipped('Could not represent Unicode chars'
 
644
                              ' in current encoding.')
 
645
        expected_dirblocks = [
 
646
                ((u'', u'.'),
 
647
                 [(name0, name0, 'file', './' + name0),
 
648
                  (name1, name1, 'directory', './' + name1),
 
649
                  (name2, name2, 'file', './' + name2),
 
650
                 ]
 
651
                ),
 
652
                ((name1, './' + name1),
 
653
                 [(name1 + '/' + name0, name0, 'file', './' + name1
 
654
                                                        + '/' + name0),
 
655
                  (name1 + '/' + name1, name1, 'directory', './' + name1
 
656
                                                            + '/' + name1),
 
657
                 ]
 
658
                ),
 
659
                ((name1 + '/' + name1, './' + name1 + '/' + name1),
 
660
                 [
 
661
                 ]
 
662
                ),
 
663
            ]
 
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)
 
670
 
 
671
    def test_unicode__walkdirs_utf8(self):
 
672
        """Walkdirs_utf8 should always return utf8 paths.
 
673
 
 
674
        The abspath portion might be in unicode or utf-8
 
675
        """
 
676
        name0 = u'0file-\xb6'
 
677
        name1 = u'1dir-\u062c\u0648'
 
678
        name2 = u'2file-\u0633'
 
679
        tree = [
 
680
            name0,
 
681
            name1 + '/',
 
682
            name1 + '/' + name0,
 
683
            name1 + '/' + name1 + '/',
 
684
            name2,
 
685
            ]
 
686
        try:
 
687
            self.build_tree(tree)
 
688
        except UnicodeError:
 
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')
 
694
 
 
695
        expected_dirblocks = [
 
696
                (('', '.'),
 
697
                 [(name0, name0, 'file', './' + name0),
 
698
                  (name1, name1, 'directory', './' + name1),
 
699
                  (name2, name2, 'file', './' + name2),
 
700
                 ]
 
701
                ),
 
702
                ((name1, './' + name1),
 
703
                 [(name1 + '/' + name0, name0, 'file', './' + name1
 
704
                                                        + '/' + name0),
 
705
                  (name1 + '/' + name1, name1, 'directory', './' + name1
 
706
                                                            + '/' + name1),
 
707
                 ]
 
708
                ),
 
709
                ((name1 + '/' + name1, './' + name1 + '/' + name1),
 
710
                 [
 
711
                 ]
 
712
                ),
 
713
            ]
 
714
        result = []
 
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')
 
725
            new_dirblock = []
 
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)
 
734
 
 
735
    def test_unicode__walkdirs_unicode_to_utf8(self):
 
736
        """walkdirs_unicode_to_utf8 should be a safe fallback everywhere
 
737
 
 
738
        The abspath portion should be in unicode
 
739
        """
 
740
        name0u = u'0file-\xb6'
 
741
        name1u = u'1dir-\u062c\u0648'
 
742
        name2u = u'2file-\u0633'
 
743
        tree = [
 
744
            name0u,
 
745
            name1u + '/',
 
746
            name1u + '/' + name0u,
 
747
            name1u + '/' + name1u + '/',
 
748
            name2u,
 
749
            ]
 
750
        try:
 
751
            self.build_tree(tree)
 
752
        except UnicodeError:
 
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')
 
758
 
 
759
        # All of the abspaths should be in unicode, all of the relative paths
 
760
        # should be in utf8
 
761
        expected_dirblocks = [
 
762
                (('', '.'),
 
763
                 [(name0, name0, 'file', './' + name0u),
 
764
                  (name1, name1, 'directory', './' + name1u),
 
765
                  (name2, name2, 'file', './' + name2u),
 
766
                 ]
 
767
                ),
 
768
                ((name1, './' + name1u),
 
769
                 [(name1 + '/' + name0, name0, 'file', './' + name1u
 
770
                                                        + '/' + name0u),
 
771
                  (name1 + '/' + name1, name1, 'directory', './' + name1u
 
772
                                                            + '/' + name1u),
 
773
                 ]
 
774
                ),
 
775
                ((name1 + '/' + name1, './' + name1u + '/' + name1u),
 
776
                 [
 
777
                 ]
 
778
                ),
 
779
            ]
 
780
        result = list(osutils._walkdirs_unicode_to_utf8('.'))
 
781
        self._filter_out_stat(result)
 
782
        self.assertEqual(expected_dirblocks, result)
 
783
 
452
784
    def assertPathCompare(self, path_less, path_greater):
453
785
        """check that path_less and path_greater compare correctly."""
454
786
        self.assertEqual(0, osutils.compare_paths_prefix_order(
580
912
            self.assertEqual([('source/lnk', 'target/lnk')], processed_links)
581
913
 
582
914
 
583
 
class TestTerminalEncoding(TestCase):
584
 
    """Test the auto-detection of proper terminal encoding."""
585
 
 
586
 
    def setUp(self):
587
 
        self._stdout = sys.stdout
588
 
        self._stderr = sys.stderr
589
 
        self._stdin = sys.stdin
590
 
        self._user_encoding = bzrlib.user_encoding
591
 
 
592
 
        self.addCleanup(self._reset)
593
 
 
594
 
        sys.stdout = StringIOWrapper()
595
 
        sys.stdout.encoding = 'stdout_encoding'
596
 
        sys.stderr = StringIOWrapper()
597
 
        sys.stderr.encoding = 'stderr_encoding'
598
 
        sys.stdin = StringIOWrapper()
599
 
        sys.stdin.encoding = 'stdin_encoding'
600
 
        bzrlib.user_encoding = 'user_encoding'
601
 
 
602
 
    def _reset(self):
603
 
        sys.stdout = self._stdout
604
 
        sys.stderr = self._stderr
605
 
        sys.stdin = self._stdin
606
 
        bzrlib.user_encoding = self._user_encoding
607
 
 
608
 
    def test_get_terminal_encoding(self):
609
 
        # first preference is stdout encoding
610
 
        self.assertEqual('stdout_encoding', osutils.get_terminal_encoding())
611
 
 
612
 
        sys.stdout.encoding = None
613
 
        # if sys.stdout is None, fall back to sys.stdin
614
 
        self.assertEqual('stdin_encoding', osutils.get_terminal_encoding())
615
 
 
616
 
        sys.stdin.encoding = None
617
 
        # and in the worst case, use bzrlib.user_encoding
618
 
        self.assertEqual('user_encoding', osutils.get_terminal_encoding())
 
915
#class TestTerminalEncoding has been moved to test_osutils_encodings.py
 
916
# [bialix] 2006/12/26
619
917
 
620
918
 
621
919
class TestSetUnsetEnv(TestCase):
677
975
        self.assertEqual(None, os.environ.get('BZR_TEST_ENV_VAR'))
678
976
        self.failIf('BZR_TEST_ENV_VAR' in os.environ)
679
977
 
 
978
 
 
979
class TestLocalTimeOffset(TestCase):
 
980
 
 
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
 
986
        # either direction.
 
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
 
989
        # probably wrong.
 
990
        eighteen_hours = 18 * 3600
 
991
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)
 
992
 
 
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)