~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: 2008-09-26 22:14:42 UTC
  • mto: This revision was merged to the branch mainline in revision 3747.
  • Revision ID: john@arbash-meinel.com-20080926221442-3r67j99sr9rwe9w0
Make message optional, don't check the memory flag directly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007 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
16
16
 
17
17
"""Tests for the osutils wrapper."""
18
18
 
 
19
from cStringIO import StringIO
19
20
import errno
20
21
import os
21
22
import socket
22
23
import stat
23
24
import sys
 
25
import time
24
26
 
25
27
import bzrlib
26
28
from bzrlib import (
27
29
    errors,
28
30
    osutils,
 
31
    tests,
29
32
    win32utils,
30
33
    )
31
34
from bzrlib.errors import BzrBadParameterNotUnicode, InvalidURL
 
35
from bzrlib.osutils import (
 
36
        is_inside_any,
 
37
        is_inside_or_parent_of_any,
 
38
        pathjoin,
 
39
        pumpfile,
 
40
        pump_string_file,
 
41
        )
32
42
from bzrlib.tests import (
 
43
        adapt_tests,
 
44
        Feature,
 
45
        probe_unicode_in_user_encoding,
 
46
        split_suite_by_re,
33
47
        StringIOWrapper,
34
 
        TestCase, 
35
 
        TestCaseInTempDir, 
 
48
        SymlinkFeature,
 
49
        TestCase,
 
50
        TestCaseInTempDir,
 
51
        TestScenarioApplier,
36
52
        TestSkipped,
37
53
        )
 
54
from bzrlib.tests.file_utils import (
 
55
    FakeReadFile,
 
56
    )
 
57
from bzrlib.tests.test__walkdirs_win32 import WalkdirsWin32Feature
 
58
 
 
59
 
 
60
def load_tests(standard_tests, module, loader):
 
61
    """Parameterize readdir tests."""
 
62
    to_adapt, result = split_suite_by_re(standard_tests, "readdir")
 
63
    adapter = TestScenarioApplier()
 
64
    from bzrlib import _readdir_py
 
65
    adapter.scenarios = [('python', {'read_dir': _readdir_py.read_dir})]
 
66
    if ReadDirFeature.available():
 
67
        adapter.scenarios.append(('pyrex',
 
68
            {'read_dir': ReadDirFeature.read_dir}))
 
69
    adapt_tests(to_adapt, adapter, result)
 
70
    return result
 
71
 
 
72
 
 
73
class _ReadDirFeature(Feature):
 
74
 
 
75
    def _probe(self):
 
76
        try:
 
77
            from bzrlib import _readdir_pyx
 
78
            self.read_dir = _readdir_pyx.read_dir
 
79
            return True
 
80
        except ImportError:
 
81
            return False
 
82
 
 
83
    def feature_name(self):
 
84
        return 'bzrlib._readdir_pyx'
 
85
 
 
86
ReadDirFeature = _ReadDirFeature()
38
87
 
39
88
 
40
89
class TestOSUtils(TestCaseInTempDir):
86
135
 
87
136
    # TODO: test fancy_rename using a MemoryTransport
88
137
 
 
138
    def test_rename_change_case(self):
 
139
        # on Windows we should be able to change filename case by rename
 
140
        self.build_tree(['a', 'b/'])
 
141
        osutils.rename('a', 'A')
 
142
        osutils.rename('b', 'B')
 
143
        # we can't use failUnlessExists on case-insensitive filesystem
 
144
        # so try to check shape of the tree
 
145
        shape = sorted(os.listdir('.'))
 
146
        self.assertEquals(['A', 'B'], shape)
 
147
 
89
148
    def test_01_rand_chars_empty(self):
90
149
        result = osutils.rand_chars(0)
91
150
        self.assertEqual(result, '')
105
164
        self.assertFalse(is_inside('foo.c', ''))
106
165
        self.assertTrue(is_inside('', 'foo.c'))
107
166
 
 
167
    def test_is_inside_any(self):
 
168
        SRC_FOO_C = pathjoin('src', 'foo.c')
 
