~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

Merge bzr.dev

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
88
90
                      bzrlib.bundle.serializer,
89
91
                      bzrlib.commands,
90
92
                      bzrlib.errors,
 
93
                      bzrlib.export,
91
94
                      bzrlib.inventory,
92
95
                      bzrlib.iterablefile,
93
96
                      bzrlib.lockdir,
94
97
                      bzrlib.merge3,
95
98
                      bzrlib.option,
96
99
                      bzrlib.osutils,
97
 
                      bzrlib.store
 
100
                      bzrlib.store,
 
101
                      bzrlib.transport,
98
102
                      ]
99
103
 
100
104
 
238
242
        if isinstance(err[1], TestSkipped):
239
243
            return self.addSkipped(test, err)    
240
244
        unittest.TestResult.addError(self, test, err)
 
245
        method = getattr(test, 'setKeepLogfile', None)
 
246
        if method is not None:
 
247
            method()
241
248
        self.extractBenchmarkTime(test)
242
249
        if self.showAll:
243
250
            self.stream.writeln("ERROR %s" % self._testTimeString())
254
261
 
255
262
    def addFailure(self, test, err):
256
263
        unittest.TestResult.addFailure(self, test, err)
 
264
        method = getattr(test, 'setKeepLogfile', None)
 
265
        if method is not None:
 
266
            method()
257
267
        self.extractBenchmarkTime(test)
258
268
        if self.showAll:
259
269
            self.stream.writeln(" FAIL %s" % self._testTimeString())
480
490
 
481
491
    _log_file_name = None
482
492
    _log_contents = ''
 
493
    _keep_log_file = False
483
494
    # record lsprof data when performing benchmark calls.
484
495
    _gather_lsprof_in_benchmarks = False
485
496
 
660
671
    def _finishLogFile(self):
661
672
        """Finished with the log file.
662
673
 
663
 
        Read contents into memory, close, and delete.
 
674
        Close the file and delete it, unless setKeepLogfile was called.
664
675
        """
665
676
        if self._log_file is None:
666
677
            return
667
678
        bzrlib.trace.disable_test_log(self._log_nonce)
668
 
        self._log_file.seek(0)
669
 
        self._log_contents = self._log_file.read()
670
679
        self._log_file.close()
671
 
        os.remove(self._log_file_name)
672
 
        self._log_file = self._log_file_name = None
 
680
        self._log_file = None
 
681
        if not self._keep_log_file:
 
682
            os.remove(self._log_file_name)
 
683
            self._log_file_name = None
 
684
 
 
685
    def setKeepLogfile(self):
 
686
        """Make the logfile not be deleted when _finishLogFile is called."""
 
687
        self._keep_log_file = True
673
688
 
674
689
    def addCleanup(self, callable):
675
690
        """Arrange to run a callable when this case is torn down.
743
758
    def log(self, *args):
744
759
        mutter(*args)
745
760
 
746
 
    def _get_log(self):
747
 
        """Return as a string the log for this test"""
748
 
        if self._log_file_name:
749
 
            return open(self._log_file_name).read()
750
 
        else:
 
761
    def _get_log(self, keep_log_file=False):
 
762
        """Return as a string the log for this test. If the file is still
 
763
        on disk and keep_log_file=False, delete the log file and store the
 
764
        content in self._log_contents."""
 
765
        # flush the log file, to get all content
 
766
        import bzrlib.trace
 
767
        bzrlib.trace._trace_file.flush()
 
768
        if self._log_contents:
751
769
            return self._log_contents
752
 
        # TODO: Delete the log after it's been read in
 
770
        if self._log_file_name is not None:
 
771
            logfile = open(self._log_file_name)
 
772
            try:
 
773
                log_contents = logfile.read()
 
774
            finally:
 
775
                logfile.close()
 
776
            if not keep_log_file:
 
777
                self._log_contents = log_contents
 
778
                os.remove(self._log_file_name)
 
779
            return log_contents
 
780
        else:
 
781
            return "DELETED log file to reduce memory footprint"
753
782
 
754
783
    def capture(self, cmd, retcode=0):
755
784
        """Shortcut that splits cmd into words, runs, and returns stdout"""
886
915
        :param universal_newlines: Convert CRLF => LF
887
916
        """
