/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_osutils.py

  • Committer: Jelmer Vernooij
  • Date: 2015-03-14 23:44:01 UTC
  • mto: This revision was merged to the branch mainline in revision 6603.
  • Revision ID: jelmer@samba.org-20150314234401-vk8pqfi2zw549uxg
Remove generation time from scripts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005-2011 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
23
24
import socket
24
 
import stat
25
25
import sys
 
26
import tempfile
26
27
import time
27
28
 
28
29
from bzrlib import (
29
30
    errors,
 
31
    lazy_regex,
30
32
    osutils,
 
33
    symbol_versioning,
31
34
    tests,
32
35
    trace,
33
36
    win32utils,
37
40
    file_utils,
38
41
    test__walkdirs_win32,
39
42
    )
40
 
 
41
 
 
42
 
class _UTF8DirReaderFeature(tests.Feature):
 
43
from bzrlib.tests.scenarios import load_tests_apply_scenarios
 
44
 
 
45
 
 
46
class _UTF8DirReaderFeature(features.Feature):
43
47
 
44
48
    def _probe(self):
45
49
        try:
52
56
    def feature_name(self):
53
57
        return 'bzrlib._readdir_pyx'
54
58
 
55
 
UTF8DirReaderFeature = _UTF8DirReaderFeature()
 
59
UTF8DirReaderFeature = features.ModuleAvailableFeature('bzrlib._readdir_pyx')
56
60
 
57
 
term_ios_feature = tests.ModuleAvailableFeature('termios')
 
61
term_ios_feature = features.ModuleAvailableFeature('termios')
58
62
 
59
63
 
60
64
def _already_unicode(s):
95
99
    return scenarios
96
100
 
97
101
 
98
 
def load_tests(basic_tests, module, loader):
99
 
    suite = loader.suiteClass()
100
 
    dir_reader_tests, remaining_tests = tests.split_suite_by_condition(
101
 
        basic_tests, tests.condition_isinstance(TestDirReader))
102
 
    tests.multiply_tests(dir_reader_tests, dir_reader_scenarios(), suite)
103
 
    suite.addTest(remaining_tests)
104
 
    return suite
 
102
load_tests = load_tests_apply_scenarios
105
103
 
106
104
 
107
105
class TestContainsWhitespace(tests.TestCase):
108
106
 
109
107
    def test_contains_whitespace(self):
110
 
        self.failUnless(osutils.contains_whitespace(u' '))
111
 
        self.failUnless(osutils.contains_whitespace(u'hello there'))
112
 
        self.failUnless(osutils.contains_whitespace(u'hellothere\n'))
113
 
        self.failUnless(osutils.contains_whitespace(u'hello\nthere'))
114
 
        self.failUnless(osutils.contains_whitespace(u'hello\rthere'))
115
 
        self.failUnless(osutils.contains_whitespace(u'hello\tthere'))
 
108
        self.assertTrue(osutils.contains_whitespace(u' '))
 
109
        self.assertTrue(osutils.contains_whitespace(u'hello there'))
 
110
        self.assertTrue(osutils.contains_whitespace(u'hellothere\n'))
 
111
        self.assertTrue(osutils.contains_whitespace(u'hello\nthere'))
 
112
        self.assertTrue(osutils.contains_whitespace(u'hello\rthere'))
 
113
        self.assertTrue(osutils.contains_whitespace(u'hello\tthere'))
116
114
 
117
115
        # \xa0 is "Non-breaking-space" which on some python locales thinks it
118
116
        # is whitespace, but we do not.
119
 
        self.failIf(osutils.contains_whitespace(u''))
120
 
        self.failIf(osutils.contains_whitespace(u'hellothere'))
121
 
        self.failIf(osutils.contains_whitespace(u'hello\xa0there'))
 
117
        self.assertFalse(osutils.contains_whitespace(u''))
 
118
        self.assertFalse(osutils.contains_whitespace(u'hellothere'))
 
119
        self.assertFalse(osutils.contains_whitespace(u'hello\xa0there'))
122
120
 
123
121
 
124
122
class TestRename(tests.TestCaseInTempDir):
138
136
        # This should work everywhere
139
137
        self.create_file('a', 'something in a\n')
140
138
        self._fancy_rename('a', 'b')
141
 
        self.failIfExists('a')
142
 
        self.failUnlessExists('b')
 
139
        self.assertPathDoesNotExist('a')
 
140
        self.assertPathExists('b')
143
141
        self.check_file_contents('b', 'something in a\n')
144
142
 
145
143
        self.create_file('a', 'new something in a\n')
152
150
        self.create_file('target', 'data in target\n')
153
151
        self.assertRaises((IOError, OSError), self._fancy_rename,
154
152
                          'missingsource', 'target')
155
 
        self.failUnlessExists('target')
 
153
        self.assertPathExists('target')
156
154
        self.check_file_contents('target', 'data in target\n')
157
155
 
158
156
    def test_fancy_rename_fails_if_source_and_target_missing(self):
163
161
        # Rename should be semi-atomic on all platforms
164
162
        self.create_file('a', 'something in a\n')
165
163
        osutils.rename('a', 'b')
166
 
        self.failIfExists('a')
167
 
        self.failUnlessExists('b')
 
164
        self.assertPathDoesNotExist('a')
 
165
        self.assertPathExists('b')
168
166
        self.check_file_contents('b', 'something in a\n')
169
167
 
170
168
        self.create_file('a', 'new something in a\n')
184
182
        shape = sorted(os.listdir('.'))
185
183
        self.assertEquals(['A', 'B'], shape)
186
184
 
187
 
    def test_rename_error(self):
188
 
        # We wrap os.rename to make it give an error including the filenames
189
 
        # https://bugs.launchpad.net/bzr/+bug/491763