169
        for dirs, fn in [(['src', 'doc'], SRC_FOO_C),
 
170
                         (['src'], SRC_FOO_C),
 
171
                         (['src'], 'src'),
 
172
                         ]:
 
173
            self.assert_(is_inside_any(dirs, fn))
 
174
        for dirs, fn in [(['src'], 'srccontrol'),
 
175
                         (['src'], 'srccontrol/foo')]:
 
176
            self.assertFalse(is_inside_any(dirs, fn))
 
177
 
 
178
    def test_is_inside_or_parent_of_any(self):
 
179
        for dirs, fn in [(['src', 'doc'], 'src/foo.c'),
 
180
                         (['src'], 'src/foo.c'),
 
181
                         (['src/bar.c'], 'src'),
 
182
                         (['src/bar.c', 'bla/foo.c'], 'src'),
 
183
                         (['src'], 'src'),
 
184
                         ]:
 
185
            self.assert_(is_inside_or_parent_of_any(dirs, fn))
 
186
            
 
187
        for dirs, fn in [(['src'], 'srccontrol'),
 
188
                         (['srccontrol/foo.c'], 'src'),
 
189
                         (['src'], 'srccontrol/foo')]:
 
190
            self.assertFalse(is_inside_or_parent_of_any(dirs, fn))
 
191
 
108
192
    def test_rmtree(self):
109
193
        # Check to remove tree with read-only files/dirs
110
194
        os.mkdir('dir')
218
302
        self.assertFormatedDelta('1 second in the future', -1)
219
303
        self.assertFormatedDelta('2 seconds in the future', -2)
220
304
 
 
305
    def test_format_date(self):
 
306
        self.assertRaises(errors.UnsupportedTimezoneFormat,
 
307
            osutils.format_date, 0, timezone='foo')
 
308
 
221
309
    def test_dereference_path(self):
222
 
        if not osutils.has_symlinks():
223
 
            raise TestSkipped('Symlinks are not supported on this platform')
 
310
        self.requireFeature(SymlinkFeature)
224
311
        cwd = osutils.realpath('.')
225
312
        os.mkdir('bar')
226
313
        bar_path = osutils.pathjoin(cwd, 'bar')
246
333
        foo_baz_path = osutils.pathjoin(foo_path, 'baz')
247
334
        self.assertEqual(baz_path, osutils.dereference_path(foo_baz_path))
248
335
 
249
 
 
250
336
    def test_changing_access(self):
251
337
        f = file('file', 'w')
252
338
        f.write('monkey')
254
340
 
255
341
        # Make a file readonly
256
342
        osutils.make_readonly('file')
257
 
        mode = osutils.lstat('file').st_mode
 
343
        mode = os.lstat('file').st_mode
258
344
        self.assertEqual(mode, mode & 0777555)
259
345
 
260
346
        # Make a file writable
261
347
        osutils.make_writable('file')
262
 
        mode = osutils.lstat('file').st_mode
 
348
        mode = os.lstat('file').st_mode
263
349
        self.assertEqual(mode, mode | 0200)
264
350
 
265
351
        if osutils.has_symlinks():
268
354
            osutils.make_readonly('dangling')
269
355
            osutils.make_writable('dangling')
270
356
 
271
 
 
272
357
    def test_kind_marker(self):
273
358
        self.assertEqual("", osutils.kind_marker("file"))
274
359
        self.assertEqual("/", osutils.kind_marker(osutils._directory_kind))
275
360
        self.assertEqual("@", osutils.kind_marker("symlink"))
276
361
        self.assertRaises(errors.BzrError, osutils.kind_marker, "unknown")
277
362
 
 
363
    def test_host_os_dereferences_symlinks(self):
 
364
        osutils.host_os_dereferences_symlinks()
 
365
 
 
366
 
 
367
class TestPumpFile(TestCase):
 
368
    """Test pumpfile method."""
 
369
    def setUp(self):
 
370
        # create a test datablock
 
371
        self.block_size = 512
 
372
        pattern = '0123456789ABCDEF'
 
373
        self.test_data = pattern * (3 * self.block_size / len(pattern))
 
