~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_remote.py

  • Committer: Vincent Ladeuil
  • Date: 2011-07-06 09:22:00 UTC
  • mfrom: (6008 +trunk)
  • mto: (6012.1.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 6013.
  • Revision ID: v.ladeuil+lp@free.fr-20110706092200-7iai2mwzc0sqdsvf
MergingĀ inĀ trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
    config,
33
33
    controldir,
34
34
    errors,
35
 
    graph,
 
35
    graph as _mod_graph,
36
36
    inventory,
37
37
    inventory_delta,
38
38
    remote,
52
52
    RemoteBranch,
53
53
    RemoteBranchFormat,
54
54
    RemoteBzrDir,
 
55
    RemoteBzrDirFormat,
55
56
    RemoteRepository,
56
57
    RemoteRepositoryFormat,
57
58
    )
58
 
from bzrlib.repofmt import groupcompress_repo, pack_repo
 
59
from bzrlib.repofmt import groupcompress_repo, knitpack_repo
59
60
from bzrlib.revision import NULL_REVISION
60
 
from bzrlib.smart import medium
 
61
from bzrlib.smart import medium, request
61
62
from bzrlib.smart.client import _SmartClient
62
 
from bzrlib.smart.repository import SmartServerRepositoryGetParentMap
 
63
from bzrlib.smart.repository import (
 
64
    SmartServerRepositoryGetParentMap,
 
65
    SmartServerRepositoryGetStream_1_19,
 
66
    )
63
67
from bzrlib.tests import (
64
68
    test_server,
65
69
    )
92
96
        self.addCleanup(self.transport.disconnect)
93
97
 
94
98
    def test_create_remote_bzrdir(self):
95
 
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
 
99
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
96
100
        self.assertIsInstance(b, BzrDir)
97
101
 
98
102
    def test_open_remote_branch(self):
99
103
        # open a standalone branch in the working directory
100
 
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
 
104
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
101
105
        branch = b.open_branch()
102
106
        self.assertIsInstance(branch, Branch)
103
107
 
121
125
        fmt = BzrDirFormat.find_format(self.transport)
122
126
        self.assertTrue(bzrdir.RemoteBzrProber
123
127
                        in controldir.ControlDirFormat._server_probers)
124
 
        self.assertIsInstance(fmt, remote.RemoteBzrDirFormat)
 
128
        self.assertIsInstance(fmt, RemoteBzrDirFormat)
125
129
 
126
130
    def test_open_detected_smart_format(self):
127
131
        fmt = BzrDirFormat.find_format(self.transport)
447
451
        client.add_expected_call(
448
452
            'BzrDir.open_branchV3', ('quack/',),
449
453
            'success', ('ref', self.get_url('referenced'))),
450
 
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
454
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
451
455
            _client=client)
452
456
        result = a_bzrdir.cloning_metadir()
453
457
        # We should have got a control dir matching the referenced branch.
466
470
        client.add_expected_call(
467
471
            'BzrDir.cloning_metadir', ('quack/', 'False'),
468
472
            'success', (control_name, '', ('branch', ''))),
469
 
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
473
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
470
474
            _client=client)
471
475
        result = a_bzrdir.cloning_metadir()
472
476
        # We should have got a reference control dir with default branch and
492
496
        client.add_expected_call(
493
497
            'BzrDir.open_2.1', ('quack/',), 'success', ('no',))
494
498
        self.assertRaises(errors.NotBranchError, RemoteBzrDir, transport,
495
 
                remote.RemoteBzrDirFormat(), _client=client, _force_probe=True)
 
499
                RemoteBzrDirFormat(), _client=client, _force_probe=True)
496
500
        self.assertFinished(client)
497
501
 
498
502
    def test_present_without_workingtree(self):
499
503
        client, transport = self.make_fake_client_and_transport()
500
504
        client.add_expected_call(
501
505
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'no'))
502
 
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
506
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
503
507
            _client=client, _force_probe=True)
504
508
        self.assertIsInstance(bd, RemoteBzrDir)
505
509
        self.assertFalse(bd.has_workingtree())
510
514
        client, transport = self.make_fake_client_and_transport()
511
515
        client.add_expected_call(
512
516
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'yes'))
513
 
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
517
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
514
518
            _client=client, _force_probe=True)
515
519
        self.assertIsInstance(bd, RemoteBzrDir)
516
520
        self.assertTrue(bd.has_workingtree())
