~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_osutils.py

  • Committer: Alexander Belchenko
  • Date: 2006-07-30 16:43:12 UTC
  • mto: (1711.2.111 jam-integration)
  • mto: This revision was merged to the branch mainline in revision 1906.
  • Revision ID: bialix@ukr.net-20060730164312-b025fd3ff0cee59e
rename  gpl.txt => COPYING.txt

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005 by Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
23
23
import sys
24
24
 
25
25
import bzrlib
26
 
from bzrlib import (
27
 
    errors,
28
 
    osutils,
29
 
    win32utils,
30
 
    )
31
26
from bzrlib.errors import BzrBadParameterNotUnicode, InvalidURL
 
27
import bzrlib.osutils as osutils
32
28
from bzrlib.tests import (
33
29
        StringIOWrapper,
34
30
        TestCase, 
39
35
 
40
36
class TestOSUtils(TestCaseInTempDir):
41
37
 
42
 
    def test_contains_whitespace(self):
43
 
        self.failUnless(osutils.contains_whitespace(u' '))
44
 
        self.failUnless(osutils.contains_whitespace(u'hello there'))
45
 
        self.failUnless(osutils.contains_whitespace(u'hellothere\n'))
46
 
        self.failUnless(osutils.contains_whitespace(u'hello\nthere'))
47
 
        self.failUnless(osutils.contains_whitespace(u'hello\rthere'))
48
 
        self.failUnless(osutils.contains_whitespace(u'hello\tthere'))
49
 
 
50
 
        # \xa0 is "Non-breaking-space" which on some python locales thinks it
51
 
        # is whitespace, but we do not.
52
 
        self.failIf(osutils.contains_whitespace(u''))
53
 
        self.failIf(osutils.contains_whitespace(u'hellothere'))
54
 
        self.failIf(osutils.contains_whitespace(u'hello\xa0there'))
55
 
 
56
38
    def test_fancy_rename(self):
57
39
        # This should work everywhere
58
40
        def rename(a, b):
96
78
        self.assertEqual(type(result), str)
97
79
        self.assertContainsRe(result, r'^[a-z0-9]{100}$')
98
80
 
99
 
    def test_is_inside(self):
100
 
        is_inside = osutils.is_inside
101
 
        self.assertTrue(is_inside('src', 'src/foo.c'))
102
 
        self.assertFalse(is_inside('src', 'srccontrol'))
103
 
        self.assertTrue(is_inside('src', 'src/a/a/a/foo.c'))
104
 
        self.assertTrue(is_inside('foo.c', 'foo.c'))
105
 
        self.assertFalse(is_inside('foo.c', ''))
106
 
        self.assertTrue(is_inside('', 'foo.c'))
107
81
 
108
82
    def test_rmtree(self):
109
83
        # Check to remove tree with read-only files/dirs
157
131
            finally:
158
132
                os.remove('socket')
159
133
 
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
 
 
166
 
    def test_get_umask(self):
167
 
        if sys.platform == 'win32':
168
 
            # umask always returns '0', no way to set it
169
 
            self.assertEqual(0, osutils.get_umask())
170
 
            return
171
 
 
172
 
        orig_umask = osutils.get_umask()
173
 
        try:
174
 
            os.umask(0222)
175
 
            self.assertEqual(0222, osutils.get_umask())
176
 
            os.umask(0022)
177
 
            self.assertEqual(0022, osutils.get_umask())
178
 
            os.umask(0002)
179
 
            self.assertEqual(0002, osutils.get_umask())
180
 
            os.umask(0027)
181
 
            self.assertEqual(0027, osutils.get_umask())
182
 
        finally:
183
 
            os.umask(orig_umask)
184
 
 
185
 
    def assertFormatedDelta(self, expected, seconds):
186
 
        """Assert osutils.format_delta formats as expected"""
187
 
        actual = osutils.format_delta(seconds)
188
 
        self.assertEqual(expected, actual)
189
 
 
190
 
    def test_format_delta(self):
191
 
        self.assertFormatedDelta('0 seconds ago', 0)
192
 
        self.assertFormatedDelta('1 second ago', 1)
193
 
        self.assertFormatedDelta('10 seconds ago', 10)
194
 
        self.assertFormatedDelta('59 seconds ago', 59)
195
 
        self.assertFormatedDelta('89 seconds ago', 89)
196
 
        self.assertFormatedDelta('1 minute, 30 seconds ago', 90)
197
 
        self.assertFormatedDelta('3 minutes, 0 seconds ago', 180)
198
 
        self.assertFormatedDelta('3 minutes, 1 second ago', 181)
199
 
        self.assertFormatedDelta('10 minutes, 15 seconds ago', 615)
200
 
        self.assertFormatedDelta('30 minutes, 59 seconds ago', 1859)
201
 
        self.assertFormatedDelta('31 minutes, 0 seconds ago', 1860)
202
 
        self.assertFormatedDelta('60 minutes, 0 seconds ago', 3600)
203
 
        self.assertFormatedDelta('89 minutes, 59 seconds ago', 5399)
204
 
        self.assertFormatedDelta('1 hour, 30 minutes ago', 5400)
205
 
        self.assertFormatedDelta('2 hours, 30 minutes ago', 9017)
206
 
        self.assertFormatedDelta('10 hours, 0 minutes ago', 36000)
207
 
        self.assertFormatedDelta('24 hours, 0 minutes ago', 86400)
208
 
        self.assertFormatedDelta('35 hours, 59 minutes ago', 129599)
209
 
        self.assertFormatedDelta('36 hours, 0 minutes ago', 129600)
210
 
        self.assertFormatedDelta('36 hours, 0 minutes ago', 129601)
211
 
        self.assertFormatedDelta('36 hours, 1 minute ago', 129660)
212
 
        self.assertFormatedDelta('36 hours, 1 minute ago', 129661)
213
 
        self.assertFormatedDelta('84 hours, 10 minutes ago', 303002)
214
 
 
215
 
        # We handle when time steps the wrong direction because computers
216
 
        # don't have synchronized clocks.
217
 
        self.assertFormatedDelta('84 hours, 10 minutes in the future', -303002)
218
 
        self.assertFormatedDelta('1 second in the future', -1)
219
 
        self.assertFormatedDelta('2 seconds in the future', -2)
220
 
 
221
 
    def test_dereference_path(self):
222
 
        if not osutils.has_symlinks():
223
 
            raise TestSkipped('Symlinks are not supported on this platform')
224
 
        cwd = osutils.realpath('.')
225
 
        os.mkdir('bar')
226
 
        bar_path = osutils.pathjoin(cwd, 'bar')
227
 
        # Using './' to avoid bug #1213894 (first path component not
228
 
        # dereferenced) in Python 2.4.1 and earlier
229
 
        self.assertEqual(bar_path, osutils.realpath('./bar'))
230
 
        os.symlink('bar', 'foo')
231
 
        self.assertEqual(bar_path, osutils.realpath('./foo'))
232
 
        
233
 
        # Does not dereference terminal symlinks
234
 
        foo_path = osutils.pathjoin(cwd, 'foo')
235
 
        self.assertEqual(foo_path, osutils.dereference_path('./foo'))
236
 
 
237
 
        # Dereferences parent symlinks
238
 
        os.mkdir('bar/baz')
239
 
        baz_path = osutils.pathjoin(bar_path, 'baz')
240
 
        self.assertEqual(baz_path, osutils.dereference_path('./foo/baz'))
241
 
 
242
 
        # Dereferences parent symlinks that are the first path element
243
 
        self.assertEqual(baz_path, osutils.dereference_path('foo/baz'))
244
 
 
245
 
        # Dereferences parent symlinks in absolute paths
246
 
        foo_baz_path = osutils.pathjoin(foo_path, 'baz')
247
 
        self.assertEqual(baz_path, osutils.dereference_path(foo_baz_path))
248
 
 
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
134
 
257
135
class TestSafeUnicode(TestCase):
258
136
 
274
152
                          '\xbb\xbb')