374
        self.test_data_len = len(self.test_data)
 
375
 
 
376
    def test_bracket_block_size(self):
 
377
        """Read data in blocks with the requested read size bracketing the
 
378
        block size."""
 
379
        # make sure test data is larger than max read size
 
380
        self.assertTrue(self.test_data_len > self.block_size)
 
381
 
 
382
        from_file = FakeReadFile(self.test_data)
 
383
        to_file = StringIO()
 
384
 
 
385
        # read (max / 2) bytes and verify read size wasn't affected
 
386
        num_bytes_to_read = self.block_size / 2
 
387
        pumpfile(from_file, to_file, num_bytes_to_read, self.block_size)
 
388
        self.assertEqual(from_file.get_max_read_size(), num_bytes_to_read)
 
389
        self.assertEqual(from_file.get_read_count(), 1)
 
390
 
 
391
        # read (max) bytes and verify read size wasn't affected
 
392
        num_bytes_to_read = self.block_size
 
393
        from_file.reset_read_count()
 
394
        pumpfile(from_file, to_file, num_bytes_to_read, self.block_size)
 
395
        self.assertEqual(from_file.get_max_read_size(), num_bytes_to_read)
 
396
        self.assertEqual(from_file.get_read_count(), 1)
 
397
 
 
398
        # read (max + 1) bytes and verify read size was limited
 
399
        num_bytes_to_read = self.block_size + 1
 
400
        from_file.reset_read_count()
 
401
        pumpfile(from_file, to_file, num_bytes_to_read, self.block_size)
 
402
        self.assertEqual(from_file.get_max_read_size(), self.block_size)
 
403
        self.assertEqual(from_file.get_read_count(), 2)
 
404
 
 
405
        # finish reading the rest of the data
 
406
        num_bytes_to_read = self.test_data_len - to_file.tell()
 
407
        pumpfile(from_file, to_file, num_bytes_to_read, self.block_size)
 
408
 
 
409
        # report error if the data wasn't equal (we only report the size due
 
410
        # to the length of the data)
 
411
        response_data = to_file.getvalue()
 
412
        if response_data != self.test_data:
 
413
            message = "Data not equal.  Expected %d bytes, received %d."
 
414
            self.fail(message % (len(response_data), self.test_data_len))
 
415
 
 
416
    def test_specified_size(self):
 
417
        """Request a transfer larger than the maximum block size and verify
 
418
        that the maximum read doesn't exceed the block_size."""
 
419
        # make sure test data is larger than max read size
 
420
        self.assertTrue(self.test_data_len > self.block_size)
 
421
 
 
422
        # retrieve data in blocks
 
423
        from_file = FakeReadFile(self.test_data)
 
424
        to_file = StringIO()
 
425
        pumpfile(from_file, to_file, self.test_data_len, self.block_size)
 
426
 
 
427
        # verify read size was equal to the maximum read size
 
428
        self.assertTrue(from_file.get_max_read_size() > 0)
 
429
        self.assertEqual(from_file.get_max_read_size(), self.block_size)
 
430
        self.assertEqual(from_file.get_read_count(), 3)
 
431
 
 
432
        # report error if the data wasn't equal (we only report the size due
 
433
        # to the length of the data)
 
434
        response_data = to_file.getvalue()
 
435
        if response_data != self.test_data:
 
436
            message = "Data not equal.  Expected %d bytes, received %d."
 
437
            self.fail(message % (len(response_data), self.test_data_len))
 
438
 
 
439
    def test_to_eof(self):
 
440
        """Read to end-of-file and verify that the reads are not larger than
 
441
        the maximum read size."""
 
442
        # make sure test data is larger than max read size
 
443
        self.assertTrue(self.test_data_len > self.block_size)
 
444
 
 
445
        # retrieve data to EOF
 
446
        from_file = FakeReadFile(self.test_data)
 
447
        to_file = StringIO()
 
448
        pumpfile(from_file, to_file, -1, self.block_size)
 
449
 
 
450
        # verify read size was equal to the maximum read size
 
