~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_osutils.py

  • Committer: Andrew Bennetts
  • Date: 2009-07-27 05:35:00 UTC
  • mfrom: (4570 +trunk)
  • mto: (4634.6.29 2.0)
  • mto: This revision was merged to the branch mainline in revision 4680.
  • Revision ID: andrew.bennetts@canonical.com-20090727053500-q76zsn2dx33jhmj5
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Tests for the osutils wrapper."""
18
18
 
19
19
from cStringIO import StringIO
20
20
import errno
21
21
import os
 
22
import re
22
23
import socket
23
24
import stat
24
25
import sys
30
31
    tests,
31
32
    win32utils,
32
33
    )
33
 
from bzrlib.errors import BzrBadParameterNotUnicode, InvalidURL
34
 
from bzrlib.osutils import (
35
 
        is_inside_any,
36
 
        is_inside_or_parent_of_any,
37
 
        pathjoin,
38
 
        pumpfile,
39
 
        pump_string_file,
40
 
        canonical_relpath,
41
 
        )
42
34
from bzrlib.tests import (
43
 
        adapt_tests,
44
 
        Feature,
45
 
        probe_unicode_in_user_encoding,
46
 
        split_suite_by_re,
47
 
        StringIOWrapper,
48
 
        SymlinkFeature,
49
 
        CaseInsCasePresFilenameFeature,
50
 
        TestCase,
51
 
        TestCaseInTempDir,
52
 
        TestScenarioApplier,
53
 
        TestSkipped,
54
 
        )
55
 
from bzrlib.tests.file_utils import (
56
 
    FakeReadFile,
 
35
    file_utils,
 
36
    test__walkdirs_win32,
57
37
    )
58
 
from bzrlib.tests.test__walkdirs_win32 import Win32ReadDirFeature
59
 
 
60
 
 
61
 
class _UTF8DirReaderFeature(Feature):
 
38
 
 
39
 
 
40
class _UTF8DirReaderFeature(tests.Feature):
62
41
 
63
42
    def _probe(self):
64
43
        try:
74
53
UTF8DirReaderFeature = _UTF8DirReaderFeature()
75
54
 
76
55
 
77
 
class TestOSUtils(TestCaseInTempDir):
 
56
def _already_unicode(s):
 
57
    return s
 
58
 
 
59
 
 
60
def _fs_enc_to_unicode(s):
 
61
    return s.decode(osutils._fs_enc)
 
62
 
 
63
 
 
64
def _utf8_to_unicode(s):
 
65
    return s.decode('UTF-8')
 
66
 
 
67
 
 
68
def dir_reader_scenarios():
 
69
    # For each dir reader we define:
 
70
 
 
71
    # - native_to_unicode: a function converting the native_abspath as returned
 
72
    #   by DirReader.read_dir to its unicode representation
 
73
 
 
74
    # UnicodeDirReader is the fallback, it should be tested on all platforms.
 
75
    scenarios = [('unicode',
 
76
                  dict(_dir_reader_class=osutils.UnicodeDirReader,
 
77
                       _native_to_unicode=_already_unicode))]
 
78
    # Some DirReaders are platform specific and even there they may not be
 
79
    # available.
 
80
    if UTF8DirReaderFeature.available():
 
81
        from bzrlib import _readdir_pyx
 
82
        scenarios.append(('utf8',
 
83
                          dict(_dir_reader_class=_readdir_pyx.UTF8DirReader,
 
84
                               _native_to_unicode=_utf8_to_unicode)))
 
85
 
 
86
    if test__walkdirs_win32.Win32ReadDirFeature.available():
 
87
        try:
 
88
            from bzrlib import _walkdirs_win32
 
89
            # TODO: check on windows, it may be that we need to use/add
 
90
            # safe_unicode instead of _fs_enc_to_unicode
 
91
            scenarios.append(
 
92
                ('win32',
 
93
                 dict(_dir_reader_class=_walkdirs_win32.Win32ReadDir,
 
94
                      _native_to_unicode=_fs_enc_to_unicode)))
 
95
        except ImportError:
 
96
            pass
 
97
    return scenarios
 
98
 
 
99
 
 
100
def load_tests(basic_tests, module, loader):
 
101
    suite = loader.suiteClass()
 
102
    dir_reader_tests, remaining_tests = tests.split_suite_by_condition(
 
103
        basic_tests, tests.condition_isinstance(TestDirReader))
 
104
    tests.multiply_tests(dir_reader_tests, dir_reader_scenarios(), suite)
 
105
    suite.addTest(remaining_tests)
 
106
    return suite
 
107
 
 
108
 
 
109
class TestContainsWhitespace(tests.TestCase):
78
110
 
79
111
    def test_contains_whitespace(self):
80
112
        self.failUnless(osutils.contains_whitespace(u' '))
90
122
        self.failIf(osutils.contains_whitespace(u'hellothere'))
91
123
        self.failIf(osutils.contains_whitespace(u'hello\xa0there'))
92
124
 
 
125
 
 
126
class TestRename(tests.TestCaseInTempDir):
 
127
 
93
128
    def test_fancy_rename(self):
94
129
        # This should work everywhere
95
130
        def rename(a, b):
133
168
        shape = sorted(os.listdir('.'))
134
169
        self.assertEquals(['A', 'B'], shape)
135
170
 
 
171
 
 
172
class TestRandChars(tests.TestCase):
 
173
 
136
174
    def test_01_rand_chars_empty(self):
137
175
        result = osutils.rand_chars(0)
138
176
        self.assertEqual(result, '')
143
181
        self.assertEqual(type(result), str)
144
182
        self.assertContainsRe(result, r'^[a-z0-9]{100}$')
145
183
 
 
184
 
 
185
class TestIsInside(tests.TestCase):
 
186
 
146
187
    def test_is_inside(self):
147
188
        is_inside = osutils.is_inside
148
189
        self.assertTrue(is_inside('src', 'src/foo.c'))
153
194
        self.assertTrue(is_inside('', 'foo.c'))
154
195
 
155
196
    def test_is_inside_any(self):
156
 
        SRC_FOO_C = pathjoin('src', 'foo.c')
 
197
        SRC_FOO_C = osutils.pathjoin('src', 'foo.c')
157
198
        for dirs, fn in [(['src', 'doc'], SRC_FOO_C),
158
199
                         (['src'], SRC_FOO_C),
159
200
                         (['src'], 'src'),
160
201
                         ]:
161
 
            self.assert_(is_inside_any(dirs, fn))
 
202
            self.assert_(osutils.is_inside_any(dirs, fn))
162
203
        for dirs, fn in [(['src'], 'srccontrol'),
163
204
                         (['src'], 'srccontrol/foo')]:
164
 
            self.assertFalse(is_inside_any(dirs, fn))
 
205
            self.assertFalse(osutils.is_inside_any(dirs, fn))
165
206
 
166
207
    def test_is_inside_or_parent_of_any(self):
167
208
        for dirs, fn in [(['src', 'doc'], 'src/foo.c'),
170
211
                         (['src/bar.c', 'bla/foo.c'], 'src'),
171
212
                         (['src'], 'src'),
172
213
                         ]:
173
 
            self.assert_(is_inside_or_parent_of_any(dirs, fn))
 
214
            self.assert_(osutils.is_inside_or_parent_of_any(dirs, fn))
174
215
 
175
216
        for dirs, fn in [(['src'], 'srccontrol'),
176
217
                         (['srccontrol/foo.c'], 'src'),
177
218
                         (['src'], 'srccontrol/foo')]:
178
 
            self.assertFalse(is_inside_or_parent_of_any(dirs, fn))
 
219
            self.assertFalse(osutils.is_inside_or_parent_of_any(dirs, fn))
 
220
 
 
221
 
 
222
class TestRmTree(tests.TestCaseInTempDir):
179
223
 
180
224
    def test_rmtree(self):
181
225
        # Check to remove tree with read-only files/dirs
195
239
        self.failIfExists('dir/file')
196
240
        self.failIfExists('dir')
197
241
 
 
242
 
 
243
class TestDeleteAny(tests.TestCaseInTempDir):
 
244
 
 
245
    def test_delete_any_readonly(self):
 
246
        # from <https://bugs.launchpad.net/bzr/+bug/218206>
 
247
        self.build_tree(['d/', 'f'])
 
248
        osutils.make_readonly('d')
 
249
        osutils.make_readonly('f')
 
250
 
 
251
        osutils.delete_any('f')
 
252
        osutils.delete_any('d')
 
253
 
 
254
 
 
255
class TestKind(tests.TestCaseInTempDir):
 
256
 
198
257
    def test_file_kind(self):
199
258
        self.build_tree(['file', 'dir/'])
200
259
        self.assertEquals('file', osutils.file_kind('file'))
230
289
                os.remove('socket')
231
290
 
232
291
    def test_kind_marker(self):
233
 
        self.assertEqual(osutils.kind_marker('file'), '')
234
 
        self.assertEqual(osutils.kind_marker('directory'), '/')
235
 
        self.assertEqual(osutils.kind_marker('symlink'), '@')
236
 
        self.assertEqual(osutils.kind_marker('tree-reference'), '+')
 
292
        self.assertEqual("", osutils.kind_marker("file"))
 
293
        self.assertEqual("/", osutils.kind_marker('directory'))
 
294
        self.assertEqual("/", osutils.kind_marker(osutils._directory_kind))
 
295
        self.assertEqual("@", osutils.kind_marker("symlink"))
 
296
        self.assertEqual("+", osutils.kind_marker("tree-reference"))
 
297
        self.assertRaises(errors.BzrError, osutils.kind_marker, "unknown")
 
298
 
 
299
 
 
300
class TestUmask(tests.TestCaseInTempDir):
237
301
 
238
302
    def test_get_umask(self):
239
303
        if sys.platform == 'win32':
242
306
            return
243
307
 
244
308
        orig_umask = osutils.get_umask()
245
 
        try:
246
 
            os.umask(0222)
247
 
            self.assertEqual(0222, osutils.get_umask())
248
 
            os.umask(0022)
249
 
            self.assertEqual(0022, osutils.get_umask())
250
 
            os.umask(0002)
251
 
            self.assertEqual(0002, osutils.get_umask())
252
 
            os.umask(0027)
253
 
            self.assertEqual(0027, osutils.get_umask())
254
 
        finally:
255
 
            os.umask(orig_umask)
 
309
        self.addCleanup(os.umask, orig_umask)
 
310
        os.umask(0222)
 
311
        self.assertEqual(0222, osutils.get_umask())
 
312
        os.umask(0022)
 
313
        self.assertEqual(0022, osutils.get_umask())
 
314
        os.umask(0002)
 
315
        self.assertEqual(0002, osutils.get_umask())
 
316
        os.umask(0027)
 
317
        self.assertEqual(0027, osutils.get_umask())
 
318
 
 
319
 
 
320
class TestDateTime(tests.TestCase):
256
321
 
257
322
    def assertFormatedDelta(self, expected, seconds):
258
323
        """Assert osutils.format_delta formats as expected"""
300
365
        # Instead blackbox.test_locale should check for localized
301
366
        # dates once they do occur in output strings.
302
367
 
 
368
    def test_local_time_offset(self):
 
369
        """Test that local_time_offset() returns a sane value."""
 
370
        offset = osutils.local_time_offset()
 
371
        self.assertTrue(isinstance(offset, int))
 
372
        # Test that the offset is no more than a eighteen hours in
 
373
        # either direction.
 
374
        # Time zone handling is system specific, so it is difficult to
 
375
        # do more specific tests, but a value outside of this range is
 
376
        # probably wrong.
 
377
        eighteen_hours = 18 * 3600
 
378
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)
 
379
 
 
380
    def test_local_time_offset_with_timestamp(self):
 
381
        """Test that local_time_offset() works with a timestamp."""
 
382
        offset = osutils.local_time_offset(1000000000.1234567)
 
383
        self.assertTrue(isinstance(offset, int))
 
384
        eighteen_hours = 18 * 3600
 
385
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)
 
386
 
 
387
 
 
388
class TestLinks(tests.TestCaseInTempDir):
 
389
 
303
390
    def test_dereference_path(self):
304
 
        self.requireFeature(SymlinkFeature)
 
391
        self.requireFeature(tests.SymlinkFeature)
305
392
        cwd = osutils.realpath('.')
306
393
        os.mkdir('bar')
307
394
        bar_path = osutils.pathjoin(cwd, 'bar')
348
435
            osutils.make_readonly('dangling')
349
436
            osutils.make_writable('dangling')
350
437
 
351
 
    def test_kind_marker(self):
352
 
        self.assertEqual("", osutils.kind_marker("file"))
353
 
        self.assertEqual("/", osutils.kind_marker(osutils._directory_kind))
354
 
        self.assertEqual("@", osutils.kind_marker("symlink"))
355
 
        self.assertRaises(errors.BzrError, osutils.kind_marker, "unknown")
356
 
 
357
438
    def test_host_os_dereferences_symlinks(self):
358
439
        osutils.host_os_dereferences_symlinks()
359
440
 
360
441
 
361
 
class TestCanonicalRelPath(TestCaseInTempDir):
 
442
class TestCanonicalRelPath(tests.TestCaseInTempDir):
362
443
 
363
 
    _test_needs_features = [CaseInsCasePresFilenameFeature]
 
444
    _test_needs_features = [tests.CaseInsCasePresFilenameFeature]
364
445
 
365
446
    def test_canonical_relpath_simple(self):
366
447
        f = file('MixedCaseName', 'w')
367
448
        f.close()
368
 
        self.failUnlessEqual(
369
 
            canonical_relpath(self.test_base_dir, 'mixedcasename'),
370
 
            'work/MixedCaseName')
 
449
        # Watch out for tricky test dir (on OSX /tmp -> /private/tmp)
 
450
        real_base_dir = osutils.realpath(self.test_base_dir)
 
451
        actual = osutils.canonical_relpath(real_base_dir, 'mixedcasename')
 
452
        self.failUnlessEqual('work/MixedCaseName', actual)
371
453
 
372
454
    def test_canonical_relpath_missing_tail(self):
373
455
        os.mkdir('MixedCaseParent')
374
 
        self.failUnlessEqual(
375
 
            canonical_relpath(self.test_base_dir, 'mixedcaseparent/nochild'),
376
 
            'work/MixedCaseParent/nochild')
377
 
 
378
 
 
379
 
class TestPumpFile(TestCase):
 
456
        # Watch out for tricky test dir (on OSX /tmp -> /private/tmp)
 
457
        real_base_dir = osutils.realpath(self.test_base_dir)
 
458
        actual = osutils.canonical_relpath(real_base_dir,
 
459
                                           'mixedcaseparent/nochild')
 
460
        self.failUnlessEqual('work/MixedCaseParent/nochild', actual)
 
461
 
 
462
 
 
463
class TestPumpFile(tests.TestCase):
380
464
    """Test pumpfile method."""
 
465
 
381
466
    def setUp(self):
 
467
        tests.TestCase.setUp(self)
382
468
        # create a test datablock
383
469
        self.block_size = 512
384
470
        pattern = '0123456789ABCDEF'
391
477
        # make sure test data is larger than max read size
392
478
        self.assertTrue(self.test_data_len > self.block_size)
393
479
 
394
 
        from_file = FakeReadFile(self.test_data)
 
480
        from_file = file_utils.FakeReadFile(self.test_data)
395
481
        to_file = StringIO()
396
482
 
397
483
        # read (max / 2) bytes and verify read size wasn't affected
398
484
        num_bytes_to_read = self.block_size / 2
399
 
        pumpfile(from_file, to_file, num_bytes_to_read, self.block_size)
 
485
        osutils.pumpfile(from_file, to_file, num_bytes_to_read, self.block_size)
400
486
        self.assertEqual(from_file.get_max_read_size(), num_bytes_to_read)
401
487
        self.assertEqual(from_file.get_read_count(), 1)
402
488
 
403
489
        # read (max) bytes and verify read size wasn't affected
404
490
        num_bytes_to_read = self.block_size
405
491
        from_file.reset_read_count()
406
 
        pumpfile(from_file, to_file, num_bytes_to_read, self.block_size)
 
492
        osutils.pumpfile(from_file, to_file, num_bytes_to_read, self.block_size)
407
493
        self.assertEqual(from_file.get_max_read_size(), num_bytes_to_read)
408
494
        self.assertEqual(from_file.get_read_count(), 1)
409
495
 
410
496
        # read (max + 1) bytes and verify read size was limited
411
497
        num_bytes_to_read = self.block_size + 1
412
498
        from_file.reset_read_count()
413
 
        pumpfile(from_file, to_file, num_bytes_to_read, self.block_size)
 
499
        osutils.pumpfile(from_file, to_file, num_bytes_to_read, self.block_size)
414
500
        self.assertEqual(from_file.get_max_read_size(), self.block_size)
415
501
        self.assertEqual(from_file.get_read_count(), 2)
416
502
 
417
503
        # finish reading the rest of the data
418
504
        num_bytes_to_read = self.test_data_len - to_file.tell()
419
 
        pumpfile(from_file, to_file, num_bytes_to_read, self.block_size)
 
505
        osutils.pumpfile(from_file, to_file, num_bytes_to_read, self.block_size)
420
506
 
421
507
        # report error if the data wasn't equal (we only report the size due
422
508
        # to the length of the data)
432
518
        self.assertTrue(self.test_data_len > self.block_size)
433
519
 
434
520
        # retrieve data in blocks
435
 
        from_file = FakeReadFile(self.test_data)
 
521
        from_file = file_utils.FakeReadFile(self.test_data)
436
522
        to_file = StringIO()
437
 
        pumpfile(from_file, to_file, self.test_data_len, self.block_size)
 
523
        osutils.pumpfile(from_file, to_file, self.test_data_len,
 
524
                         self.block_size)
438
525
 
439
526
        # verify read size was equal to the maximum read size
440
527
        self.assertTrue(from_file.get_max_read_size() > 0)
455
542
        self.assertTrue(self.test_data_len > self.block_size)
456
543
 
457
544
        # retrieve data to EOF
458
 
        from_file = FakeReadFile(self.test_data)
 
545
        from_file = file_utils.FakeReadFile(self.test_data)
459
546
        to_file = StringIO()
460
 
        pumpfile(from_file, to_file, -1, self.block_size)
 
547
        osutils.pumpfile(from_file, to_file, -1, self.block_size)
461
548
 
462
549
        # verify read size was equal to the maximum read size
463
550
        self.assertEqual(from_file.get_max_read_size(), self.block_size)
475
562
        test verifies that any existing usages of pumpfile will not be broken
476
563
        with this new version."""