190
 
        err = self.assertRaises(OSError, osutils.rename,
191
 
            'nonexistent', 'target')
192
 
        self.assertContainsString(str(err), 'nonexistent')
 
185
    def test_rename_exception(self):
 
186
        try:
 
187
            osutils.rename('nonexistent_path', 'different_nonexistent_path')
 
188
        except OSError, e:
 
189
            self.assertEqual(e.old_filename, 'nonexistent_path')
 
190
            self.assertEqual(e.new_filename, 'different_nonexistent_path')
 
191
            self.assertTrue('nonexistent_path' in e.strerror)
 
192
            self.assertTrue('different_nonexistent_path' in e.strerror)
193
193
 
194
194
 
195
195
class TestRandChars(tests.TestCase):
242
242
            self.assertFalse(osutils.is_inside_or_parent_of_any(dirs, fn))
243
243
 
244
244
 
 
245
class TestLstat(tests.TestCaseInTempDir):
 
246
 
 
247
    def test_lstat_matches_fstat(self):
 
248
        # On Windows, lstat and fstat don't always agree, primarily in the
 
249
        # 'st_ino' and 'st_dev' fields. So we force them to be '0' in our
 
250
        # custom implementation.
 
251
        if sys.platform == 'win32':
 
252
            # We only have special lstat/fstat if we have the extension.
 
253
            # Without it, we may end up re-reading content when we don't have
 
254
            # to, but otherwise it doesn't effect correctness.
 
255
            self.requireFeature(test__walkdirs_win32.win32_readdir_feature)
 
256
        f = open('test-file.txt', 'wb')
 
257
        self.addCleanup(f.close)
 
258
        f.write('some content\n')
 
259
        f.flush()
 
260
        self.assertEqualStat(osutils.fstat(f.fileno()),
 
261
                             osutils.lstat('test-file.txt'))
 
262
 
 
263
 
245
264
class TestRmTree(tests.TestCaseInTempDir):
246
265
 
247
266
    def test_rmtree(self):
259
278
 
260
279
        osutils.rmtree('dir')
261
280
 
262
 
        self.failIfExists('dir/file')
263
 
        self.failIfExists('dir')
 
281
        self.assertPathDoesNotExist('dir/file')
 
282
        self.assertPathDoesNotExist('dir')
264
283
 
265
284
 
266
285
class TestDeleteAny(tests.TestCaseInTempDir):
418
437
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)
419
438
 
420
439
 
 
440
class TestFdatasync(tests.TestCaseInTempDir):
 
441
 
 
442
    def do_fdatasync(self):
 
443
        f = tempfile.NamedTemporaryFile()
 
444
        osutils.fdatasync(f.fileno())
 
445
        f.close()
 
446
 
 
447
    @staticmethod
 
448
    def raise_eopnotsupp(*args, **kwargs):
 
449
        raise IOError(errno.EOPNOTSUPP, os.strerror(errno.EOPNOTSUPP))
 
450
 
 
451
    @staticmethod
 
452
    def raise_enotsup(*args, **kwargs):
 
453
        raise IOError(errno.ENOTSUP, os.strerror(errno.ENOTSUP))
 
454
 
 
455
    def test_fdatasync_handles_system_function(self):
 
456
        self.overrideAttr(os, "fdatasync")
 
457
        self.do_fdatasync()
 
458
 
 
459
    def test_fdatasync_handles_no_fdatasync_no_fsync(self):
 
460
        self.overrideAttr(os, "fdatasync")
 
461
        self.overrideAttr(os, "fsync")
 
462
        self.do_fdatasync()
 
463
 
 
464
    def test_fdatasync_handles_no_EOPNOTSUPP(self):
 
465
        self.overrideAttr(errno, "EOPNOTSUPP")
 
466
        self.do_fdatasync()
 
467
 
 
468
    def test_fdatasync_catches_ENOTSUP(self):
 
469
        enotsup = getattr(errno, "ENOTSUP", None)
 
470
        if enotsup is None:
 
471
            raise tests.TestNotApplicable("No ENOTSUP on this platform")
 
472
        self.overrideAttr(os, "fdatasync", self.raise_enotsup)
 
473
        self.do_fdatasync()
 
474
 
 
475
    def test_fdatasync_catches_EOPNOTSUPP(self):
 
476
        enotsup = getattr(errno, "EOPNOTSUPP", None)
 
477
        if enotsup is None:
 
478
            raise tests.TestNotApplicable("No EOPNOTSUPP on this platform")
 
479
        self.overrideAttr(os, "fdatasync", self.raise_eopnotsupp)
 
480
        self.do_fdatasync()
 
481
 
 
482
 
421
483
class TestLinks(tests.TestCaseInTempDir):
422
484
 
423
485
    def test_dereference_path(self):
424
 
        self.requireFeature(tests.SymlinkFeature)
 
486
        self.requireFeature(features.SymlinkFeature)
425
487
        cwd = osutils.realpath('.')
426
488
        os.mkdir('bar')
427
489
        bar_path = osutils.pathjoin(cwd, 'bar')
474
536
 
475
537
class TestCanonicalRelPath(tests.TestCaseInTempDir):
476
538
 
477
 
    _test_needs_features = [tests.CaseInsCasePresFilenameFeature]
 
539
    _test_needs_features = [features.CaseInsCasePresFilenameFeature]
478
540
 
479
541
    def test_canonical_relpath_simple(self):
480
542
        f = file('MixedCaseName', 'w')
481
543
        f.close()
482
544
        actual = osutils.canonical_relpath(self.test_base_dir, 'mixedcasename')
483
 
        self.failUnlessEqual('work/MixedCaseName', actual)
 
545
        self.assertEqual('work/MixedCaseName', actual)
