~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
        # We can only do this if we have one of our TestCases, not if
 
246
        # we have a doctest.
 
247
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
248
        if setKeepLogfile is not None:
 
249
            setKeepLogfile()
241
250
        self.extractBenchmarkTime(test)
242
251
        if self.showAll:
243
252
            self.stream.writeln("ERROR %s" % self._testTimeString())
254
263
 
255
264
    def addFailure(self, test, err):
256
265
        unittest.TestResult.addFailure(self, test, err)
 
266
        # We can only do this if we have one of our TestCases, not if
 
267
        # we have a doctest.
 
268
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
269
        if setKeepLogfile is not None:
 
270
            setKeepLogfile()
257
271
        self.extractBenchmarkTime(test)
258
272
        if self.showAll:
259
273
            self.stream.writeln(" FAIL %s" % self._testTimeString())
480
494
 
481
495
    _log_file_name = None
482
496
    _log_contents = ''
 
497
    _keep_log_file = False
483
498
    # record lsprof data when performing benchmark calls.
484
499
    _gather_lsprof_in_benchmarks = False
485
500
 
660
675
    def _finishLogFile(self):
661
676
        """Finished with the log file.
662
677
 
663
 
        Read contents into memory, close, and delete.
 
678
        Close the file and delete it, unless setKeepLogfile was called.
664
679
        """
665
680
        if self._log_file is None:
666
681
            return
667
682
        bzrlib.trace.disable_test_log(self._log_nonce)
668
 
        self._log_file.seek(0)
669
 
        self._log_contents = self._log_file.read()
670
683
        self._log_file.close()
671
 
        os.remove(self._log_file_name)
672
 
        self._log_file = self._log_file_name = None
 
684
        self._log_file = None
 
685
        if not self._keep_log_file:
 
686
            os.remove(self._log_file_name)
 
687
            self._log_file_name = None
 
688
 
 
689
    def setKeepLogfile(self):
 
690
        """Make the logfile not be deleted when _finishLogFile is called."""
 
691
        self._keep_log_file = True
673
692
 
674
693
    def addCleanup(self, callable):
675
694
        """Arrange to run a callable when this case is torn down.
684
703
 
685
704
    def _cleanEnvironment(self):
686
705
        new_env = {
 
706
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
687
707
            'HOME': os.getcwd(),
688
708
            'APPDATA': os.getcwd(),
689
709
            'BZR_EMAIL': None,
743
763
    def log(self, *args):
744
764
        mutter(*args)
745
765
 
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:
 
766
    def _get_log(self, keep_log_file=False):
 
767
        """Return as a string the log for this test. If the file is still
 
768
        on disk and keep_log_file=False, delete the log file and store the
 
769
        content in self._log_contents."""
 
770
        # flush the log file, to get all content
 
771
        import bzrlib.trace
 
772
        bzrlib.trace._trace_file.flush()
 
773
        if self._log_contents:
751
774
            return self._log_contents
752
 
        # TODO: Delete the log after it's been read in
 
775
        if self._log_file_name is not None:
 
776
            logfile = open(self._log_file_name)
 
777
            try:
 
778
                log_contents = logfile.read()
 
779
            finally:
 
780
                logfile.close()
 
781
            if not keep_log_file:
 
782
                self._log_contents = log_contents
 
783
                os.remove(self._log_file_name)
 
784
            return log_contents
 
785
        else:
 
786
            return "DELETED log file to reduce memory footprint"
753
787
 
754
788
    def capture(self, cmd, retcode=0):
755
789
        """Shortcut that splits cmd into words, runs, and returns stdout"""
756
790
        return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
757
791
 
758
 
    def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None):
 
792
    def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None,
 
793
                         working_dir=None):
759
794
        """Invoke bzr and return (stdout, stderr).
760
795
 
761
796
        Useful for code that wants to check the contents of the
776
811
        :param retcode: expected return code, or None for don't-care.
777
812
        :param encoding: encoding for sys.stdout and sys.stderr
778
813
        :param stdin: A string to be used as stdin for the command.
 
814
        :param working_dir: Change to this directory before running