477
564
        # retrieve data using default (old) pumpfile method
478
 
        from_file = FakeReadFile(self.test_data)
 
565
        from_file = file_utils.FakeReadFile(self.test_data)
479
566
        to_file = StringIO()
480
 
        pumpfile(from_file, to_file)
 
567
        osutils.pumpfile(from_file, to_file)
481
568
 
482
569
        # report error if the data wasn't equal (we only report the size due
483
570
        # to the length of the data)
492
579
            activity.append((length, direction))
493
580
        from_file = StringIO(self.test_data)
494
581
        to_file = StringIO()
495
 
        pumpfile(from_file, to_file, buff_size=500,
496
 
                 report_activity=log_activity, direction='read')
 
582
        osutils.pumpfile(from_file, to_file, buff_size=500,
 
583
                         report_activity=log_activity, direction='read')
497
584
        self.assertEqual([(500, 'read'), (500, 'read'), (500, 'read'),
498
585
                          (36, 'read')], activity)
499
586
 
500
587
        from_file = StringIO(self.test_data)
501
588
        to_file = StringIO()
502
589
        del activity[:]
503
 
        pumpfile(from_file, to_file, buff_size=500,
504
 
                 report_activity=log_activity, direction='write')
 
590
        osutils.pumpfile(from_file, to_file, buff_size=500,
 
591
                         report_activity=log_activity, direction='write')
