~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: 2010-02-10 17:52:08 UTC
  • mfrom: (5021 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5023.
  • Revision ID: john@arbash-meinel.com-20100210175208-bubuwav4uqigu291
Merge bzr.dev 5021 to resolve NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008, 2009 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
20
20
import errno
21
21
import os
22
22
import re
23
 
import select
24
23
import socket
 
24
import stat
25
25
import sys
26
26
import time
27
27
 
28
28
from bzrlib import (
29
29
    errors,
30
 
    lazy_regex,
31
30
    osutils,
32
 
    symbol_versioning,
33
31
    tests,
34
32
    trace,
35
33
    win32utils,
36
34
    )
37
35
from bzrlib.tests import (
38
 
    features,
39
36
    file_utils,
40
37
    test__walkdirs_win32,
41
38
    )
42
 
from bzrlib.tests.scenarios import load_tests_apply_scenarios
43
 
 
44
 
 
45
 
class _UTF8DirReaderFeature(features.Feature):
 
39
 
 
40
 
 
41
class _UTF8DirReaderFeature(tests.Feature):
46
42
 
47
43
    def _probe(self):
48
44
        try:
55
51
    def feature_name(self):
56
52
        return 'bzrlib._readdir_pyx'
57
53
 
58
 
UTF8DirReaderFeature = features.ModuleAvailableFeature('bzrlib._readdir_pyx')
 
54
UTF8DirReaderFeature = _UTF8DirReaderFeature()
59
55
 
60
 
term_ios_feature = features.ModuleAvailableFeature('termios')
 
56
term_ios_feature = tests.ModuleAvailableFeature('termios')
61
57
 
62
58
 
63
59
def _already_unicode(s):
98
94
    return scenarios
99
95
 
100
96
 
101
 
load_tests = load_tests_apply_scenarios
 
97
def load_tests(basic_tests, module, loader):
 
98
    suite = loader.suiteClass()
 
99
    dir_reader_tests, remaining_tests = tests.split_suite_by_condition(
 
100
        basic_tests, tests.condition_isinstance(TestDirReader))
 
101
    tests.multiply_tests(dir_reader_tests, dir_reader_scenarios(), suite)
 
102
    suite.addTest(remaining_tests)
 
103
    return suite
102
104
 
103
105
 
104
106
class TestContainsWhitespace(tests.TestCase):
105
107
 
106
108
    def test_contains_whitespace(self):
107
 
        self.assertTrue(osutils.contains_whitespace(u' '))
108
 
        self.assertTrue(osutils.contains_whitespace(u'hello there'))
109
 
        self.assertTrue(osutils.contains_whitespace(u'hellothere\n'))
110
 
        self.assertTrue(osutils.contains_whitespace(u'hello\nthere'))
111
 
        self.assertTrue(osutils.contains_whitespace(u'hello\rthere'))
112
 
        self.assertTrue(osutils.contains_whitespace(u'hello\tthere'))
 
109
        self.failUnless(osutils.contains_whitespace(u' '))
 
110
        self.failUnless(osutils.contains_whitespace(u'hello there'))
 
111
        self.failUnless(osutils.contains_whitespace(u'hellothere\n'))
 
112
        self.failUnless(osutils.contains_whitespace(u'hello\nthere'))
 
113
        self.failUnless(osutils.contains_whitespace(u'hello\rthere'))
 
114
        self.failUnless(osutils.contains_whitespace(u'hello\tthere'))
113
115
 
114
116
        # \xa0 is "Non-breaking-space" which on some python locales thinks it
115
117
        # is whitespace, but we do not.
116
 
        self.assertFalse(osutils.contains_whitespace(u''))
117
 
        self.assertFalse(osutils.contains_whitespace(u'hellothere'))
118
 
        self.assertFalse(osutils.contains_whitespace(u'hello\xa0there'))
 
118
        self.failIf(osutils.contains_whitespace(u''))
 
119
        self.failIf(osutils.contains_whitespace(u'hellothere'))
 
120
        self.failIf(osutils.contains_whitespace(u'hello\xa0there'))
119
121
 
120
122
 
121
123
class TestRename(tests.TestCaseInTempDir):
135
137
        # This should work everywhere
136
138
        self.create_file('a', 'something in a\n')
137
139
        self._fancy_rename('a', 'b')
138
 
        self.assertPathDoesNotExist('a')
139
 
        self.assertPathExists('b')
 
140
        self.failIfExists('a')
 
141
        self.failUnlessExists('b')
140
142
        self.check_file_contents('b', 'something in a\n')
141
143
 
142
144
        self.create_file('a', 'new something in a\n')
149
151
        self.create_file('target', 'data in target\n')
150
152
        self.assertRaises((IOError, OSError), self._fancy_rename,
151
153
                          'missingsource', 'target')
152
 
        self.assertPathExists('target')
 
154
        self.failUnlessExists('target')
153
155
        self.check_file_contents('target', 'data in target\n')
154
156
 
155
157
    def test_fancy_rename_fails_if_source_and_target_missing(self):
160
162
        # Rename should be semi-atomic on all platforms
161
163
        self.create_file('a', 'something in a\n')
162
164
        osutils.rename('a', 'b')
163
 
        self.assertPathDoesNotExist('a')
164
 
        self.assertPathExists('b')
 
165
        self.failIfExists('a')
 
166
        self.failUnlessExists('b')
165
167
        self.check_file_contents('b', 'something in a\n')
166
168
 
167
169
        self.create_file('a', 'new something in a\n')
232
234
            self.assertFalse(osutils.is_inside_or_parent_of_any(dirs, fn))
233
235
 
234
236
 
235
 
class TestLstat(tests.TestCaseInTempDir):
236
 
 
237
 
    def test_lstat_matches_fstat(self):
238
 
        # On Windows, lstat and fstat don't always agree, primarily in the
239
 
        # 'st_ino' and 'st_dev' fields. So we force them to be '0' in our
240
 
        # custom implementation.
241
 
        if sys.platform == 'win32':
242
 
            # We only have special lstat/fstat if we have the extension.
243
 
            # Without it, we may end up re-reading content when we don't have
244
 
            # to, but otherwise it doesn't effect correctness.
245
 
            self.requireFeature(test__walkdirs_win32.win32_readdir_feature)
246
 
        f = open('test-file.txt', 'wb')
247
 
        self.addCleanup(f.close)
248
 
        f.write('some content\n')
249
 
        f.flush()
250
 
        self.assertEqualStat(osutils.fstat(f.fileno()),
251
 
                             osutils.lstat('test-file.txt'))
252
 
 
253
 
 
254
237
class TestRmTree(tests.TestCaseInTempDir):
255
238
 
256
239
    def test_rmtree(self):
268
251
 
269
252
        osutils.rmtree('dir')
270
253
 
271
 
        self.assertPathDoesNotExist('dir/file')
272
 
        self.assertPathDoesNotExist('dir')
 
254
        self.failIfExists('dir/file')
 
255
        self.failIfExists('dir')
273
256
 
274
257
 
275
258
class TestDeleteAny(tests.TestCaseInTempDir):
326
309
        self.assertEqual("/", osutils.kind_marker(osutils._directory_kind))
327
310
        self.assertEqual("@", osutils.kind_marker("symlink"))
328
311
        self.assertEqual("+", osutils.kind_marker("tree-reference"))
329
 
        self.assertEqual("", osutils.kind_marker("fifo"))
330
 
        self.assertEqual("", osutils.kind_marker("socket"))
331
 
        self.assertEqual("", osutils.kind_marker("unknown"))
 
312
        self.assertRaises(errors.BzrError, osutils.kind_marker, "unknown")
332
313
 
333
314
 
334
315
class TestUmask(tests.TestCaseInTempDir):
430
411
class TestLinks(tests.TestCaseInTempDir):
431
412
 
432
413
    def test_dereference_path(self):
433
 
        self.requireFeature(features.SymlinkFeature)
 
414
        self.requireFeature(tests.SymlinkFeature)
434
415
        cwd = osutils.realpath('.')
435
416
        os.mkdir('bar')
436
417
        bar_path = osutils.pathjoin(cwd, 'bar')
483
464
 
484
465
class TestCanonicalRelPath(tests.TestCaseInTempDir):
485
466
 
486
 
    _test_needs_features = [features.CaseInsCasePresFilenameFeature]
 
467
    _test_needs_features = [tests.CaseInsCasePresFilenameFeature]
487
468
 
488
469
    def test_canonical_relpath_simple(self):
489
470
        f = file('MixedCaseName', 'w')
490
471
        f.close()
491
472
        actual = osutils.canonical_relpath(self.test_base_dir, 'mixedcasename')
492
 
        self.assertEqual('work/MixedCaseName', actual)
 
473
        self.failUnlessEqual('work/MixedCaseName', actual)
493
474
 
494
475
    def test_canonical_relpath_missing_tail(self):
495
476
        os.mkdir('MixedCaseParent')
496
477
        actual = osutils.canonical_relpath(self.test_base_dir,
497
478
                                           'mixedcaseparent/nochild')
498
 
        self.assertEqual('work/MixedCaseParent/nochild', actual)
 
479
        self.failUnlessEqual('work/MixedCaseParent/nochild', actual)
499
480
 
500
481
 
501
482
class Test_CICPCanonicalRelpath(tests.TestCaseWithTransport):
819
800
        self.assertEqual(None, osutils.safe_file_id(None))
820
801
 
821
802
 
822
 
class TestPosixFuncs(tests.TestCase):
823
 
    """Test that the posix version of normpath returns an appropriate path
824
 
       when used with 2 leading slashes."""
825
 
 
826
 
    def test_normpath(self):
827
 
        self.assertEqual('/etc/shadow', osutils._posix_normpath('/etc/shadow'))
828
 
        self.assertEqual('/etc/shadow', osutils._posix_normpath('//etc/shadow'))
829
 
        self.assertEqual('/etc/shadow', osutils._posix_normpath('///etc/shadow'))
830
 
 
831
 
 
832
803
class TestWin32Funcs(tests.TestCase):
833
804
    """Test that _win32 versions of os utilities return appropriate paths."""
834
805
 
887
858
        self.assertEqual('//HOST/path', osutils._win98_abspath('//HOST/path'))
888
859
        # relative path
889
860
        cwd = osutils.getcwd().rstrip('/')
890
 
        drive = osutils.ntpath.splitdrive(cwd)[0]
 
861
        drive = osutils._nt_splitdrive(cwd)[0]
891
862
        self.assertEqual(cwd+'/path', osutils._win98_abspath('path'))
892
863
        self.assertEqual(drive+'/path', osutils._win98_abspath('/path'))
893
864
        # unicode path
899
870
    """Test win32 functions that create files."""
900
871
 
901
872
    def test_getcwd(self):
902
 
        self.requireFeature(features.UnicodeFilenameFeature)
 
873
        self.requireFeature(tests.UnicodeFilenameFeature)
903
874
        os.mkdir(u'mu-\xb5')
904
875
        os.chdir(u'mu-\xb5')
905
876
        # TODO: jam 20060427 This will probably fail on Mac OSX because
935
906
        b.close()
936
907
 
937
908
        osutils._win32_rename('b', 'a')
938
 
        self.assertPathExists('a')
939
 
        self.assertPathDoesNotExist('b')
 
909
        self.failUnlessExists('a')
 
910
        self.failIfExists('b')
940
911
        self.assertFileEqual('baz\n', 'a')
941
912
 
942
913
    def test_rename_missing_file(self):
995
966
    """Test mac special functions that require directories."""
996
967
 
997
968
    def test_getcwd(self):
998
 
        self.requireFeature(features.UnicodeFilenameFeature)
 
969
        self.requireFeature(tests.UnicodeFilenameFeature)
999
970
        os.mkdir(u'B\xe5gfors')
1000
971
        os.chdir(u'B\xe5gfors')
1001
972
        self.assertEndsWith(osutils._mac_getcwd(), u'B\xe5gfors')
1002
973
 
1003
974
    def test_getcwd_nonnorm(self):
1004
 
        self.requireFeature(features.UnicodeFilenameFeature)
 
975
        self.requireFeature(tests.UnicodeFilenameFeature)
1005
976
        # Test that _mac_getcwd() will normalize this path
1006
977
        os.mkdir(u'Ba\u030agfors')
1007
978
        os.chdir(u'Ba\u030agfors')
1090
1061
        self.assertExpectedBlocks(expected_dirblocks[1:], result)
1091
1062
 
1092
1063
    def test_walkdirs_os_error(self):
1093
 
        # <https://bugs.launchpad.net/bzr/+bug/338653>
 
1064
        # <https://bugs.edge.launchpad.net/bzr/+bug/338653>
1094
1065
        # Pyrex readdir didn't raise useful messages if it had an error
1095
1066
        # reading the directory
1096
1067
        if sys.platform == 'win32':
1097
1068
            raise tests.TestNotApplicable(
1098
1069
                "readdir IOError not tested on win32")
1099
 
        self.requireFeature(features.not_running_as_root)
1100
1070
        os.mkdir("test-unreadable")
1101
1071
        os.chmod("test-unreadable", 0000)
1102
1072
        # must chmod it back so that it can be removed
1110
1080
        # Ensure the message contains the file name
1111
1081
        self.assertContainsRe(str(e), "\./test-unreadable")
1112
1082
 
1113
 
 
1114
 
    def test_walkdirs_encoding_error(self):
1115
 
        # <https://bugs.launchpad.net/bzr/+bug/488519>
1116
 
        # walkdirs didn't raise a useful message when the filenames
1117
 
        # are not using the filesystem's encoding
1118
 
 
1119
 
        # require a bytestring based filesystem
1120
 
        self.requireFeature(features.ByteStringNamedFilesystem)
1121
 
 
1122
 
        tree = [
1123
 
            '.bzr',
1124
 
            '0file',
1125
 
            '1dir/',
1126
 
            '1dir/0file',
1127
 
            '1dir/1dir/',
1128
 
            '1file'
1129
 
            ]
1130
 
 
1131
 
        self.build_tree(tree)
1132
 
 
1133
 
        # rename the 1file to a latin-1 filename
1134
 
        os.rename("./1file", "\xe8file")
1135
 
        if "\xe8file" not in os.listdir("."):
1136
 
            self.skip("Lack filesystem that preserves arbitrary bytes")
1137
 
 
1138
 
        self._save_platform_info()
1139
 
        win32utils.winver = None # Avoid the win32 detection code
1140
 
        osutils._fs_enc = 'UTF-8'
1141
 
 
1142
 
        # this should raise on error
1143
 
        def attempt():
1144
 
            for dirdetail, dirblock in osutils.walkdirs('.'):
1145
 
                pass
1146
 
 
1147
 
        self.assertRaises(errors.BadFilenameEncoding, attempt)
1148
 
 
1149
1083
    def test__walkdirs_utf8(self):
1150
1084
        tree = [
1151
1085
            '.bzr',
1218
1152
        self._save_platform_info()
1219
1153
        win32utils.winver = None # Avoid the win32 detection code
1220
1154
        osutils._fs_enc = 'UTF-8'
1221
 
        self.assertDirReaderIs(
1222
 
            UTF8DirReaderFeature.module.UTF8DirReader)
 
1155
        self.assertDirReaderIs(UTF8DirReaderFeature.reader)
1223
1156
 
1224
1157
    def test_force_walkdirs_utf8_fs_ascii(self):
1225
1158
        self.requireFeature(UTF8DirReaderFeature)
1226
1159
        self._save_platform_info()
1227
1160
        win32utils.winver = None # Avoid the win32 detection code
1228
1161
        osutils._fs_enc = 'US-ASCII'
1229
 
        self.assertDirReaderIs(
1230
 
            UTF8DirReaderFeature.module.UTF8DirReader)
 
1162
        self.assertDirReaderIs(UTF8DirReaderFeature.reader)
1231
1163
 
1232
1164
    def test_force_walkdirs_utf8_fs_ANSI(self):
1233
1165
        self.requireFeature(UTF8DirReaderFeature)
1234
1166
        self._save_platform_info()
1235
1167
        win32utils.winver = None # Avoid the win32 detection code
1236
1168
        osutils._fs_enc = 'ANSI_X3.4-1968'
1237
 
        self.assertDirReaderIs(
1238
 
            UTF8DirReaderFeature.module.UTF8DirReader)
 
1169
        self.assertDirReaderIs(UTF8DirReaderFeature.reader)
1239
1170
 
1240
1171
    def test_force_walkdirs_utf8_fs_latin1(self):
1241
1172
        self._save_platform_info()
1259
1190
 
1260
1191
    def test_unicode_walkdirs(self):
1261
1192
        """Walkdirs should always return unicode paths."""
1262
 
        self.requireFeature(features.UnicodeFilenameFeature)
 
1193
        self.requireFeature(tests.UnicodeFilenameFeature)
1263
1194
        name0 = u'0file-\xb6'
1264
1195
        name1 = u'1dir-\u062c\u0648'
1265
1196
        name2 = u'2file-\u0633'
1302
1233
 
1303
1234
        The abspath portion might be in unicode or utf-8
1304
1235
        """
1305
 
        self.requireFeature(features.UnicodeFilenameFeature)
 
1236
        self.requireFeature(tests.UnicodeFilenameFeature)
1306
1237
        name0 = u'0file-\xb6'
1307
1238
        name1 = u'1dir-\u062c\u0648'
1308
1239
        name2 = u'2file-\u0633'
1363
1294
 
1364
1295
        The abspath portion should be in unicode
1365
1296
        """
1366
 
        self.requireFeature(features.UnicodeFilenameFeature)
 
1297
        self.requireFeature(tests.UnicodeFilenameFeature)
1367
1298
        # Use the unicode reader. TODO: split into driver-and-driven unit
1368
1299
        # tests.
1369
1300
        self._save_platform_info()
1410
1341
 
1411
1342
    def test__walkdirs_utf8_win32readdir(self):
1412
1343
        self.requireFeature(test__walkdirs_win32.win32_readdir_feature)
1413
 
        self.requireFeature(features.UnicodeFilenameFeature)
 
1344
        self.requireFeature(tests.UnicodeFilenameFeature)
1414
1345
        from bzrlib._walkdirs_win32 import Win32ReadDir
1415
1346
        self._save_platform_info()
1416
1347
        osutils._selected_dir_reader = Win32ReadDir()
1467
1398
    def test__walkdirs_utf_win32_find_file_stat_file(self):
1468
1399
        """make sure our Stat values are valid"""
1469
1400
        self.requireFeature(test__walkdirs_win32.win32_readdir_feature)
1470
 
        self.requireFeature(features.UnicodeFilenameFeature)
 
1401
        self.requireFeature(tests.UnicodeFilenameFeature)
1471
1402
        from bzrlib._walkdirs_win32 import Win32ReadDir
1472
1403
        name0u = u'0file-\xb6'
1473
1404
        name0 = name0u.encode('utf8')
1491
1422
    def test__walkdirs_utf_win32_find_file_stat_directory(self):
1492
1423
        """make sure our Stat values are valid"""
1493
1424
        self.requireFeature(test__walkdirs_win32.win32_readdir_feature)
1494
 
        self.requireFeature(features.UnicodeFilenameFeature)
 
1425
        self.requireFeature(tests.UnicodeFilenameFeature)
1495
1426
        from bzrlib._walkdirs_win32 import Win32ReadDir
1496
1427
        name0u = u'0dir-\u062c\u0648'
1497
1428
        name0 = name0u.encode('utf8')
1597
1528
        self.assertEqual(['c'], os.listdir('target/b'))
1598
1529
 
1599
1530
    def test_copy_tree_symlinks(self):
1600
 
        self.requireFeature(features.SymlinkFeature)
 
1531
        self.requireFeature(tests.SymlinkFeature)
1601
1532
        self.build_tree(['source/'])
1602
1533
        os.symlink('a/generic/path', 'source/lnk')
1603
1534
        osutils.copy_tree('source', 'target')
1628
1559
                          ('d', 'source/b', 'target/b'),
1629
1560
                          ('f', 'source/b/c', 'target/b/c'),
1630
1561
                         ], processed_files)