779
815
        """
780
816
        if encoding is None:
781
817
            encoding = bzrlib.user_encoding
797
833
            stdout=stdout,
798
834
            stderr=stderr)
799
835
        bzrlib.ui.ui_factory.stdin = stdin
 
836
 
 
837
        cwd = None
 
838
        if working_dir is not None:
 
839
            cwd = osutils.getcwd()
 
840
            os.chdir(working_dir)
 
841
 
800
842
        try:
801
843
            result = self.apply_redirected(stdin, stdout, stderr,
802
844
                                           bzrlib.commands.run_bzr_catch_errors,
804
846
        finally:
805
847
            logger.removeHandler(handler)
806
848
            bzrlib.ui.ui_factory = old_ui_factory
 
849
            if cwd is not None:
 
850
                os.chdir(cwd)
807
851
 
808
852
        out = stdout.getvalue()
809
853
        err = stderr.getvalue()
830
874
        retcode = kwargs.pop('retcode', 0)
831
875
        encoding = kwargs.pop('encoding', None)
832
876
        stdin = kwargs.pop('stdin', None)
833
 
        return self.run_bzr_captured(args, retcode=retcode, encoding=encoding, stdin=stdin)
 
877
        working_dir = kwargs.pop('working_dir', None)
 
878
        return self.run_bzr_captured(args, retcode=retcode, encoding=encoding,
 
879
                                     stdin=stdin, working_dir=working_dir)
834
880
 
835
881
    def run_bzr_decode(self, *args, **kwargs):
836
882
        if 'encoding' in kwargs:
886
932
        :param universal_newlines: Convert CRLF => LF
887
933
        """
888
934
        env_changes = kwargs.get('env_changes', {})
889
 
 
 
935
        working_dir = kwargs.get('working_dir', None)
 
936
        process = self.start_bzr_subprocess(args, env_changes=env_changes,
 
937
                                            working_dir=working_dir)
 
938
        # We distinguish between retcode=None and retcode not passed.
 
939
        supplied_retcode = kwargs.get('retcode', 0)
 
940
        return self.finish_bzr_subprocess(process, retcode=supplied_retcode,
 
941
            universal_newlines=kwargs.get('universal_newlines', False),
 
942
            process_args=args)
 
943
 
 
944
    def start_bzr_subprocess(self, process_args, env_changes=None,
 
945
                             skip_if_plan_to_signal=False,
 
946
                             working_dir=None):
 
947
        """Start bzr in a subprocess for testing.
 
948
 
 
949
        This starts a new Python interpreter and runs bzr in there.
 
950
        This should only be used for tests that have a justifiable need for
 
951
        this isolation: e.g. they are testing startup time, or signal
 
952
        handling, or early startup code, etc.  Subprocess code can't be
 
953
        profiled or debugged so easily.
 
954
 
 
955
        :param process_args: a list of arguments to pass to the bzr executable,
 
956
            for example `['--version']`.
 
957
        :param env_changes: A dictionary which lists changes to environment
 
958
            variables. A value of None will unset the env variable.
 
959
            The values must be strings. The change will only occur in the
 
960
            child, so you don't need to fix the environment after running.
 
961
        :param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
 
962
            is not available.
 
963
 
 
964
        :returns: Popen object for the started process.
 
965
        """
 
966
        if skip_if_plan_to_signal:
 
967
            if not getattr(os, 'kill', None):
 
968
                raise TestSkipped("os.kill not available.")
 
969
 
 
970
        if env_changes is None:
 
971
            env_changes = {}
890
972
        old_env = {}
891
973
 
892
974
        def cleanup_environment():
897
979
            for env_var, value in old_env.iteritems():
898
980
                osutils.set_or_unset_env(env_var, value)
899
981
 
900
 
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
901
 
        args = list(args)
 
982
        bzr_path = self.get_bzr_path()
 
983
 
 
984
        cwd = None
 
985
        if working_dir is not None:
 
986
            cwd = osutils.getcwd()
 
987
            os.chdir(working_dir)
902
988
 
903
989
        try:
904
990
            # win32 subprocess doesn't support preexec_fn
905
991
            # so we will avoid using it on all platforms, just to
906
992
            # make sure the code path is used, and we don't break on win32