484
546
 
485
547
    def test_canonical_relpath_missing_tail(self):
486
548
        os.mkdir('MixedCaseParent')
487
549
        actual = osutils.canonical_relpath(self.test_base_dir,
488
550
                                           'mixedcaseparent/nochild')
489
 
        self.failUnlessEqual('work/MixedCaseParent/nochild', actual)
 
551
        self.assertEqual('work/MixedCaseParent/nochild', actual)
490
552
 
491
553
 
492
554
class Test_CICPCanonicalRelpath(tests.TestCaseWithTransport):
536
598
    """Test pumpfile method."""
537
599
 
538
600
    def setUp(self):
539
 
        tests.TestCase.setUp(self)
 
601
        super(TestPumpFile, self).setUp()
540
602
        # create a test datablock
541
603
        self.block_size = 512
542
604
        pattern = '0123456789ABCDEF'
810
872
        self.assertEqual(None, osutils.safe_file_id(None))
811
873
 
812
874
 
 
875
class TestSendAll(tests.TestCase):
 
876
 
 
877
    def test_send_with_disconnected_socket(self):
 
878
        class DisconnectedSocket(object):
 
879
            def __init__(self, err):
 
880
                self.err = err
 
881
            def send(self, content):
 
882
                raise self.err
 
883
            def close(self):
 
884
                pass
 
885
        # All of these should be treated as ConnectionReset
 
886
        errs = []
 
887
        for err_cls in (IOError, socket.error):
 
888
            for errnum in osutils._end_of_stream_errors:
 
889
                errs.append(err_cls(errnum))
 
890
        for err in errs:
 
891
            sock = DisconnectedSocket(err)
 
892
            self.assertRaises(errors.ConnectionReset,
 
893
                osutils.send_all, sock, 'some more content')
 
894
 
 
895
    def test_send_with_no_progress(self):
 
896
        # See https://bugs.launchpad.net/bzr/+bug/1047309
 
897
        # It seems that paramiko can get into a state where it doesn't error,
 
898
        # but it returns 0 bytes sent for requests over and over again.
 
899
        class NoSendingSocket(object):
 
900
            def __init__(self):
 
901
                self.call_count = 0
 
902
            def send(self, bytes):
 
903
                self.call_count += 1
 
904
                if self.call_count > 100:
 
905
                    # Prevent the test suite from hanging
 
906
                    raise RuntimeError('too many calls')
 
907
                return 0
 
908
        sock = NoSendingSocket()
 
909
        self.assertRaises(errors.ConnectionReset,
 
910
                          osutils.send_all, sock, 'content')
 
911
        self.assertEqual(1, sock.call_count)
 
912
 
 
913
 
 
914
class TestPosixFuncs(tests.TestCase):
 
915
    """Test that the posix version of normpath returns an appropriate path
 
916
       when used with 2 leading slashes."""
 
917
 
 
918
    def test_normpath(self):
 
919
        self.assertEqual('/etc/shadow', osutils._posix_normpath('/etc/shadow'))
 
920
        self.assertEqual('/etc/shadow', osutils._posix_normpath('//etc/shadow'))
 
921
        self.assertEqual('/etc/shadow', osutils._posix_normpath('///etc/shadow'))
 
922
 
 
923
 
813
924
class TestWin32Funcs(tests.TestCase):
814
925
    """Test that _win32 versions of os utilities return appropriate paths."""
815
926
 
832
943
                         osutils._win32_pathjoin('path/to', 'C:/foo'))
833
944
        self.assertEqual('path/to/foo',
834
945
                         osutils._win32_pathjoin('path/to/', 'foo'))