888
917
        env_changes = kwargs.get('env_changes', {})
889
 
 
 
918
        process = self.start_bzr_subprocess(args, env_changes=env_changes)
 
919
        # We distinguish between retcode=None and retcode not passed.
 
920
        supplied_retcode = kwargs.get('retcode', 0)
 
921
        return self.finish_bzr_subprocess(process, retcode=supplied_retcode,
 
922
            universal_newlines=kwargs.get('universal_newlines', False),
 
923
            process_args=args)
 
924
 
 
925
    def start_bzr_subprocess(self, process_args, env_changes=None,
 
926
                             skip_if_plan_to_signal=False):
 
927
        """Start bzr in a subprocess for testing.
 
928
 
 
929
        This starts a new Python interpreter and runs bzr in there.
 
930
        This should only be used for tests that have a justifiable need for
 
931
        this isolation: e.g. they are testing startup time, or signal
 
932
        handling, or early startup code, etc.  Subprocess code can't be
 
933
        profiled or debugged so easily.
 
934
 
 
935
        :param process_args: a list of arguments to pass to the bzr executable,
 
936
            for example `['--version']`.
 
937
        :param env_changes: A dictionary which lists changes to environment
 
938
            variables. A value of None will unset the env variable.
 
939
            The values must be strings. The change will only occur in the
 
940
            child, so you don't need to fix the environment after running.
 
941
        :param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
 
942
            is not available.
 
943
 
 
944
        :returns: Popen object for the started process.
 
945
        """
 
946
        if skip_if_plan_to_signal:
 
947
            if not getattr(os, 'kill', None):
 
948
                raise TestSkipped("os.kill not available.")
 
949
 
 
950
        if env_changes is None:
 
951
            env_changes = {}
890
952
        old_env = {}
891
953
 
892
954
        def cleanup_environment():
897
959
            for env_var, value in old_env.iteritems():
898
960
                osutils.set_or_unset_env(env_var, value)
899
961
 
900
 
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
901
 
        args = list(args)
 
962
        bzr_path = self.get_bzr_path()
902
963
 
903
964
        try:
904
965
            # win32 subprocess doesn't support preexec_fn
905
966
            # so we will avoid using it on all platforms, just to
906
967
            # make sure the code path is used, and we don't break on win32
907
968
            cleanup_environment()
908
 
            process = Popen([sys.executable, bzr_path]+args,
909
 
                             stdout=PIPE, stderr=PIPE)
 
969
            process = Popen([sys.executable, bzr_path] + list(process_args),
 
970
                             stdin=PIPE, stdout=PIPE, stderr=PIPE)
910
971
        finally:
911
972
            restore_environment()
912
 
            
913
 
        out = process.stdout.read()
914
 
        err = process.stderr.read()
915
 
 
916
 
        if kwargs.get('universal_newlines', False):
 
973
        return process
 
974
 
 
975
    def get_bzr_path(self):
 
976
        """Return the path of the 'bzr' executable for this test suite."""
 
977
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
 
978
        if not os.path.isfile(bzr_path):
 
979
            # We are probably installed. Assume sys.argv is the right file
 
980
            bzr_path = sys.argv[0]
 
981
        return bzr_path
 
982
 
 
983
    def finish_bzr_subprocess(self, process, retcode=0, send_signal=None,
 
984
                              universal_newlines=False, process_args=None):
 
985
        """Finish the execution of process.
 
986
 
 
987
        :param process: the Popen object returned from start_bzr_subprocess.
 
988
        :param retcode: The status code that is expected.  Defaults to 0.  If
 
989
            None is supplied, the status code is not checked.
 
990
        :param send_signal: an optional signal to send to the process.
 
991
        :param universal_newlines: Convert CRLF => LF
 
992
        :returns: (stdout, stderr)
 
993
        """
 
994
        if send_signal is not None:
 
995
            os.kill(process.pid, send_signal)
 
996
        out, err = process.communicate()
 
997
 
 
998
        if universal_newlines:
917
999
            out = out.replace('\r\n', '\n')