523
527
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
524
528
        client.add_expected_call(
525
529
            'BzrDir.open', ('quack/',), 'success', ('yes',))
526
 
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
530
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
527
531
            _client=client, _force_probe=True)
528
532
        self.assertIsInstance(bd, RemoteBzrDir)
529
533
        self.assertFinished(client)
545
549
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
546
550
        client.add_expected_call(
547
551
            'BzrDir.open', ('quack/',), 'success', ('yes',))
548
 
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
552
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
549
553
            _client=client, _force_probe=True)
550
554
        self.assertIsInstance(bd, RemoteBzrDir)
551
555
        self.assertFinished(client)
582
586
        client.add_expected_call(
583
587
            'Branch.get_stacked_on_url', ('quack/',),
584
588
            'error', ('NotStacked',))
585
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
589
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
586
590
            _client=client)
587
591
        result = bzrdir.open_branch()
588
592
        self.assertIsInstance(result, RemoteBranch)
595
599
        transport = transport.clone('quack')
596
600
        client = FakeClient(transport.base)
597
601
        client.add_error_response('nobranch')
598
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
602
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
599
603
            _client=client)
600
604
        self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
601
605
        self.assertEqual(
612
616
        transport = MemoryTransport()
613
617
        # no requests on the network - catches other api calls being made.
614
618
        client = FakeClient(transport.base)
615
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
619
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
616
620
            _client=client)
617
621
        # patch the open_branch call to record that it was called.
618
622
        bzrdir.open_branch = open_branch
637
641
        client.add_expected_call(
638
642
            'Branch.get_stacked_on_url', ('~hello/',),
639
643
            'error', ('NotStacked',))
640
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
644
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
641
645
            _client=client)
642
646
        result = bzrdir.open_branch()
643
647
        self.assertFinished(client)
660
664
        client.add_success_response(
661
665
            'ok', '', rich_response, subtree_response, external_lookup,
662
666
            network_name)
663
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
667
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
664
668
            _client=client)
665
669
        result = bzrdir.open_repository()
666
670
        self.assertEqual(
712
716
            'BzrDir.create_branch', ('quack/', network_name),
713
717
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
714
718
            reference_repo_name))
715
 
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
719
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
716
720
            _client=client)
717
721
        branch = a_bzrdir.create_branch()
718
722
        # We should have got a remote branch
740
744
            'BzrDir.create_branch', ('extra/quack/', network_name),
741
745
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
742
746
            reference_repo_name))
743
 
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
747
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
744
748
            _client=client)
745
749
        branch = a_bzrdir.create_branch(repository=repo)
746
750
        # We should have got a remote branch
775
779
                'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
776
780
                'False'),
777
781
            'success', ('ok', 'yes', 'yes', 'yes', network_name))
778
 
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
782
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
779
783
            _client=client)
780
784
        repo = a_bzrdir.create_repository()
781
785
        # We should have got a remote repository
810
814
        client.add_success_response('stat', '0', '65535')
811
815
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
812
816
            _client=client)
813
 
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
 
817
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
814
818
            _client=client)
815
819
        repo = bzrdir.open_repository()
816
820
        self.assertEqual(
843
847
        client.add_success_response('stat', '0', '65535')
844
848
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
845
849
            _client=client)
846
 
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
 
850
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
847
851
            _client=client)
848
852
        repo = bzrdir.open_repository()
849
853
        self.assertEqual(
864
868
        transport = transport.clone('quack')
865
869
        client = FakeClient(transport.base)
866
870
        client.add_success_response('ok', '', 'no', 'no', 'no', network_name)
867
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
871
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
868
872
            _client=client)
869
873
        repo = bzrdir.open_repository()
