1
1
# Copyright (C) 2005, 2006 by Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
# GNU General Public License for more details.
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
65
61
from bzrlib.revision import common_ancestor
66
62
import bzrlib.store
67
63
import bzrlib.trace
68
from bzrlib.transport import get_transport
64
from bzrlib.transport import urlescape, get_transport
69
65
import bzrlib.transport
70
66
from bzrlib.transport.local import LocalRelpathServer
71
67
from bzrlib.transport.readonly import ReadonlyServer
72
68
from bzrlib.trace import mutter
73
from bzrlib.tests import TestUtil
74
from bzrlib.tests.TestUtil import (
69
from bzrlib.tests.TestUtil import TestLoader, TestSuite
78
70
from bzrlib.tests.treeshape import build_tree_contents
79
import bzrlib.urlutils as urlutils
80
71
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
82
73
default_transport = LocalRelpathServer
121
107
bzrlib.tests.bzrdir_implementations,
122
108
bzrlib.tests.interrepository_implementations,
123
109
bzrlib.tests.interversionedfile_implementations,
124
bzrlib.tests.intertree_implementations,
125
110
bzrlib.tests.repository_implementations,
126
111
bzrlib.tests.revisionstore_implementations,
127
bzrlib.tests.tree_implementations,
128
112
bzrlib.tests.workingtree_implementations,
353
324
test_root = TestCaseInTempDir.TEST_ROOT
354
325
if result.wasSuccessful() or not self.keep_output:
355
326
if test_root is not None:
356
# If LANG=C we probably have created some bogus paths
357
# which rmtree(unicode) will fail to delete
358
# so make sure we are using rmtree(str) to delete everything
359
# except on win32, where rmtree(str) will fail
360
# since it doesn't have the property of byte-stream paths
361
# (they are either ascii or mbcs)
362
if sys.platform == 'win32':
363
# make sure we are using the unicode win32 api
364
test_root = unicode(test_root)
366
test_root = test_root.encode(
367
sys.getfilesystemencoding())
368
osutils.rmtree(test_root)
327
osutils.rmtree(test_root)
370
329
if self.pb is not None:
371
330
self.pb.note("Failed tests working directories are in '%s'\n",
401
360
class CommandFailed(Exception):
405
class StringIOWrapper(object):
406
"""A wrapper around cStringIO which just adds an encoding attribute.
408
Internally we can check sys.stdout to see what the output encoding
409
should be. However, cStringIO has no encoding attribute that we can
410
set. So we wrap it instead.
415
def __init__(self, s=None):
417
self.__dict__['_cstring'] = StringIO(s)
419
self.__dict__['_cstring'] = StringIO()
421
def __getattr__(self, name, getattr=getattr):
422
return getattr(self.__dict__['_cstring'], name)
424
def __setattr__(self, name, val):
425
if name == 'encoding':
426
self.__dict__['encoding'] = val
428
return setattr(self._cstring, name, val)
431
363
class TestCase(unittest.TestCase):
432
364
"""Base class for bzr unit tests.
674
598
"""Shortcut that splits cmd into words, runs, and returns stdout"""
675
599
return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
677
def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None):
601
def run_bzr_captured(self, argv, retcode=0, stdin=None):
678
602
"""Invoke bzr and return (stdout, stderr).
680
604
Useful for code that wants to check the contents of the
691
615
errors, and with logging set to something approximating the
692
616
default, so that error reporting can be checked.
694
:param argv: arguments to invoke bzr
695
:param retcode: expected return code, or None for don't-care.
696
:param encoding: encoding for sys.stdout and sys.stderr
618
argv -- arguments to invoke bzr
619
retcode -- expected return code, or None for don't-care.
697
620
:param stdin: A string to be used as stdin for the command.
700
encoding = bzrlib.user_encoding
701
622
if stdin is not None:
702
623
stdin = StringIO(stdin)
703
stdout = StringIOWrapper()
704
stderr = StringIOWrapper()
705
stdout.encoding = encoding
706
stderr.encoding = encoding
708
self.log('run bzr: %r', argv)
626
self.log('run bzr: %s', ' '.join(argv))
709
627
# FIXME: don't call into logging here
710
628
handler = logging.StreamHandler(stderr)
629
handler.setFormatter(bzrlib.trace.QuietFormatter())
711
630
handler.setLevel(logging.INFO)
712
631
logger = logging.getLogger('')
713
632
logger.addHandler(handler)
724
643
logger.removeHandler(handler)
725
644
bzrlib.ui.ui_factory = old_ui_factory
727
645
out = stdout.getvalue()
728
646
err = stderr.getvalue()
730
self.log('output:\n%r', out)
648
self.log('output:\n%s', out)
732
self.log('errors:\n%r', err)
650
self.log('errors:\n%s', err)
733
651
if retcode is not None:
734
self.assertEquals(retcode, result)
652
self.assertEquals(result, retcode)
737
655
def run_bzr(self, *args, **kwargs):
747
665
:param stdin: A string to be used as stdin for the command.
749
667
retcode = kwargs.pop('retcode', 0)
750
encoding = kwargs.pop('encoding', None)
751
668
stdin = kwargs.pop('stdin', None)
752
return self.run_bzr_captured(args, retcode=retcode, encoding=encoding, stdin=stdin)
754
def run_bzr_decode(self, *args, **kwargs):
755
if kwargs.has_key('encoding'):
756
encoding = kwargs['encoding']
758
encoding = bzrlib.user_encoding
759
return self.run_bzr(*args, **kwargs)[0].decode(encoding)
761
def run_bzr_error(self, error_regexes, *args, **kwargs):
762
"""Run bzr, and check that stderr contains the supplied regexes
764
:param error_regexes: Sequence of regular expressions which
765
must each be found in the error output. The relative ordering
767
:param args: command-line arguments for bzr
768
:param kwargs: Keyword arguments which are interpreted by run_bzr
769
This function changes the default value of retcode to be 3,
770
since in most cases this is run when you expect bzr to fail.
771
:return: (out, err) The actual output of running the command (in case you
772
want to do more inspection)
775
# Make sure that commit is failing because there is nothing to do
776
self.run_bzr_error(['no changes to commit'],
777
'commit', '-m', 'my commit comment')
778
# Make sure --strict is handling an unknown file, rather than
779
# giving us the 'nothing to do' error
780
self.build_tree(['unknown'])
781
self.run_bzr_error(['Commit refused because there are unknown files'],
782
'commit', '--strict', '-m', 'my commit comment')
784
kwargs.setdefault('retcode', 3)
785
out, err = self.run_bzr(*args, **kwargs)
786
for regex in error_regexes:
787
self.assertContainsRe(err, regex)
790
def run_bzr_subprocess(self, *args, **kwargs):
791
"""Run bzr in a subprocess for testing.
793
This starts a new Python interpreter and runs bzr in there.
794
This should only be used for tests that have a justifiable need for
795
this isolation: e.g. they are testing startup time, or signal
796
handling, or early startup code, etc. Subprocess code can't be
797
profiled or debugged so easily.
799
:param retcode: The status code that is expected. Defaults to 0. If
800
None is supplied, the status code is not checked.
802
bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
804
process = Popen([sys.executable, bzr_path]+args, stdout=PIPE,
806
out = process.stdout.read()
807
err = process.stderr.read()
808
retcode = process.wait()
809
supplied_retcode = kwargs.get('retcode', 0)
810
if supplied_retcode is not None:
811
assert supplied_retcode == retcode
669
return self.run_bzr_captured(args, retcode, stdin)
814
671
def check_inventory_shape(self, inv, shape):
815
672
"""Compare an inventory to a list of expected names.
976
831
VFS's. If the transport is readonly or None,
977
832
"." is opened automatically.
979
# It's OK to just create them using forward slashes on windows.
834
# XXX: It's OK to just create them using forward slashes on windows?
980
835
if transport is None or transport.is_readonly():
981
836
transport = get_transport(".")
982
837
for name in shape:
983
838
self.assert_(isinstance(name, basestring))
984
839
if name[-1] == '/':
985
transport.mkdir(urlutils.escape(name[:-1]))
840
transport.mkdir(urlescape(name[:-1]))
987
842
if line_endings == 'binary':
992
847
raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
993
content = "contents of %s%s" % (name.encode('utf-8'), end)
994
# Technically 'put()' is the right command. However, put
995
# uses an AtomicFile, which requires an extra rename into place
996
# As long as the files didn't exist in the past, append() will
997
# do the same thing as put()
998
# On jam's machine, make_kernel_like_tree is:
999
# put: 4.5-7.5s (averaging 6s)
1001
transport.append(urlutils.escape(name), StringIO(content))
848
content = "contents of %s%s" % (name, end)
849
transport.put(urlescape(name), StringIO(content))
1003
851
def build_tree_contents(self, shape):
1004
852
build_tree_contents(shape)
1123
970
def make_bzrdir(self, relpath, format=None):
1125
972
url = self.get_url(relpath)
1126
mutter('relpath %r => url %r', relpath, url)
1127
segments = url.split('/')
973
segments = relpath.split('/')
1128
974
if segments and segments[-1] not in ('', '.'):
1129
parent = '/'.join(segments[:-1])
975
parent = self.get_url('/'.join(segments[:-1]))
1130
976
t = get_transport(parent)
1132
978
t.mkdir(segments[-1])
1265
1105
This function can be replaced if you need to change the default test
1266
1106
suite on a global basis, but it is not encouraged.
1108
from doctest import DocTestSuite
1110
global MODULES_TO_DOCTEST
1269
1113
'bzrlib.tests.test_ancestry',
1270
1114
'bzrlib.tests.test_api',
1271
'bzrlib.tests.test_atomicfile',
1272
1115
'bzrlib.tests.test_bad_files',
1273
1116
'bzrlib.tests.test_branch',
1274
'bzrlib.tests.test_bundle',
1275
1117
'bzrlib.tests.test_bzrdir',
1276
1118
'bzrlib.tests.test_command',
1277
1119
'bzrlib.tests.test_commit',
1288
1130
'bzrlib.tests.test_graph',
1289
1131
'bzrlib.tests.test_hashcache',
1290
1132
'bzrlib.tests.test_http',
1291
'bzrlib.tests.test_http_response',
1292
1133
'bzrlib.tests.test_identitymap',
1293
'bzrlib.tests.test_ignores',
1294
1134
'bzrlib.tests.test_inv',
1295
1135
'bzrlib.tests.test_knit',
1296
1136
'bzrlib.tests.test_lockdir',
1331
1170
'bzrlib.tests.test_transactions',
1332
1171
'bzrlib.tests.test_transform',
1333
1172
'bzrlib.tests.test_transport',
1334
'bzrlib.tests.test_tree',
1335
1173
'bzrlib.tests.test_tsort',
1336
1174
'bzrlib.tests.test_tuned_gzip',
1337
1175
'bzrlib.tests.test_ui',
1338
1176
'bzrlib.tests.test_upgrade',
1339
'bzrlib.tests.test_urlutils',
1340
1177
'bzrlib.tests.test_versionedfile',
1341
1178
'bzrlib.tests.test_weave',
1342
1179
'bzrlib.tests.test_whitebox',
1344
1181
'bzrlib.tests.test_xml',
1346
1183
test_transport_implementations = [
1347
'bzrlib.tests.test_transport_implementations',
1348
'bzrlib.tests.test_read_bundle',
1350
suite = TestUtil.TestSuite()
1184
'bzrlib.tests.test_transport_implementations']
1351
1187
loader = TestUtil.TestLoader()
1352
suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
1353
1188
from bzrlib.transport import TransportTestProviderAdapter
1354
1189
adapter = TransportTestProviderAdapter()
1355
1190
adapt_modules(test_transport_implementations, adapter, loader, suite)
1191
suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
1356
1192
for package in packages_to_test():
1357
1193
suite.addTest(package.test_suite())
1358
1194
for m in MODULES_TO_TEST:
1359
1195
suite.addTest(loader.loadTestsFromModule(m))
1360
for m in MODULES_TO_DOCTEST:
1361
suite.addTest(doctest.DocTestSuite(m))
1196
for m in (MODULES_TO_DOCTEST):
1197
suite.addTest(DocTestSuite(m))
1362
1198
for name, plugin in bzrlib.plugin.all_plugins().items():
1363
1199
if getattr(plugin, 'test_suite', None) is not None:
1364
1200
suite.addTest(plugin.test_suite())