550
551
errors.NoSuchRevision, branch.set_revision_history, ['rev-id'])
554
def test_tip_change_rejected(self):
555
"""TipChangeRejected responses cause a TipChangeRejected exception to
558
transport = MemoryTransport()
559
transport.mkdir('branch')
560
transport = transport.clone('branch')
561
client = FakeClient(transport.base)
563
client.add_success_response('ok', 'branch token', 'repo token')
565
rejection_msg_unicode = u'rejection message\N{INTERROBANG}'
566
rejection_msg_utf8 = rejection_msg_unicode.encode('utf8')
567
client.add_error_response('TipChangeRejected', rejection_msg_utf8)
569
client.add_success_response('ok')
571
bzrdir = RemoteBzrDir(transport, _client=False)
572
repo = RemoteRepository(bzrdir, None, _client=client)
573
branch = RemoteBranch(bzrdir, repo, _client=client)
574
branch._ensure_real = lambda: None
576
self.addCleanup(branch.unlock)
579
# The 'TipChangeRejected' error response triggered by calling
580
# set_revision_history causes a TipChangeRejected exception.
581
err = self.assertRaises(
582
errors.TipChangeRejected, branch.set_revision_history, ['rev-id'])
583
# The UTF-8 message from the response has been decoded into a unicode
585
self.assertIsInstance(err.msg, unicode)
586
self.assertEqual(rejection_msg_unicode, err.msg)
554
589
class TestBranchSetLastRevisionInfo(tests.TestCase):
686
723
self.assertEqual(('UnexpectedError',), err.error_tuple)
726
def test_tip_change_rejected(self):
727
"""TipChangeRejected responses cause a TipChangeRejected exception to
730
transport = MemoryTransport()
731
transport.mkdir('branch')
732
transport = transport.clone('branch')
733
client = FakeClient(transport.base)
735
client.add_success_response('ok', 'branch token', 'repo token')
737
client.add_error_response('TipChangeRejected', 'rejection message')
739
client.add_success_response('ok')
741
bzrdir = RemoteBzrDir(transport, _client=False)
742
repo = RemoteRepository(bzrdir, None, _client=client)
743
branch = RemoteBranch(bzrdir, repo, _client=client)
744
# This is a hack to work around the problem that RemoteBranch currently
745
# unnecessarily invokes _ensure_real upon a call to lock_write.
746
branch._ensure_real = lambda: None
747
# Lock the branch, reset the record of remote calls.
749
self.addCleanup(branch.unlock)
752
# The 'TipChangeRejected' error response triggered by calling
753
# set_last_revision_info causes a TipChangeRejected exception.
754
err = self.assertRaises(
755
errors.TipChangeRejected,
756
branch.set_last_revision_info, 123, 'revid')
757
self.assertEqual('rejection message', err.msg)
690
760
class TestBranchControlGetBranchConf(tests.TestCaseWithMemoryTransport):
691
761
"""Getting the branch configuration should use an abstract method not vfs.
1182
1253
self.assertFalse(isinstance(dest_repo, RemoteRepository))
1183
1254
self.assertTrue(isinstance(src_repo, RemoteRepository))
1184
1255
src_repo.copy_content_into(dest_repo)
1258
class TestErrorTranslationBase(tests.TestCaseWithMemoryTransport):
1259
"""Base class for unit tests for bzrlib.remote._translate_error."""
1261
def translateTuple(self, error_tuple, **context):
1262
"""Call _translate_error with an ErrorFromSmartServer built from the
1265
:param error_tuple: A tuple of a smart server response, as would be
1266
passed to an ErrorFromSmartServer.
1267
:kwargs context: context items to call _translate_error with.
1269
:returns: The error raised by _translate_error.
1271
# Raise the ErrorFromSmartServer before passing it as an argument,
1272
# because _translate_error may need to re-raise it with a bare 'raise'
1274
server_error = errors.ErrorFromSmartServer(error_tuple)
1275
translated_error = self.translateErrorFromSmartServer(
1276
server_error, **context)
1277
return translated_error
1279
def translateErrorFromSmartServer(self, error_object, **context):
1280
"""Like translateTuple, but takes an already constructed
1281
ErrorFromSmartServer rather than a tuple.
1285
except errors.ErrorFromSmartServer, server_error:
1286
translated_error = self.assertRaises(
1287
errors.BzrError, remote._translate_error, server_error,
1289
return translated_error
1292
class TestErrorTranslationSuccess(TestErrorTranslationBase):
1293
"""Unit tests for bzrlib.remote._translate_error.
1295
Given an ErrorFromSmartServer (which has an error tuple from a smart
1296
server) and some context, _translate_error raises more specific errors from
1299
This test case covers the cases where _translate_error succeeds in
1300
translating an ErrorFromSmartServer to something better. See
1301
TestErrorTranslationRobustness for other cases.
1304
def test_NoSuchRevision(self):
1305
branch = self.make_branch('')
1307
translated_error = self.translateTuple(
1308
('NoSuchRevision', revid), branch=branch)
1309
expected_error = errors.NoSuchRevision(branch, revid)
1310
self.assertEqual(expected_error, translated_error)
1312
def test_nosuchrevision(self):
1313
repository = self.make_repository('')
1315
translated_error = self.translateTuple(
1316
('nosuchrevision', revid), repository=repository)
1317
expected_error = errors.NoSuchRevision(repository, revid)
1318
self.assertEqual(expected_error, translated_error)
1320
def test_nobranch(self):
1321
bzrdir = self.make_bzrdir('')
1322
translated_error = self.translateTuple(('nobranch',), bzrdir=bzrdir)
1323
expected_error = errors.NotBranchError(path=bzrdir.root_transport.base)
1324
self.assertEqual(expected_error, translated_error)
1326
def test_LockContention(self):
1327
translated_error = self.translateTuple(('LockContention',))
1328
expected_error = errors.LockContention('(remote lock)')
1329
self.assertEqual(expected_error, translated_error)
1331
def test_UnlockableTransport(self):
1332
bzrdir = self.make_bzrdir('')
1333
translated_error = self.translateTuple(
1334
('UnlockableTransport',), bzrdir=bzrdir)
1335
expected_error = errors.UnlockableTransport(bzrdir.root_transport)
1336
self.assertEqual(expected_error, translated_error)
1338
def test_LockFailed(self):
1339
lock = 'str() of a server lock'
1340
why = 'str() of why'
1341
translated_error = self.translateTuple(('LockFailed', lock, why))
1342
expected_error = errors.LockFailed(lock, why)
1343
self.assertEqual(expected_error, translated_error)
1345
def test_TokenMismatch(self):
1346
token = 'a lock token'
1347
translated_error = self.translateTuple(('TokenMismatch',), token=token)
1348
expected_error = errors.TokenMismatch(token, '(remote token)')
1349
self.assertEqual(expected_error, translated_error)
1351
def test_Diverged(self):
1352
branch = self.make_branch('a')
1353
other_branch = self.make_branch('b')
1354
translated_error = self.translateTuple(
1355
('Diverged',), branch=branch, other_branch=other_branch)
1356
expected_error = errors.DivergedBranches(branch, other_branch)
1357
self.assertEqual(expected_error, translated_error)
1360
class TestErrorTranslationRobustness(TestErrorTranslationBase):
1361
"""Unit tests for bzrlib.remote._translate_error's robustness.
1363
TestErrorTranslationSuccess is for cases where _translate_error can
1364
translate successfully. This class about how _translate_err behaves when
1365
it fails to translate: it re-raises the original error.
1368
def test_unrecognised_server_error(self):
1369
"""If the error code from the server is not recognised, the original
1370
ErrorFromSmartServer is propagated unmodified.
1372
error_tuple = ('An unknown error tuple',)
1373
server_error = errors.ErrorFromSmartServer(error_tuple)
1374
translated_error = self.translateErrorFromSmartServer(server_error)
1375
self.assertEqual(server_error, translated_error)
1377
def test_context_missing_a_key(self):
1378
"""In case of a bug in the client, or perhaps an unexpected response
1379
from a server, _translate_error returns the original error tuple from
1380
the server and mutters a warning.
1382
# To translate a NoSuchRevision error _translate_error needs a 'branch'
1383
# in the context dict. So let's give it an empty context dict instead
1384
# to exercise its error recovery.
1386
error_tuple = ('NoSuchRevision', 'revid')
1387
server_error = errors.ErrorFromSmartServer(error_tuple)
1388
translated_error = self.translateErrorFromSmartServer(server_error)
1389
self.assertEqual(server_error, translated_error)
1390
# In addition to re-raising ErrorFromSmartServer, some debug info has
1391
# been muttered to the log file for developer to look at.
1392
self.assertContainsRe(
1393
self._get_log(keep_log_file=True),
1394
"Missing key 'branch' in context")