1631
 
        self.assertPathDoesNotExist('target')
 
1562
        self.failIfExists('target')
1632
1563
        if osutils.has_symlinks():
1633
1564
            self.assertEqual([('source/lnk', 'target/lnk')], processed_links)
1634
1565
 
1680
1611
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', None)
1681
1612
        self.assertEqual('foo', old)
1682
1613
        self.assertEqual(None, os.environ.get('BZR_TEST_ENV_VAR'))
1683
 
        self.assertFalse('BZR_TEST_ENV_VAR' in os.environ)
 
1614
        self.failIf('BZR_TEST_ENV_VAR' in os.environ)
1684
1615
 
1685
1616
 
1686
1617
class TestSizeShaFile(tests.TestCaseInTempDir):
1737
1668
 
1738
1669
class TestReCompile(tests.TestCase):
1739
1670
 
1740
 
    def _deprecated_re_compile_checked(self, *args, **kwargs):
1741
 
        return self.applyDeprecated(symbol_versioning.deprecated_in((2, 2, 0)),
1742
 
            osutils.re_compile_checked, *args, **kwargs)
1743
 
 
1744
1671
    def test_re_compile_checked(self):
1745
 
        r = self._deprecated_re_compile_checked(r'A*', re.IGNORECASE)
 
1672
        r = osutils.re_compile_checked(r'A*', re.IGNORECASE)
