/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/__init__.py

  • Committer: John Arbash Meinel
  • Date: 2006-10-06 05:53:44 UTC
  • mfrom: (2063 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2071.
  • Revision ID: john@arbash-meinel.com-20061006055344-e73b97b7c6ca6e72
[merge] bzr.dev 2063

Show diffs side-by-side

added added

removed removed

Lines of Context:
43
43
import time
44
44
 
45
45
 
 
46
from bzrlib import memorytree
46
47
import bzrlib.branch
47
48
import bzrlib.bzrdir as bzrdir
48
49
import bzrlib.commands
49
50
import bzrlib.bundle.serializer
50
51
import bzrlib.errors as errors
 
52
import bzrlib.export
51
53
import bzrlib.inventory
52
54
import bzrlib.iterablefile
53
55
import bzrlib.lockdir
69
71
from bzrlib.transport import get_transport
70
72
import bzrlib.transport
71
73
from bzrlib.transport.local import LocalRelpathServer
 
74
from bzrlib.transport.memory import MemoryServer
72
75
from bzrlib.transport.readonly import ReadonlyServer
73
76
from bzrlib.trace import mutter
74
77
from bzrlib.tests import TestUtil
86
89
MODULES_TO_DOCTEST = [
87
90
                      bzrlib.bundle.serializer,
88
91
                      bzrlib.errors,
 
92
                      bzrlib.export,
89
93
                      bzrlib.inventory,
90
94
                      bzrlib.iterablefile,
91
95
                      bzrlib.lockdir,
92
96
                      bzrlib.merge3,
93
97
                      bzrlib.option,
94
 
                      bzrlib.store
 
98
                      bzrlib.store,
95
99
                      ]
96
100
 
97
101
 
235
239
        if isinstance(err[1], TestSkipped):
236
240
            return self.addSkipped(test, err)    
237
241
        unittest.TestResult.addError(self, test, err)
 
242
        # We can only do this if we have one of our TestCases, not if
 
243
        # we have a doctest.
 
244
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
245
        if setKeepLogfile is not None:
 
246
            setKeepLogfile()
238
247
        self.extractBenchmarkTime(test)
239
248
        if self.showAll:
240
249
            self.stream.writeln("ERROR %s" % self._testTimeString())
251
260
 
252
261
    def addFailure(self, test, err):
253
262
        unittest.TestResult.addFailure(self, test, err)
 
263
        # We can only do this if we have one of our TestCases, not if
 
264
        # we have a doctest.
 
265
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
266
        if setKeepLogfile is not None:
 
267
            setKeepLogfile()
254
268
        self.extractBenchmarkTime(test)
255
269
        if self.showAll:
256
270
            self.stream.writeln(" FAIL %s" % self._testTimeString())
377
391
        # This is still a little bogus, 
378
392
        # but only a little. Folk not using our testrunner will
379
393
        # have to delete their temp directories themselves.
380
 
        test_root = TestCaseInTempDir.TEST_ROOT
 
394
        test_root = TestCaseWithMemoryTransport.TEST_ROOT
381
395
        if result.wasSuccessful() or not self.keep_output:
382
396
            if test_root is not None:
383
397
                # If LANG=C we probably have created some bogus paths
401
415
                self.stream.writeln(
402
416
                    "Failed tests working directories are in '%s'\n" %
403
417
                    test_root)
404
 
        TestCaseInTempDir.TEST_ROOT = None
 
418
        TestCaseWithMemoryTransport.TEST_ROOT = None
405
419
        if self.pb is not None:
406
420
            self.pb.clear()
407
421
        return result
477
491
 
478
492
    _log_file_name = None
479
493
    _log_contents = ''
 
494
    _keep_log_file = False
480
495
    # record lsprof data when performing benchmark calls.
481
496
    _gather_lsprof_in_benchmarks = False
482
497
 
657
672
    def _finishLogFile(self):
658
673
        """Finished with the log file.
659
674
 
660
 
        Read contents into memory, close, and delete.
 
675
        Close the file and delete it, unless setKeepLogfile was called.
661
676
        """
662
677
        if self._log_file is None:
663
678
            return
664
679
        bzrlib.trace.disable_test_log(self._log_nonce)
665
 
        self._log_file.seek(0)
666
 
        self._log_contents = self._log_file.read()
667
680
        self._log_file.close()
668
 
        os.remove(self._log_file_name)
669
 
        self._log_file = self._log_file_name = None
 
681
        self._log_file = None
 
682
        if not self._keep_log_file:
 
683
            os.remove(self._log_file_name)
 
684
            self._log_file_name = None
 
685
 
 
686
    def setKeepLogfile(self):
 
687
        """Make the logfile not be deleted when _finishLogFile is called."""
 
688
        self._keep_log_file = True
670
689
 
671
690
    def addCleanup(self, callable):
672
691
        """Arrange to run a callable when this case is torn down.
681
700
 
682
701
    def _cleanEnvironment(self):
683
702
        new_env = {
 
703
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
684
704
            'HOME': os.getcwd(),
685
705
            'APPDATA': os.getcwd(),
686
706
            'BZR_EMAIL': None,
740
760
    def log(self, *args):
741
761
        mutter(*args)
742
762
 
743
 
    def _get_log(self):
744
 
        """Return as a string the log for this test"""
745
 
        if self._log_file_name:
746
 
            return open(self._log_file_name).read()
747
 
        else:
 
763
    def _get_log(self, keep_log_file=False):
 
764
        """Return as a string the log for this test. If the file is still
 
765
        on disk and keep_log_file=False, delete the log file and store the
 
766
        content in self._log_contents."""
 
767
        # flush the log file, to get all content
 
768
        import bzrlib.trace
 
769
        bzrlib.trace._trace_file.flush()
 
770
        if self._log_contents:
748
771
            return self._log_contents
749
 
        # TODO: Delete the log after it's been read in
 
772
        if self._log_file_name is not None:
 
773
            logfile = open(self._log_file_name)
 
774
            try:
 
775
                log_contents = logfile.read()
 
776
            finally:
 
777
                logfile.close()
 
778
            if not keep_log_file:
 
779
                self._log_contents = log_contents
 
780
                os.remove(self._log_file_name)
 
781
            return log_contents
 
782
        else:
 
783
            return "DELETED log file to reduce memory footprint"
750
784
 
751
785
    def capture(self, cmd, retcode=0):
752
786
        """Shortcut that splits cmd into words, runs, and returns stdout"""
753
787
        return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
754
788
 
755
 
    def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None):
 
789
    def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None,
 
790
                         working_dir=None):
756
791
        """Invoke bzr and return (stdout, stderr).
757
792
 
758
793
        Useful for code that wants to check the contents of the
773
808
        :param retcode: expected return code, or None for don't-care.
774
809
        :param encoding: encoding for sys.stdout and sys.stderr
775
810
        :param stdin: A string to be used as stdin for the command.
 
811
        :param working_dir: Change to this directory before running
776
812
        """
777
813
        if encoding is None:
778
814
            encoding = bzrlib.user_encoding
794
830
            stdout=stdout,
795
831
            stderr=stderr)
796
832
        bzrlib.ui.ui_factory.stdin = stdin
 
833
 
 
834
        cwd = None
 
835
        if working_dir is not None:
 
836
            cwd = osutils.getcwd()
 
837
            os.chdir(working_dir)
 
838
 
797
839
        try:
798
840
            result = self.apply_redirected(stdin, stdout, stderr,
799
841
                                           bzrlib.commands.run_bzr_catch_errors,
801
843
        finally:
802
844
            logger.removeHandler(handler)
803
845
            bzrlib.ui.ui_factory = old_ui_factory
 
846
            if cwd is not None:
 
847
                os.chdir(cwd)
804
848
 
805
849
        out = stdout.getvalue()
806
850
        err = stderr.getvalue()
827
871
        retcode = kwargs.pop('retcode', 0)
828
872
        encoding = kwargs.pop('encoding', None)
829
873
        stdin = kwargs.pop('stdin', None)
830
 
        return self.run_bzr_captured(args, retcode=retcode, encoding=encoding, stdin=stdin)
 
874
        working_dir = kwargs.pop('working_dir', None)
 
875
        return self.run_bzr_captured(args, retcode=retcode, encoding=encoding,
 
876
                                     stdin=stdin, working_dir=working_dir)
831
877
 
832
878
    def run_bzr_decode(self, *args, **kwargs):
833
879
        if 'encoding' in kwargs:
883
929
        :param universal_newlines: Convert CRLF => LF
884
930
        """
885
931
        env_changes = kwargs.get('env_changes', {})
886
 
 
 
932
        working_dir = kwargs.get('working_dir', None)
 
933
        process = self.start_bzr_subprocess(args, env_changes=env_changes,
 
934
                                            working_dir=working_dir)
 
935
        # We distinguish between retcode=None and retcode not passed.
 
936
        supplied_retcode = kwargs.get('retcode', 0)
 
937
        return self.finish_bzr_subprocess(process, retcode=supplied_retcode,
 
938
            universal_newlines=kwargs.get('universal_newlines', False),
 
939
            process_args=args)
 
940
 
 
941
    def start_bzr_subprocess(self, process_args, env_changes=None,
 
942
                             skip_if_plan_to_signal=False,
 
943
                             working_dir=None):
 
944
        """Start bzr in a subprocess for testing.
 
945
 
 
946
        This starts a new Python interpreter and runs bzr in there.
 
947
        This should only be used for tests that have a justifiable need for
 
948
        this isolation: e.g. they are testing startup time, or signal
 
949
        handling, or early startup code, etc.  Subprocess code can't be
 
950
        profiled or debugged so easily.
 
951
 
 
952
        :param process_args: a list of arguments to pass to the bzr executable,
 
953
            for example `['--version']`.
 
954
        :param env_changes: A dictionary which lists changes to environment
 
955
            variables. A value of None will unset the env variable.
 
956
            The values must be strings. The change will only occur in the
 
957
            child, so you don't need to fix the environment after running.
 
958
        :param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
 
959
            is not available.
 
960
 
 
961
        :returns: Popen object for the started process.
 
962
        """
 
963
        if skip_if_plan_to_signal:
 
964
            if not getattr(os, 'kill', None):
 
965
                raise TestSkipped("os.kill not available.")
 
966
 
 
967
        if env_changes is None:
 
968
            env_changes = {}
887
969
        old_env = {}
888
970
 
889
971
        def cleanup_environment():
894
976
            for env_var, value in old_env.iteritems():
895
977
                osutils.set_or_unset_env(env_var, value)
896
978
 
897
 
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
898
 
        args = list(args)
 
979
        bzr_path = self.get_bzr_path()
 
980
 
 
981
        cwd = None
 
982
        if working_dir is not None:
 
983
            cwd = osutils.getcwd()
 
984
            os.chdir(working_dir)
899
985
 
900
986
        try:
901
987
            # win32 subprocess doesn't support preexec_fn
902
988
            # so we will avoid using it on all platforms, just to
903
989
            # make sure the code path is used, and we don't break on win32
904
990
            cleanup_environment()
905
 
            process = Popen([sys.executable, bzr_path]+args,
906
 
                             stdout=PIPE, stderr=PIPE)
 
991
            process = Popen([sys.executable, bzr_path] + list(process_args),
 
992
                             stdin=PIPE, stdout=PIPE, stderr=PIPE)
907
993
        finally:
908
994
            restore_environment()
909
 
            
910
 
        out = process.stdout.read()
911
 
        err = process.stderr.read()
912
 
 
913
 
        if kwargs.get('universal_newlines', False):
 
995
            if cwd is not None:
 
996
                os.chdir(cwd)
 
997
 
 
998
        return process
 
999
 
 
1000
    def get_bzr_path(self):
 
1001
        """Return the path of the 'bzr' executable for this test suite."""
 
1002
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
 
1003
        if not os.path.isfile(bzr_path):
 
1004
            # We are probably installed. Assume sys.argv is the right file
 
1005
            bzr_path = sys.argv[0]
 
1006
        return bzr_path
 
1007
 
 
1008
    def finish_bzr_subprocess(self, process, retcode=0, send_signal=None,
 
1009
                              universal_newlines=False, process_args=None):
 
1010
        """Finish the execution of process.
 
1011
 
 
1012
        :param process: the Popen object returned from start_bzr_subprocess.
 
1013
        :param retcode: The status code that is expected.  Defaults to 0.  If
 
1014
            None is supplied, the status code is not checked.
 
1015
        :param send_signal: an optional signal to send to the process.
 
1016
        :param universal_newlines: Convert CRLF => LF
 
1017
        :returns: (stdout, stderr)
 
1018
        """
 
1019
        if send_signal is not None:
 
1020
            os.kill(process.pid, send_signal)
 
1021
        out, err = process.communicate()
 
1022
 
 
1023
        if universal_newlines:
914
1024
            out = out.replace('\r\n', '\n')
915
1025
            err = err.replace('\r\n', '\n')
916
1026
 
917
 
        retcode = process.wait()
918
 
        supplied_retcode = kwargs.get('retcode', 0)
919
 
        if supplied_retcode is not None:
920
 
            assert supplied_retcode == retcode
 
1027
        if retcode is not None and retcode != process.returncode:
 
1028
            if process_args is None:
 
1029
                process_args = "(unknown args)"
 
1030
            mutter('Output of bzr %s:\n%s', process_args, out)
 
1031
            mutter('Error for bzr %s:\n%s', process_args, err)
 
1032
            self.fail('Command bzr %s failed with retcode %s != %s'
 
1033
                      % (process_args, retcode, process.returncode))
921
1034
        return [out, err]
922
1035
 
923
1036
    def check_inventory_shape(self, inv, shape):
992
1105
 
993
1106
BzrTestBase = TestCase
994
1107
 
 
1108
 
 
1109
class TestCaseWithMemoryTransport(TestCase):
 
1110
    """Common test class for tests that do not need disk resources.
 
1111
 
 
1112
    Tests that need disk resources should derive from TestCaseWithTransport.
 
1113
 
 
1114
    TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
 
1115
 
 
1116
    For TestCaseWithMemoryTransport the test_home_dir is set to the name of
 
1117
    a directory which does not exist. This serves to help ensure test isolation
 
1118
    is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
 
1119
    must exist. However, TestCaseWithMemoryTransport does not offer local
 
1120
    file defaults for the transport in tests, nor does it obey the command line
 
1121
    override, so tests that accidentally write to the common directory should
 
1122
    be rare.
 
1123
    """
 
1124
 
 
1125
    TEST_ROOT = None
 
1126
    _TEST_NAME = 'test'
 
1127
 
 
1128
 
 
1129
    def __init__(self, methodName='runTest'):
 
1130
        # allow test parameterisation after test construction and before test
 
1131
        # execution. Variables that the parameteriser sets need to be 
 
1132
        # ones that are not set by setUp, or setUp will trash them.
 
1133
        super(TestCaseWithMemoryTransport, self).__init__(methodName)
 
1134
        self.transport_server = default_transport
 
1135
        self.transport_readonly_server = None
 
1136
 
 
1137
    def failUnlessExists(self, path):
 
1138
        """Fail unless path, which may be abs or relative, exists."""
 
1139
        self.failUnless(osutils.lexists(path))
 
1140
 
 
1141
    def failIfExists(self, path):
 
1142
        """Fail if path, which may be abs or relative, exists."""
 
1143
        self.failIf(osutils.lexists(path))
 
1144
        
 
1145
    def get_transport(self):
 
1146
        """Return a writeable transport for the test scratch space"""
 
1147
        t = get_transport(self.get_url())
 
1148
        self.assertFalse(t.is_readonly())
 
1149
        return t
 
1150
 
 
1151
    def get_readonly_transport(self):
 
1152
        """Return a readonly transport for the test scratch space
 
1153
        
 
1154
        This can be used to test that operations which should only need
 
1155
        readonly access in fact do not try to write.
 
1156
        """
 
1157
        t = get_transport(self.get_readonly_url())
 
1158
        self.assertTrue(t.is_readonly())
 
1159
        return t
 
1160
 
 
1161
    def get_readonly_server(self):
 
1162
        """Get the server instance for the readonly transport
 
1163
 
 
1164
        This is useful for some tests with specific servers to do diagnostics.
 
1165
        """
 
1166
        if self.__readonly_server is None:
 
1167
            if self.transport_readonly_server is None:
 
1168
                # readonly decorator requested
 
1169
                # bring up the server
 
1170
                self.get_url()
 
1171
                self.__readonly_server = ReadonlyServer()
 
1172
                self.__readonly_server.setUp(self.__server)
 
1173
            else:
 
1174
                self.__readonly_server = self.transport_readonly_server()
 
1175
                self.__readonly_server.setUp()
 
1176
            self.addCleanup(self.__readonly_server.tearDown)
 
1177
        return self.__readonly_server
 
1178
 
 
1179
    def get_readonly_url(self, relpath=None):
 
1180
        """Get a URL for the readonly transport.
 
1181
 
 
1182
        This will either be backed by '.' or a decorator to the transport 
 
1183
        used by self.get_url()
 
1184
        relpath provides for clients to get a path relative to the base url.
 
1185
        These should only be downwards relative, not upwards.
 
1186
        """
 
1187
        base = self.get_readonly_server().get_url()
 
1188
        if relpath is not None:
 
1189
            if not base.endswith('/'):
 
1190
                base = base + '/'
 
1191
            base = base + relpath
 
1192
        return base
 
1193
 
 
1194
    def get_server(self):
 
1195
        """Get the read/write server instance.
 
1196
 
 
1197
        This is useful for some tests with specific servers that need
 
1198
        diagnostics.
 
1199
 
 
1200
        For TestCaseWithMemoryTransport this is always a MemoryServer, and there
 
1201
        is no means to override it.
 
1202
        """
 
1203
        if self.__server is None:
 
1204
            self.__server = MemoryServer()
 
1205
            self.__server.setUp()
 
1206
            self.addCleanup(self.__server.tearDown)
 
1207
        return self.__server
 
1208
 
 
1209
    def get_url(self, relpath=None):
 
1210
        """Get a URL (or maybe a path) for the readwrite transport.
 
1211
 
 
1212
        This will either be backed by '.' or to an equivalent non-file based
 
1213
        facility.
 
1214
        relpath provides for clients to get a path relative to the base url.
 
1215
        These should only be downwards relative, not upwards.
 
1216
        """
 
1217
        base = self.get_server().get_url()
 
1218
        if relpath is not None and relpath != '.':
 
1219
            if not base.endswith('/'):
 
1220
                base = base + '/'
 
1221
            # XXX: Really base should be a url; we did after all call
 
1222
            # get_url()!  But sometimes it's just a path (from
 
1223
            # LocalAbspathServer), and it'd be wrong to append urlescaped data
 
1224
            # to a non-escaped local path.
 
1225
            if base.startswith('./') or base.startswith('/'):
 
1226
                base += relpath
 
1227
            else:
 
1228
                base += urlutils.escape(relpath)
 
1229
        return base
 
1230
 
 
1231
    def _make_test_root(self):
 
1232
        if TestCaseWithMemoryTransport.TEST_ROOT is not None:
 
1233
            return
 
1234
        i = 0
 
1235
        while True:
 
1236
            root = u'test%04d.tmp' % i
 
1237
            try:
 
1238
                os.mkdir(root)
 
1239
            except OSError, e:
 
1240
                if e.errno == errno.EEXIST:
 
1241
                    i += 1
 
1242
                    continue
 
1243
                else:
 
1244
                    raise
 
1245
            # successfully created
 
1246
            TestCaseWithMemoryTransport.TEST_ROOT = osutils.abspath(root)
 
1247
            break
 
1248
        # make a fake bzr directory there to prevent any tests propagating
 
1249
        # up onto the source directory's real branch
 
1250
        bzrdir.BzrDir.create_standalone_workingtree(
 
1251
            TestCaseWithMemoryTransport.TEST_ROOT)
 
1252
 
 
1253
    def makeAndChdirToTestDir(self):
 
1254
        """Create a temporary directories for this one test.
 
1255
        
 
1256
        This must set self.test_home_dir and self.test_dir and chdir to
 
1257
        self.test_dir.
 
1258
        
 
1259
        For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
 
1260
        """
 
1261
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
 
1262
        self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
 
1263
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
 
1264
        
 
1265
    def make_branch(self, relpath, format=None):
 
1266
        """Create a branch on the transport at relpath."""
 
1267
        repo = self.make_repository(relpath, format=format)
 
1268
        return repo.bzrdir.create_branch()
 
1269
 
 
1270
    def make_bzrdir(self, relpath, format=None):
 
1271
        try:
 
1272
            # might be a relative or absolute path
 
1273
            maybe_a_url = self.get_url(relpath)
 
1274
            segments = maybe_a_url.rsplit('/', 1)
 
1275
            t = get_transport(maybe_a_url)
 
1276
            if len(segments) > 1 and segments[-1] not in ('', '.'):
 
1277
                try:
 
1278
                    t.mkdir('.')
 
1279
                except errors.FileExists:
 
1280
                    pass
 
1281
            if format is None:
 
1282
                format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
 
1283
            return format.initialize_on_transport(t)
 
1284
        except errors.UninitializableFormat:
 
1285
            raise TestSkipped("Format %s is not initializable." % format)
 
1286
 
 
1287
    def make_repository(self, relpath, shared=False, format=None):
 
1288
        """Create a repository on our default transport at relpath."""
 
1289
        made_control = self.make_bzrdir(relpath, format=format)
 
1290
        return made_control.create_repository(shared=shared)
 
1291
 
 
1292
    def make_branch_and_memory_tree(self, relpath):
 
1293
        """Create a branch on the default transport and a MemoryTree for it."""
 
1294
        b = self.make_branch(relpath)
 
1295
        return memorytree.MemoryTree.create_on_branch(b)
 
1296
 
 
1297
    def overrideEnvironmentForTesting(self):
 
1298
        os.environ['HOME'] = self.test_home_dir
 
1299
        os.environ['APPDATA'] = self.test_home_dir
 
1300
        
 
1301
    def setUp(self):
 
1302
        super(TestCaseWithMemoryTransport, self).setUp()
 
1303
        self._make_test_root()
 
1304
        _currentdir = os.getcwdu()
 
1305
        def _leaveDirectory():
 
1306
            os.chdir(_currentdir)
 
1307
        self.addCleanup(_leaveDirectory)
 
1308
        self.makeAndChdirToTestDir()
 
1309
        self.overrideEnvironmentForTesting()
 
1310
        self.__readonly_server = None
 
1311
        self.__server = None
 
1312
 
995
1313
     
996
 
class TestCaseInTempDir(TestCase):
 
1314
class TestCaseInTempDir(TestCaseWithMemoryTransport):
997
1315
    """Derived class that runs a test within a temporary directory.
998
1316
 
999
1317
    This is useful for tests that need to create a branch, etc.
1006
1324
    InTempDir is an old alias for FunctionalTestCase.
1007
1325
    """
1008
1326
 
1009
 
    TEST_ROOT = None
1010
 
    _TEST_NAME = 'test'
1011
1327
    OVERRIDE_PYTHON = 'python'
1012
1328
 
1013
1329
    def check_file_contents(self, filename, expect):
1018
1334
            self.log("actually: %r" % contents)
1019
1335
            self.fail("contents of %s not as expected" % filename)
1020
1336
 
1021
 
    def _make_test_root(self):
1022
 
        if TestCaseInTempDir.TEST_ROOT is not None:
1023
 
            return
1024
 
        i = 0
1025
 
        while True:
1026
 
            root = u'test%04d.tmp' % i
1027
 
            try:
1028
 
                os.mkdir(root)
1029
 
            except OSError, e:
1030
 
                if e.errno == errno.EEXIST:
1031
 
                    i += 1
1032
 
                    continue
1033
 
                else:
1034
 
                    raise
1035
 
            # successfully created
1036
 
            TestCaseInTempDir.TEST_ROOT = osutils.abspath(root)
1037
 
            break
1038
 
        # make a fake bzr directory there to prevent any tests propagating
1039
 
        # up onto the source directory's real branch
1040
 
        bzrdir.BzrDir.create_standalone_workingtree(TestCaseInTempDir.TEST_ROOT)
1041
 
 
1042
 
    def setUp(self):
1043
 
        super(TestCaseInTempDir, self).setUp()
1044
 
        self._make_test_root()
1045
 
        _currentdir = os.getcwdu()
 
1337
    def makeAndChdirToTestDir(self):
 
1338
        """See TestCaseWithMemoryTransport.makeAndChdirToTestDir().
 
1339
        
 
1340
        For TestCaseInTempDir we create a temporary directory based on the test
 
1341
        name and then create two subdirs - test and home under it.
 
1342
        """
1046
1343
        # shorten the name, to avoid test failures due to path length
1047
1344
        short_id = self.id().replace('bzrlib.tests.', '') \
1048
1345
                   .replace('__main__.', '')[-100:]
1065
1362
                os.mkdir(self.test_dir)
1066
1363
                os.chdir(self.test_dir)
1067
1364
                break
1068
 
        os.environ['HOME'] = self.test_home_dir
1069
 
        os.environ['APPDATA'] = self.test_home_dir
1070
 
        def _leaveDirectory():
1071
 
            os.chdir(_currentdir)
1072
 
        self.addCleanup(_leaveDirectory)
1073
 
        
 
1365
 
1074
1366
    def build_tree(self, shape, line_endings='native', transport=None):
1075
1367
        """Build a test tree according to a pattern.
1076
1368
 
1117
1409
    def build_tree_contents(self, shape):
1118
1410
        build_tree_contents(shape)
1119
1411
 
1120
 
    def failUnlessExists(self, path):
1121
 
        """Fail unless path, which may be abs or relative, exists."""
1122
 
        self.failUnless(osutils.lexists(path))
1123
 
 
1124
 
    def failIfExists(self, path):
1125
 
        """Fail if path, which may be abs or relative, exists."""
1126
 
        self.failIf(osutils.lexists(path))
1127
 
        
1128
1412
    def assertFileEqual(self, content, path):
1129
1413
        """Fail if path does not contain 'content'."""
1130
1414
        self.failUnless(osutils.lexists(path))
1146
1430
    readwrite one must both define get_url() as resolving to os.getcwd().
1147
1431
    """
1148
1432
 
1149
 
    def __init__(self, methodName='testMethod'):
1150
 
        super(TestCaseWithTransport, self).__init__(methodName)
1151
 
        self.__readonly_server = None
1152
 
        self.__server = None
1153
 
        self.transport_server = default_transport
1154
 
        self.transport_readonly_server = None
1155
 
 
1156
 
    def get_readonly_url(self, relpath=None):
1157
 
        """Get a URL for the readonly transport.
1158
 
 
1159
 
        This will either be backed by '.' or a decorator to the transport 
1160
 
        used by self.get_url()
1161
 
        relpath provides for clients to get a path relative to the base url.
1162
 
        These should only be downwards relative, not upwards.
1163
 
        """
1164
 
        base = self.get_readonly_server().get_url()
1165
 
        if relpath is not None:
1166
 
            if not base.endswith('/'):
1167
 
                base = base + '/'
1168
 
            base = base + relpath
1169
 
        return base
1170
 
 
1171
 
    def get_readonly_server(self):
1172
 
        """Get the server instance for the readonly transport
1173
 
 
1174
 
        This is useful for some tests with specific servers to do diagnostics.
1175
 
        """
1176
 
        if self.__readonly_server is None:
1177
 
            if self.transport_readonly_server is None:
1178
 
                # readonly decorator requested
1179
 
                # bring up the server
1180
 
                self.get_url()
1181
 
                self.__readonly_server = ReadonlyServer()
1182
 
                self.__readonly_server.setUp(self.__server)
1183
 
            else:
1184
 
                self.__readonly_server = self.transport_readonly_server()
1185
 
                self.__readonly_server.setUp()
1186
 
            self.addCleanup(self.__readonly_server.tearDown)
1187
 
        return self.__readonly_server
1188
 
 
1189
1433
    def get_server(self):
1190
 
        """Get the read/write server instance.
 
1434
        """See TestCaseWithMemoryTransport.
1191
1435
 
1192
1436
        This is useful for some tests with specific servers that need
1193
1437
        diagnostics.
1198
1442
            self.addCleanup(self.__server.tearDown)
1199
1443
        return self.__server
1200
1444
 
1201
 
    def get_url(self, relpath=None):
1202
 
        """Get a URL for the readwrite transport.
1203
 
 
1204
 
        This will either be backed by '.' or to an equivalent non-file based
1205
 
        facility.
1206
 
        relpath provides for clients to get a path relative to the base url.
1207
 
        These should only be downwards relative, not upwards.
1208
 
        """
1209
 
        base = self.get_server().get_url()
1210
 
        if relpath is not None and relpath != '.':
1211
 
            if not base.endswith('/'):
1212
 
                base = base + '/'
1213
 
            base = base + urlutils.escape(relpath)
1214
 
        return base
1215
 
 
1216
 
    def get_transport(self):
1217
 
        """Return a writeable transport for the test scratch space"""
1218
 
        t = get_transport(self.get_url())
1219
 
        self.assertFalse(t.is_readonly())
1220
 
        return t
1221
 
 
1222
 
    def get_readonly_transport(self):
1223
 
        """Return a readonly transport for the test scratch space
1224
 
        
1225
 
        This can be used to test that operations which should only need
1226
 
        readonly access in fact do not try to write.
1227
 
        """
1228
 
        t = get_transport(self.get_readonly_url())
1229
 
        self.assertTrue(t.is_readonly())
1230
 
        return t
1231
 
 
1232
 
    def make_branch(self, relpath, format=None):
1233
 
        """Create a branch on the transport at relpath."""
1234
 
        repo = self.make_repository(relpath, format=format)
1235
 
        return repo.bzrdir.create_branch()
1236
 
 
1237
 
    def make_bzrdir(self, relpath, format=None):
1238
 
        try:
1239
 
            url = self.get_url(relpath)
1240
 
            mutter('relpath %r => url %r', relpath, url)
1241
 
            segments = url.split('/')
1242
 
            if segments and segments[-1] not in ('', '.'):
1243
 
                parent = '/'.join(segments[:-1])
1244
 
                t = get_transport(parent)
1245
 
                try:
1246
 
                    t.mkdir(segments[-1])
1247
 
                except errors.FileExists:
1248
 
                    pass
1249
 
            if format is None:
1250
 
                format=bzrlib.bzrdir.BzrDirFormat.get_default_format()
1251
 
            # FIXME: make this use a single transport someday. RBC 20060418
1252
 
            return format.initialize_on_transport(get_transport(relpath))
1253
 
        except errors.UninitializableFormat:
1254
 
            raise TestSkipped("Format %s is not initializable." % format)
1255
 
 
1256
 
    def make_repository(self, relpath, shared=False, format=None):
1257
 
        """Create a repository on our default transport at relpath."""
1258
 
        made_control = self.make_bzrdir(relpath, format=format)
1259
 
        return made_control.create_repository(shared=shared)
1260
 
 
1261
1445
    def make_branch_and_tree(self, relpath, format=None):
1262
1446
        """Create a branch on the transport and a tree locally.
1263
1447
 
1264
 
        Returns the tree.
 
1448
        If the transport is not a LocalTransport, the Tree can't be created on
 
1449
        the transport.  In that case the working tree is created in the local
 
1450
        directory, and the returned tree's branch and repository will also be
 
1451
        accessed locally.
 
1452
 
 
1453
        This will fail if the original default transport for this test
 
1454
        case wasn't backed by the working directory, as the branch won't
 
1455
        be on disk for us to open it.  
 
1456
 
 
1457
        :param format: The BzrDirFormat.
 
1458
        :returns: the WorkingTree.
1265
1459
        """
1266
1460
        # TODO: always use the local disk path for the working tree,
1267
1461
        # this obviously requires a format that supports branch references
1271
1465
        try:
1272
1466
            return b.bzrdir.create_workingtree()
1273
1467
        except errors.NotLocalUrl:
1274
 
            # new formats - catch No tree error and create
1275
 
            # a branch reference and a checkout.
1276
 
            # old formats at that point - raise TestSkipped.
1277
 
            # TODO: rbc 20060208
1278
 
            return WorkingTreeFormat2().initialize(bzrdir.BzrDir.open(relpath))
 
1468
            # We can only make working trees locally at the moment.  If the
 
1469
            # transport can't support them, then reopen the branch on a local
 
1470
            # transport, and create the working tree there.  
 
1471
            #
 
1472
            # Possibly we should instead keep
 
1473
            # the non-disk-backed branch and create a local checkout?
 
1474
            bd = bzrdir.BzrDir.open(relpath)
 
1475
            return bd.create_workingtree()
1279
1476
 
1280
1477
    def assertIsDirectory(self, relpath, transport):
1281
1478
        """Assert that relpath within transport is a directory.
1292
1489
            self.fail("path %s is not a directory; has mode %#o"
1293
1490
                      % (relpath, mode))
1294
1491
 
 
1492
    def setUp(self):
 
1493
        super(TestCaseWithTransport, self).setUp()
 
1494
        self.__server = None
 
1495
        self.transport_server = default_transport
 
1496
 
1295
1497
 
1296
1498
class ChrootedTestCase(TestCaseWithTransport):
1297
1499
    """A support class that provides readonly urls outside the local namespace.
1323
1525
def run_suite(suite, name='test', verbose=False, pattern=".*",
1324
1526
              stop_on_failure=False, keep_output=False,
1325
1527
              transport=None, lsprof_timed=None, bench_history=None):
1326
 
    TestCaseInTempDir._TEST_NAME = name
1327
1528
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
1328
1529
    if verbose:
1329
1530
        verbosity = 2
1402
1603
                   'bzrlib.tests.test_errors',
1403
1604
                   'bzrlib.tests.test_escaped_store',
1404
1605
                   'bzrlib.tests.test_fetch',
 
1606
                   'bzrlib.tests.test_ftp_transport',
1405
1607
                   'bzrlib.tests.test_gpg',
1406
1608
                   'bzrlib.tests.test_graph',
1407
1609
                   'bzrlib.tests.test_hashcache',
1415
1617
                   'bzrlib.tests.test_lockdir',
1416
1618
                   'bzrlib.tests.test_lockable_files',
1417
1619
                   'bzrlib.tests.test_log',
 
1620
                   'bzrlib.tests.test_memorytree',
1418
1621
                   'bzrlib.tests.test_merge',
1419
1622
                   'bzrlib.tests.test_merge3',
1420
1623
                   'bzrlib.tests.test_merge_core',
1439
1642
                   'bzrlib.tests.test_selftest',
1440
1643
                   'bzrlib.tests.test_setup',
1441
1644
                   'bzrlib.tests.test_sftp_transport',
1442
 
                   'bzrlib.tests.test_ftp_transport',
1443
1645
                   'bzrlib.tests.test_smart_add',
 
1646
                   'bzrlib.tests.test_smart_transport',
1444
1647
                   'bzrlib.tests.test_source',
1445
1648
                   'bzrlib.tests.test_status',
1446
1649
                   'bzrlib.tests.test_store',
1453
1656
                   'bzrlib.tests.test_transform',
1454
1657
                   'bzrlib.tests.test_transport',
1455
1658
                   'bzrlib.tests.test_tree',
 
1659
                   'bzrlib.tests.test_treebuilder',
1456
1660
                   'bzrlib.tests.test_tsort',
1457
1661
                   'bzrlib.tests.test_tuned_gzip',
1458
1662
                   'bzrlib.tests.test_ui',
1460
1664
                   'bzrlib.tests.test_urlutils',
1461
1665
                   'bzrlib.tests.test_versionedfile',
1462
1666
                   'bzrlib.tests.test_version',
 
1667
                   'bzrlib.tests.test_version_info',
1463
1668
                   'bzrlib.tests.test_weave',
1464
1669
                   'bzrlib.tests.test_whitebox',
1465
1670
                   'bzrlib.tests.test_workingtree',