~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2006-10-04 03:41:15 UTC
  • mfrom: (1986.2.7 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20061004034115-7728b1aad33e6433
(Robert Collins) Add TestCaseWithMemoryTransport, a test class specifically for doing tests with memory transports and no disk resources.

Show diffs side-by-side

added added

removed removed

Lines of Context:
71
71
from bzrlib.transport import get_transport
72
72
import bzrlib.transport
73
73
from bzrlib.transport.local import LocalRelpathServer
 
74
from bzrlib.transport.memory import MemoryServer
74
75
from bzrlib.transport.readonly import ReadonlyServer
75
76
from bzrlib.trace import mutter
76
77
from bzrlib.tests import TestUtil
394
395
        # This is still a little bogus, 
395
396
        # but only a little. Folk not using our testrunner will
396
397
        # have to delete their temp directories themselves.
397
 
        test_root = TestCaseInTempDir.TEST_ROOT
 
398
        test_root = TestCaseWithMemoryTransport.TEST_ROOT
398
399
        if result.wasSuccessful() or not self.keep_output:
399
400
            if test_root is not None:
400
401
                # If LANG=C we probably have created some bogus paths
418
419
                self.stream.writeln(
419
420
                    "Failed tests working directories are in '%s'\n" %
420
421
                    test_root)
421
 
        TestCaseInTempDir.TEST_ROOT = None
 
422
        TestCaseWithMemoryTransport.TEST_ROOT = None
422
423
        if self.pb is not None:
423
424
            self.pb.clear()
424
425
        return result
1108
1109
 
1109
1110
BzrTestBase = TestCase
1110
1111
 
 
1112
 
 
1113
class TestCaseWithMemoryTransport(TestCase):
 
1114
    """Common test class for tests that do not need disk resources.
 
1115
 
 
1116
    Tests that need disk resources should derive from TestCaseWithTransport.
 
1117
 
 
1118
    TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
 
1119
 
 
1120
    For TestCaseWithMemoryTransport the test_home_dir is set to the name of
 
1121
    a directory which does not exist. This serves to help ensure test isolation
 
1122
    is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
 
1123
    must exist. However, TestCaseWithMemoryTransport does not offer local
 
1124
    file defaults for the transport in tests, nor does it obey the command line
 
1125
    override, so tests that accidentally write to the common directory should
 
1126
    be rare.
 
1127
    """
 
1128
 
 
1129
    TEST_ROOT = None
 
1130
    _TEST_NAME = 'test'
 
1131
 
 
1132
 
 
1133
    def __init__(self, methodName='runTest'):
 
1134
        # allow test parameterisation after test construction and before test
 
1135
        # execution. Variables that the parameteriser sets need to be 
 
1136
        # ones that are not set by setUp, or setUp will trash them.
 
1137
        super(TestCaseWithMemoryTransport, self).__init__(methodName)
 
1138
        self.transport_server = default_transport
 
1139
        self.transport_readonly_server = None
 
1140
 
 
1141
    def failUnlessExists(self, path):
 
1142
        """Fail unless path, which may be abs or relative, exists."""
 
1143
        self.failUnless(osutils.lexists(path))
 
1144
 
 
1145
    def failIfExists(self, path):
 
1146
        """Fail if path, which may be abs or relative, exists."""
 
1147
        self.failIf(osutils.lexists(path))
 
1148
        
 
1149
    def get_transport(self):
 
1150
        """Return a writeable transport for the test scratch space"""
 
1151
        t = get_transport(self.get_url())
 
1152
        self.assertFalse(t.is_readonly())
 
1153
        return t
 
1154
 
 
1155
    def get_readonly_transport(self):
 
1156
        """Return a readonly transport for the test scratch space
 
1157
        
 
1158
        This can be used to test that operations which should only need
 
1159
        readonly access in fact do not try to write.
 
1160
        """
 
1161
        t = get_transport(self.get_readonly_url())
 
1162
        self.assertTrue(t.is_readonly())
 
1163
        return t
 
1164
 
 
1165
    def get_readonly_server(self):
 
1166
        """Get the server instance for the readonly transport
 
1167
 
 
1168
        This is useful for some tests with specific servers to do diagnostics.
 
1169
        """
 
1170
        if self.__readonly_server is None:
 
1171
            if self.transport_readonly_server is None:
 
1172
                # readonly decorator requested
 
1173
                # bring up the server
 
1174
                self.get_url()
 
1175
                self.__readonly_server = ReadonlyServer()
 
1176
                self.__readonly_server.setUp(self.__server)
 
1177
            else:
 
1178
                self.__readonly_server = self.transport_readonly_server()
 
1179
                self.__readonly_server.setUp()
 
1180
            self.addCleanup(self.__readonly_server.tearDown)
 
1181
        return self.__readonly_server
 
1182
 
 
1183
    def get_readonly_url(self, relpath=None):
 
1184
        """Get a URL for the readonly transport.
 
1185
 
 
1186
        This will either be backed by '.' or a decorator to the transport 
 
1187
        used by self.get_url()
 
1188
        relpath provides for clients to get a path relative to the base url.
 
1189
        These should only be downwards relative, not upwards.
 
1190
        """
 
1191
        base = self.get_readonly_server().get_url()
 
1192
        if relpath is not None:
 
1193
            if not base.endswith('/'):
 
1194
                base = base + '/'
 
1195
            base = base + relpath
 
1196
        return base
 
1197
 
 
1198
    def get_server(self):
 
1199
        """Get the read/write server instance.
 
1200
 
 
1201
        This is useful for some tests with specific servers that need
 
1202
        diagnostics.
 
1203
 
 
1204
        For TestCaseWithMemoryTransport this is always a MemoryServer, and there
 
1205
        is no means to override it.
 
1206
        """
 
1207
        if self.__server is None:
 
1208
            self.__server = MemoryServer()
 
1209
            self.__server.setUp()
 
1210
            self.addCleanup(self.__server.tearDown)
 
1211
        return self.__server
 
1212
 
 
1213
    def get_url(self, relpath=None):
 
1214
        """Get a URL (or maybe a path) for the readwrite transport.
 
1215
 
 
1216
        This will either be backed by '.' or to an equivalent non-file based
 
1217
        facility.
 
1218
        relpath provides for clients to get a path relative to the base url.
 
1219
        These should only be downwards relative, not upwards.
 
1220
        """
 
1221
        base = self.get_server().get_url()
 
1222
        if relpath is not None and relpath != '.':
 
1223
            if not base.endswith('/'):
 
1224
                base = base + '/'
 
1225
            # XXX: Really base should be a url; we did after all call
 
1226
            # get_url()!  But sometimes it's just a path (from
 
1227
            # LocalAbspathServer), and it'd be wrong to append urlescaped data
 
1228
            # to a non-escaped local path.
 
1229
            if base.startswith('./') or base.startswith('/'):
 
1230
                base += relpath
 
1231
            else:
 
1232
                base += urlutils.escape(relpath)
 
1233
        return base
 
1234
 
 
1235
    def _make_test_root(self):
 
1236
        if TestCaseWithMemoryTransport.TEST_ROOT is not None:
 
1237
            return
 
1238
        i = 0
 
1239
        while True:
 
1240
            root = u'test%04d.tmp' % i
 
1241
            try:
 
1242
                os.mkdir(root)
 
1243
            except OSError, e:
 
1244
                if e.errno == errno.EEXIST:
 
1245
                    i += 1
 
1246
                    continue
 
1247
                else:
 
1248
                    raise
 
1249
            # successfully created
 
1250
            TestCaseWithMemoryTransport.TEST_ROOT = osutils.abspath(root)
 
1251
            break
 
1252
        # make a fake bzr directory there to prevent any tests propagating
 
1253
        # up onto the source directory's real branch
 
1254
        bzrdir.BzrDir.create_standalone_workingtree(
 
1255
            TestCaseWithMemoryTransport.TEST_ROOT)
 
1256
 
 
1257
    def makeAndChdirToTestDir(self):
 
1258
        """Create a temporary directories for this one test.
 
1259
        
 
1260
        This must set self.test_home_dir and self.test_dir and chdir to
 
1261
        self.test_dir.
 
1262
        
 
1263
        For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
 
1264
        """
 
1265
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
 
1266
        self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
 
1267
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
 
1268
        
 
1269
    def make_branch(self, relpath, format=None):
 
1270
        """Create a branch on the transport at relpath."""
 
1271
        repo = self.make_repository(relpath, format=format)
 
1272
        return repo.bzrdir.create_branch()
 
1273
 
 
1274
    def make_bzrdir(self, relpath, format=None):
 
1275
        try:
 
1276
            # might be a relative or absolute path
 
1277
            maybe_a_url = self.get_url(relpath)
 
1278
            segments = maybe_a_url.rsplit('/', 1)
 
1279
            t = get_transport(maybe_a_url)
 
1280
            if len(segments) > 1 and segments[-1] not in ('', '.'):
 
1281
                try:
 
1282
                    t.mkdir('.')
 
1283
                except errors.FileExists:
 
1284
                    pass
 
1285
            if format is None:
 
1286
                format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
 
1287
            return format.initialize_on_transport(t)
 
1288
        except errors.UninitializableFormat:
 
1289
            raise TestSkipped("Format %s is not initializable." % format)
 
1290
 
 
1291
    def make_repository(self, relpath, shared=False, format=None):
 
1292
        """Create a repository on our default transport at relpath."""
 
1293
        made_control = self.make_bzrdir(relpath, format=format)
 
1294
        return made_control.create_repository(shared=shared)
 
1295
 
 
1296
    def make_branch_and_memory_tree(self, relpath):
 
1297
        """Create a branch on the default transport and a MemoryTree for it."""
 
1298
        b = self.make_branch(relpath)
 
1299
        return memorytree.MemoryTree.create_on_branch(b)
 
1300
 
 
1301
    def overrideEnvironmentForTesting(self):
 
1302
        os.environ['HOME'] = self.test_home_dir
 
1303
        os.environ['APPDATA'] = self.test_home_dir
 
1304
        
 
1305
    def setUp(self):
 
1306
        super(TestCaseWithMemoryTransport, self).setUp()
 
1307
        self._make_test_root()
 
1308
        _currentdir = os.getcwdu()
 
1309
        def _leaveDirectory():
 
1310
            os.chdir(_currentdir)
 
1311
        self.addCleanup(_leaveDirectory)
 
1312
        self.makeAndChdirToTestDir()
 
1313
        self.overrideEnvironmentForTesting()
 
1314
        self.__readonly_server = None
 
1315
        self.__server = None
 
1316
 
1111
1317
     
1112
 
class TestCaseInTempDir(TestCase):
 
1318
class TestCaseInTempDir(TestCaseWithMemoryTransport):
1113
1319
    """Derived class that runs a test within a temporary directory.
1114
1320
 
1115
1321
    This is useful for tests that need to create a branch, etc.
1122
1328
    InTempDir is an old alias for FunctionalTestCase.
1123
1329
    """
1124
1330
 
1125
 
    TEST_ROOT = None
1126
 
    _TEST_NAME = 'test'
1127
1331
    OVERRIDE_PYTHON = 'python'
1128
1332
 
1129
1333
    def check_file_contents(self, filename, expect):
1134
1338
            self.log("actually: %r" % contents)
1135
1339
            self.fail("contents of %s not as expected" % filename)
1136
1340
 
1137
 
    def _make_test_root(self):
1138
 
        if TestCaseInTempDir.TEST_ROOT is not None:
1139
 
            return
1140
 
        i = 0
1141
 
        while True:
1142
 
            root = u'test%04d.tmp' % i
1143
 
            try:
1144
 
                os.mkdir(root)
1145
 
            except OSError, e:
1146
 
                if e.errno == errno.EEXIST:
1147
 
                    i += 1
1148
 
                    continue
1149
 
                else:
1150
 
                    raise
1151
 
            # successfully created
1152
 
            TestCaseInTempDir.TEST_ROOT = osutils.abspath(root)
1153
 
            break
1154
 
        # make a fake bzr directory there to prevent any tests propagating
1155
 
        # up onto the source directory's real branch
1156
 
        bzrdir.BzrDir.create_standalone_workingtree(TestCaseInTempDir.TEST_ROOT)
1157
 
 
1158
 
    def setUp(self):
1159
 
        super(TestCaseInTempDir, self).setUp()
1160
 
        self._make_test_root()
1161
 
        _currentdir = os.getcwdu()
 
1341
    def makeAndChdirToTestDir(self):
 
1342
        """See TestCaseWithMemoryTransport.makeAndChdirToTestDir().
 
1343
        
 
1344
        For TestCaseInTempDir we create a temporary directory based on the test
 
1345
        name and then create two subdirs - test and home under it.
 
1346
        """
1162
1347
        # shorten the name, to avoid test failures due to path length
1163
1348
        short_id = self.id().replace('bzrlib.tests.', '') \
1164
1349
                   .replace('__main__.', '')[-100:]
1181
1366
                os.mkdir(self.test_dir)
1182
1367
                os.chdir(self.test_dir)
1183
1368
                break
1184
 
        os.environ['HOME'] = self.test_home_dir
1185
 
        os.environ['APPDATA'] = self.test_home_dir
1186
 
        def _leaveDirectory():
1187
 
            os.chdir(_currentdir)
1188
 
        self.addCleanup(_leaveDirectory)
1189
 
        
 
1369
 
1190
1370
    def build_tree(self, shape, line_endings='native', transport=None):
1191
1371
        """Build a test tree according to a pattern.
1192
1372
 
1233
1413
    def build_tree_contents(self, shape):
1234
1414
        build_tree_contents(shape)
1235
1415
 
1236
 
    def failUnlessExists(self, path):
1237
 
        """Fail unless path, which may be abs or relative, exists."""
1238
 
        self.failUnless(osutils.lexists(path))
1239
 
 
1240
 
    def failIfExists(self, path):
1241
 
        """Fail if path, which may be abs or relative, exists."""
1242
 
        self.failIf(osutils.lexists(path))
1243
 
        
1244
1416
    def assertFileEqual(self, content, path):
1245
1417
        """Fail if path does not contain 'content'."""
1246
1418
        self.failUnless(osutils.lexists(path))
1262
1434
    readwrite one must both define get_url() as resolving to os.getcwd().
1263
1435
    """
1264
1436
 
1265
 
    def __init__(self, methodName='testMethod'):
1266
 
        super(TestCaseWithTransport, self).__init__(methodName)
1267
 
        self.__readonly_server = None
1268
 
        self.__server = None
1269
 
        self.transport_server = default_transport
1270
 
        self.transport_readonly_server = None
1271
 
 
1272
 
    def get_readonly_url(self, relpath=None):
1273
 
        """Get a URL for the readonly transport.
1274
 
 
1275
 
        This will either be backed by '.' or a decorator to the transport 
1276
 
        used by self.get_url()
1277
 
        relpath provides for clients to get a path relative to the base url.
1278
 
        These should only be downwards relative, not upwards.
1279
 
        """
1280
 
        base = self.get_readonly_server().get_url()
1281
 
        if relpath is not None:
1282
 
            if not base.endswith('/'):
1283
 
                base = base + '/'
1284
 
            base = base + relpath
1285
 
        return base
1286
 
 
1287
 
    def get_readonly_server(self):
1288
 
        """Get the server instance for the readonly transport
1289
 
 
1290
 
        This is useful for some tests with specific servers to do diagnostics.
1291
 
        """
1292
 
        if self.__readonly_server is None:
1293
 
            if self.transport_readonly_server is None:
1294
 
                # readonly decorator requested
1295
 
                # bring up the server
1296
 
                self.get_url()
1297
 
                self.__readonly_server = ReadonlyServer()
1298
 
                self.__readonly_server.setUp(self.__server)
1299
 
            else:
1300
 
                self.__readonly_server = self.transport_readonly_server()
1301
 
                self.__readonly_server.setUp()
1302
 
            self.addCleanup(self.__readonly_server.tearDown)
1303
 
        return self.__readonly_server
1304
 
 
1305
1437
    def get_server(self):
1306
 
        """Get the read/write server instance.
 
1438
        """See TestCaseWithMemoryTransport.
1307
1439
 
1308
1440
        This is useful for some tests with specific servers that need
1309
1441
        diagnostics.
1314
1446
            self.addCleanup(self.__server.tearDown)
1315
1447
        return self.__server
1316
1448
 
1317
 
    def get_url(self, relpath=None):
1318
 
        """Get a URL (or maybe a path) for the readwrite transport.
1319
 
 
1320
 
        This will either be backed by '.' or to an equivalent non-file based
1321
 
        facility.
1322
 
        relpath provides for clients to get a path relative to the base url.
1323
 
        These should only be downwards relative, not upwards.
1324
 
        """
1325
 
        base = self.get_server().get_url()
1326
 
        if relpath is not None and relpath != '.':
1327
 
            if not base.endswith('/'):
1328
 
                base = base + '/'
1329
 
            # XXX: Really base should be a url; we did after all call
1330
 
            # get_url()!  But sometimes it's just a path (from
1331
 
            # LocalAbspathServer), and it'd be wrong to append urlescaped data
1332
 
            # to a non-escaped local path.
1333
 
            if base.startswith('./') or base.startswith('/'):
1334
 
                base += relpath
1335
 
            else:
1336
 
                base += urlutils.escape(relpath)
1337
 
        return base
1338
 
 
1339
 
    def get_transport(self):
1340
 
        """Return a writeable transport for the test scratch space"""
1341
 
        t = get_transport(self.get_url())
1342
 
        self.assertFalse(t.is_readonly())
1343
 
        return t
1344
 
 
1345
 
    def get_readonly_transport(self):
1346
 
        """Return a readonly transport for the test scratch space
1347
 
        
1348
 
        This can be used to test that operations which should only need
1349
 
        readonly access in fact do not try to write.
1350
 
        """
1351
 
        t = get_transport(self.get_readonly_url())
1352
 
        self.assertTrue(t.is_readonly())
1353
 
        return t
1354
 
 
1355
 
    def make_branch(self, relpath, format=None):
1356
 
        """Create a branch on the transport at relpath."""
1357
 
        repo = self.make_repository(relpath, format=format)
1358
 
        return repo.bzrdir.create_branch()
1359
 
 
1360
 
    def make_bzrdir(self, relpath, format=None):
1361
 
        try:
1362
 
            # might be a relative or absolute path
1363
 
            maybe_a_url = self.get_url(relpath)
1364
 
            segments = maybe_a_url.rsplit('/', 1)
1365
 
            t = get_transport(maybe_a_url)
1366
 
            if len(segments) > 1 and segments[-1] not in ('', '.'):
1367
 
                try:
1368
 
                    t.mkdir('.')
1369
 
                except errors.FileExists:
1370
 
                    pass
1371
 
            if format is None:
1372
 
                format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
1373
 
            return format.initialize_on_transport(t)
1374
 
        except errors.UninitializableFormat:
1375
 
            raise TestSkipped("Format %s is not initializable." % format)
1376
 
 
1377
 
    def make_repository(self, relpath, shared=False, format=None):
1378
 
        """Create a repository on our default transport at relpath."""
1379
 
        made_control = self.make_bzrdir(relpath, format=format)
1380
 
        return made_control.create_repository(shared=shared)
1381
 
 
1382
 
    def make_branch_and_memory_tree(self, relpath):
1383
 
        """Create a branch on the default transport and a MemoryTree for it."""
1384
 
        b = self.make_branch(relpath)
1385
 
        return memorytree.MemoryTree.create_on_branch(b)
1386
 
 
1387
1449
    def make_branch_and_tree(self, relpath, format=None):
1388
1450
        """Create a branch on the transport and a tree locally.
1389
1451
 
1431
1493
            self.fail("path %s is not a directory; has mode %#o"
1432
1494
                      % (relpath, mode))
1433
1495
 
 
1496
    def setUp(self):
 
1497
        super(TestCaseWithTransport, self).setUp()
 
1498
        self.__server = None
 
1499
        self.transport_server = default_transport
 
1500
 
1434
1501
 
1435
1502
class ChrootedTestCase(TestCaseWithTransport):
1436
1503
    """A support class that provides readonly urls outside the local namespace.
1462
1529
def run_suite(suite, name='test', verbose=False, pattern=".*",
1463
1530
              stop_on_failure=False, keep_output=False,
1464
1531
              transport=None, lsprof_timed=None, bench_history=None):
1465
 
    TestCaseInTempDir._TEST_NAME = name
1466
1532
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
1467
1533
    if verbose:
1468
1534
        verbosity = 2