870
874
        self.assertEqual(
877
881
 
878
882
    def test_success(self):
879
883
        """Simple test for typical successful call."""
880
 
        fmt = bzrdir.RemoteBzrDirFormat()
 
884
        fmt = RemoteBzrDirFormat()
881
885
        default_format_name = BzrDirFormat.get_default_format().network_name()
882
886
        transport = self.get_transport()
883
887
        client = FakeClient(transport.base)
899
903
        """Error responses are translated, e.g. 'PermissionDenied' raises the
900
904
        corresponding error from the client.
901
905
        """
902
 
        fmt = bzrdir.RemoteBzrDirFormat()
 
906
        fmt = RemoteBzrDirFormat()
903
907
        default_format_name = BzrDirFormat.get_default_format().network_name()
904
908
        transport = self.get_transport()
905
909
        client = FakeClient(transport.base)
923
927
        """Integration test for error translation."""
924
928
        transport = self.make_smart_server('foo')
925
929
        transport = transport.clone('no-such-path')
926
 
        fmt = bzrdir.RemoteBzrDirFormat()
 
930
        fmt = RemoteBzrDirFormat()
927
931
        err = self.assertRaises(errors.NoSuchFile,
928
932
            fmt.initialize_on_transport_ex, transport, create_prefix=False)
929
933
 
960
964
 
961
965
    def make_remote_bzrdir(self, transport, client):
962
966
        """Make a RemotebzrDir using 'client' as the _client."""
963
 
        return RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
967
        return RemoteBzrDir(transport, RemoteBzrDirFormat(),
964
968
            _client=client)
965
969
 
966
970
 
1168
1172
            [('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
1169
1173
 
1170
1174
 
 
1175
class TestBranchHeadsToFetch(RemoteBranchTestCase):
 
1176
 
 
1177
    def test_uses_last_revision_info_and_tags_by_default(self):
 
1178
        transport = MemoryTransport()
 
1179
        client = FakeClient(transport.base)
 
1180
        client.add_expected_call(
 
1181
            'Branch.get_stacked_on_url', ('quack/',),
 
1182
            'error', ('NotStacked',))
 
1183
        client.add_expected_call(
 
1184
            'Branch.last_revision_info', ('quack/',),
 
1185
            'success', ('ok', '1', 'rev-tip'))
 
1186
        # XXX: this will break if the default format's serialization of tags
 
1187
        # changes, or if the RPC for fetching tags changes from get_tags_bytes.
 
1188
        client.add_expected_call(
 
1189
            'Branch.get_tags_bytes', ('quack/',),
 
1190
            'success', ('d5:tag-17:rev-foo5:tag-27:rev-bare',))
 
1191
        transport.mkdir('quack')
 
1192
        transport = transport.clone('quack')
 
1193
        branch = self.make_remote_branch(transport, client)
 
1194
        result = branch.heads_to_fetch()
 
1195
        self.assertFinished(client)
 
1196
        self.assertEqual(
 
1197
            (set(['rev-tip']), set(['rev-foo', 'rev-bar'])), result)
 
1198
 
 
1199
    def test_uses_rpc_for_formats_with_non_default_heads_to_fetch(self):
 
1200
        transport = MemoryTransport()
 
1201
        client = FakeClient(transport.base)
 
1202
        client.add_expected_call(
 
1203
            'Branch.get_stacked_on_url', ('quack/',),
 
1204
            'error', ('NotStacked',))
 
1205
        client.add_expected_call(
 
1206
            'Branch.heads_to_fetch', ('quack/',),
 
1207
            'success', (['tip'], ['tagged-1', 'tagged-2']))
 
1208
        transport.mkdir('quack')
 
1209
        transport = transport.clone('quack')
 
1210
        branch = self.make_remote_branch(transport, client)
 
1211
        branch._format._use_default_local_heads_to_fetch = lambda: False
 
1212
        result = branch.heads_to_fetch()
 
1213
        self.assertFinished(client)
 
1214
        self.assertEqual((set(['tip']), set(['tagged-1', 'tagged-2'])), result)
 
1215
 
 
1216
    def test_backwards_compatible(self):
 
1217
        self.setup_smart_server_with_call_log()
 
1218
        # Make a branch with a single revision.
 
1219
        builder = self.make_branch_builder('foo')
 
1220
        builder.start_series()
 
1221
        builder.build_snapshot('tip', None, [
 
1222
            ('add', ('', 'root-id', 'directory', ''))])
 
1223
        builder.finish_series()
 
1224
        branch = builder.get_branch()
 
1225
        # Add two tags to that branch
 
1226
        branch.tags.set_tag('tag-1', 'rev-1')
 
1227
        branch.tags.set_tag('tag-2', 'rev-2')
 
1228
        self.addCleanup(branch.lock_read().unlock)
 
1229
        # Disable the heads_to_fetch verb
 
1230
        verb = 'Branch.heads_to_fetch'
 
1231
        self.disable_verb(verb)
 
1232
        self.reset_smart_call_log()
 
1233
        result = branch.heads_to_fetch()
 
1234
        self.assertEqual((set(['tip']), set(['rev-1', 'rev-2'])), result)
 
1235
        self.assertEqual(
 
1236
            ['Branch.last_revision_info', 'Branch.get_tags_bytes'],
 
1237
            [call.call.method for call in self.hpss_calls])
 
1238
 
 
1239
 
1171
1240
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
1172
1241
 
1173
1242
    def test_empty_branch(self):
1228
1297
        client.add_expected_call(
1229
1298
            'Branch.get_stacked_on_url', ('stacked/',),
1230
1299
            'success', ('ok', vfs_url))
1231
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
1300
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1232
1301
            _client=client)
1233
1302
        repo_fmt = remote.RemoteRepositoryFormat()
1234
1303
        repo_fmt._custom_format = stacked_branch.repository._format
1261
1330
        # this will also do vfs access, but that goes direct to the transport
1262
1331
        # and isn't seen by the FakeClient.
1263
1332
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1264
 
            remote.RemoteBzrDirFormat(), _client=client)
 
1333
            RemoteBzrDirFormat(), _client=client)