835
 
        self.assertEqual('/foo',
 
946
 
 
947
    def test_pathjoin_late_bugfix(self):
 
948
        if sys.version_info < (2, 7, 6):
 
949
            expected = '/foo'
 
950
        else:
 
951
            expected = 'C:/foo'
 
952
        self.assertEqual(expected,
836
953
                         osutils._win32_pathjoin('C:/path/to/', '/foo'))
837
 
        self.assertEqual('/foo',
 
954
        self.assertEqual(expected,
838
955
                         osutils._win32_pathjoin('C:\\path\\to\\', '\\foo'))
839
956
 
840
957
    def test_normpath(self):
868
985
        self.assertEqual('//HOST/path', osutils._win98_abspath('//HOST/path'))
869
986
        # relative path
870
987
        cwd = osutils.getcwd().rstrip('/')
871
 
        drive = osutils._nt_splitdrive(cwd)[0]
 
988
        drive = osutils.ntpath.splitdrive(cwd)[0]
872
989
        self.assertEqual(cwd+'/path', osutils._win98_abspath('path'))
873
990
        self.assertEqual(drive+'/path', osutils._win98_abspath('/path'))
874
991
        # unicode path
880
997
    """Test win32 functions that create files."""
881
998
 
882
999
    def test_getcwd(self):
883
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1000
        self.requireFeature(features.UnicodeFilenameFeature)
884
1001
        os.mkdir(u'mu-\xb5')
885
1002
        os.chdir(u'mu-\xb5')
886
1003
        # TODO: jam 20060427 This will probably fail on Mac OSX because
916
1033
        b.close()
917
1034
 
918
1035
        osutils._win32_rename('b', 'a')
919
 
        self.failUnlessExists('a')
920
 
        self.failIfExists('b')
 
1036
        self.assertPathExists('a')
 
1037
        self.assertPathDoesNotExist('b')
921
1038
        self.assertFileEqual('baz\n', 'a')
922
1039
 
923
1040
    def test_rename_missing_file(self):
976
1093
    """Test mac special functions that require directories."""
977
1094
 
978
1095
    def test_getcwd(self):
979
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1096
        self.requireFeature(features.UnicodeFilenameFeature)
980
1097
        os.mkdir(u'B\xe5gfors')
981
1098
        os.chdir(u'B\xe5gfors')
982
1099
        self.assertEndsWith(osutils._mac_getcwd(), u'B\xe5gfors')
983
1100
 
984
1101
    def test_getcwd_nonnorm(self):
985
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1102
        self.requireFeature(features.UnicodeFilenameFeature)
986
1103
        # Test that _mac_getcwd() will normalize this path
987
1104
        os.mkdir(u'Ba\u030agfors')
988
1105
        os.chdir(u'Ba\u030agfors')
1071
1188
        self.assertExpectedBlocks(expected_dirblocks[1:], result)
1072
1189
 
1073
1190
    def test_walkdirs_os_error(self):
1074
 
        # <https://bugs.edge.launchpad.net/bzr/+bug/338653>
 
1191
        # <https://bugs.launchpad.net/bzr/+bug/338653>
1075
1192
        # Pyrex readdir didn't raise useful messages if it had an error
1076
1193
        # reading the directory
1077
1194
        if sys.platform == 'win32':
1078
1195
            raise tests.TestNotApplicable(
1079
1196
                "readdir IOError not tested on win32")
 
1197
        self.requireFeature(features.not_running_as_root)
1080
1198
        os.mkdir("test-unreadable")
1081
1199
        os.chmod("test-unreadable", 0000)
1082
1200
        # must chmod it back so that it can be removed
1090
1208
        # Ensure the message contains the file name
1091
1209
        self.assertContainsRe(str(e), "\./test-unreadable")
1092
1210
 
 
1211
 
 
1212
    def test_walkdirs_encoding_error(self):
 
1213
        # <https://bugs.launchpad.net/bzr/+bug/488519>
 
1214
        # walkdirs didn't raise a useful message when the filenames
 
1215
        # are not using the filesystem's encoding
 
1216
 
 
1217
        # require a bytestring based filesystem
 
1218
        self.requireFeature(features.ByteStringNamedFilesystem)
 
1219
 
 
1220
        tree = [
 
1221
            '.bzr',
 
1222
            '0file',
 
1223
            '1dir/',
 
1224
            '1dir/0file',
 
1225
            '1dir/1dir/',
 
1226
            '1file'
 
1227
            ]
 
1228
 
 
1229
        self.build_tree(tree)
 
1230
 
 
1231
        # rename the 1file to a latin-1 filename
 
1232
        os.rename("./1file", "\xe8file")
 
1233
        if "\xe8file" not in os.listdir("."):
 
1234
            self.skip("Lack filesystem that preserves arbitrary bytes")
 
1235
 
 
1236
        self._save_platform_info()
 
1237
        win32utils.winver = None # Avoid the win32 detection code
 
1238
        osutils._fs_enc = 'UTF-8'
 
1239
 
 
1240
        # this should raise on error
 
1241
        def attempt():
 
1242
            for dirdetail, dirblock in osutils.walkdirs('.'):
 
1243
                pass
 
1244
 
 
1245
        self.assertRaises(errors.BadFilenameEncoding, attempt)
 
1246
 
1093
1247
    def test__walkdirs_utf8(self):
1094
1248
        tree = [
1095
1249
            '.bzr',
1161
1315
        self.requireFeature(UTF8DirReaderFeature)
1162
1316
        self._save_platform_info()
1163
1317
        win32utils.winver = None # Avoid the win32 detection code
1164
 
        osutils._fs_enc = 'UTF-8'
1165
 
        self.assertDirReaderIs(UTF8DirReaderFeature.reader)
 
1318
        osutils._fs_enc = 'utf-8'
 
1319
        self.assertDirReaderIs(
 
1320
            UTF8DirReaderFeature.module.UTF8DirReader)
1166
1321
 
1167
1322
    def test_force_walkdirs_utf8_fs_ascii(self):
1168
1323
        self.requireFeature(UTF8DirReaderFeature)
1169
1324
        self._save_platform_info()
1170
1325
        win32utils.winver = None # Avoid the win32 detection code
1171
 
        osutils._fs_enc = 'US-ASCII'
1172
 
        self.assertDirReaderIs(UTF8DirReaderFeature.reader)
1173
 
 
1174
 
    def test_force_walkdirs_utf8_fs_ANSI(self):
1175
 
        self.requireFeature(UTF8DirReaderFeature)
1176
 
        self._save_platform_info()
1177
 
        win32utils.winver = None # Avoid the win32 detection code
1178
 
        osutils._fs_enc = 'ANSI_X3.4-1968'
1179
 
        self.assertDirReaderIs(UTF8DirReaderFeature.reader)
 
1326
        osutils._fs_enc = 'ascii'
 
1327
        self.assertDirReaderIs(
 
1328
            UTF8DirReaderFeature.module.UTF8DirReader)
1180
1329
 
1181
1330
    def test_force_walkdirs_utf8_fs_latin1(self):
1182
1331
        self._save_platform_info()
1183
1332
        win32utils.winver = None # Avoid the win32 detection code
1184
 
        osutils._fs_enc = 'latin1'
 
1333
        osutils._fs_enc = 'iso-8859-1'
1185
1334
        self.assertDirReaderIs(osutils.UnicodeDirReader)
1186
1335
 
1187
1336
    def test_force_walkdirs_utf8_nt(self):
1200
1349
 
1201
1350
    def test_unicode_walkdirs(self):
1202
1351
        """Walkdirs should always return unicode paths."""
1203
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1352
        self.requireFeature(features.UnicodeFilenameFeature)
1204
1353
        name0 = u'0file-\xb6'
1205
1354
        name1 = u'1dir-\u062c\u0648'
1206
1355
        name2 = u'2file-\u0633'
1243
1392
 
1244
1393
        The abspath portion might be in unicode or utf-8
1245
1394
        """
1246
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1395
        self.requireFeature(features.UnicodeFilenameFeature)
1247
1396
        name0 = u'0file-\xb6'
1248
1397
        name1 = u'1dir-\u062c\u0648'
1249
1398
        name2 = u'2file-\u0633'
1304
1453
 
1305
1454
        The abspath portion should be in unicode
1306
1455
        """
1307
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1456
        self.requireFeature(features.UnicodeFilenameFeature)
1308
1457
        # Use the unicode reader. TODO: split into driver-and-driven unit
1309
1458
        # tests.
1310
1459
        self._save_platform_info()
1351
1500
 
1352
1501
    def test__walkdirs_utf8_win32readdir(self):
1353
1502
        self.requireFeature(test__walkdirs_win32.win32_readdir_feature)
1354
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1503
        self.requireFeature(features.UnicodeFilenameFeature)
1355
1504
        from bzrlib._walkdirs_win32 import Win32ReadDir
1356
1505
        self._save_platform_info()
1357
1506
        osutils._selected_dir_reader = Win32ReadDir()
1408
1557
    def test__walkdirs_utf_win32_find_file_stat_file(self):
1409
1558
        """make sure our Stat values are valid"""
1410
1559
        self.requireFeature(test__walkdirs_win32.win32_readdir_feature)
1411
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1560
        self.requireFeature(features.UnicodeFilenameFeature)
1412
1561
        from bzrlib._walkdirs_win32 import Win32ReadDir
1413
1562
        name0u = u'0file-\xb6'
1414
1563
        name0 = name0u.encode('utf8')
1432
1581
    def test__walkdirs_utf_win32_find_file_stat_directory(self):
1433
1582
        """make sure our Stat values are valid"""
1434
1583
        self.requireFeature(test__walkdirs_win32.win32_readdir_feature)
1435
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1584
        self.requireFeature(features.UnicodeFilenameFeature)
1436
1585
        from bzrlib._walkdirs_win32 import Win32ReadDir
1437
1586
        name0u = u'0dir-\u062c\u0648'
1438
1587
        name0 = name0u.encode('utf8')
1538
1687
        self.assertEqual(['c'], os.listdir('target/b'))
1539
1688
 
1540
1689
    def test_copy_tree_symlinks(self):
1541
 
        self.requireFeature(tests.SymlinkFeature)
 
1690
        self.requireFeature(features.SymlinkFeature)
1542
1691
        self.build_tree(['source/'])
1543
1692
        os.symlink('a/generic/path', 'source/lnk')
1544
1693
        osutils.copy_tree('source', 'target')
1569
1718
                          ('d', 'source/b', 'target/b'),
1570
1719
                          ('f', 'source/b/c', 'target/b/c'),
1571
1720
                         ], processed_files)
1572
 
        self.failIfExists('target')
 
1721
        self.assertPathDoesNotExist('target')
1573
1722
        if osutils.has_symlinks():
1574
1723
            self.assertEqual([('source/lnk', 'target/lnk')], processed_links)
1575
1724
 
1621
1770
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', None)
1622
1771
        self.assertEqual('foo', old)
1623
1772
        self.assertEqual(None, os.environ.get('BZR_TEST_ENV_VAR'))
1624
 
        self.failIf('BZR_TEST_ENV_VAR' in os.environ)
 
1773
        self.assertFalse('BZR_TEST_ENV_VAR' in os.environ)
1625
1774
 
1626
1775
 
1627
1776
class TestSizeShaFile(tests.TestCaseInTempDir):
1678
1827
 
1679
1828
class TestReCompile(tests.TestCase):
1680
1829
 
 
1830
    def _deprecated_re_compile_checked(self, *args, **kwargs):
 
1831
        return self.applyDeprecated(symbol_versioning.deprecated_in((2, 2, 0)),
 
1832
            osutils.re_compile_checked, *args, **kwargs)
 
1833
 
1681
1834
    def test_re_compile_checked(self):
1682
 
        r = osutils.re_compile_checked(r'A*', re.IGNORECASE)
 
1835
        r = self._deprecated_re_compile_checked(r'A*', re.IGNORECASE)
1683
1836
        self.assertTrue(r.match('aaaa'))
1684
1837
        self.assertTrue(r.match('aAaA'))
1685
1838
 
1686
1839
    def test_re_compile_checked_error(self):
1687
1840
        # like https://bugs.launchpad.net/bzr/+bug/251352
 
1841
 
 
1842
        # Due to possible test isolation error, re.compile is not lazy at
 
1843
        # this point. We re-install lazy compile.
 
1844
        lazy_regex.install_lazy_compile()
1688
1845
        err = self.assertRaises(
1689
1846
            errors.BzrCommandError,
1690
 
            osutils.re_compile_checked, '*', re.IGNORECASE, 'test case')
 
1847
            self._deprecated_re_compile_checked, '*', re.IGNORECASE, 'test case')