451
        self.assertEqual(from_file.get_max_read_size(), self.block_size)
 
452
        self.assertEqual(from_file.get_read_count(), 4)
 
453
 
 
454
        # report error if the data wasn't equal (we only report the size due
 
455
        # to the length of the data)
 
456
        response_data = to_file.getvalue()
 
457
        if response_data != self.test_data:
 
458
            message = "Data not equal.  Expected %d bytes, received %d."
 
459
            self.fail(message % (len(response_data), self.test_data_len))
 
460
 
 
461
    def test_defaults(self):
 
462
        """Verifies that the default arguments will read to EOF -- this
 
463
        test verifies that any existing usages of pumpfile will not be broken
 
464
        with this new version."""
 
465
        # retrieve data using default (old) pumpfile method
 
466
        from_file = FakeReadFile(self.test_data)
 
467
        to_file = StringIO()
 
468
        pumpfile(from_file, to_file)
 
469
 
 
470
        # report error if the data wasn't equal (we only report the size due
 
471
        # to the length of the data)
 
472
        response_data = to_file.getvalue()
 
473
        if response_data != self.test_data:
 
474
            message = "Data not equal.  Expected %d bytes, received %d."
 
475
            self.fail(message % (len(response_data), self.test_data_len))
 
476
 
 
477
 
 
478
class TestPumpStringFile(TestCase):
 
479
 
 
480
    def test_empty(self):
 
481
        output = StringIO()
 
482
        pump_string_file("", output)
 
483
        self.assertEqual("", output.getvalue())
 
484
 
 
485
    def test_more_than_segment_size(self):
 
486
        output = StringIO()
 
487
        pump_string_file("123456789", output, 2)
 
488
        self.assertEqual("123456789", output.getvalue())
 
489
 
 
490
    def test_segment_size(self):
 
491
        output = StringIO()
 
492
        pump_string_file("12", output, 2)
 
493
        self.assertEqual("12", output.getvalue())
 
494
 
 
495
    def test_segment_size_multiple(self):
 
496
        output = StringIO()
 
497
        pump_string_file("1234", output, 2)
 
498
        self.assertEqual("1234", output.getvalue())
 
499
 
278
500
 
279
501
class TestSafeUnicode(TestCase):
280
502
 
319
541
class TestSafeRevisionId(TestCase):
320
542
 
321
543
    def test_from_ascii_string(self):
 
544
        # this shouldn't give a warning because it's getting an ascii string
322
545
        self.assertEqual('foobar', osutils.safe_revision_id('foobar'))
323
546
 
324
547
    def test_from_unicode_string_ascii_contents(self):
446
669
        #       osutils.getcwd() renormalize the path.
447
670
        self.assertEndsWith(osutils._win32_getcwd(), u'mu-\xb5')
448
671
 
 
672
    def test_minimum_path_selection(self):
 
673
        self.assertEqual(set(),
 
674
            osutils.minimum_path_selection([]))
 
675
        self.assertEqual(set(['a', 'b']),
 
676
            osutils.minimum_path_selection(['a', 'b']))
 
677
        self.assertEqual(set(['a/', 'b']),
 
678
            osutils.minimum_path_selection(['a/', 'b']))
 
679
        self.assertEqual(set(['a/', 'b']),
 
680
            osutils.minimum_path_selection(['a/c', 'a/', 'b']))
 
681
 
449
682
    def test_mkdtemp(self):
450
683
        tmpdir = osutils._win32_mkdtemp(dir='.')
451
684
        self.assertFalse('\\' in tmpdir)
546
779
 
547
780
class TestWalkDirs(TestCaseInTempDir):
548
781
 
 
782
    def test_readdir(self):
 
783
        tree = [
 
784
            '.bzr/',
 
785
            '0file',
 
786
            '1dir/',
 
787
            '1dir/0file',
 
788
            '1dir/1dir/',
 
789
            '2file'
 
790
            ]
 
791
        self.build_tree(tree)
 
792
        expected_names = ['.bzr', '0file', '1dir', '2file']
 
793
        # read_dir returns pairs, which form a table with either None in all
 