275
153
 
276
154
 
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
 
 
350
155
class TestWin32Funcs(TestCase):
351
156
    """Test that the _win32 versions of os utilities return appropriate paths."""
352
157
 
353
158
    def test_abspath(self):
354
159
        self.assertEqual('C:/foo', osutils._win32_abspath('C:\\foo'))
355
160
        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'))
358
161
 
359
162
    def test_realpath(self):
360
163
        self.assertEqual('C:/foo', osutils._win32_realpath('C:\\foo'))
388
191
        self.assertEqual('H:/foo', osutils._win32_fixdrive('H:/foo'))
389
192
        self.assertEqual('C:\\foo', osutils._win32_fixdrive('c:\\foo'))
390
193
 
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
 
 
407
194
 
408
195
class TestWin32FuncsDirs(TestCaseInTempDir):
409
196
    """Test win32 functions that create files."""
410
197
    
411
198
    def test_getcwd(self):
412
 
        if win32utils.winver == 'Windows 98':
413
 
            raise TestSkipped('Windows 98 cannot handle unicode filenames')
414
199
        # Make sure getcwd can handle unicode filenames
415
200
        try:
416
201
            os.mkdir(u'mu-\xb5')
471
256
        except (IOError, OSError), e:
472
257
            self.assertEqual(errno.ENOENT, e.errno)