1691
1848
        self.assertEqual(
1692
 
            "Invalid regular expression in test case: '*': "
1693
 
            "nothing to repeat",
 
1849
            'Invalid regular expression in test case: '
 
1850
            '"*" nothing to repeat',
1694
1851
            str(err))
1695
1852
 
1696
1853
 
1697
1854
class TestDirReader(tests.TestCaseInTempDir):
1698
1855
 
 
1856
    scenarios = dir_reader_scenarios()
 
1857
 
1699
1858
    # Set by load_tests
1700
1859
    _dir_reader_class = None
1701
1860
    _native_to_unicode = None
1702
1861
 
1703
1862
    def setUp(self):
1704
 
        tests.TestCaseInTempDir.setUp(self)
 
1863
        super(TestDirReader, self).setUp()
1705
1864
        self.overrideAttr(osutils,
1706
1865
                          '_selected_dir_reader', self._dir_reader_class())
1707
1866
 
1801
1960
        return filtered_dirblocks
1802
1961
 
1803
1962
    def test_walk_unicode_tree(self):
1804
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1963
        self.requireFeature(features.UnicodeFilenameFeature)
1805
1964
        tree, expected_dirblocks = self._get_unicode_tree()
1806
1965
        self.build_tree(tree)
1807
1966
        result = list(osutils._walkdirs_utf8('.'))