794
        # the first columns, or a sort key to get best on-disk-read order, 
 
795
        # and the disk path name in utf-8 encoding in the second column.
 
796
        read_result = self.read_dir('.')
 
797
        # The second column is always the names, and every name except "." and
 
798
        # ".." should be present.
 
799
        names = sorted([row[1] for row in read_result])
 
800
        self.assertEqual(expected_names, names)
 
801
        expected_sort_key = None
 
802
        if read_result[0][0] is None:
 
803
            # No sort key returned - all keys must None
 
804
            operator = self.assertEqual
 
805
        else:
 
806
            # A sort key in the first row implies sort keys in the other rows.
 
807
            operator = self.assertNotEqual
 
808
        for row in read_result:
 
809
            operator(None, row[0])
 
810
 
 
811
    def test_compiled_extension_exists(self):
 
812
        self.requireFeature(ReadDirFeature)
 
813
        
549
814
    def test_walkdirs(self):
550
815
        tree = [
551
816
            '.bzr',
647
912
                new_dirblock.append((info[0], info[1], info[2], info[4]))
648
913
            dirblock[:] = new_dirblock
649
914
 
 
915
    def test__walkdirs_utf8_selection(self):
 
916
        # Just trigger the function once, to make sure it has selected a real
 
917
        # implementation.
 
918
        list(osutils._walkdirs_utf8('.'))
 
919
        if WalkdirsWin32Feature.available():
 
920
            # If the compiled form is available, make sure it is used
 
921
            from bzrlib._walkdirs_win32 import _walkdirs_utf8_win32_find_file
 
922
            self.assertIs(_walkdirs_utf8_win32_find_file,
 
923
                          osutils._real_walkdirs_utf8)
 
924
        elif sys.platform == 'win32':
 
925
            self.assertIs(osutils._walkdirs_unicode_to_utf8,
 
926
                          osutils._real_walkdirs_utf8)
 
927
        elif osutils._fs_enc.upper() in ('UTF-8', 'ASCII', 'ANSI_X3.4-1968'): # ascii
 
928
            self.assertIs(osutils._walkdirs_fs_utf8,
 
929
                          osutils._real_walkdirs_utf8)
 
930
        else:
 
931
            self.assertIs(osutils._walkdirs_unicode_to_utf8,
 
932
                          osutils._real_walkdirs_utf8)
 
933
 
 
934
    def _save_platform_info(self):
 
935
        cur_winver = win32utils.winver
 
936
        cur_fs_enc = osutils._fs_enc
 
937
        cur_real_walkdirs_utf8 = osutils._real_walkdirs_utf8
 
938
        def restore():
 
939
            win32utils.winver = cur_winver
 
940
            osutils._fs_enc = cur_fs_enc
 
941
            osutils._real_walkdirs_utf8 = cur_real_walkdirs_utf8
 
942
        self.addCleanup(restore)
 
943
 
 
944
    def assertWalkdirsUtf8Is(self, expected):
 
945
        """Assert the right implementation for _walkdirs_utf8 is chosen."""
 
946
        # Force it to redetect
 
947
        osutils._real_walkdirs_utf8 = None
 
948
        # Nothing to list, but should still trigger the selection logic
 
949
        self.assertEqual([(('', '.'), [])], list(osutils._walkdirs_utf8('.')))
 
950
        self.assertIs(expected, osutils._real_walkdirs_utf8)
 
951
 
 
952
    def test_force_walkdirs_utf8_fs_utf8(self):
 
953
        self._save_platform_info()
 
954
        win32utils.winver = None # Avoid the win32 detection code
 
955
        osutils._fs_enc = 'UTF-8'
 
956
        self.assertWalkdirsUtf8Is(osutils._walkdirs_fs_utf8)
 
957
 
 
958
    def test_force_walkdirs_utf8_fs_ascii(self):
 
959
        self._save_platform_info()
 
960
        win32utils.winver = None # Avoid the win32 detection code
 
961
        osutils._fs_enc = 'US-ASCII'
 
962
        self.assertWalkdirsUtf8Is(osutils._walkdirs_fs_utf8)
 
963
 
 
964
    def test_force_walkdirs_utf8_fs_ANSI(self):
 
965
        self._save_platform_info()
 
966
        win32utils.winver = None # Avoid the win32 detection code
 
967
        osutils._fs_enc = 'ANSI_X3.4-1968'
 
968
        self.assertWalkdirsUtf8Is(osutils._walkdirs_fs_utf8)
 
969
 
 
970
    def test_force_walkdirs_utf8_fs_latin1(self):
 
971
        self._save_platform_info()
 
972
        win32utils.winver = None # Avoid the win32 detection code
 
973
        osutils._fs_enc = 'latin1'
 
974
        self.assertWalkdirsUtf8Is(osutils._walkdirs_unicode_to_utf8)
 
975
 
 
976
    def test_force_walkdirs_utf8_nt(self):
 
977
        self.requireFeature(WalkdirsWin32Feature)
 
978
        self._save_platform_info()
 
979
        win32utils.winver = 'Windows NT'
 
980
        from bzrlib._walkdirs_win32 import _walkdirs_utf8_win32_find_file
 
981
        self.assertWalkdirsUtf8Is(_walkdirs_utf8_win32_find_file)
 
982
 
 
983
    def test_force_walkdirs_utf8_nt(self):
 
984
        self.requireFeature(WalkdirsWin32Feature)
 
985
        self._save_platform_info()
 
986
        win32utils.winver = 'Windows 98'
 
987
        self.assertWalkdirsUtf8Is(osutils._walkdirs_unicode_to_utf8)
 
988
 
650
989
    def test_unicode_walkdirs(self):
651
990
        """Walkdirs should always return unicode paths."""
652
991
        name0 = u'0file-\xb6'
803
1142
        self._filter_out_stat(result)
804
1143
        self.assertEqual(expected_dirblocks, result)
805
1144
 
 
1145
    def test__walkdirs_utf_win32_find_file(self):
 
1146
        self.requireFeature(WalkdirsWin32Feature)
 
1147
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1148
        from bzrlib._walkdirs_win32 import _walkdirs_utf8_win32_find_file
 
1149
        name0u = u'0file-\xb6'
 
1150
        name1u = u'1dir-\u062c\u0648'
 
1151
        name2u = u'2file-\u0633'
 
1152
        tree = [
 
1153
            name0u,
 
1154
            name1u + '/',
 
1155
            name1u + '/' + name0u,
 
1156
            name1u + '/' + name1u + '/',
 
1157
            name2u,
 
1158
            ]
 
1159
        self.build_tree(tree)
 
1160
        name0 = name0u.encode('utf8')
 
1161
        name1 = name1u.encode('utf8')
 
1162
        name2 = name2u.encode('utf8')
 
1163
 
 
1164
        # All of the abspaths should be in unicode, all of the relative paths
 
1165
        # should be in utf8
 
1166
        expected_dirblocks = [
 
1167
                (('', '.'),
 
1168
                 [(name0, name0, 'file', './' + name0u),
 
1169
                  (name1, name1, 'directory', './' + name1u),
 
1170
                  (name2, name2, 'file', './' + name2u),
 
1171
                 ]
 
1172
                ),
 
1173
                ((name1, './' + name1u),
 
1174
                 [(name1 + '/' + name0, name0, 'file', './' + name1u
 
1175
                                                        + '/' + name0u),
 
1176
                  (name1 + '/' + name1, name1, 'directory', './' + name1u
 
1177
                                                            + '/' + name1u),
 
1178
                 ]
 
1179
                ),
 
1180
                ((name1 + '/' + name1, './' + name1u + '/' + name1u),
 
1181
                 [
 
1182
                 ]
 
1183
                ),
 
1184
            ]
 
1185
        result = list(_walkdirs_utf8_win32_find_file(u'.'))
 
1186
        self._filter_out_stat(result)
 
1187
        self.assertEqual(expected_dirblocks, result)
 
1188
 
 
1189
    def assertStatIsCorrect(self, path, win32stat):
 
1190
        os_stat = os.stat(path)
 
1191
        self.assertEqual(os_stat.st_size, win32stat.st_size)
 
1192
        self.assertAlmostEqual(os_stat.st_mtime, win32stat.st_mtime, places=4)
 
1193
        self.assertAlmostEqual(os_stat.st_ctime, win32stat.st_ctime, places=4)
 
1194
        self.assertAlmostEqual(os_stat.st_atime, win32stat.st_atime, places=4)
 
1195
        self.assertEqual(os_stat.st_dev, win32stat.st_dev)
 
1196
        self.assertEqual(os_stat.st_ino, win32stat.st_ino)
 
1197
        self.assertEqual(os_stat.st_mode, win32stat.st_mode)
 
1198
 
 
1199
    def test__walkdirs_utf_win32_find_file_stat_file(self):
 
1200
        """make sure our Stat values are valid"""
 
1201
        self.requireFeature(WalkdirsWin32Feature)
 
1202
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1203
        from bzrlib._walkdirs_win32 import _walkdirs_utf8_win32_find_file
 
1204
        name0u = u'0file-\xb6'
 
1205
        name0 = name0u.encode('utf8')
 
1206
        self.build_tree([name0u])
 
1207
        # I hate to sleep() here, but I'm trying to make the ctime different
 
1208
        # from the mtime
 
1209
        time.sleep(2)
 
1210
        f = open(name0u, 'ab')
 
1211
        try:
 
1212
            f.write('just a small update')
 
1213
        finally:
 
1214
            f.close()
 
1215
 
 
1216
        result = list(_walkdirs_utf8_win32_find_file(u'.'))
 
1217
        entry = result[0][1][0]
 
1218
        self.assertEqual((name0, name0, 'file'), entry[:3])
 
1219
        self.assertEqual(u'./' + name0u, entry[4])
 
1220
        self.assertStatIsCorrect(entry[4], entry[3])
 
1221
        self.assertNotEqual(entry[3].st_mtime, entry[3].st_ctime)
 
1222
 
 
1223
    def test__walkdirs_utf_win32_find_file_stat_directory(self):
 
1224
        """make sure our Stat values are valid"""
 
1225
        self.requireFeature(WalkdirsWin32Feature)
 
1226
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1227
        from bzrlib._walkdirs_win32 import _walkdirs_utf8_win32_find_file
 
1228
        name0u = u'0dir-\u062c\u0648'
 
1229
        name0 = name0u.encode('utf8')
 
1230
        self.build_tree([name0u + '/'])
 
1231
 
 
1232
        result = list(_walkdirs_utf8_win32_find_file(u'.'))
 
1233
        entry = result[0][1][0]
 
1234
        self.assertEqual((name0, name0, 'directory'), entry[:3])
 
1235
        self.assertEqual(u'./' + name0u, entry[4])
 
1236
        self.assertStatIsCorrect(entry[4], entry[3])
 
1237
 
806
1238
    def assertPathCompare(self, path_less, path_greater):
807
1239
        """check that path_less and path_greater compare correctly."""
808
1240
        self.assertEqual(0, osutils.compare_paths_prefix_order(
897
1329
        self.assertEqual(['c'], os.listdir('target/b'))
898
1330
 
899
1331
    def test_copy_tree_symlinks(self):
900
 
        if not osutils.has_symlinks():
901
 
            return
 
1332
        self.requireFeature(SymlinkFeature)
902
1333
        self.build_tree(['source/'])
903
1334
        os.symlink('a/generic/path', 'source/lnk')
904
1335
        osutils.copy_tree('source', 'target')
971
1402
        
972
1403
        So Unicode strings must be encoded.
973
1404
        """
974
 
        # Try a few different characters, to see if we can get
975
 
        # one that will be valid in the user_encoding
976
 
        possible_vals = [u'm\xb5', u'\xe1', u'\u0410']
977
 
        for uni_val in possible_vals:
978
 
            try:
979
 
                env_val = uni_val.encode(bzrlib.user_encoding)
980
 
            except UnicodeEncodeError:
981
 
                # Try a different character
982
 
                pass
983
 
            else:
984
 
                break
985
 
        else:
 
1405
        uni_val, env_val = probe_unicode_in_user_encoding()
 
1406
        if uni_val is None:
986
1407
            raise TestSkipped('Cannot find a unicode character that works in'
987
1408
                              ' encoding %s' % (bzrlib.user_encoding,))
988
1409
 
1018
1439
        self.assertTrue(isinstance(offset, int))
1019
1440
        eighteen_hours = 18 * 3600
1020
1441
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)
 
1442
 
 
1443
 
 
1444
class TestShaFileByName(TestCaseInTempDir):
 
1445
 
 
1446
    def test_sha_empty(self):
 
1447
        self.build_tree_contents([('foo', '')])
 
1448
        expected_sha = osutils.sha_string('')
 
1449
        self.assertEqual(expected_sha, osutils.sha_file_by_name('foo'))
 
1450
 
 
1451
    def test_sha_mixed_endings(self):
 
1452
        text = 'test\r\nwith\nall\rpossible line endings\r\n'
 
1453
        self.build_tree_contents([('foo', text)])
 
1454
        expected_sha = osutils.sha_string(text)
 
1455
        self.assertEqual(expected_sha, osutils.sha_file_by_name('foo'))
 
1456
 
 
1457
 
 
1458
_debug_text = \
 
1459
r'''# Copyright (C) 2005, 2006 Canonical Ltd
 
1460
#
 
1461
# This program is free software; you can redistribute it and/or modify
 
1462
# it under the terms of the GNU General Public License as published by
 
1463
# the Free Software Foundation; either version 2 of the License, or
 
1464
# (at your option) any later version.
 
1465
#
 
1466
# This program is distributed in the hope that it will be useful,
 
1467
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
1468
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
1469
# GNU General Public License for more details.
 
1470
#
 
1471
# You should have received a copy of the GNU General Public License
 
1472
# along with this program; if not, write to the Free Software
 
1473
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
1474
 
 
1475
 
 
1476
# NOTE: If update these, please also update the help for global-options in
 
1477
#       bzrlib/help_topics/__init__.py
 
1478
 
 
1479
debug_flags = set()
 
1480
"""Set of flags that enable different debug behaviour.
 
1481
 
 
1482
These are set with eg ``-Dlock`` on the bzr command line.
 
1483
 
 
1484
Options include:
 
1485
 
 
1486
 * auth - show authentication sections used
 
1487
 * error - show stack traces for all top level exceptions
 
1488
 * evil - capture call sites that do expensive or badly-scaling operations.
 
1489
 * fetch - trace history copying between repositories
 
1490
 * graph - trace graph traversal information
 
1491
 * hashcache - log every time a working file is read to determine its hash
 
1492
 * hooks - trace hook execution
 
1493
 * hpss - trace smart protocol requests and responses
 
1494
 * http - trace http connections, requests and responses
 
1495
 * index - trace major index operations
 
1496
 * knit - trace knit operations
 
1497
 * lock - trace when lockdir locks are taken or released
 
1498
 * merge - emit information for debugging merges
 
1499
 * pack - emit information about pack operations
 
1500
 
 
1501
"""
 
1502
'''
 
1503
 
 
1504
 
 
1505
class TestResourceLoading(TestCaseInTempDir):
 
1506
 
 
1507
    def test_resource_string(self):
 
1508
        # test resource in bzrlib
 
1509
        text = osutils.resource_string('bzrlib', 'debug.py')
 
1510
        self.assertEquals(_debug_text, text)
 
1511
        # test resource under bzrlib
 
1512
        text = osutils.resource_string('bzrlib.ui', 'text.py')
 
1513
        self.assertContainsRe(text, "class TextUIFactory")
 
1514
        # test unsupported package
 
1515
        self.assertRaises(errors.BzrError, osutils.resource_string, 'zzzz',
 
1516
            'yyy.xx')
 
1517
        # test unknown resource
 
1518
        self.assertRaises(IOError, osutils.resource_string, 'bzrlib', 'yyy.xx')