1265
1334
        branch = bzrdir.open_branch()
1266
1335
        result = branch.get_stacked_on_url()
1267
1336
        self.assertEqual('../base', result)
1294
1363
            'Branch.get_stacked_on_url', ('stacked/',),
1295
1364
            'success', ('ok', '../base'))
1296
1365
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1297
 
            remote.RemoteBzrDirFormat(), _client=client)
 
1366
            RemoteBzrDirFormat(), _client=client)
1298
1367
        branch = bzrdir.open_branch()
1299
1368
        result = branch.get_stacked_on_url()
1300
1369
        self.assertEqual('../base', result)
1308
1377
class TestBranchSetLastRevision(RemoteBranchTestCase):
1309
1378
 
1310
1379
    def test_set_empty(self):
1311
 
        # set_revision_history([]) is translated to calling
 
1380
        # _set_last_revision_info('null:') is translated to calling
1312
1381
        # Branch.set_last_revision(path, '') on the wire.
1313
1382
        transport = MemoryTransport()
1314
1383
        transport.mkdir('branch')
1336
1405
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1337
1406
        branch._ensure_real = lambda: None
1338
1407
        branch.lock_write()
1339
 
        result = branch.set_revision_history([])
 
1408
        result = branch._set_last_revision(NULL_REVISION)
1340
1409
        branch.unlock()
1341
1410
        self.assertEqual(None, result)
1342
1411
        self.assertFinished(client)
1343
1412
 
1344
1413
    def test_set_nonempty(self):
1345
 
        # set_revision_history([rev-id1, ..., rev-idN]) is translated to calling
 
1414
        # set_last_revision_info(N, rev-idN) is translated to calling
1346
1415
        # Branch.set_last_revision(path, rev-idN) on the wire.
1347
1416
        transport = MemoryTransport()
1348
1417
        transport.mkdir('branch')
1374
1443
        branch._ensure_real = lambda: None
1375
1444
        # Lock the branch, reset the record of remote calls.
1376
1445
        branch.lock_write()
1377
 
        result = branch.set_revision_history(['rev-id1', 'rev-id2'])
 
1446
        result = branch._set_last_revision('rev-id2')
1378
1447
        branch.unlock()
1379
1448
        self.assertEqual(None, result)
1380
1449
        self.assertFinished(client)
1410
1479
        branch = self.make_remote_branch(transport, client)
1411
1480
        branch.lock_write()
1412
1481
        self.assertRaises(
1413
 
            errors.NoSuchRevision, branch.set_revision_history, ['rev-id'])
 
1482
            errors.NoSuchRevision, branch._set_last_revision, 'rev-id')
1414
1483
        branch.unlock()
1415
1484
        self.assertFinished(client)
1416
1485
 
1447
1516
        branch._ensure_real = lambda: None
1448
1517
        branch.lock_write()
1449
1518
        # The 'TipChangeRejected' error response triggered by calling
1450
 
        # set_revision_history causes a TipChangeRejected exception.
 
1519
        # set_last_revision_info causes a TipChangeRejected exception.
1451
1520
        err = self.assertRaises(
1452
 
            errors.TipChangeRejected, branch.set_revision_history, ['rev-id'])
 
1521
            errors.TipChangeRejected,
 
1522
            branch._set_last_revision, 'rev-id')
1453
1523
        # The UTF-8 message from the response has been decoded into a unicode