1746
1673
        self.assertTrue(r.match('aaaa'))
1747
1674
        self.assertTrue(r.match('aAaA'))
1748
1675
 
1749
1676
    def test_re_compile_checked_error(self):
1750
1677
        # like https://bugs.launchpad.net/bzr/+bug/251352
1751
 
 
1752
 
        # Due to possible test isolation error, re.compile is not lazy at
1753
 
        # this point. We re-install lazy compile.
1754
 
        lazy_regex.install_lazy_compile()
1755
1678
        err = self.assertRaises(
1756
1679
            errors.BzrCommandError,
1757
 
            self._deprecated_re_compile_checked, '*', re.IGNORECASE, 'test case')
 
1680
            osutils.re_compile_checked, '*', re.IGNORECASE, 'test case')
1758
1681
        self.assertEqual(
1759
 
            'Invalid regular expression in test case: '
1760
 
            '"*" nothing to repeat',
 
1682
            "Invalid regular expression in test case: '*': "
 
1683
            "nothing to repeat",
1761
1684
            str(err))
1762
1685
 
1763
1686
 
1764
1687
class TestDirReader(tests.TestCaseInTempDir):
1765
1688
 
1766
 
    scenarios = dir_reader_scenarios()
1767
 
 
1768
1689
    # Set by load_tests