1808
1967
        self.assertEqual(expected_dirblocks, self._filter_out(result))
1809
1968
 
1810
1969
    def test_symlink(self):
1811
 
        self.requireFeature(tests.SymlinkFeature)
1812
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1970
        self.requireFeature(features.SymlinkFeature)
 
1971
        self.requireFeature(features.UnicodeFilenameFeature)
1813
1972
        target = u'target\N{Euro Sign}'
1814
1973
        link_name = u'l\N{Euro Sign}nk'
1815
1974
        os.symlink(target, link_name)
1833
1992
    But prior python versions failed to properly encode the passed unicode
1834
1993
    string.
1835
1994
    """
1836
 
    _test_needs_features = [tests.SymlinkFeature, tests.UnicodeFilenameFeature]
 
1995
    _test_needs_features = [features.SymlinkFeature, features.UnicodeFilenameFeature]
1837
1996
 
1838
1997
    def setUp(self):
1839
1998
        super(tests.TestCaseInTempDir, self).setUp()
1842
2001
        os.symlink(self.target, self.link)
1843
2002
 
1844
2003
    def test_os_readlink_link_encoding(self):
1845
 
        if sys.version_info < (2, 6):
1846
 
            self.assertRaises(UnicodeEncodeError, os.readlink, self.link)
1847
 
        else:
1848
 
            self.assertEquals(self.target,  os.readlink(self.link))
 
2004
        self.assertEquals(self.target,  os.readlink(self.link))
1849
2005
 
1850
2006
    def test_os_readlink_link_decoding(self):
1851
2007
        self.assertEquals(self.target.encode(osutils._fs_enc),
1863
2019
        self.assertIsInstance(concurrency, int)
1864
2020
 
1865
2021
    def test_local_concurrency_environment_variable(self):
1866
 
        os.environ['BZR_CONCURRENCY'] = '2'
 
2022
        self.overrideEnv('BZR_CONCURRENCY', '2')
1867
2023
        self.assertEqual(2, osutils.local_concurrency(use_cache=False))
1868
 
        os.environ['BZR_CONCURRENCY'] = '3'
 
2024
        self.overrideEnv('BZR_CONCURRENCY', '3')
1869
2025
        self.assertEqual(3, osutils.local_concurrency(use_cache=False))
1870
 
        os.environ['BZR_CONCURRENCY'] = 'foo'
 
2026
        self.overrideEnv('BZR_CONCURRENCY', 'foo')
1871
2027
        self.assertEqual(1, osutils.local_concurrency(use_cache=False))
1872
2028
 
1873
2029
    def test_option_concurrency(self):
1874
 
        os.environ['BZR_CONCURRENCY'] = '1'
 
2030
        self.overrideEnv('BZR_CONCURRENCY', '1')
1875
2031
        self.run_bzr('rocks --concurrency 42')
1876
 
        # Command line overrides envrionment variable
 
2032
        # Command line overrides environment variable
1877
2033
        self.assertEquals('42', os.environ['BZR_CONCURRENCY'])
1878
2034
        self.assertEquals(42, osutils.local_concurrency(use_cache=False))
1879
2035
 
1917
2073
 
1918
2074
class TestTerminalWidth(tests.TestCase):
1919
2075
 
 
2076
    def setUp(self):
 
2077
        super(TestTerminalWidth, self).setUp()
 
2078
        self._orig_terminal_size_state = osutils._terminal_size_state
 
2079
        self._orig_first_terminal_size = osutils._first_terminal_size
 
2080
        self.addCleanup(self.restore_osutils_globals)
 
2081
        osutils._terminal_size_state = 'no_data'
 
2082
        osutils._first_terminal_size = None
 
2083
 
 
2084
    def restore_osutils_globals(self):
 
2085
        osutils._terminal_size_state = self._orig_terminal_size_state
 
2086
        osutils._first_terminal_size = self._orig_first_terminal_size
 
2087
 
1920
2088
    def replace_stdout(self, new):
1921
2089
        self.overrideAttr(sys, 'stdout', new)
1922
2090
 
1937
2105
    def test_defaults_to_BZR_COLUMNS(self):
1938
2106
        # BZR_COLUMNS is set by the test framework
1939
2107
        self.assertNotEqual('12', os.environ['BZR_COLUMNS'])
1940
 
        os.environ['BZR_COLUMNS'] = '12'
 
2108
        self.overrideEnv('BZR_COLUMNS', '12')
1941
2109
        self.assertEqual(12, osutils.terminal_width())
1942
2110
 
 
2111
    def test_BZR_COLUMNS_0_no_limit(self):
 
2112
        self.overrideEnv('BZR_COLUMNS', '0')
 
2113
        self.assertEqual(None, osutils.terminal_width())
 
2114
 
1943
2115
    def test_falls_back_to_COLUMNS(self):
1944
 
        del os.environ['BZR_COLUMNS']
 
2116
        self.overrideEnv('BZR_COLUMNS', None)
1945
2117
        self.assertNotEqual('42', os.environ['COLUMNS'])
1946
2118
        self.set_fake_tty()
1947
 
        os.environ['COLUMNS'] = '42'
 
2119
        self.overrideEnv('COLUMNS', '42')
1948
2120
        self.assertEqual(42, osutils.terminal_width())
1949
2121
 
1950
2122
    def test_tty_default_without_columns(self):
1951
 
        del os.environ['BZR_COLUMNS']
1952
 
        del os.environ['COLUMNS']
 
2123
        self.overrideEnv('BZR_COLUMNS', None)
 
2124
        self.overrideEnv('COLUMNS', None)
1953
2125
 
1954
2126
        def terminal_size(w, h):
1955
2127
            return 42, 42
1962
2134
        self.assertEqual(42, osutils.terminal_width())
1963
2135
 
1964
2136
    def test_non_tty_default_without_columns(self):
1965
 
        del os.environ['BZR_COLUMNS']
1966
 
        del os.environ['COLUMNS']
 
2137
        self.overrideEnv('BZR_COLUMNS', None)
 
2138
        self.overrideEnv('COLUMNS', None)
1967
2139
        self.replace_stdout(None)
1968
2140
        self.assertEqual(None, osutils.terminal_width())
1969
2141
 
1979
2151
        else:
1980
2152
            self.overrideAttr(termios, 'TIOCGWINSZ')
1981
2153
            del termios.TIOCGWINSZ
1982
 
        del os.environ['BZR_COLUMNS']
1983
 
        del os.environ['COLUMNS']
 
2154
        self.overrideEnv('BZR_COLUMNS', None)
 
2155
        self.overrideEnv('COLUMNS', None)
1984
2156
        # Whatever the result is, if we don't raise an exception, it's ok.
1985
2157
        osutils.terminal_width()
1986
2158
 
 
2159
 
1987
2160
class TestCreationOps(tests.TestCaseInTempDir):
1988
2161
    _test_needs_features = [features.chown_feature]
1989
2162
 
1990
2163
    def setUp(self):
1991
 
        tests.TestCaseInTempDir.setUp(self)
 
2164
        super(TestCreationOps, self).setUp()
1992
2165
        self.overrideAttr(os, 'chown', self._dummy_chown)
1993
2166
 
1994
2167
        # params set by call to _dummy_chown
2018
2191
        self.assertEquals(self.path, 'test_file')
2019
2192
        self.assertEquals(self.uid, s.st_uid)
2020
2193
        self.assertEquals(self.gid, s.st_gid)
 
2194
 
 
2195
 
 
2196
class TestPathFromEnviron(tests.TestCase):
 
2197
 
 
2198
    def test_is_unicode(self):
 
2199
        self.overrideEnv('BZR_TEST_PATH', './anywhere at all/')
 
2200
        path = osutils.path_from_environ('BZR_TEST_PATH')
 
2201
        self.assertIsInstance(path, unicode)
 
2202
        self.assertEqual(u'./anywhere at all/', path)
 
2203
 
 
2204
    def test_posix_path_env_ascii(self):
 
2205
        self.overrideEnv('BZR_TEST_PATH', '/tmp')
 
2206
        home = osutils._posix_path_from_environ('BZR_TEST_PATH')
 
2207
        self.assertIsInstance(home, unicode)
 
2208
        self.assertEqual(u'/tmp', home)
 
2209
 
 
2210
    def test_posix_path_env_unicode(self):
 
2211
        self.requireFeature(features.ByteStringNamedFilesystem)
 
2212
        self.overrideEnv('BZR_TEST_PATH', '/home/\xa7test')
 
2213
        self.overrideAttr(osutils, "_fs_enc", "iso8859-1")
 
2214
        self.assertEqual(u'/home/\xa7test',
 
2215
            osutils._posix_path_from_environ('BZR_TEST_PATH'))
 
2216
        osutils._fs_enc = "iso8859-5"
 
2217
        self.assertEqual(u'/home/\u0407test',
 
2218
            osutils._posix_path_from_environ('BZR_TEST_PATH'))
 
2219
        osutils._fs_enc = "utf-8"
 
2220
        self.assertRaises(errors.BadFilenameEncoding,
 
2221
            osutils._posix_path_from_environ, 'BZR_TEST_PATH')
 
2222
 
 
2223
 
 
2224
class TestGetHomeDir(tests.TestCase):
 
2225
 
 
2226
    def test_is_unicode(self):
 
2227
        home = osutils._get_home_dir()
 
2228
        self.assertIsInstance(home, unicode)
 
2229
 
 
2230
    def test_posix_homeless(self):
 
2231
        self.overrideEnv('HOME', None)
 
2232
        home = osutils._get_home_dir()
 
2233
        self.assertIsInstance(home, unicode)
 
2234
 
 
2235
    def test_posix_home_ascii(self):
 
2236
        self.overrideEnv('HOME', '/home/test')
 
2237
        home = osutils._posix_get_home_dir()
 
2238
        self.assertIsInstance(home, unicode)
 
2239
        self.assertEqual(u'/home/test', home)
 
2240
 
 
2241
    def test_posix_home_unicode(self):
 
2242
        self.requireFeature(features.ByteStringNamedFilesystem)
 
2243
        self.overrideEnv('HOME', '/home/\xa7test')
 
2244
        self.overrideAttr(osutils, "_fs_enc", "iso8859-1")
 
2245
        self.assertEqual(u'/home/\xa7test', osutils._posix_get_home_dir())
 
2246
        osutils._fs_enc = "iso8859-5"
 
2247
        self.assertEqual(u'/home/\u0407test', osutils._posix_get_home_dir())
 
2248
        osutils._fs_enc = "utf-8"
 
2249
        self.assertRaises(errors.BadFilenameEncoding,
 
2250
            osutils._posix_get_home_dir)
 
2251
 
 
2252
 
 
2253
class TestGetuserUnicode(tests.TestCase):
 
2254
 
 
2255
    def test_is_unicode(self):
 
2256
        user = osutils.getuser_unicode()
 
2257
        self.assertIsInstance(user, unicode)
 
2258
 
 
2259
    def envvar_to_override(self):
 
2260
        if sys.platform == "win32":
 
2261
            # Disable use of platform calls on windows so envvar is used
 
2262
            self.overrideAttr(win32utils, 'has_ctypes', False)
 
2263
            return 'USERNAME' # only variable used on windows
 
2264
        return 'LOGNAME' # first variable checked by getpass.getuser()
 
2265
 
 
2266
    def test_ascii_user(self):
 
2267
        self.overrideEnv(self.envvar_to_override(), 'jrandom')
 
2268
        self.assertEqual(u'jrandom', osutils.getuser_unicode())
 
2269
 
 
2270
    def test_unicode_user(self):
 
2271
        ue = osutils.get_user_encoding()
 
2272
        uni_val, env_val = tests.probe_unicode_in_user_encoding()
 
2273
        if uni_val is None:
 
2274
            raise tests.TestSkipped(
 
2275
                'Cannot find a unicode character that works in encoding %s'
 
2276
                % (osutils.get_user_encoding(),))
 
2277
        uni_username = u'jrandom' + uni_val
 
2278
        encoded_username = uni_username.encode(ue)
 
2279
        self.overrideEnv(self.envvar_to_override(), encoded_username)
 
2280
        self.assertEqual(uni_username, osutils.getuser_unicode())
 
2281
 
 
2282
 
 
2283
class TestBackupNames(tests.TestCase):
 
2284
 
 
2285
    def setUp(self):
 
2286
        super(TestBackupNames, self).setUp()
 
2287
        self.backups = []
 
2288
 
 
2289
    def backup_exists(self, name):
 
2290
        return name in self.backups
 
2291
 
 
2292
    def available_backup_name(self, name):
 
2293
        backup_name = osutils.available_backup_name(name, self.backup_exists)
 
2294
        self.backups.append(backup_name)
 
2295
        return backup_name
 
2296
 
 
2297
    def assertBackupName(self, expected, name):
 
2298
        self.assertEqual(expected, self.available_backup_name(name))
 
2299
 
 
2300
    def test_empty(self):
 
2301
        self.assertBackupName('file.~1~', 'file')
 
2302
 
 
2303
    def test_existing(self):
 
2304
        self.available_backup_name('file')
 
2305
        self.available_backup_name('file')
 
2306
        self.assertBackupName('file.~3~', 'file')
 
2307
        # Empty slots are found, this is not a strict requirement and may be
 
2308
        # revisited if we test against all implementations.
 
2309
        self.backups.remove('file.~2~')
 
2310
        self.assertBackupName('file.~2~', 'file')
 
2311
 
 
2312
 
 
2313
class TestFindExecutableInPath(tests.TestCase):
 
2314
 
 
2315
    def test_windows(self):
 
2316
        if sys.platform != 'win32':
 
2317
            raise tests.TestSkipped('test requires win32')
 
2318
        self.assertTrue(osutils.find_executable_on_path('explorer') is not None)
 
2319
        self.assertTrue(
 
2320
            osutils.find_executable_on_path('explorer.exe') is not None)
 
2321
        self.assertTrue(
 
2322
            osutils.find_executable_on_path('EXPLORER.EXE') is not None)
 
2323
        self.assertTrue(
 
2324
            osutils.find_executable_on_path('THIS SHOULD NOT EXIST') is None)
 
2325
        self.assertTrue(osutils.find_executable_on_path('file.txt') is None)
 
2326
        
 
2327
    def test_windows_app_path(self):
 
2328
        if sys.platform != 'win32':
 
2329
            raise tests.TestSkipped('test requires win32')
 
2330
        # Override PATH env var so that exe can only be found on App Path
 
2331
        self.overrideEnv('PATH', '')
 
2332
        # Internt Explorer is always registered in the App Path
 
2333
        self.assertTrue(osutils.find_executable_on_path('iexplore') is not None)
 
2334
 
 
2335
    def test_other(self):
 
2336
        if sys.platform == 'win32':
 
2337
            raise tests.TestSkipped('test requires non-win32')
 
2338
        self.assertTrue(osutils.find_executable_on_path('sh') is not None)
 
2339
        self.assertTrue(
 
2340
            osutils.find_executable_on_path('THIS SHOULD NOT EXIST') is None)
 
2341
 
 
2342
 
 
2343
class TestEnvironmentErrors(tests.TestCase):
 
2344
    """Test handling of environmental errors"""
 
2345
 
 
2346
    def test_is_oserror(self):
 
2347
        self.assertTrue(osutils.is_environment_error(
 
2348
            OSError(errno.EINVAL, "Invalid parameter")))
 
2349
 
 
2350
    def test_is_ioerror(self):
 
2351
        self.assertTrue(osutils.is_environment_error(
 
2352
            IOError(errno.EINVAL, "Invalid parameter")))
 
2353
 
 
2354
    def test_is_socket_error(self):
 
2355
        self.assertTrue(osutils.is_environment_error(
 
2356
            socket.error(errno.EINVAL, "Invalid parameter")))
 
2357
 
 
2358
    def test_is_select_error(self):
 
2359
        self.assertTrue(osutils.is_environment_error(
 
2360
            select.error(errno.EINVAL, "Invalid parameter")))
 
2361
 
 
2362
    def test_is_pywintypes_error(self):
 
2363
        self.requireFeature(features.pywintypes)
 
2364
        import pywintypes
 
2365
        self.assertTrue(osutils.is_environment_error(
 
2366
            pywintypes.error(errno.EINVAL, "Invalid parameter", "Caller")))