1454
1524
        # object.
1455
1525
        self.assertIsInstance(err.msg, unicode)
1870
1940
        client = FakeClient(transport.base)
1871
1941
        transport = transport.clone(transport_path)
1872
1942
        # we do not want bzrdir to make any remote calls
1873
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
1943
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1874
1944
            _client=False)
1875
1945
        repo = RemoteRepository(bzrdir, None, _client=client)
1876
1946
        return repo, client
1884
1954
 
1885
1955
    def test_get_format_description(self):
1886
1956
        remote_format = RemoteBranchFormat()
1887
 
        real_format = branch.BranchFormat.get_default_format()
 
1957
        real_format = branch.format_registry.get_default()
1888
1958
        remote_format._network_name = real_format.network_name()
1889
1959
        self.assertEqual(remoted_description(real_format),
1890
1960
            remote_format.get_format_description())
1897
1967
        true_format = RemoteRepositoryFormat()
1898
1968
        true_format._network_name = true_name
1899
1969
        self.assertEqual(True, true_format.fast_deltas)
1900
 
        false_name = pack_repo.RepositoryFormatKnitPack1().network_name()
 
1970
        false_name = knitpack_repo.RepositoryFormatKnitPack1().network_name()
1901
1971
        false_format = RemoteRepositoryFormat()
1902
1972
        false_format._network_name = false_name
1903
1973
        self.assertEqual(False, false_format.fast_deltas)
1904
1974
 
1905
1975
    def test_get_format_description(self):
1906
1976
        remote_repo_format = RemoteRepositoryFormat()
1907
 
        real_format = repository.RepositoryFormat.get_default_format()
 
1977
        real_format = repository.format_registry.get_default()
1908
1978
        remote_repo_format._network_name = real_format.network_name()
1909
1979
        self.assertEqual(remoted_description(real_format),
1910
1980
            remote_repo_format.get_format_description())
2468
2538
        the client is finished.