918
1000
            err = err.replace('\r\n', '\n')
919
1001
 
920
 
        retcode = process.wait()
921
 
        supplied_retcode = kwargs.get('retcode', 0)
922
 
        if supplied_retcode is not None:
923
 
            assert supplied_retcode == retcode
 
1002
        if retcode is not None and retcode != process.returncode:
 
1003
            if process_args is None:
 
1004
                process_args = "(unknown args)"
 
1005
            mutter('Output of bzr %s:\n%s', process_args, out)
 
1006
            mutter('Error for bzr %s:\n%s', process_args, err)
 
1007
            self.fail('Command bzr %s failed with retcode %s != %s'
 
1008
                      % (process_args, retcode, process.returncode))
924
1009
        return [out, err]
925
1010
 
926
1011
    def check_inventory_shape(self, inv, shape):
1202
1287
        return self.__server
1203
1288
 
1204
1289
    def get_url(self, relpath=None):
1205
 
        """Get a URL for the readwrite transport.
 
1290
        """Get a URL (or maybe a path) for the readwrite transport.
1206
1291
 
1207
1292
        This will either be backed by '.' or to an equivalent non-file based
1208
1293
        facility.
1213
1298
        if relpath is not None and relpath != '.':
1214
1299
            if not base.endswith('/'):
1215
1300
                base = base + '/'
1216
 
            base = base + urlutils.escape(relpath)
 
1301
            # XXX: Really base should be a url; we did after all call
 
1302
            # get_url()!  But sometimes it's just a path (from
 
1303
            # LocalAbspathServer), and it'd be wrong to append urlescaped data
 
1304
            # to a non-escaped local path.
 
1305
            if base.startswith('./') or base.startswith('/'):
 
1306
                base += relpath
 
1307
            else:
 
1308
                base += urlutils.escape(relpath)
1217
1309
        return base
1218
1310
 
1219
1311
    def get_transport(self):
1239
1331
 
1240
1332
    def make_bzrdir(self, relpath, format=None):
1241
1333
        try:
1242
 
            url = self.get_url(relpath)
1243
 
            mutter('relpath %r => url %r', relpath, url)
1244
 
            segments = url.split('/')
1245
 
            if segments and segments[-1] not in ('', '.'):
1246
 
                parent = '/'.join(segments[:-1])
1247
 
                t = get_transport(parent)
 
1334
            # might be a relative or absolute path
 
1335
            maybe_a_url = self.get_url(relpath)
 
1336
            segments = maybe_a_url.rsplit('/', 1)
 
1337
            t = get_transport(maybe_a_url)
 
1338
            if len(segments) > 1 and segments[-1] not in ('', '.'):
1248
1339
                try:
1249
 
                    t.mkdir(segments[-1])
 
1340
                    t.mkdir('.')
1250
1341
                except errors.FileExists:
1251
1342
                    pass
1252
1343
            if format is None:
1253
 
                format=bzrlib.bzrdir.BzrDirFormat.get_default_format()
1254
 
            # FIXME: make this use a single transport someday. RBC 20060418
1255
 
            return format.initialize_on_transport(get_transport(relpath))
 
1344
                format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
 
1345
            return format.initialize_on_transport(t)
1256
1346
        except errors.UninitializableFormat:
1257
1347
            raise TestSkipped("Format %s is not initializable." % format)
1258
1348
 
1261
1351
        made_control = self.make_bzrdir(relpath, format=format)
1262
1352
        return made_control.create_repository(shared=shared)
1263
1353
 
 
1354
    def make_branch_and_memory_tree(self, relpath):
 
1355
        """Create a branch on the default transport and a MemoryTree for it."""
 
1356
        b = self.make_branch(relpath)
 
1357
        return memorytree.MemoryTree.create_on_branch(b)
 
1358
 
1264
1359
    def make_branch_and_tree(self, relpath, format=None):