473
258
 
474
 
    def test_splitpath(self):
475
 
        def check(expected, path):
476
 
            self.assertEqual(expected, osutils.splitpath(path))
477
 
 
478
 
        check(['a'], 'a')
479
 
        check(['a', 'b'], 'a/b')
480
 
        check(['a', 'b'], 'a/./b')
481
 
        check(['a', '.b'], 'a/.b')
482
 
        check(['a', '.b'], 'a\\.b')
483
 
 
484
 
        self.assertRaises(errors.BzrError, osutils.splitpath, 'a/../b')
485
 
 
486
259
 
487
260
class TestMacFuncsDirs(TestCaseInTempDir):
488
261
    """Test mac special functions that require directories."""
508
281
        os.chdir(u'Ba\u030agfors')
509
282
        self.assertEndsWith(osutils._mac_getcwd(), u'B\xe5gfors')
510
283
 
511
 
 
512
284
class TestSplitLines(TestCase):
513
285
 
514
286
    def test_split_unicode(self):
535
307
            ]
536
308
        self.build_tree(tree)
537
309
        expected_dirblocks = [
538
 
                (('', '.'),
539
 
                 [('0file', '0file', 'file'),
540
 
                  ('1dir', '1dir', 'directory'),
541
 
                  ('2file', '2file', 'file'),
542
 
                 ]
543
 
                ),
544
 
                (('1dir', './1dir'),
545
 
                 [('1dir/0file', '0file', 'file'),
546
 
                  ('1dir/1dir', '1dir', 'directory'),
547
 
                 ]
548
 
                ),
549
 
                (('1dir/1dir', './1dir/1dir'),
550
 
                 [
551
 
                 ]
552
 
                ),
553
 
            ]
554
 
        result = []
555
 
        found_bzrdir = False
556
 
        for dirdetail, dirblock in osutils.walkdirs('.'):
557
 
            if len(dirblock) and dirblock[0][1] == '.bzr':
558
 
                # this tests the filtering of selected paths
559
 
                found_bzrdir = True
560
 
                del dirblock[0]
561
 
            result.append((dirdetail, dirblock))
562
 
 
563
 
        self.assertTrue(found_bzrdir)
564
 
        self.assertEqual(expected_dirblocks,
565
 
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
566
 
        # you can search a subdir only, with a supplied prefix.
567
 
        result = []
568
 
        for dirblock in osutils.walkdirs('./1dir', '1dir'):
569
 
            result.append(dirblock)
570
 
        self.assertEqual(expected_dirblocks[1:],
571
 
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
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)
 
310
                [
 
311
                    ('0file', '0file', 'file'),
 
312
                    ('1dir', '1dir', 'directory'),
 
313
                    ('2file', '2file', 'file'),
 
314
                ],
 
315
                [
 
316
                    ('1dir/0file', '0file', 'file'),
 
317
                    ('1dir/1dir', '1dir', 'directory'),
 
318
                ],
 
319
                [
 
320
                ],
 
321
            ]
 