2469
2539
        """
2470
2540
        sink = repo._get_sink()
2471
 
        fmt = repository.RepositoryFormat.get_default_format()
 
2541
        fmt = repository.format_registry.get_default()
2472
2542
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2473
2543
        self.assertEqual([], resume_tokens)
2474
2544
        self.assertEqual(set(), missing_keys)
2574
2644
                return True
2575
2645
        repo._real_repository = FakeRealRepository()
2576
2646
        sink = repo._get_sink()
2577
 
        fmt = repository.RepositoryFormat.get_default_format()
 
2647
        fmt = repository.format_registry.get_default()
2578
2648
        stream = self.make_stream_with_inv_deltas(fmt)
2579
2649
        resume_tokens, missing_keys = sink.insert_stream(stream, fmt, [])
2580
2650
        # Every record from the first inventory delta should have been sent to
2800
2870
             ('pack collection autopack',)],
2801
2871
            client._calls)
2802
2872
 
 
2873
    def test_oom_error_reporting(self):
 
2874
        """An out-of-memory condition on the server is reported clearly"""
 
2875
        transport_path = 'quack'
 
2876
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2877
        client.add_expected_call(
 
2878
            'PackRepository.autopack', ('quack/',),
 
2879
            'error', ('MemoryError',))
 
2880
        err = self.assertRaises(errors.BzrError, repo.autopack)
 
2881
        self.assertContainsRe(str(err), "^remote server out of mem")
 
2882
 
2803
2883
 
2804
2884
class TestErrorTranslationBase(tests.TestCaseWithMemoryTransport):
2805
2885
    """Base class for unit tests for bzrlib.remote._translate_error."""
2878
2958
            detail='extra detail')
2879
2959
        self.assertEqual(expected_error, translated_error)
2880
2960
 
 
2961
    def test_norepository(self):
 
2962
        bzrdir = self.make_bzrdir('')
 
2963
        translated_error = self.translateTuple(('norepository',),
 
2964
            bzrdir=bzrdir)
 
2965
        expected_error = errors.NoRepositoryPresent(bzrdir)
 
2966
        self.assertEqual(expected_error, translated_error)
 
2967
 
2881
2968
    def test_LockContention(self):
2882
2969
        translated_error = self.translateTuple(('LockContention',))
2883
2970
        expected_error = errors.LockContention('(remote lock)')
2911
2998
        expected_error = errors.DivergedBranches(branch, other_branch)
2912
2999
        self.assertEqual(expected_error, translated_error)
2913
3000
 
 
3001
    def test_NotStacked(self):
 
3002
        branch = self.make_branch('')
 
3003
        translated_error = self.translateTuple(('NotStacked',), branch=branch)
 
3004
        expected_error = errors.NotStacked(branch)
 
3005
        self.assertEqual(expected_error, translated_error)
 
3006
 
2914
3007
    def test_ReadError_no_args(self):
2915
3008
        path = 'a path'
2916
3009
        translated_error = self.translateTuple(('ReadError',), path=path)
2932
3025
 
2933
3026
    def test_PermissionDenied_no_args(self):
2934
3027
        path = 'a path'
2935
 
        translated_error = self.translateTuple(('PermissionDenied',), path=path)
 
3028
        translated_error = self.translateTuple(('PermissionDenied',),
 
3029
            path=path)
2936
3030
        expected_error = errors.PermissionDenied(path)
2937
3031
        self.assertEqual(expected_error, translated_error)
2938
3032
 
2961
3055
        expected_error = errors.PermissionDenied(path, extra)
2962
3056
        self.assertEqual(expected_error, translated_error)
2963
3057
 
 
3058
    # GZ 2011-03-02: TODO test for PermissionDenied with non-ascii 'extra'
 
3059
 
 
3060
    def test_NoSuchFile_context_path(self):
 
3061
        local_path = "local path"
 
3062
        translated_error = self.translateTuple(('ReadError', "remote path"),
 
3063
            path=local_path)
 
3064
        expected_error = errors.ReadError(local_path)
 
3065
        self.assertEqual(expected_error, translated_error)
 
3066
 
 
3067
    def test_NoSuchFile_without_context(self):
 
3068
        remote_path = "remote path"
 
3069
        translated_error = self.translateTuple(('ReadError', remote_path))
 
3070
        expected_error = errors.ReadError(remote_path)
 
3071
        self.assertEqual(expected_error, translated_error)
 
3072
 
 
3073
    def test_ReadOnlyError(self):
 
3074
        translated_error = self.translateTuple(('ReadOnlyError',))
 
3075
        expected_error = errors.TransportNotPossible("readonly transport")
 
3076
        self.assertEqual(expected_error, translated_error)
 
3077
 
 
3078
    def test_MemoryError(self):
 
3079
        translated_error = self.translateTuple(('MemoryError',))
 
3080
        self.assertStartsWith(str(translated_error),
 
3081
            "remote server out of memory")
 
3082
 
 
3083
    def test_generic_IndexError_no_classname(self):
 
3084
        err = errors.ErrorFromSmartServer(('error', "list index out of range"))
 
3085
        translated_error = self.translateErrorFromSmartServer(err)
 
3086
        expected_error = errors.UnknownErrorFromSmartServer(err)
 
3087
        self.assertEqual(expected_error, translated_error)
 
3088
 
 
3089
    # GZ 2011-03-02: TODO test generic non-ascii error string
 
3090
 
 
3091
    def test_generic_KeyError(self):
 
3092
        err = errors.ErrorFromSmartServer(('error', 'KeyError', "1"))
 
3093
        translated_error = self.translateErrorFromSmartServer(err)
 
3094
        expected_error = errors.UnknownErrorFromSmartServer(err)
 
3095
        self.assertEqual(expected_error, translated_error)
 
3096
 
2964
3097
 
2965
3098
class TestErrorTranslationRobustness(TestErrorTranslationBase):
2966
3099
    """Unit tests for bzrlib.remote._translate_error's robustness.
3111
3244
        _, stacked = branch_factory()
3112
3245
        source = stacked.repository._get_source(target_repository_format)
3113
3246
        tip = stacked.last_revision()
3114
 
        revs = stacked.repository.get_ancestry(tip)
3115
 
        search = graph.PendingAncestryResult([tip], stacked.repository)
 
3247
        stacked.repository._ensure_real()
 
3248
        graph = stacked.repository.get_graph()
 
3249
        revs = [r for (r,ps) in graph.iter_ancestry([tip])
 
3250
                if r != NULL_REVISION]
 
3251
        revs.reverse()
 
3252
        search = _mod_graph.PendingAncestryResult([tip], stacked.repository)
3116
3253
        self.reset_smart_call_log()
3117
3254
        stream = source.get_stream(search)
3118
 
        if None in revs:
3119
 
            revs.remove(None)