505
592
        self.assertEqual([(500, 'write'), (500, 'write'), (500, 'write'),
506
593
                          (36, 'write')], activity)
507
594
 
509
596
        from_file = StringIO(self.test_data)
510
597
        to_file = StringIO()
511
598
        del activity[:]
512
 
        pumpfile(from_file, to_file, buff_size=500, read_length=1028,
513
 
                 report_activity=log_activity, direction='read')
 
599
        osutils.pumpfile(from_file, to_file, buff_size=500, read_length=1028,
 
600
                         report_activity=log_activity, direction='read')
514
601
        self.assertEqual([(500, 'read'), (500, 'read'), (28, 'read')], activity)
515
602
 
516
603
 
517
604
 
518
 
class TestPumpStringFile(TestCase):
 
605
class TestPumpStringFile(tests.TestCase):
519
606
 
520
607
    def test_empty(self):
521
608
        output = StringIO()
522
 
        pump_string_file("", output)
 
609
        osutils.pump_string_file("", output)
523
610
        self.assertEqual("", output.getvalue())
524
611
 
525
612
    def test_more_than_segment_size(self):
526
613
        output = StringIO()
527
 
        pump_string_file("123456789", output, 2)
 
614
        osutils.pump_string_file("123456789", output, 2)
528
615
        self.assertEqual("123456789", output.getvalue())
529
616
 
530
617
    def test_segment_size(self):
531
618
        output = StringIO()
532
 
        pump_string_file("12", output, 2)
 
619
        osutils.pump_string_file("12", output, 2)
533
620
        self.assertEqual("12", output.getvalue())
534
621
 
535
622
    def test_segment_size_multiple(self):
536
623
        output = StringIO()
537
 
        pump_string_file("1234", output, 2)
 