907
993
            cleanup_environment()
908
 
            process = Popen([sys.executable, bzr_path]+args,
909
 
                             stdout=PIPE, stderr=PIPE)
 
994
            process = Popen([sys.executable, bzr_path] + list(process_args),
 
995
                             stdin=PIPE, stdout=PIPE, stderr=PIPE)
910
996
        finally:
911
997
            restore_environment()
912
 
            
913
 
        out = process.stdout.read()
914
 
        err = process.stderr.read()
915
 
 
916
 
        if kwargs.get('universal_newlines', False):
 
998
            if cwd is not None:
 
999
                os.chdir(cwd)
 
1000
 
 
1001
        return process
 
1002
 
 
1003
    def get_bzr_path(self):
 
1004
        """Return the path of the 'bzr' executable for this test suite."""
 
1005
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
 
1006
        if not os.path.isfile(bzr_path):
 
1007
            # We are probably installed. Assume sys.argv is the right file
 
1008
            bzr_path = sys.argv[0]
 
1009
        return bzr_path
 
1010
 
 
1011
    def finish_bzr_subprocess(self, process, retcode=0, send_signal=None,
 
1012
                              universal_newlines=False, process_args=None):
 
1013
        """Finish the execution of process.
 
1014
 
 
1015
        :param process: the Popen object returned from start_bzr_subprocess.
 
1016
        :param retcode: The status code that is expected.  Defaults to 0.  If
 
1017
            None is supplied, the status code is not checked.
 
1018
        :param send_signal: an optional signal to send to the process.
 
1019
        :param universal_newlines: Convert CRLF => LF
 
1020
        :returns: (stdout, stderr)
 
1021
        """
 
1022
        if send_signal is not None:
 
1023
            os.kill(process.pid, send_signal)
 
1024
        out, err = process.communicate()
 
1025
 
 
1026
        if universal_newlines:
917
1027
            out = out.replace('\r\n', '\n')
918
1028
            err = err.replace('\r\n', '\n')
919
1029
 
920
 
        retcode = process.wait()
921
 
        supplied_retcode = kwargs.get('retcode', 0)
922
 
        if supplied_retcode is not None:
923
 
            assert supplied_retcode == retcode
 
1030
        if retcode is not None and retcode != process.returncode:
 
1031
            if process_args is None:
 
1032
                process_args = "(unknown args)"
 
1033
            mutter('Output of bzr %s:\n%s', process_args, out)
 
1034
            mutter('Error for bzr %s:\n%s', process_args, err)
 
1035
            self.fail('Command bzr %s failed with retcode %s != %s'
 
1036
                      % (process_args, retcode, process.returncode))
924
1037
        return [out, err]
925
1038
 
926
1039
    def check_inventory_shape(self, inv, shape):
1202
1315
        return self.__server
1203
1316
 
1204
1317
    def get_url(self, relpath=None):
1205
 
        """Get a URL for the readwrite transport.
 
1318
        """Get a URL (or maybe a path) for the readwrite transport.
1206
1319
 
1207
1320
        This will either be backed by '.' or to an equivalent non-file based
1208
1321
        facility.
1213
1326
        if relpath is not None and relpath != '.':
1214
1327
            if not base.endswith('/'):
1215
1328
                base = base + '/'
1216
 
            base = base + urlutils.escape(relpath)
 
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)
1217
1337
        return base
1218
1338
 
1219
1339
    def get_transport(self):
1239
1359
 
1240
1360
    def make_bzrdir(self, relpath, format=None):
1241
1361
        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)
 
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 ('', '.'):
1248
1367
                try:
1249
 
                    t.mkdir(segments[-1])
 
1368
                    t.mkdir('.')
1250
1369
                except errors.FileExists:
1251
1370
                    pass
1252
1371
            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))
 
1372
                format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
 
1373
            return format.initialize_on_transport(t)
1256
1374
        except errors.UninitializableFormat:
1257
1375
            raise TestSkipped("Format %s is not initializable." % format)
1258
1376
 
1261
1379
        made_control = self.make_bzrdir(relpath, format=format)
1262
1380
        return made_control.create_repository(shared=shared)