1265
1360
        """Create a branch on the transport and a tree locally.
1266
1361
 
1267
 
        Returns the tree.
 
1362
        If the transport is not a LocalTransport, the Tree can't be created on
 
1363
        the transport.  In that case the working tree is created in the local
 
1364
        directory, and the returned tree's branch and repository will also be
 
1365
        accessed locally.
 
1366
 
 
1367
        This will fail if the original default transport for this test
 
1368
        case wasn't backed by the working directory, as the branch won't
 
1369
        be on disk for us to open it.  
 
1370
 
 
1371
        :param format: The BzrDirFormat.
 
1372
        :returns: the WorkingTree.
1268
1373
        """
1269
1374
        # TODO: always use the local disk path for the working tree,
1270
1375
        # this obviously requires a format that supports branch references
1274
1379
        try:
1275
1380
            return b.bzrdir.create_workingtree()
1276
1381
        except errors.NotLocalUrl:
1277
 
            # new formats - catch No tree error and create
1278
 
            # a branch reference and a checkout.
1279
 
            # old formats at that point - raise TestSkipped.
1280
 
            # TODO: rbc 20060208
1281
 
            return WorkingTreeFormat2().initialize(bzrdir.BzrDir.open(relpath))
 
1382
            # We can only make working trees locally at the moment.  If the
 
1383
            # transport can't support them, then reopen the branch on a local
 
1384
            # transport, and create the working tree there.  
 
1385
            #
 
1386
            # Possibly we should instead keep
 
1387
            # the non-disk-backed branch and create a local checkout?
 
1388
            bd = bzrdir.BzrDir.open(relpath)
 
1389
            return bd.create_workingtree()
1282
1390
 
1283
1391
    def assertIsDirectory(self, relpath, transport):
1284
1392
        """Assert that relpath within transport is a directory.
1405
1513
                   'bzrlib.tests.test_errors',
1406
1514
                   'bzrlib.tests.test_escaped_store',
1407
1515
                   'bzrlib.tests.test_fetch',
 
1516
                   'bzrlib.tests.test_ftp_transport',
1408
1517
                   'bzrlib.tests.test_gpg',
1409
1518
                   'bzrlib.tests.test_graph',
1410
1519
                   'bzrlib.tests.test_hashcache',
1414
1523
                   'bzrlib.tests.test_ignores',
1415
1524
                   'bzrlib.tests.test_inv',
1416
1525
                   'bzrlib.tests.test_knit',
 
1526
                   'bzrlib.tests.test_lazy_import',
1417
1527
                   'bzrlib.tests.test_lockdir',
1418
1528
                   'bzrlib.tests.test_lockable_files',
1419
1529
                   'bzrlib.tests.test_log',
 
1530
                   'bzrlib.tests.test_memorytree',
1420
1531
                   'bzrlib.tests.test_merge',
1421
1532
                   'bzrlib.tests.test_merge3',
1422
1533
                   'bzrlib.tests.test_merge_core',
1441
1552
                   'bzrlib.tests.test_selftest',
1442
1553
                   'bzrlib.tests.test_setup',
1443
1554
                   'bzrlib.tests.test_sftp_transport',
1444
 
                   'bzrlib.tests.test_ftp_transport',
1445
1555
                   'bzrlib.tests.test_smart_add',
 
1556
                   'bzrlib.tests.test_smart_transport',
1446
1557
                   'bzrlib.tests.test_source',
1447
1558
                   'bzrlib.tests.test_status',
1448
1559
                   'bzrlib.tests.test_store',
1455
1566
                   'bzrlib.tests.test_transform',
1456
1567
                   'bzrlib.tests.test_transport',
1457
1568
                   'bzrlib.tests.test_tree',
 
1569
                   'bzrlib.tests.test_treebuilder',
1458
1570
                   'bzrlib.tests.test_tsort',
1459
1571
                   'bzrlib.tests.test_tuned_gzip',
1460
1572
                   'bzrlib.tests.test_ui',
1462
1574
                   'bzrlib.tests.test_urlutils',
1463
1575
                   'bzrlib.tests.test_versionedfile',
1464
1576
                   'bzrlib.tests.test_version',
 
1577
                   'bzrlib.tests.test_version_info',
1465
1578
                   'bzrlib.tests.test_weave',
1466
1579
                   'bzrlib.tests.test_whitebox',
1467
1580
                   'bzrlib.tests.test_workingtree',