624
        osutils.pump_string_file("1234", output, 2)
538
625
        self.assertEqual("1234", output.getvalue())
539
626
 
540
627
 
541
 
class TestSafeUnicode(TestCase):
 
628
class TestRelpath(tests.TestCase):
 
629
 
 
630
    def test_simple_relpath(self):
 
631
        cwd = osutils.getcwd()
 
632
        subdir = cwd + '/subdir'
 
633
        self.assertEqual('subdir', osutils.relpath(cwd, subdir))
 
634
 
 
635
    def test_deep_relpath(self):
 
636
        cwd = osutils.getcwd()
 
637
        subdir = cwd + '/sub/subsubdir'
 
638
        self.assertEqual('sub/subsubdir', osutils.relpath(cwd, subdir))
 
639
 
 
640
    def test_not_relative(self):
 
641
        self.assertRaises(errors.PathNotChild,
 
642
                          osutils.relpath, 'C:/path', 'H:/path')
 
643
        self.assertRaises(errors.PathNotChild,
 
644
                          osutils.relpath, 'C:/', 'H:/path')
 
645
 
 
646
 
 
647
class TestSafeUnicode(tests.TestCase):
542
648
 
543
649
    def test_from_ascii_string(self):
544
650
        self.assertEqual(u'foobar', osutils.safe_unicode('foobar'))
553
659
        self.assertEqual(u'foo\xae', osutils.safe_unicode('foo\xc2\xae'))
554
660
 
555
661
    def test_bad_utf8_string(self):
