131
113
b = BzrDir.open_from_transport(self.transport).open_branch()
132
114
self.assertStartsWith(str(b), 'RemoteBranch(')
134
def test_remote_branch_format_supports_stacking(self):
136
self.make_branch('unstackable', format='pack-0.92')
137
b = BzrDir.open_from_transport(t.clone('unstackable')).open_branch()
138
self.assertFalse(b._format.supports_stacking())
139
self.make_branch('stackable', format='1.9')
140
b = BzrDir.open_from_transport(t.clone('stackable')).open_branch()
141
self.assertTrue(b._format.supports_stacking())
143
def test_remote_repo_format_supports_external_references(self):
145
bd = self.make_bzrdir('unstackable', format='pack-0.92')
146
r = bd.create_repository()
147
self.assertFalse(r._format.supports_external_lookups)
148
r = BzrDir.open_from_transport(t.clone('unstackable')).open_repository()
149
self.assertFalse(r._format.supports_external_lookups)
150
bd = self.make_bzrdir('stackable', format='1.9')
151
r = bd.create_repository()
152
self.assertTrue(r._format.supports_external_lookups)
153
r = BzrDir.open_from_transport(t.clone('stackable')).open_repository()
154
self.assertTrue(r._format.supports_external_lookups)
157
117
class FakeProtocol(object):
158
118
"""Lookalike SmartClientRequestProtocolOne allowing body reading tests."""
410
362
call.call.method == verb])
411
363
self.assertEqual(1, call_count)
413
def test_branch_reference(self):
414
transport = self.get_transport('quack')
415
referenced = self.make_branch('referenced')
416
expected = referenced.bzrdir.cloning_metadir()
417
client = FakeClient(transport.base)
418
client.add_expected_call(
419
'BzrDir.cloning_metadir', ('quack/', 'False'),
420
'error', ('BranchReference',)),
421
client.add_expected_call(
422
'BzrDir.open_branchV2', ('quack/',),
423
'success', ('ref', self.get_url('referenced'))),
424
a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
426
result = a_bzrdir.cloning_metadir()
427
# We should have got a control dir matching the referenced branch.
428
self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
429
self.assertEqual(expected._repository_format, result._repository_format)
430
self.assertEqual(expected._branch_format, result._branch_format)
431
client.finished_test()
433
365
def test_current_server(self):
434
366
transport = self.get_transport('.')
435
367
transport = transport.clone('quack')
455
387
class TestBzrDirOpenBranch(TestRemote):
457
def test_backwards_compat(self):
458
self.setup_smart_server_with_call_log()
459
self.make_branch('.')
460
a_dir = BzrDir.open(self.get_url('.'))
461
self.reset_smart_call_log()
462
verb = 'BzrDir.open_branchV2'
463
self.disable_verb(verb)
464
format = a_dir.open_branch()
465
call_count = len([call for call in self.hpss_calls if
466
call.call.method == verb])
467
self.assertEqual(1, call_count)
469
389
def test_branch_present(self):
470
390
reference_format = self.get_repo_format()
471
391
network_name = reference_format.network_name()
472
branch_network_name = self.get_branch_format().network_name()
473
392
transport = MemoryTransport()
474
393
transport.mkdir('quack')
475
394
transport = transport.clone('quack')
476
395
client = FakeClient(transport.base)
477
396
client.add_expected_call(
478
'BzrDir.open_branchV2', ('quack/',),
479
'success', ('branch', branch_network_name))
397
'BzrDir.open_branch', ('quack/',),
398
'success', ('ok', ''))
480
399
client.add_expected_call(
481
400
'BzrDir.find_repositoryV3', ('quack/',),
482
401
'success', ('ok', '', 'no', 'no', 'no', network_name))
528
447
client = FakeClient(transport.base)
529
448
reference_format = self.get_repo_format()
530
449
network_name = reference_format.network_name()
531
branch_network_name = self.get_branch_format().network_name()
532
450
client.add_expected_call(
533
'BzrDir.open_branchV2', ('~hello/',),
534
'success', ('branch', branch_network_name))
451
'BzrDir.open_branch', ('~hello/',),
452
'success', ('ok', ''))
535
453
client.add_expected_call(
536
454
'BzrDir.find_repositoryV3', ('~hello/',),
537
455
'success', ('ok', '', 'no', 'no', 'no', network_name))
838
754
self.assertEqual('http://foo/', result)
841
class TestBranchGetTagsBytes(RemoteBranchTestCase):
843
def test_backwards_compat(self):
844
self.setup_smart_server_with_call_log()
845
branch = self.make_branch('.')
846
self.reset_smart_call_log()
847
verb = 'Branch.get_tags_bytes'
848
self.disable_verb(verb)
849
branch.tags.get_tag_dict()
850
call_count = len([call for call in self.hpss_calls if
851
call.call.method == verb])
852
self.assertEqual(1, call_count)
854
def test_trivial(self):
855
transport = MemoryTransport()
856
client = FakeClient(transport.base)
857
client.add_expected_call(
858
'Branch.get_stacked_on_url', ('quack/',),
859
'error', ('NotStacked',))
860
client.add_expected_call(
861
'Branch.get_tags_bytes', ('quack/',),
863
transport.mkdir('quack')
864
transport = transport.clone('quack')
865
branch = self.make_remote_branch(transport, client)
866
result = branch.tags.get_tag_dict()
867
client.finished_test()
868
self.assertEqual({}, result)
871
757
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
873
759
def test_empty_branch(self):
943
827
stacked_branch = self.make_branch('stacked', format='1.6')
944
828
stacked_branch.set_stacked_on_url('../base')
945
829
client = FakeClient(self.get_url())
946
branch_network_name = self.get_branch_format().network_name()
947
830
client.add_expected_call(
948
'BzrDir.open_branchV2', ('stacked/',),
949
'success', ('branch', branch_network_name))
831
'BzrDir.open_branch', ('stacked/',),
832
'success', ('ok', ''))
950
833
client.add_expected_call(
951
834
'BzrDir.find_repositoryV3', ('stacked/',),
952
'success', ('ok', '', 'no', 'no', 'yes',
835
'success', ('ok', '', 'no', 'no', 'no',
953
836
stacked_branch.repository._format.network_name()))
954
837
# called twice, once from constructor and then again by us
955
838
client.add_expected_call(
979
862
reference_format = self.get_repo_format()
980
863
network_name = reference_format.network_name()
981
864
client = FakeClient(self.get_url())
982
branch_network_name = self.get_branch_format().network_name()
983
865
client.add_expected_call(
984
'BzrDir.open_branchV2', ('stacked/',),
985
'success', ('branch', branch_network_name))
866
'BzrDir.open_branch', ('stacked/',),
867
'success', ('ok', ''))
986
868
client.add_expected_call(
987
869
'BzrDir.find_repositoryV3', ('stacked/',),
988
'success', ('ok', '', 'no', 'no', 'yes', network_name))
870
'success', ('ok', '', 'no', 'no', 'no', network_name))
989
871
# called twice, once from constructor and then again by us
990
872
client.add_expected_call(
991
873
'Branch.get_stacked_on_url', ('stacked/',),
1332
1215
self.assertEqual('rejection message', err.msg)
1335
class TestBranchGetSetConfig(RemoteBranchTestCase):
1218
class TestBranchControlGetBranchConf(tests.TestCaseWithMemoryTransport):
1219
"""Getting the branch configuration should use an abstract method not vfs.
1337
1222
def test_get_branch_conf(self):
1338
# in an empty branch we decode the response properly
1339
client = FakeClient()
1340
client.add_expected_call(
1341
'Branch.get_stacked_on_url', ('memory:///',),
1342
'error', ('NotStacked',),)
1343
client.add_success_response_with_body('# config file body', 'ok')
1344
transport = MemoryTransport()
1345
branch = self.make_remote_branch(transport, client)
1346
config = branch.get_config()
1347
config.has_explicit_nickname()
1349
[('call', 'Branch.get_stacked_on_url', ('memory:///',)),
1350
('call_expecting_body', 'Branch.get_config_file', ('memory:///',))],
1353
def test_get_multi_line_branch_conf(self):
1354
# Make sure that multiple-line branch.conf files are supported
1356
# https://bugs.edge.launchpad.net/bzr/+bug/354075
1357
client = FakeClient()
1358
client.add_expected_call(
1359
'Branch.get_stacked_on_url', ('memory:///',),
1360
'error', ('NotStacked',),)
1361
client.add_success_response_with_body('a = 1\nb = 2\nc = 3\n', 'ok')
1362
transport = MemoryTransport()
1363
branch = self.make_remote_branch(transport, client)
1364
config = branch.get_config()
1365
self.assertEqual(u'2', config.get_user_option('b'))
1367
def test_set_option(self):
1368
client = FakeClient()
1369
client.add_expected_call(
1370
'Branch.get_stacked_on_url', ('memory:///',),
1371
'error', ('NotStacked',),)
1372
client.add_expected_call(
1373
'Branch.lock_write', ('memory:///', '', ''),
1374
'success', ('ok', 'branch token', 'repo token'))
1375
client.add_expected_call(
1376
'Branch.set_config_option', ('memory:///', 'branch token',
1377
'repo token', 'foo', 'bar', ''),
1379
client.add_expected_call(
1380
'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
1382
transport = MemoryTransport()
1383
branch = self.make_remote_branch(transport, client)
1385
config = branch._get_config()
1386
config.set_option('foo', 'bar')
1388
client.finished_test()
1390
def test_backwards_compat_set_option(self):
1391
self.setup_smart_server_with_call_log()
1392
branch = self.make_branch('.')
1393
verb = 'Branch.set_config_option'
1394
self.disable_verb(verb)
1396
self.addCleanup(branch.unlock)
1397
self.reset_smart_call_log()
1398
branch._get_config().set_option('value', 'name')
1399
self.assertLength(10, self.hpss_calls)
1400
self.assertEqual('value', branch._get_config().get_option('name'))
1223
raise tests.KnownFailure('branch.conf is not retrieved by get_config_file')
1224
## # We should see that branch.get_config() does a single rpc to get the
1225
## # remote configuration file, abstracting away where that is stored on
1226
## # the server. However at the moment it always falls back to using the
1227
## # vfs, and this would need some changes in config.py.
1229
## # in an empty branch we decode the response properly
1230
## client = FakeClient([(('ok', ), '# config file body')], self.get_url())
1231
## # we need to make a real branch because the remote_branch.control_files
1232
## # will trigger _ensure_real.
1233
## branch = self.make_branch('quack')
1234
## transport = branch.bzrdir.root_transport
1235
## # we do not want bzrdir to make any remote calls
1236
## bzrdir = RemoteBzrDir(transport, _client=False)
1237
## branch = RemoteBranch(bzrdir, None, _client=client)
1238
## config = branch.get_config()
1239
## self.assertEqual(
1240
## [('call_expecting_body', 'Branch.get_config_file', ('quack/',))],
1403
1244
class TestBranchLockWrite(RemoteBranchTestCase):
1631
1458
self.assertEqual({r1: (NULL_REVISION,)}, parents)
1632
1459
self.assertEqual(
1633
1460
[('call_with_body_bytes_expecting_body',
1634
'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
1461
'Repository.get_parent_map', ('quack/', r2), '\n\n0'),
1636
1462
('call_with_body_bytes_expecting_body',
1637
'Repository.get_parent_map', ('quack/', 'include-missing:', r1),
1463
'Repository.get_parent_map', ('quack/', r1), '\n\n0'),
1643
1468
def test_get_parent_map_reconnects_if_unknown_method(self):
1644
1469
transport_path = 'quack'
1645
rev_id = 'revision-id'
1646
1470
repo, client = self.setup_fake_client_and_repository(transport_path)
1647
client.add_unknown_method_response('Repository.get_parent_map')
1648
client.add_success_response_with_body(rev_id, 'ok')
1471
client.add_unknown_method_response('Repository,get_parent_map')
1472
client.add_success_response_with_body('', 'ok')
1649
1473
self.assertFalse(client._medium._is_remote_before((1, 2)))
1650
parents = repo.get_parent_map([rev_id])
1474
rev_id = 'revision-id'
1475
expected_deprecations = [
1476
'bzrlib.remote.RemoteRepository.get_revision_graph was deprecated '
1478
parents = self.callDeprecated(
1479
expected_deprecations, repo.get_parent_map, [rev_id])
1651
1480
self.assertEqual(
1652
1481
[('call_with_body_bytes_expecting_body',
1653
'Repository.get_parent_map', ('quack/', 'include-missing:',
1482
'Repository.get_parent_map', ('quack/', rev_id), '\n\n0'),
1655
1483
('disconnect medium',),
1656
1484
('call_expecting_body', 'Repository.get_revision_graph',
1657
1485
('quack/', ''))],
1659
1487
# The medium is now marked as being connected to an older server
1660
1488
self.assertTrue(client._medium._is_remote_before((1, 2)))
1661
self.assertEqual({rev_id: ('null:',)}, parents)
1663
1490
def test_get_parent_map_fallback_parentless_node(self):
1664
1491
"""get_parent_map falls back to get_revision_graph on old servers. The
1690
1521
errors.UnexpectedSmartServerResponse,
1691
1522
repo.get_parent_map, ['a-revision-id'])
1693
def test_get_parent_map_negative_caches_missing_keys(self):
1694
self.setup_smart_server_with_call_log()
1695
repo = self.make_repository('foo')
1696
self.assertIsInstance(repo, RemoteRepository)
1698
self.addCleanup(repo.unlock)
1699
self.reset_smart_call_log()
1700
graph = repo.get_graph()
1701
self.assertEqual({},
1702
graph.get_parent_map(['some-missing', 'other-missing']))
1703
self.assertLength(1, self.hpss_calls)
1704
# No call if we repeat this
1705
self.reset_smart_call_log()
1706
graph = repo.get_graph()
1707
self.assertEqual({},
1708
graph.get_parent_map(['some-missing', 'other-missing']))
1709
self.assertLength(0, self.hpss_calls)
1710
# Asking for more unknown keys makes a request.
1711
self.reset_smart_call_log()
1712
graph = repo.get_graph()
1713
self.assertEqual({},
1714
graph.get_parent_map(['some-missing', 'other-missing',
1716
self.assertLength(1, self.hpss_calls)
1718
def disableExtraResults(self):
1719
old_flag = SmartServerRepositoryGetParentMap.no_extra_results
1720
SmartServerRepositoryGetParentMap.no_extra_results = True
1722
SmartServerRepositoryGetParentMap.no_extra_results = old_flag
1723
self.addCleanup(reset_values)
1725
def test_null_cached_missing_and_stop_key(self):
1726
self.setup_smart_server_with_call_log()
1727
# Make a branch with a single revision.
1728
builder = self.make_branch_builder('foo')
1729
builder.start_series()
1730
builder.build_snapshot('first', None, [
1731
('add', ('', 'root-id', 'directory', ''))])
1732
builder.finish_series()
1733
branch = builder.get_branch()
1734
repo = branch.repository
1735
self.assertIsInstance(repo, RemoteRepository)
1736
# Stop the server from sending extra results.
1737
self.disableExtraResults()
1739
self.addCleanup(repo.unlock)
1740
self.reset_smart_call_log()
1741
graph = repo.get_graph()
1742
# Query for 'first' and 'null:'. Because 'null:' is a parent of
1743
# 'first' it will be a candidate for the stop_keys of subsequent
1744
# requests, and because 'null:' was queried but not returned it will be
1745
# cached as missing.
1746
self.assertEqual({'first': ('null:',)},
1747
graph.get_parent_map(['first', 'null:']))
1748
# Now query for another key. This request will pass along a recipe of
1749
# start and stop keys describing the already cached results, and this
1750
# recipe's revision count must be correct (or else it will trigger an
1751
# error from the server).
1752
self.assertEqual({}, graph.get_parent_map(['another-key']))
1753
# This assertion guards against disableExtraResults silently failing to
1754
# work, thus invalidating the test.
1755
self.assertLength(2, self.hpss_calls)
1757
def test_get_parent_map_gets_ghosts_from_result(self):
1758
# asking for a revision should negatively cache close ghosts in its
1760
self.setup_smart_server_with_call_log()
1761
tree = self.make_branch_and_memory_tree('foo')
1764
builder = treebuilder.TreeBuilder()
1765
builder.start_tree(tree)
1767
builder.finish_tree()
1768
tree.set_parent_ids(['non-existant'], allow_leftmost_as_ghost=True)
1769
rev_id = tree.commit('')
1773
self.addCleanup(tree.unlock)
1774
repo = tree.branch.repository
1775
self.assertIsInstance(repo, RemoteRepository)
1777
repo.get_parent_map([rev_id])
1778
self.reset_smart_call_log()
1779
# Now asking for rev_id's ghost parent should not make calls
1780
self.assertEqual({}, repo.get_parent_map(['non-existant']))
1781
self.assertLength(0, self.hpss_calls)
1784
1525
class TestGetParentMapAllowsNew(tests.TestCaseWithTransport):
1996
1734
self.assertEqual([], client._calls)
1999
class TestRepositoryInsertStream(TestRemoteRepository):
2001
def test_unlocked_repo(self):
2002
transport_path = 'quack'
2003
repo, client = self.setup_fake_client_and_repository(transport_path)
2004
client.add_expected_call(
2005
'Repository.insert_stream', ('quack/', ''),
2007
client.add_expected_call(
2008
'Repository.insert_stream', ('quack/', ''),
2010
sink = repo._get_sink()
2011
fmt = repository.RepositoryFormat.get_default_format()
2012
resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2013
self.assertEqual([], resume_tokens)
2014
self.assertEqual(set(), missing_keys)
2015
client.finished_test()
2017
def test_locked_repo_with_no_lock_token(self):
2018
transport_path = 'quack'
2019
repo, client = self.setup_fake_client_and_repository(transport_path)
2020
client.add_expected_call(
2021
'Repository.lock_write', ('quack/', ''),
2022
'success', ('ok', ''))
2023
client.add_expected_call(
2024
'Repository.insert_stream', ('quack/', ''),
2026
client.add_expected_call(
2027
'Repository.insert_stream', ('quack/', ''),
2030
sink = repo._get_sink()
2031
fmt = repository.RepositoryFormat.get_default_format()
2032
resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2033
self.assertEqual([], resume_tokens)
2034
self.assertEqual(set(), missing_keys)
2035
client.finished_test()
2037
def test_locked_repo_with_lock_token(self):
2038
transport_path = 'quack'
2039
repo, client = self.setup_fake_client_and_repository(transport_path)
2040
client.add_expected_call(
2041
'Repository.lock_write', ('quack/', ''),
2042
'success', ('ok', 'a token'))
2043
client.add_expected_call(
2044
'Repository.insert_stream_locked', ('quack/', '', 'a token'),
2046
client.add_expected_call(
2047
'Repository.insert_stream_locked', ('quack/', '', 'a token'),
2050
sink = repo._get_sink()
2051
fmt = repository.RepositoryFormat.get_default_format()
2052
resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2053
self.assertEqual([], resume_tokens)
2054
self.assertEqual(set(), missing_keys)
2055
client.finished_test()
2058
1737
class TestRepositoryTarball(TestRemoteRepository):
2060
1739
# This is a canned tarball reponse we can validate against
2389
2064
# revision, then open it over hpss - we should be able to see that
2391
2066
base_transport = self.get_transport()
2392
base_builder = self.make_branch_builder('base', format='1.9')
2067
base_builder = self.make_branch_builder('base', format='1.6')
2393
2068
base_builder.start_series()
2394
2069
base_revid = base_builder.build_snapshot('rev-id', None,
2395
2070
[('add', ('', None, 'directory', None))],
2397
2072
base_builder.finish_series()
2398
stacked_branch = self.make_branch('stacked', format='1.9')
2073
stacked_branch = self.make_branch('stacked', format='1.6')
2399
2074
stacked_branch.set_stacked_on_url('../base')
2400
2075
# start a server looking at this
2401
2076
smart_server = server.SmartTCPServer_for_testing()
2422
2097
remote_repo.unlock()
2424
2099
def prepare_stacked_remote_branch(self):
2425
"""Get stacked_upon and stacked branches with content in each."""
2426
self.setup_smart_server_with_call_log()
2427
tree1 = self.make_branch_and_tree('tree1', format='1.9')
2100
smart_server = server.SmartTCPServer_for_testing()
2101
smart_server.setUp()
2102
self.addCleanup(smart_server.tearDown)
2103
tree1 = self.make_branch_and_tree('tree1')
2428
2104
tree1.commit('rev1', rev_id='rev1')
2429
tree2 = tree1.branch.bzrdir.sprout('tree2', stacked=True
2430
).open_workingtree()
2431
tree2.commit('local changes make me feel good.')
2432
branch2 = Branch.open(self.get_url('tree2'))
2105
tree2 = self.make_branch_and_tree('tree2', format='1.6')
2106
tree2.branch.set_stacked_on_url(tree1.branch.base)
2107
branch2 = Branch.open(smart_server.get_url() + '/tree2')
2433
2108
branch2.lock_read()
2434
2109
self.addCleanup(branch2.unlock)
2435
return tree1.branch, branch2
2437
2112
def test_stacked_get_parent_map(self):
2438
2113
# the public implementation of get_parent_map obeys stacking
2439
_, branch = self.prepare_stacked_remote_branch()
2114
branch = self.prepare_stacked_remote_branch()
2440
2115
repo = branch.repository
2441
2116
self.assertEqual(['rev1'], repo.get_parent_map(['rev1']).keys())
2443
2118
def test_unstacked_get_parent_map(self):
2444
2119
# _unstacked_provider.get_parent_map ignores stacking
2445
_, branch = self.prepare_stacked_remote_branch()
2120
branch = self.prepare_stacked_remote_branch()
2446
2121
provider = branch.repository._unstacked_provider
2447
2122
self.assertEqual([], provider.get_parent_map(['rev1']).keys())
2449
def fetch_stream_to_rev_order(self, stream):
2451
for kind, substream in stream:
2452
if not kind == 'revisions':
2455
for content in substream:
2456
result.append(content.key[-1])
2459
def get_ordered_revs(self, format, order):
2460
"""Get a list of the revisions in a stream to format format.
2462
:param format: The format of the target.
2463
:param order: the order that target should have requested.
2464
:result: The revision ids in the stream, in the order seen,
2465
the topological order of revisions in the source.
2467
unordered_format = bzrdir.format_registry.get(format)()
2468
target_repository_format = unordered_format.repository_format
2470
self.assertEqual(order, target_repository_format._fetch_order)
2471
trunk, stacked = self.prepare_stacked_remote_branch()
2472
source = stacked.repository._get_source(target_repository_format)
2473
tip = stacked.last_revision()
2474
revs = stacked.repository.get_ancestry(tip)
2475
search = graph.PendingAncestryResult([tip], stacked.repository)
2476
self.reset_smart_call_log()
2477
stream = source.get_stream(search)
2480
# We trust that if a revision is in the stream the rest of the new
2481
# content for it is too, as per our main fetch tests; here we are
2482
# checking that the revisions are actually included at all, and their
2484
return self.fetch_stream_to_rev_order(stream), revs
2486
def test_stacked_get_stream_unordered(self):
2487
# Repository._get_source.get_stream() from a stacked repository with
2488
# unordered yields the full data from both stacked and stacked upon
2490
rev_ord, expected_revs = self.get_ordered_revs('1.9', 'unordered')
2491
self.assertEqual(set(expected_revs), set(rev_ord))
2492
# Getting unordered results should have made a streaming data request
2493
# from the server, then one from the backing branch.
2494
self.assertLength(2, self.hpss_calls)
2496
def test_stacked_get_stream_topological(self):
2497
# Repository._get_source.get_stream() from a stacked repository with
2498
# topological sorting yields the full data from both stacked and
2499
# stacked upon sources in topological order.
2500
rev_ord, expected_revs = self.get_ordered_revs('knit', 'topological')
2501
self.assertEqual(expected_revs, rev_ord)
2502
# Getting topological sort requires VFS calls still
2503
self.assertLength(12, self.hpss_calls)
2505
def test_stacked_get_stream_groupcompress(self):
2506
# Repository._get_source.get_stream() from a stacked repository with
2507
# groupcompress sorting yields the full data from both stacked and
2508
# stacked upon sources in groupcompress order.
2509
raise tests.TestSkipped('No groupcompress ordered format available')
2510
rev_ord, expected_revs = self.get_ordered_revs('dev5', 'groupcompress')
2511
self.assertEqual(expected_revs, reversed(rev_ord))
2512
# Getting unordered results should have made a streaming data request
2513
# from the backing branch, and one from the stacked on branch.
2514
self.assertLength(2, self.hpss_calls)
2517
2125
class TestRemoteBranchEffort(tests.TestCaseWithTransport):