1769
1690
    _dir_reader_class = None
1770
1691
    _native_to_unicode = None
1870
1791
        return filtered_dirblocks
1871
1792
 
1872
1793
    def test_walk_unicode_tree(self):
1873
 
        self.requireFeature(features.UnicodeFilenameFeature)
 
1794
        self.requireFeature(tests.UnicodeFilenameFeature)
1874
1795
        tree, expected_dirblocks = self._get_unicode_tree()
1875
1796
        self.build_tree(tree)
1876
1797
        result = list(osutils._walkdirs_utf8('.'))
1877
1798
        self.assertEqual(expected_dirblocks, self._filter_out(result))
1878
1799
 
1879
1800
    def test_symlink(self):
1880
 
        self.requireFeature(features.SymlinkFeature)
1881
 
        self.requireFeature(features.UnicodeFilenameFeature)
 
1801
        self.requireFeature(tests.SymlinkFeature)
 
1802
        self.requireFeature(tests.UnicodeFilenameFeature)
1882
1803
        target = u'target\N{Euro Sign}'
1883
1804
        link_name = u'l\N{Euro Sign}nk'
1884
1805
        os.symlink(target, link_name)
1902
1823
    But prior python versions failed to properly encode the passed unicode
1903
1824
    string.
1904
1825
    """
1905
 
    _test_needs_features = [features.SymlinkFeature, features.UnicodeFilenameFeature]
 
1826
    _test_needs_features = [tests.SymlinkFeature, tests.UnicodeFilenameFeature]
1906
1827
 
1907
1828
    def setUp(self):
1908
1829
        super(tests.TestCaseInTempDir, self).setUp()
1911
1832
        os.symlink(self.target, self.link)
1912
1833
 
1913
1834
    def test_os_readlink_link_encoding(self):
1914
 
        self.assertEquals(self.target,  os.readlink(self.link))
 
1835
        if sys.version_info < (2, 6):
 
1836
            self.assertRaises(UnicodeEncodeError, os.readlink, self.link)
 
1837
        else:
 
1838
            self.assertEquals(self.target,  os.readlink(self.link))
1915
1839
 
1916
1840
    def test_os_readlink_link_decoding(self):
1917
1841
        self.assertEquals(self.target.encode(osutils._fs_enc),
1929
1853
        self.assertIsInstance(concurrency, int)
1930
1854
 
1931
1855
    def test_local_concurrency_environment_variable(self):
1932
 
        self.overrideEnv('BZR_CONCURRENCY', '2')
 
1856
        os.environ['BZR_CONCURRENCY'] = '2'
1933
1857
        self.assertEqual(2, osutils.local_concurrency(use_cache=False))
1934
 
        self.overrideEnv('BZR_CONCURRENCY', '3')
 
1858
        os.environ['BZR_CONCURRENCY'] = '3'
1935
1859
        self.assertEqual(3, osutils.local_concurrency(use_cache=False))
1936
 
        self.overrideEnv('BZR_CONCURRENCY', 'foo')
 
1860
        os.environ['BZR_CONCURRENCY'] = 'foo'
1937
1861
        self.assertEqual(1, osutils.local_concurrency(use_cache=False))
1938
1862
 
1939
1863
    def test_option_concurrency(self):
1940
 
        self.overrideEnv('BZR_CONCURRENCY', '1')
 
1864
        os.environ['BZR_CONCURRENCY'] = '1'
1941
1865
        self.run_bzr('rocks --concurrency 42')
1942
 
        # Command line overrides environment variable
 
1866
        # Command line overrides envrionment variable
1943
1867
        self.assertEquals('42', os.environ['BZR_CONCURRENCY'])
1944
1868
        self.assertEquals(42, osutils.local_concurrency(use_cache=False))
1945
1869
 
1983
1907
 
1984
1908
class TestTerminalWidth(tests.TestCase):
1985
1909
 
1986
 
    def setUp(self):
1987
 
        tests.TestCase.setUp(self)
1988
 
        self._orig_terminal_size_state = osutils._terminal_size_state
1989
 
        self._orig_first_terminal_size = osutils._first_terminal_size
1990
 
        self.addCleanup(self.restore_osutils_globals)
1991
 
        osutils._terminal_size_state = 'no_data'
1992
 
        osutils._first_terminal_size = None
1993
 
 
1994
 
    def restore_osutils_globals(self):
1995
 
        osutils._terminal_size_state = self._orig_terminal_size_state
1996
 
        osutils._first_terminal_size = self._orig_first_terminal_size
1997
 
 
1998
1910
    def replace_stdout(self, new):
1999
1911
        self.overrideAttr(sys, 'stdout', new)
2000
1912
 
2015
1927
    def test_defaults_to_BZR_COLUMNS(self):
2016
1928
        # BZR_COLUMNS is set by the test framework
2017
1929
        self.assertNotEqual('12', os.environ['BZR_COLUMNS'])
2018
 
        self.overrideEnv('BZR_COLUMNS', '12')
 
1930
        os.environ['BZR_COLUMNS'] = '12'
2019
1931
        self.assertEqual(12, osutils.terminal_width())
2020
1932
 
2021
 
    def test_BZR_COLUMNS_0_no_limit(self):
2022
 
        self.overrideEnv('BZR_COLUMNS', '0')
2023
 
        self.assertEqual(None, osutils.terminal_width())
2024
 
 
2025
1933
    def test_falls_back_to_COLUMNS(self):
2026
 
        self.overrideEnv('BZR_COLUMNS', None)
 
1934
        del os.environ['BZR_COLUMNS']
2027
1935
        self.assertNotEqual('42', os.environ['COLUMNS'])
2028
1936
        self.set_fake_tty()
2029
 
        self.overrideEnv('COLUMNS', '42')
 
1937
        os.environ['COLUMNS'] = '42'
2030
1938
        self.assertEqual(42, osutils.terminal_width())
2031
1939
 
2032
1940
    def test_tty_default_without_columns(self):
2033
 
        self.overrideEnv('BZR_COLUMNS', None)
2034
 
        self.overrideEnv('COLUMNS', None)
 
1941
        del os.environ['BZR_COLUMNS']
 
1942
        del os.environ['COLUMNS']
2035
1943
 
2036
1944
        def terminal_size(w, h):
2037
1945
            return 42, 42
2044
1952
        self.assertEqual(42, osutils.terminal_width())
2045
1953
 
2046
1954
    def test_non_tty_default_without_columns(self):
2047
 
        self.overrideEnv('BZR_COLUMNS', None)
2048
 
        self.overrideEnv('COLUMNS', None)
 
1955
        del os.environ['BZR_COLUMNS']
 
1956
        del os.environ['COLUMNS']
2049
1957
        self.replace_stdout(None)
2050
1958
        self.assertEqual(None, osutils.terminal_width())
2051
1959
 
2061
1969
        else:
2062
1970
            self.overrideAttr(termios, 'TIOCGWINSZ')
2063
1971
            del termios.TIOCGWINSZ
2064
 
        self.overrideEnv('BZR_COLUMNS', None)
2065
 
        self.overrideEnv('COLUMNS', None)
 
1972
        del os.environ['BZR_COLUMNS']
 
1973
        del os.environ['COLUMNS']
2066
1974
        # Whatever the result is, if we don't raise an exception, it's ok.
2067
1975
        osutils.terminal_width()
2068
 
 
2069
 
 
2070
 
class TestCreationOps(tests.TestCaseInTempDir):
2071
 
    _test_needs_features = [features.chown_feature]
2072
 
 
2073
 
    def setUp(self):
2074
 
        tests.TestCaseInTempDir.setUp(self)
2075
 
        self.overrideAttr(os, 'chown', self._dummy_chown)
2076
 
 
2077
 
        # params set by call to _dummy_chown
2078
 
        self.path = self.uid = self.gid = None
2079
 
 
2080
 
    def _dummy_chown(self, path, uid, gid):
2081
 
        self.path, self.uid, self.gid = path, uid, gid
2082
 
 
2083
 
    def test_copy_ownership_from_path(self):
2084
 
        """copy_ownership_from_path test with specified src."""
2085
 
        ownsrc = '/'
2086
 
        f = open('test_file', 'wt')
2087
 
        osutils.copy_ownership_from_path('test_file', ownsrc)
2088
 
 
2089
 
        s = os.stat(ownsrc)
2090
 
        self.assertEquals(self.path, 'test_file')
2091
 
        self.assertEquals(self.uid, s.st_uid)
2092
 
        self.assertEquals(self.gid, s.st_gid)
2093
 
 
2094
 
    def test_copy_ownership_nonesrc(self):
2095
 
        """copy_ownership_from_path test with src=None."""
2096
 
        f = open('test_file', 'wt')
2097
 
        # should use parent dir for permissions
2098
 
        osutils.copy_ownership_from_path('test_file')
2099
 
 
2100
 
        s = os.stat('..')
2101
 
        self.assertEquals(self.path, 'test_file')
2102
 
        self.assertEquals(self.uid, s.st_uid)
2103
 
        self.assertEquals(self.gid, s.st_gid)
2104
 
 
2105
 
 
2106
 
class TestGetuserUnicode(tests.TestCase):
2107
 
 
2108
 
    def test_ascii_user(self):
2109
 
        self.overrideEnv('LOGNAME', 'jrandom')
2110
 
        self.assertEqual(u'jrandom', osutils.getuser_unicode())
2111
 
 
2112
 
    def test_unicode_user(self):
2113
 
        ue = osutils.get_user_encoding()
2114
 
        uni_val, env_val = tests.probe_unicode_in_user_encoding()
2115
 
        if uni_val is None:
2116
 
            raise tests.TestSkipped(
2117
 
                'Cannot find a unicode character that works in encoding %s'
2118
 
                % (osutils.get_user_encoding(),))
2119
 
        uni_username = u'jrandom' + uni_val
2120
 
        encoded_username = uni_username.encode(ue)
2121
 
        self.overrideEnv('LOGNAME', encoded_username)
2122
 
        self.assertEqual(uni_username, osutils.getuser_unicode())
2123
 
        self.overrideEnv('LOGNAME', u'jrandom\xb6'.encode(ue))
2124
 
        self.assertEqual(u'jrandom\xb6', osutils.getuser_unicode())
2125
 
 
2126
 
    def test_no_username_bug_660174(self):
2127
 
        self.requireFeature(features.win32_feature)
2128
 
        for name in ('LOGNAME', 'USER', 'LNAME', 'USERNAME'):
2129
 
            self.overrideEnv(name, None)
2130
 
        self.assertEqual(u'UNKNOWN', osutils.getuser_unicode())
2131
 
 
2132
 
 
2133
 
class TestBackupNames(tests.TestCase):
2134
 
 
2135
 
    def setUp(self):
2136
 
        super(TestBackupNames, self).setUp()
2137
 
        self.backups = []
2138
 
 
2139
 
    def backup_exists(self, name):
2140
 
        return name in self.backups
2141
 
 
2142
 
    def available_backup_name(self, name):
2143
 
        backup_name = osutils.available_backup_name(name, self.backup_exists)
2144
 
        self.backups.append(backup_name)
2145
 
        return backup_name
2146
 
 
2147
 
    def assertBackupName(self, expected, name):
2148
 
        self.assertEqual(expected, self.available_backup_name(name))
2149
 
 
2150
 
    def test_empty(self):
2151
 
        self.assertBackupName('file.~1~', 'file')
2152
 
 
2153
 
    def test_existing(self):
2154
 
        self.available_backup_name('file')
2155
 
        self.available_backup_name('file')
2156
 
        self.assertBackupName('file.~3~', 'file')
2157
 
        # Empty slots are found, this is not a strict requirement and may be
2158
 
        # revisited if we test against all implementations.
2159
 
        self.backups.remove('file.~2~')
2160
 
        self.assertBackupName('file.~2~', 'file')
2161
 
 
2162
 
 
2163
 
class TestFindExecutableInPath(tests.TestCase):
2164
 
 
2165
 
    def test_windows(self):
2166
 
        if sys.platform != 'win32':
2167
 
            raise tests.TestSkipped('test requires win32')
2168
 
        self.assertTrue(osutils.find_executable_on_path('explorer') is not None)
2169
 
        self.assertTrue(
2170
 
            osutils.find_executable_on_path('explorer.exe') is not None)
2171
 
        self.assertTrue(
2172
 
            osutils.find_executable_on_path('EXPLORER.EXE') is not None)
2173
 
        self.assertTrue(
2174
 
            osutils.find_executable_on_path('THIS SHOULD NOT EXIST') is None)
2175
 
        self.assertTrue(osutils.find_executable_on_path('file.txt') is None)
2176
 
 
2177
 
    def test_other(self):
2178
 
        if sys.platform == 'win32':
2179
 
            raise tests.TestSkipped('test requires non-win32')
2180
 
        self.assertTrue(osutils.find_executable_on_path('sh') is not None)
2181
 
        self.assertTrue(
2182
 
            osutils.find_executable_on_path('THIS SHOULD NOT EXIST') is None)
2183
 
 
2184
 
 
2185
 
class TestEnvironmentErrors(tests.TestCase):
2186
 
    """Test handling of environmental errors"""
2187
 
 
2188
 
    def test_is_oserror(self):
2189
 
        self.assertTrue(osutils.is_environment_error(
2190
 
            OSError(errno.EINVAL, "Invalid parameter")))
2191
 
 
2192
 
    def test_is_ioerror(self):
2193
 
        self.assertTrue(osutils.is_environment_error(
2194
 
            IOError(errno.EINVAL, "Invalid parameter")))
2195
 
 
2196
 
    def test_is_socket_error(self):
2197
 
        self.assertTrue(osutils.is_environment_error(
2198
 
            socket.error(errno.EINVAL, "Invalid parameter")))
2199
 
 
2200
 
    def test_is_select_error(self):
2201
 
        self.assertTrue(osutils.is_environment_error(
2202
 
            select.error(errno.EINVAL, "Invalid parameter")))
2203
 
 
2204
 
    def test_is_pywintypes_error(self):
2205
 
        self.requireFeature(features.pywintypes)
2206
 
        import pywintypes
2207
 
        self.assertTrue(osutils.is_environment_error(
2208
 
            pywintypes.error(errno.EINVAL, "Invalid parameter", "Caller")))