322
        result = []
 
323
        found_bzrdir = False
 
324
        for dirblock in osutils.walkdirs('.'):
 
325
            if len(dirblock) and dirblock[0][1] == '.bzr':
 
326
                # this tests the filtering of selected paths
 
327
                found_bzrdir = True
 
328
                del dirblock[0]
 
329
            result.append(dirblock)
 
330
 
 
331
        self.assertTrue(found_bzrdir)
 
332
        self.assertEqual(expected_dirblocks,
 
333
            [[line[0:3] for line in block] for block in result])
 
334
        # you can search a subdir only, with a supplied prefix.
 
335
        result = []
 
336
        for dirblock in osutils.walkdirs('1dir', '1dir'):
 
337
            result.append(dirblock)
 
338
        self.assertEqual(expected_dirblocks[1:],
 
339
            [[line[0:3] for line in block] for block in result])
783
340
 
784
341
    def assertPathCompare(self, path_less, path_greater):
785
342
        """check that path_less and path_greater compare correctly."""
859
416
            sorted(original_paths, cmp=osutils.compare_paths_prefix_order))
860
417
 
861
418
 
862
 
class TestCopyTree(TestCaseInTempDir):
863
 
    
864
 
    def test_copy_basic_tree(self):
865
 
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
866
 
        osutils.copy_tree('source', 'target')
867
 
        self.assertEqual(['a', 'b'], sorted(os.listdir('target')))
868
 
        self.assertEqual(['c'], os.listdir('target/b'))
869
 
 
870
 
    def test_copy_tree_target_exists(self):
871
 
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c',
872
 
                         'target/'])
873
 
        osutils.copy_tree('source', 'target')
874
 
        self.assertEqual(['a', 'b'], sorted(os.listdir('target')))
875
 
        self.assertEqual(['c'], os.listdir('target/b'))
876
 
 
877
 
    def test_copy_tree_symlinks(self):
878
 
        if not osutils.has_symlinks():
879
 
            return
880
 
        self.build_tree(['source/'])
881
 
        os.symlink('a/generic/path', 'source/lnk')
882
 
        osutils.copy_tree('source', 'target')
883
 
        self.assertEqual(['lnk'], os.listdir('target'))
884
 
        self.assertEqual('a/generic/path', os.readlink('target/lnk'))
885
 
 
886
 
    def test_copy_tree_handlers(self):
887
 
        processed_files = []
888
 
        processed_links = []
889
 
        def file_handler(from_path, to_path):
890
 
            processed_files.append(('f', from_path, to_path))
891
 
        def dir_handler(from_path, to_path):
892
 
            processed_files.append(('d', from_path, to_path))
893
 
        def link_handler(from_path, to_path):
894
 
            processed_links.append((from_path, to_path))
895
 
        handlers = {'file':file_handler,
896
 
                    'directory':dir_handler,
897
 
                    'symlink':link_handler,
898
 
                   }
899
 
 
900
 
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
901
 
        if osutils.has_symlinks():
902
 
            os.symlink('a/generic/path', 'source/lnk')
903
 
        osutils.copy_tree('source', 'target', handlers=handlers)
904
 
 
905
 
        self.assertEqual([('d', 'source', 'target'),
906
 
                          ('f', 'source/a', 'target/a'),
907
 
                          ('d', 'source/b', 'target/b'),
908
 
                          ('f', 'source/b/c', 'target/b/c'),
909
 
                         ], processed_files)
910
 
        self.failIfExists('target')
911
 
        if osutils.has_symlinks():
912
 
            self.assertEqual([('source/lnk', 'target/lnk')], processed_links)
913
 
 
914
 
 
915
 
#class TestTerminalEncoding has been moved to test_osutils_encodings.py
916
 
# [bialix] 2006/12/26
917
 
 
918
 
 
919
 
class TestSetUnsetEnv(TestCase):
920
 
    """Test updating the environment"""
 
419
class TestTerminalEncoding(TestCase):
 
420
    """Test the auto-detection of proper terminal encoding."""
921
421
 
922
422
    def setUp(self):
923
 
        super(TestSetUnsetEnv, self).setUp()