3120
3255
        # We trust that if a revision is in the stream the rest of the new
3121
3256
        # content for it is too, as per our main fetch tests; here we are
3122
3257
        # checking that the revisions are actually included at all, and their
3161
3296
        self.assertEqual(expected_revs, rev_ord)
3162
3297
        # Getting topological sort requires VFS calls still - one of which is
3163
3298
        # pushing up from the bound branch.
3164
 
        self.assertLength(13, self.hpss_calls)
 
3299
        self.assertLength(14, self.hpss_calls)
3165
3300
 
3166
3301
    def test_stacked_get_stream_groupcompress(self):
3167
3302
        # Repository._get_source.get_stream() from a stacked repository with
3208
3343
 
3209
3344
    def test_copy_content_into_avoids_revision_history(self):
3210
3345
        local = self.make_branch('local')
3211
 
        remote_backing_tree = self.make_branch_and_tree('remote')
3212
 
        remote_backing_tree.commit("Commit.")
 
3346
        builder = self.make_branch_builder('remote')
 
3347
        builder.build_commit(message="Commit.")
3213
3348
        remote_branch_url = self.smart_server.get_url() + 'remote'
3214
3349
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3215
3350
        local.repository.fetch(remote_branch.repository)
3216
3351
        self.hpss_calls = []
3217
3352
        remote_branch.copy_content_into(local)
3218
3353
        self.assertFalse('Branch.revision_history' in self.hpss_calls)
 
3354
 
 
3355
    def test_fetch_everything_needs_just_one_call(self):
 
3356
        local = self.make_branch('local')
 
3357
        builder = self.make_branch_builder('remote')
 
3358
        builder.build_commit(message="Commit.")
 
3359
        remote_branch_url = self.smart_server.get_url() + 'remote'
 
3360
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
 
3361
        self.hpss_calls = []
 
3362
        local.repository.fetch(remote_branch.repository,
 
3363
                fetch_spec=_mod_graph.EverythingResult(remote_branch.repository))
 
3364
        self.assertEqual(['Repository.get_stream_1.19'], self.hpss_calls)
 
3365
 
 
3366
    def override_verb(self, verb_name, verb):
 
3367
        request_handlers = request.request_handlers
 
3368
        orig_verb = request_handlers.get(verb_name)
 
3369
        request_handlers.register(verb_name, verb, override_existing=True)
 
3370
        self.addCleanup(request_handlers.register, verb_name, orig_verb,
 
3371
                override_existing=True)
 
3372
 
 
3373
    def test_fetch_everything_backwards_compat(self):
 
3374
        """Can fetch with EverythingResult even with pre 2.4 servers.
 
3375
        
 
3376
        Pre-2.4 do not support 'everything' searches with the
 
3377
        Repository.get_stream_1.19 verb.
 
3378
        """
 
3379
        verb_log = []
 
3380
        class OldGetStreamVerb(SmartServerRepositoryGetStream_1_19):
 
3381
            """A version of the Repository.get_stream_1.19 verb patched to
 
3382
            reject 'everything' searches the way 2.3 and earlier do.
 
3383
            """
 
3384
            def recreate_search(self, repository, search_bytes, discard_excess=False):
 
3385
                verb_log.append(search_bytes.split('\n', 1)[0])
 
3386
                if search_bytes == 'everything':
 
3387
                    return (None, request.FailedSmartServerResponse(('BadSearch',)))
 
3388
                return super(OldGetStreamVerb,
 
3389
                        self).recreate_search(repository, search_bytes,
 
3390
                            discard_excess=discard_excess)
 
3391
        self.override_verb('Repository.get_stream_1.19', OldGetStreamVerb)
 
3392
        local = self.make_branch('local')
 
3393
        builder = self.make_branch_builder('remote')
 
3394
        builder.build_commit(message="Commit.")
 
3395
        remote_branch_url = self.smart_server.get_url() + 'remote'
 
3396
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
 
3397
        self.hpss_calls = []
 
3398
        local.repository.fetch(remote_branch.repository,
 
3399
                fetch_spec=_mod_graph.EverythingResult(remote_branch.repository))
 
3400
        # make sure the overridden verb was used
 
3401
        self.assertLength(1, verb_log)
 
3402
        # more than one HPSS call is needed, but because it's a VFS callback
 
3403
        # its hard to predict exactly how many.
 
3404
        self.assertTrue(len(self.hpss_calls) > 1)
 
3405