1263
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
 
1264
1387
    def make_branch_and_tree(self, relpath, format=None):
1265
1388
        """Create a branch on the transport and a tree locally.
1266
1389
 
1267
 
        Returns the tree.
 
1390
        If the transport is not a LocalTransport, the Tree can't be created on
 
1391
        the transport.  In that case the working tree is created in the local
 
1392
        directory, and the returned tree's branch and repository will also be
 
1393
        accessed locally.
 
1394
 
 
1395
        This will fail if the original default transport for this test
 
1396
        case wasn't backed by the working directory, as the branch won't
 
1397
        be on disk for us to open it.  
 
1398
 
 
1399
        :param format: The BzrDirFormat.
 
1400
        :returns: the WorkingTree.
1268
1401
        """
1269
1402
        # TODO: always use the local disk path for the working tree,
1270
1403
        # this obviously requires a format that supports branch references
1274
1407
        try:
1275
1408
            return b.bzrdir.create_workingtree()
1276
1409
        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))
 
1410
            # We can only make working trees locally at the moment.  If the
 
1411
            # transport can't support them, then reopen the branch on a local
 
1412
            # transport, and create the working tree there.  
 
1413
            #
 
1414
            # Possibly we should instead keep
 
1415
            # the non-disk-backed branch and create a local checkout?
 
1416
            bd = bzrdir.BzrDir.open(relpath)
 
1417
            return bd.create_workingtree()
1282
1418
 
1283
1419
    def assertIsDirectory(self, relpath, transport):
1284
1420
        """Assert that relpath within transport is a directory.
1405
1541
                   'bzrlib.tests.test_errors',
1406
1542
                   'bzrlib.tests.test_escaped_store',
1407
1543
                   'bzrlib.tests.test_fetch',
 
1544
                   'bzrlib.tests.test_ftp_transport',
1408
1545
                   'bzrlib.tests.test_gpg',
1409
1546
                   'bzrlib.tests.test_graph',
1410
1547
                   'bzrlib.tests.test_hashcache',
1414
1551
                   'bzrlib.tests.test_ignores',
1415
1552
                   'bzrlib.tests.test_inv',
1416
1553
                   'bzrlib.tests.test_knit',
 
1554
                   'bzrlib.tests.test_lazy_import',
1417
1555
                   'bzrlib.tests.test_lockdir',
1418
1556
                   'bzrlib.tests.test_lockable_files',
1419
1557
                   'bzrlib.tests.test_log',
 
1558
                   'bzrlib.tests.test_memorytree',
1420
1559
                   'bzrlib.tests.test_merge',
1421
1560
                   'bzrlib.tests.test_merge3',
1422
1561
                   'bzrlib.tests.test_merge_core',
1441
1580
                   'bzrlib.tests.test_selftest',
1442
1581
                   'bzrlib.tests.test_setup',
1443
1582
                   'bzrlib.tests.test_sftp_transport',
1444
 
                   'bzrlib.tests.test_ftp_transport',
1445
1583
                   'bzrlib.tests.test_smart_add',
 
1584
                   'bzrlib.tests.test_smart_transport',
1446
1585
                   'bzrlib.tests.test_source',
1447
1586
                   'bzrlib.tests.test_status',
1448
1587
                   'bzrlib.tests.test_store',
1455
1594
                   'bzrlib.tests.test_transform',
1456
1595
                   'bzrlib.tests.test_transport',
1457
1596
                   'bzrlib.tests.test_tree',
 
1597
                   'bzrlib.tests.test_treebuilder',
1458
1598
                   'bzrlib.tests.test_tsort',
1459
1599
                   'bzrlib.tests.test_tuned_gzip',
1460
1600
                   'bzrlib.tests.test_ui',
1462
1602
                   'bzrlib.tests.test_urlutils',
1463
1603
                   'bzrlib.tests.test_versionedfile',
1464
1604
                   'bzrlib.tests.test_version',
 
1605
                   'bzrlib.tests.test_version_info',
1465
1606
                   'bzrlib.tests.test_weave',
1466
1607
                   'bzrlib.tests.test_whitebox',
1467
1608
                   'bzrlib.tests.test_workingtree',