924
 
 
925
 
        self.assertEqual(None, os.environ.get('BZR_TEST_ENV_VAR'),
926
 
                         'Environment was not cleaned up properly.'
927
 
                         ' Variable BZR_TEST_ENV_VAR should not exist.')
928
 
        def cleanup():
929
 
            if 'BZR_TEST_ENV_VAR' in os.environ:
930
 
                del os.environ['BZR_TEST_ENV_VAR']
931
 
 
932
 
        self.addCleanup(cleanup)
933
 
 
934
 
    def test_set(self):
935
 
        """Test that we can set an env variable"""
936
 
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'foo')
937
 
        self.assertEqual(None, old)
938
 
        self.assertEqual('foo', os.environ.get('BZR_TEST_ENV_VAR'))
939
 
 
940
 
    def test_double_set(self):
941
 
        """Test that we get the old value out"""
942
 
        osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'foo')
943
 
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'bar')
944
 
        self.assertEqual('foo', old)
945
 
        self.assertEqual('bar', os.environ.get('BZR_TEST_ENV_VAR'))
946
 
 
947
 
    def test_unicode(self):
948
 
        """Environment can only contain plain strings
949
 
        
950
 
        So Unicode strings must be encoded.
951
 
        """
952
 
        # Try a few different characters, to see if we can get
953
 
        # one that will be valid in the user_encoding
954
 
        possible_vals = [u'm\xb5', u'\xe1', u'\u0410']
955
 
        for uni_val in possible_vals:
956
 
            try:
957
 
                env_val = uni_val.encode(bzrlib.user_encoding)
958
 
            except UnicodeEncodeError:
959
 
                # Try a different character
960
 
                pass
961
 
            else:
962
 
                break
963
 
        else:
964
 
            raise TestSkipped('Cannot find a unicode character that works in'
965
 
                              ' encoding %s' % (bzrlib.user_encoding,))
966
 
 
967
 
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', uni_val)
968
 
        self.assertEqual(env_val, os.environ.get('BZR_TEST_ENV_VAR'))
969
 
 
970
 
    def test_unset(self):
971
 
        """Test that passing None will remove the env var"""
972
 
        osutils.set_or_unset_env('BZR_TEST_ENV_VAR', 'foo')
973
 
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', None)
974
 
        self.assertEqual('foo', old)
975
 
        self.assertEqual(None, os.environ.get('BZR_TEST_ENV_VAR'))
976
 
        self.failIf('BZR_TEST_ENV_VAR' in os.environ)
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)
 
423
        self._stdout = sys.stdout
 
424
        self._stderr = sys.stderr
 
425
        self._stdin = sys.stdin
 
426
        self._user_encoding = bzrlib.user_encoding
 
427
 
 
428
        self.addCleanup(self._reset)
 
429
 
 
430
        sys.stdout = StringIOWrapper()
 
431
        sys.stdout.encoding = 'stdout_encoding'
 
432
        sys.stderr = StringIOWrapper()
 
433
        sys.stderr.encoding = 'stderr_encoding'
 
434
        sys.stdin = StringIOWrapper()
 
435
        sys.stdin.encoding = 'stdin_encoding'
 
436
        bzrlib.user_encoding = 'user_encoding'
 
437
 
 
438
    def _reset(self):
 
439
        sys.stdout = self._stdout
 
440
        sys.stderr = self._stderr
 
441
        sys.stdin = self._stdin
 
442
        bzrlib.user_encoding = self._user_encoding
 
443
 
 
444
    def test_get_terminal_encoding(self):
 
445
        # first preference is stdout encoding
 
446
        self.assertEqual('stdout_encoding', osutils.get_terminal_encoding())
 
447
 
 
448
        sys.stdout.encoding = None
 
449
        # if sys.stdout is None, fall back to sys.stdin
 
450
        self.assertEqual('stdin_encoding', osutils.get_terminal_encoding())
 
451
 
 
452
        sys.stdin.encoding = None
 
453
        # and in the worst case, use bzrlib.user_encoding
 
454
        self.assertEqual('user_encoding', osutils.get_terminal_encoding())
 
455