556
 
        self.assertRaises(BzrBadParameterNotUnicode,
 
662
        self.assertRaises(errors.BzrBadParameterNotUnicode,
557
663
                          osutils.safe_unicode,
558
664
                          '\xbb\xbb')
559
665
 
560
666
 
561
 
class TestSafeUtf8(TestCase):
 
667
class TestSafeUtf8(tests.TestCase):
562
668
 
563
669
    def test_from_ascii_string(self):
564
670
        f = 'foobar'
574
680
        self.assertEqual('foo\xc2\xae', osutils.safe_utf8('foo\xc2\xae'))
575
681
 
576
682
    def test_bad_utf8_string(self):
577
 
        self.assertRaises(BzrBadParameterNotUnicode,
 
683
        self.assertRaises(errors.BzrBadParameterNotUnicode,
578
684
                          osutils.safe_utf8, '\xbb\xbb')
579
685
 
580
686
 
581
 
class TestSafeRevisionId(TestCase):
 
687
class TestSafeRevisionId(tests.TestCase):
582
688
 
583
689
    def test_from_ascii_string(self):
584
690
        # this shouldn't give a warning because it's getting an ascii string
606
712
        self.assertEqual(None, osutils.safe_revision_id(None))
607
713
 
608
714
 
609
 
class TestSafeFileId(TestCase):
 
715
class TestSafeFileId(tests.TestCase):
610
716
 
611
717
    def test_from_ascii_string(self):
612
718
        self.assertEqual('foobar', osutils.safe_file_id('foobar'))
632
738
        self.assertEqual(None, osutils.safe_file_id(None))
633
739
 
634
740
 
635
 
class TestWin32Funcs(TestCase):
636
 
    """Test that the _win32 versions of os utilities return appropriate paths."""
 
741
class TestWin32Funcs(tests.TestCase):
 
742
    """Test that _win32 versions of os utilities return appropriate paths."""
637
743
 
638
744
    def test_abspath(self):
639
745
        self.assertEqual('C:/foo', osutils._win32_abspath('C:\\foo'))
646
752
        self.assertEqual('C:/foo', osutils._win32_realpath('C:/foo'))
647
753
 
648
754
    def test_pathjoin(self):
649
 
        self.assertEqual('path/to/foo', osutils._win32_pathjoin('path', 'to', 'foo'))
650
 
        self.assertEqual('C:/foo', osutils._win32_pathjoin('path\\to', 'C:\\foo'))
651
 
        self.assertEqual('C:/foo', osutils._win32_pathjoin('path/to', 'C:/foo'))
652
 
        self.assertEqual('path/to/foo', osutils._win32_pathjoin('path/to/', 'foo'))
653
 
        self.assertEqual('/foo', osutils._win32_pathjoin('C:/path/to/', '/foo'))
654
 
        self.assertEqual('/foo', osutils._win32_pathjoin('C:\\path\\to\\', '\\foo'))
 
755
        self.assertEqual('path/to/foo',
 
756
                         osutils._win32_pathjoin('path', 'to', 'foo'))
 
757
        self.assertEqual('C:/foo',
 
758
                         osutils._win32_pathjoin('path\\to', 'C:\\foo'))
 
759
        self.assertEqual('C:/foo',
 
760
                         osutils._win32_pathjoin('path/to', 'C:/foo'))
 
761
        self.assertEqual('path/to/foo',
 
762
                         osutils._win32_pathjoin('path/to/', 'foo'))
 
763
        self.assertEqual('/foo',
 
764
                         osutils._win32_pathjoin('C:/path/to/', '/foo'))
 
765
        self.assertEqual('/foo',
 
766
                         osutils._win32_pathjoin('C:\\path\\to\\', '\\foo'))
655
767
 
656
768
    def test_normpath(self):
657
 
        self.assertEqual('path/to/foo', osutils._win32_normpath(r'path\\from\..\to\.\foo'))
658
 
        self.assertEqual('path/to/foo', osutils._win32_normpath('path//from/../to/./foo'))
 
769
        self.assertEqual('path/to/foo',
 
770
                         osutils._win32_normpath(r'path\\from\..\to\.\foo'))
 
771
        self.assertEqual('path/to/foo',
 
772
                         osutils._win32_normpath('path//from/../to/./foo'))
659
773
 
660
774
    def test_getcwd(self):
661
775
        cwd = osutils._win32_getcwd()
690
804
        self.assertEqual(cwd+'/'+u, osutils._win98_abspath(u))
691
805
 
692
806
 
693
 
class TestWin32FuncsDirs(TestCaseInTempDir):
 
807
class TestWin32FuncsDirs(tests.TestCaseInTempDir):
694
808
    """Test win32 functions that create files."""
695
809
 
696
810
    def test_getcwd(self):
697
 
        if win32utils.winver == 'Windows 98':
698
 
            raise TestSkipped('Windows 98 cannot handle unicode filenames')
699
 
        # Make sure getcwd can handle unicode filenames
700
 
        try:
701
 
            os.mkdir(u'mu-\xb5')
702
 
        except UnicodeError:
703
 
            raise TestSkipped("Unable to create Unicode filename")
704
 
 
 
811
        self.requireFeature(tests.UnicodeFilenameFeature)
 
812
        os.mkdir(u'mu-\xb5')
705
813
        os.chdir(u'mu-\xb5')
706
814
        # TODO: jam 20060427 This will probably fail on Mac OSX because
707
815
        #       it will change the normalization of B\xe5gfors
712
820
    def test_minimum_path_selection(self):
713
821
        self.assertEqual(set(),
714
822
            osutils.minimum_path_selection([]))
 
823
        self.assertEqual(set(['a']),
 
824
            osutils.minimum_path_selection(['a']))
715
825
        self.assertEqual(set(['a', 'b']),
716
826
            osutils.minimum_path_selection(['a', 'b']))
717
827
        self.assertEqual(set(['a/', 'b']),
718
828
            osutils.minimum_path_selection(['a/', 'b']))
719
829
        self.assertEqual(set(['a/', 'b']),
720
830
            osutils.minimum_path_selection(['a/c', 'a/', 'b']))
 
831
        self.assertEqual(set(['a-b', 'a', 'a0b']),
 
832
            osutils.minimum_path_selection(['a-b', 'a/b', 'a0b', 'a']))
721
833
 
722
834
    def test_mkdtemp(self):
723
835
        tmpdir = osutils._win32_mkdtemp(dir='.')
779
891
        self.assertRaises(errors.BzrError, osutils.splitpath, 'a/../b')
780
892
 
781
893
 
782
 
class TestMacFuncsDirs(TestCaseInTempDir):
 
894
class TestParentDirectories(tests.TestCaseInTempDir):
 
895
    """Test osutils.parent_directories()"""
 
896
 
 
897
    def test_parent_directories(self):
 
898
        self.assertEqual([], osutils.parent_directories('a'))
 
899
        self.assertEqual(['a'], osutils.parent_directories('a/b'))
 
900
        self.assertEqual(['a/b', 'a'], osutils.parent_directories('a/b/c'))
 
901
 
 
902
 
 
903
class TestMacFuncsDirs(tests.TestCaseInTempDir):
783
904
    """Test mac special functions that require directories."""
784
905
 
785
906
    def test_getcwd(self):
786
 
        # On Mac, this will actually create Ba\u030agfors
787
 
        # but chdir will still work, because it accepts both paths
788
 
        try:
789
 
            os.mkdir(u'B\xe5gfors')
790
 
        except UnicodeError:
791
 
            raise TestSkipped("Unable to create Unicode filename")
792
 
 
 
907
        self.requireFeature(tests.UnicodeFilenameFeature)
 
908
        os.mkdir(u'B\xe5gfors')
793
909
        os.chdir(u'B\xe5gfors')
794
910
        self.assertEndsWith(osutils._mac_getcwd(), u'B\xe5gfors')
795
911
 
796
912
    def test_getcwd_nonnorm(self):
 
913
        self.requireFeature(tests.UnicodeFilenameFeature)
797
914
        # Test that _mac_getcwd() will normalize this path
798
 
        try:
799
 
            os.mkdir(u'Ba\u030agfors')
800
 
        except UnicodeError:
801
 
            raise TestSkipped("Unable to create Unicode filename")
802
 
 
 
915
        os.mkdir(u'Ba\u030agfors')
803
916
        os.chdir(u'Ba\u030agfors')
804
917
        self.assertEndsWith(osutils._mac_getcwd(), u'B\xe5gfors')
805
918
 
806
919
 
807
 
class TestChunksToLines(TestCase):
 
920
class TestChunksToLines(tests.TestCase):
808
921
 
809
922
    def test_smoketest(self):
810
923
        self.assertEqual(['foo\n', 'bar\n', 'baz\n'],
821
934
        self.assertIs(chunks_to_lines, osutils.chunks_to_lines)
822
935
 
823
936
 
824
 
class TestSplitLines(TestCase):
 
937
class TestSplitLines(tests.TestCase):
825
938
 
826
939
    def test_split_unicode(self):
827
940
        self.assertEqual([u'foo\n', u'bar\xae'],
834
947
                         osutils.split_lines('foo\rbar\n'))
835
948
 
836
949
 
837
 
class TestWalkDirs(TestCaseInTempDir):
 
950
class TestWalkDirs(tests.TestCaseInTempDir):
 
951
 
 
952
    def assertExpectedBlocks(self, expected, result):
 
953
        self.assertEqual(expected,
 
954
                         [(dirinfo, [line[0:3] for line in block])
 
955
                          for dirinfo, block in result])
838
956
 
839
957
    def test_walkdirs(self):
840
958
        tree = [
873
991
            result.append((dirdetail, dirblock))
874
992
 
875
993
        self.assertTrue(found_bzrdir)
876
 
        self.assertEqual(expected_dirblocks,
877
 
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
 
994
        self.assertExpectedBlocks(expected_dirblocks, result)
878
995
        # you can search a subdir only, with a supplied prefix.
879
996
        result = []
880
997
        for dirblock in osutils.walkdirs('./1dir', '1dir'):
881
998
            result.append(dirblock)
882
 
        self.assertEqual(expected_dirblocks[1:],
883
 
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
 
999
        self.assertExpectedBlocks(expected_dirblocks[1:], result)
 
1000
 
 
1001
    def test_walkdirs_os_error(self):
 
1002
        # <https://bugs.edge.launchpad.net/bzr/+bug/338653>
 
1003
        # Pyrex readdir didn't raise useful messages if it had an error
 
1004
        # reading the directory
 
1005
        if sys.platform == 'win32':
 
1006
            raise tests.TestNotApplicable(
 
1007
                "readdir IOError not tested on win32")
 
1008
        os.mkdir("test-unreadable")
 
1009
        os.chmod("test-unreadable", 0000)
 
1010
        # must chmod it back so that it can be removed
 
1011
        self.addCleanup(os.chmod, "test-unreadable", 0700)
 
1012
        # The error is not raised until the generator is actually evaluated.
 
1013
        # (It would be ok if it happened earlier but at the moment it
 
1014
        # doesn't.)
 
1015
        e = self.assertRaises(OSError, list, osutils._walkdirs_utf8("."))
 
1016
        self.assertEquals('./test-unreadable', e.filename)
 
1017
        self.assertEquals(errno.EACCES, e.errno)
 
1018
        # Ensure the message contains the file name
 
1019
        self.assertContainsRe(str(e), "\./test-unreadable")
884
1020
 
885
1021
    def test__walkdirs_utf8(self):
886
1022
        tree = [
919
1055
            result.append((dirdetail, dirblock))
920
1056
 
921
1057
        self.assertTrue(found_bzrdir)
922
 
        self.assertEqual(expected_dirblocks,
923
 
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
 
1058
        self.assertExpectedBlocks(expected_dirblocks, result)
 
1059
 
924
1060
        # you can search a subdir only, with a supplied prefix.
925
1061
        result = []
926
1062
        for dirblock in osutils.walkdirs('./1dir', '1dir'):
927
1063
            result.append(dirblock)
928
 
        self.assertEqual(expected_dirblocks[1:],
929
 
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
 
1064
        self.assertExpectedBlocks(expected_dirblocks[1:], result)
930
1065
 
931
1066
    def _filter_out_stat(self, result):
932
1067
        """Filter out the stat value from the walkdirs result"""
947
1082
            osutils._selected_dir_reader = cur_dir_reader
948
1083
        self.addCleanup(restore)
949
1084
 
950
 
    def assertReadFSDirIs(self, expected):
 
1085
    def assertDirReaderIs(self, expected):
951
1086
        """Assert the right implementation for _walkdirs_utf8 is chosen."""
952
1087
        # Force it to redetect
953
1088
        osutils._selected_dir_reader = None
960
1095
        self._save_platform_info()
961
1096
        win32utils.winver = None # Avoid the win32 detection code
962
1097
        osutils._fs_enc = 'UTF-8'
963
 
        self.assertReadFSDirIs(UTF8DirReaderFeature.reader)
 
1098
        self.assertDirReaderIs(UTF8DirReaderFeature.reader)
964
1099
 
965
1100
    def test_force_walkdirs_utf8_fs_ascii(self):
966
1101
        self.requireFeature(UTF8DirReaderFeature)
967
1102
        self._save_platform_info()
968
1103
        win32utils.winver = None # Avoid the win32 detection code
969
1104
        osutils._fs_enc = 'US-ASCII'
970
 
        self.assertReadFSDirIs(UTF8DirReaderFeature.reader)
 
1105
        self.assertDirReaderIs(UTF8DirReaderFeature.reader)
971
1106
 
972
1107
    def test_force_walkdirs_utf8_fs_ANSI(self):
973
1108
        self.requireFeature(UTF8DirReaderFeature)
974
1109
        self._save_platform_info()
975
1110
        win32utils.winver = None # Avoid the win32 detection code
976
1111
        osutils._fs_enc = 'ANSI_X3.4-1968'
977
 
        self.assertReadFSDirIs(UTF8DirReaderFeature.reader)
 
1112
        self.assertDirReaderIs(UTF8DirReaderFeature.reader)
978
1113
 
979
1114
    def test_force_walkdirs_utf8_fs_latin1(self):
980
1115
        self._save_platform_info()
981
1116
        win32utils.winver = None # Avoid the win32 detection code
982
1117
        osutils._fs_enc = 'latin1'
983
 
        self.assertReadFSDirIs(osutils.UnicodeDirReader)
 
1118
        self.assertDirReaderIs(osutils.UnicodeDirReader)
984
1119
 
985
1120
    def test_force_walkdirs_utf8_nt(self):
986
1121
        # Disabled because the thunk of the whole walkdirs api is disabled.
987
 
        self.requireFeature(Win32ReadDirFeature)
 
1122
        self.requireFeature(test__walkdirs_win32.Win32ReadDirFeature)
988
1123
        self._save_platform_info()
989
1124
        win32utils.winver = 'Windows NT'
990
1125
        from bzrlib._walkdirs_win32 import Win32ReadDir
991
 
        self.assertReadFSDirIs(Win32ReadDir)
 
1126
        self.assertDirReaderIs(Win32ReadDir)
992
1127
 
993
1128
    def test_force_walkdirs_utf8_98(self):
994
 
        self.requireFeature(Win32ReadDirFeature)
 
1129
        self.requireFeature(test__walkdirs_win32.Win32ReadDirFeature)
995
1130
        self._save_platform_info()
996
1131
        win32utils.winver = 'Windows 98'
997
 
        self.assertReadFSDirIs(osutils.UnicodeDirReader)
 
1132
        self.assertDirReaderIs(osutils.UnicodeDirReader)
998
1133
 
999
1134
    def test_unicode_walkdirs(self):
1000
1135
        """Walkdirs should always return unicode paths."""
 
1136
        self.requireFeature(tests.UnicodeFilenameFeature)
1001
1137
        name0 = u'0file-\xb6'
1002
1138
        name1 = u'1dir-\u062c\u0648'
1003
1139
        name2 = u'2file-\u0633'
1008
1144
            name1 + '/' + name1 + '/',
1009
1145
            name2,
1010
1146
            ]
1011
 
        try:
1012
 
            self.build_tree(tree)
1013
 
        except UnicodeError:
1014
 
            raise TestSkipped('Could not represent Unicode chars'
1015
 
                              ' in current encoding.')
 
1147
        self.build_tree(tree)
1016
1148
        expected_dirblocks = [
1017
1149
                ((u'', u'.'),
1018
1150
                 [(name0, name0, 'file', './' + name0),
1044
1176
 
1045
1177
        The abspath portion might be in unicode or utf-8
1046
1178
        """
 
1179
        self.requireFeature(tests.UnicodeFilenameFeature)
1047
1180
        name0 = u'0file-\xb6'
1048
1181
        name1 = u'1dir-\u062c\u0648'
1049
1182
        name2 = u'2file-\u0633'
1054
1187
            name1 + '/' + name1 + '/',
1055
1188
            name2,
1056
1189
            ]
1057
 
        try:
1058
 
            self.build_tree(tree)
1059
 
        except UnicodeError:
1060
 
            raise TestSkipped('Could not represent Unicode chars'
1061
 
                              ' in current encoding.')
 
1190
        self.build_tree(tree)
1062
1191
        name0 = name0.encode('utf8')
1063
1192
        name1 = name1.encode('utf8')
1064
1193
        name2 = name2.encode('utf8')
1108
1237
 
1109
1238
        The abspath portion should be in unicode
1110
1239
        """
 
1240
        self.requireFeature(tests.UnicodeFilenameFeature)
1111
1241
        # Use the unicode reader. TODO: split into driver-and-driven unit
1112
1242
        # tests.
1113
1243
        self._save_platform_info()
1122
1252
            name1u + '/' + name1u + '/',
1123
1253
            name2u,
1124
1254
            ]
1125
 
        try:
1126
 
            self.build_tree(tree)
1127
 
        except UnicodeError:
1128
 
            raise TestSkipped('Could not represent Unicode chars'
1129
 
                              ' in current encoding.')
 
1255
        self.build_tree(tree)
1130
1256
        name0 = name0u.encode('utf8')
1131
1257
        name1 = name1u.encode('utf8')
1132
1258
        name2 = name2u.encode('utf8')
1157
1283
        self.assertEqual(expected_dirblocks, result)
1158
1284
 
1159
1285
    def test__walkdirs_utf8_win32readdir(self):
1160
 
        self.requireFeature(Win32ReadDirFeature)
 
1286
        self.requireFeature(test__walkdirs_win32.Win32ReadDirFeature)
1161
1287
        self.requireFeature(tests.UnicodeFilenameFeature)
1162
1288
        from bzrlib._walkdirs_win32 import Win32ReadDir
1163
1289
        self._save_platform_info()
1214
1340
 
1215
1341
    def test__walkdirs_utf_win32_find_file_stat_file(self):
1216
1342
        """make sure our Stat values are valid"""
1217
 
        self.requireFeature(Win32ReadDirFeature)
 
1343
        self.requireFeature(test__walkdirs_win32.Win32ReadDirFeature)
1218
1344
        self.requireFeature(tests.UnicodeFilenameFeature)
1219
1345
        from bzrlib._walkdirs_win32 import Win32ReadDir
1220
1346
        name0u = u'0file-\xb6'
1238
1364
 
1239
1365
    def test__walkdirs_utf_win32_find_file_stat_directory(self):
1240
1366
        """make sure our Stat values are valid"""
1241
 
        self.requireFeature(Win32ReadDirFeature)
 
1367
        self.requireFeature(test__walkdirs_win32.Win32ReadDirFeature)
1242
1368
        self.requireFeature(tests.UnicodeFilenameFeature)
1243
1369
        from bzrlib._walkdirs_win32 import Win32ReadDir
1244
1370
        name0u = u'0dir-\u062c\u0648'
1329
1455
            sorted(original_paths, cmp=osutils.compare_paths_prefix_order))
1330
1456
 
1331
1457
 
1332
 
class TestCopyTree(TestCaseInTempDir):
 
1458
class TestCopyTree(tests.TestCaseInTempDir):
1333
1459
 
1334
1460
    def test_copy_basic_tree(self):
1335
1461
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
1345
1471
        self.assertEqual(['c'], os.listdir('target/b'))
1346
1472
 
1347
1473
    def test_copy_tree_symlinks(self):
1348
 
        self.requireFeature(SymlinkFeature)
 
1474
        self.requireFeature(tests.SymlinkFeature)
1349
1475
        self.build_tree(['source/'])
1350
1476
        os.symlink('a/generic/path', 'source/lnk')
1351
1477
        osutils.copy_tree('source', 'target')
1381
1507
            self.assertEqual([('source/lnk', 'target/lnk')], processed_links)
1382
1508
 
1383
1509
 
1384
 
#class TestTerminalEncoding has been moved to test_osutils_encodings.py
1385
 
# [bialix] 2006/12/26
1386
 
 
1387
 
 
1388
 
class TestSetUnsetEnv(TestCase):
 
1510
class TestSetUnsetEnv(tests.TestCase):
1389
1511
    """Test updating the environment"""
1390
1512
 
1391
1513
    def setUp(self):
1418
1540
 
1419
1541
        So Unicode strings must be encoded.
1420
1542
        """
1421
 
        uni_val, env_val = probe_unicode_in_user_encoding()
 
1543
        uni_val, env_val = tests.probe_unicode_in_user_encoding()
1422
1544
        if uni_val is None:
1423
 
            raise TestSkipped('Cannot find a unicode character that works in'
1424
 
                              ' encoding %s' % (osutils.get_user_encoding(),))
 
1545
            raise tests.TestSkipped(
 
1546
                'Cannot find a unicode character that works in encoding %s'
 
1547
                % (osutils.get_user_encoding(),))
1425
1548
 
1426
1549
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', uni_val)
1427
1550
        self.assertEqual(env_val, os.environ.get('BZR_TEST_ENV_VAR'))
1435
1558
        self.failIf('BZR_TEST_ENV_VAR' in os.environ)
1436
1559
 
1437
1560
 
1438
 
class TestLocalTimeOffset(TestCase):
1439
 
 
1440
 
    def test_local_time_offset(self):
1441
 
        """Test that local_time_offset() returns a sane value."""
1442
 
        offset = osutils.local_time_offset()
1443
 
        self.assertTrue(isinstance(offset, int))
1444
 
        # Test that the offset is no more than a eighteen hours in
1445
 
        # either direction.
1446
 
        # Time zone handling is system specific, so it is difficult to
1447
 
        # do more specific tests, but a value outside of this range is
1448
 
        # probably wrong.
1449
 
        eighteen_hours = 18 * 3600
1450
 
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)
1451
 
 
1452
 
    def test_local_time_offset_with_timestamp(self):
1453
 
        """Test that local_time_offset() works with a timestamp."""
1454
 
        offset = osutils.local_time_offset(1000000000.1234567)
1455
 
        self.assertTrue(isinstance(offset, int))
1456
 
        eighteen_hours = 18 * 3600
1457
 
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)
1458
 
 
1459
 
 
1460
 
class TestShaFileByName(TestCaseInTempDir):
1461
 
 
1462
 
    def test_sha_empty(self):
1463
 
        self.build_tree_contents([('foo', '')])
1464
 
        expected_sha = osutils.sha_string('')
1465
 
        self.assertEqual(expected_sha, osutils.sha_file_by_name('foo'))
1466
 
 
1467
 
    def test_sha_mixed_endings(self):
1468
 
        text = 'test\r\nwith\nall\rpossible line endings\r\n'
1469
 
        self.build_tree_contents([('foo', text)])
1470
 
        expected_sha = osutils.sha_string(text)
1471
 
        self.assertEqual(expected_sha, osutils.sha_file_by_name('foo'))
1472
 
 
1473
 
 
1474
 
class TestResourceLoading(TestCaseInTempDir):
 
1561
class TestSizeShaFile(tests.TestCaseInTempDir):
 
1562
 
 
1563
    def test_sha_empty(self):
 
1564
        self.build_tree_contents([('foo', '')])
 
1565
        expected_sha = osutils.sha_string('')
 
1566
        f = open('foo')
 
1567
        self.addCleanup(f.close)
 
1568
        size, sha = osutils.size_sha_file(f)
 
1569
        self.assertEqual(0, size)
 
1570
        self.assertEqual(expected_sha, sha)
 
1571
 
 
1572
    def test_sha_mixed_endings(self):
 
1573
        text = 'test\r\nwith\nall\rpossible line endings\r\n'
 
1574
        self.build_tree_contents([('foo', text)])
 
1575
        expected_sha = osutils.sha_string(text)
 
1576
        f = open('foo')
 
1577
        self.addCleanup(f.close)
 
1578
        size, sha = osutils.size_sha_file(f)
 
1579
        self.assertEqual(38, size)
 
1580
        self.assertEqual(expected_sha, sha)
 
1581
 
 
1582
 
 
1583
class TestShaFileByName(tests.TestCaseInTempDir):
 
1584
 
 
1585
    def test_sha_empty(self):
 
1586
        self.build_tree_contents([('foo', '')])
 
1587
        expected_sha = osutils.sha_string('')
 
1588
        self.assertEqual(expected_sha, osutils.sha_file_by_name('foo'))
 
1589
 
 
1590
    def test_sha_mixed_endings(self):
 
1591
        text = 'test\r\nwith\nall\rpossible line endings\r\n'
 
1592
        self.build_tree_contents([('foo', text)])
 
1593
        expected_sha = osutils.sha_string(text)
 
1594
        self.assertEqual(expected_sha, osutils.sha_file_by_name('foo'))
 
1595
 
 
1596
 
 
1597
class TestResourceLoading(tests.TestCaseInTempDir):
1475
1598
 
1476
1599
    def test_resource_string(self):
1477
1600
        # test resource in bzrlib
1485
1608
            'yyy.xx')
1486
1609
        # test unknown resource
1487
1610
        self.assertRaises(IOError, osutils.resource_string, 'bzrlib', 'yyy.xx')
 
1611
 
 
1612
 
 
1613
class TestReCompile(tests.TestCase):
 
1614
 
 
1615
    def test_re_compile_checked(self):
 
1616
        r = osutils.re_compile_checked(r'A*', re.IGNORECASE)
 
1617
        self.assertTrue(r.match('aaaa'))
 
1618
        self.assertTrue(r.match('aAaA'))
 
1619
 
 
1620
    def test_re_compile_checked_error(self):
 
1621
        # like https://bugs.launchpad.net/bzr/+bug/251352
 
1622
        err = self.assertRaises(
 
1623
            errors.BzrCommandError,
 
1624
            osutils.re_compile_checked, '*', re.IGNORECASE, 'test case')
 
1625
        self.assertEqual(
 
1626
            "Invalid regular expression in test case: '*': "
 
1627
            "nothing to repeat",
 
1628
            str(err))
 
1629
 
 
1630
 
 
1631
class TestDirReader(tests.TestCaseInTempDir):
 
1632
 
 
1633
    # Set by load_tests
 
1634
    _dir_reader_class = None
 
1635
    _native_to_unicode = None
 
1636
 
 
1637
    def setUp(self):
 
1638
        tests.TestCaseInTempDir.setUp(self)
 
1639
 
 
1640
        # Save platform specific info and reset it
 
1641
        cur_dir_reader = osutils._selected_dir_reader
 
1642
 
 
1643
        def restore():
 
1644
            osutils._selected_dir_reader = cur_dir_reader
 
1645
        self.addCleanup(restore)
 
1646
 
 
1647
        osutils._selected_dir_reader = self._dir_reader_class()
 
1648
 
 
1649
    def _get_ascii_tree(self):
 
1650
        tree = [
 
1651
            '0file',
 
1652
            '1dir/',
 
1653
            '1dir/0file',
 
1654
            '1dir/1dir/',
 
1655
            '2file'
 
1656
            ]
 
1657
        expected_dirblocks = [
 
1658
                (('', '.'),
 
1659
                 [('0file', '0file', 'file'),
 
1660
                  ('1dir', '1dir', 'directory'),
 
1661
                  ('2file', '2file', 'file'),
 
1662
                 ]
 
1663
                ),
 
1664
                (('1dir', './1dir'),
 
1665
                 [('1dir/0file', '0file', 'file'),
 
1666
                  ('1dir/1dir', '1dir', 'directory'),
 
1667
                 ]
 
1668
                ),
 
1669
                (('1dir/1dir', './1dir/1dir'),
 
1670
                 [
 
1671
                 ]
 
1672
                ),
 
1673
            ]
 
1674
        return tree, expected_dirblocks
 
1675
 
 
1676
    def test_walk_cur_dir(self):
 
1677
        tree, expected_dirblocks = self._get_ascii_tree()
 
1678
        self.build_tree(tree)
 
1679
        result = list(osutils._walkdirs_utf8('.'))
 
1680
        # Filter out stat and abspath
 
1681
        self.assertEqual(expected_dirblocks,
 
1682
                         [(dirinfo, [line[0:3] for line in block])
 
1683
                          for dirinfo, block in result])
 
1684
 
 
1685
    def test_walk_sub_dir(self):
 
1686
        tree, expected_dirblocks = self._get_ascii_tree()
 
1687
        self.build_tree(tree)
 
1688
        # you can search a subdir only, with a supplied prefix.
 
1689
        result = list(osutils._walkdirs_utf8('./1dir', '1dir'))
 
1690
        # Filter out stat and abspath
 
1691
        self.assertEqual(expected_dirblocks[1:],
 
1692
                         [(dirinfo, [line[0:3] for line in block])
 
1693
                          for dirinfo, block in result])
 
1694
 
 
1695
    def _get_unicode_tree(self):
 
1696
        name0u = u'0file-\xb6'
 
1697
        name1u = u'1dir-\u062c\u0648'
 
1698
        name2u = u'2file-\u0633'
 
1699
        tree = [
 
1700
            name0u,
 
1701
            name1u + '/',
 
1702
            name1u + '/' + name0u,
 
1703
            name1u + '/' + name1u + '/',
 
1704
            name2u,
 
1705
            ]
 
1706
        name0 = name0u.encode('UTF-8')
 
1707
        name1 = name1u.encode('UTF-8')
 
1708
        name2 = name2u.encode('UTF-8')
 
1709
        expected_dirblocks = [
 
1710
                (('', '.'),
 
1711
                 [(name0, name0, 'file', './' + name0u),
 
1712
                  (name1, name1, 'directory', './' + name1u),
 
1713
                  (name2, name2, 'file', './' + name2u),
 
1714
                 ]
 
1715
                ),
 
1716
                ((name1, './' + name1u),
 
1717
                 [(name1 + '/' + name0, name0, 'file', './' + name1u
 
1718
                                                        + '/' + name0u),
 
1719
                  (name1 + '/' + name1, name1, 'directory', './' + name1u
 
1720
                                                            + '/' + name1u),
 
1721
                 ]
 
1722
                ),
 
1723
                ((name1 + '/' + name1, './' + name1u + '/' + name1u),
 
1724
                 [
 
1725
                 ]
 
1726
                ),
 
1727
            ]
 
1728
        return tree, expected_dirblocks
 
1729
 
 
1730
    def _filter_out(self, raw_dirblocks):
 
1731
        """Filter out a walkdirs_utf8 result.
 
1732
 
 
1733
        stat field is removed, all native paths are converted to unicode
 
1734
        """
 
1735
        filtered_dirblocks = []
 
1736
        for dirinfo, block in raw_dirblocks:
 
1737
            dirinfo = (dirinfo[0], self._native_to_unicode(dirinfo[1]))
 
1738
            details = []
 
1739
            for line in block:
 
1740
                details.append(line[0:3] + (self._native_to_unicode(line[4]), ))
 
1741
            filtered_dirblocks.append((dirinfo, details))
 
1742
        return filtered_dirblocks
 
1743
 
 
1744
    def test_walk_unicode_tree(self):
 
1745
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1746
        tree, expected_dirblocks = self._get_unicode_tree()
 
1747
        self.build_tree(tree)
 
1748
        result = list(osutils._walkdirs_utf8('.'))
 
1749
        self.assertEqual(expected_dirblocks, self._filter_out(result))
 
1750
 
 
1751
    def test_symlink(self):
 
1752
        self.requireFeature(tests.SymlinkFeature)
 
1753
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1754
        target = u'target\N{Euro Sign}'
 
1755
        link_name = u'l\N{Euro Sign}nk'
 
1756
        os.symlink(target, link_name)
 
1757
        target_utf8 = target.encode('UTF-8')
 
1758
        link_name_utf8 = link_name.encode('UTF-8')
 
1759
        expected_dirblocks = [
 
1760
                (('', '.'),
 
1761
                 [(link_name_utf8, link_name_utf8,
 
1762
                   'symlink', './' + link_name),],
 
1763
                 )]
 
1764
        result = list(osutils._walkdirs_utf8('.'))
 
1765
        self.assertEqual(expected_dirblocks, self._filter_out(result))
 
1766
 
 
1767
 
 
1768
class TestReadLink(tests.TestCaseInTempDir):
 
1769
    """Exposes os.readlink() problems and the osutils solution.
 
1770
 
 
1771
    The only guarantee offered by os.readlink(), starting with 2.6, is that a
 
1772
    unicode string will be returned if a unicode string is passed.
 
1773
 
 
1774
    But prior python versions failed to properly encode the passed unicode
 
1775
    string.
 
1776
    """
 
1777
    _test_needs_features = [tests.SymlinkFeature, tests.UnicodeFilenameFeature]
 
1778
 
 
1779
    def setUp(self):
 
1780
        super(tests.TestCaseInTempDir, self).setUp()
 
1781
        self.link = u'l\N{Euro Sign}ink'
 
1782
        self.target = u'targe\N{Euro Sign}t'
 
1783
        os.symlink(self.target, self.link)
 
1784
 
 
1785
    def test_os_readlink_link_encoding(self):
 
1786
        if sys.version_info < (2, 6):
 
1787
            self.assertRaises(UnicodeEncodeError, os.readlink, self.link)
 
1788
        else:
 
1789
            self.assertEquals(self.target,  os.readlink(self.link))
 
1790
 
 
1791
    def test_os_readlink_link_decoding(self):
 
1792
        self.assertEquals(self.target.encode(osutils._fs_enc),
 
1793
                          os.readlink(self.link.encode(osutils._fs_enc)))
 
1794
 
 
1795
 
 
1796
class TestConcurrency(tests.TestCase):
 
1797
 
 
1798
    def test_local_concurrency(self):
 
1799
        concurrency = osutils.local_concurrency()
 
1800
        self.assertIsInstance(concurrency, int)