~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_remote.py

  • Committer: John Ferlito
  • Date: 2009-09-02 04:31:45 UTC
  • mto: (4665.7.1 serve-init)
  • mto: This revision was merged to the branch mainline in revision 4913.
  • Revision ID: johnf@inodes.org-20090902043145-gxdsfw03ilcwbyn5
Add a debian init script for bzr --serve

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2011 Canonical Ltd
 
1
# Copyright (C) 2006, 2007, 2008, 2009 Canonical Ltd
2
2
#
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
27
27
from cStringIO import StringIO
28
28
 
29
29
from bzrlib import (
30
 
    branch,
31
30
    bzrdir,
32
31
    config,
33
 
    controldir,
34
32
    errors,
35
33
    graph,
36
34
    inventory,
37
35
    inventory_delta,
 
36
    pack,
38
37
    remote,
39
38
    repository,
 
39
    smart,
40
40
    tests,
41
 
    transport,
42
41
    treebuilder,
 
42
    urlutils,
43
43
    versionedfile,
44
44
    )
45
45
from bzrlib.branch import Branch
46
 
from bzrlib.bzrdir import (
47
 
    BzrDir,
48
 
    BzrDirFormat,
49
 
    RemoteBzrProber,
50
 
    )
 
46
from bzrlib.bzrdir import BzrDir, BzrDirFormat
51
47
from bzrlib.remote import (
52
48
    RemoteBranch,
53
49
    RemoteBranchFormat,
56
52
    RemoteRepository,
57
53
    RemoteRepositoryFormat,
58
54
    )
59
 
from bzrlib.repofmt import groupcompress_repo, knitpack_repo
 
55
from bzrlib.repofmt import groupcompress_repo, pack_repo
60
56
from bzrlib.revision import NULL_REVISION
61
 
from bzrlib.smart import medium, request
 
57
from bzrlib.smart import server, medium
62
58
from bzrlib.smart.client import _SmartClient
63
 
from bzrlib.smart.repository import (
64
 
    SmartServerRepositoryGetParentMap,
65
 
    SmartServerRepositoryGetStream_1_19,
66
 
    )
 
59
from bzrlib.smart.repository import SmartServerRepositoryGetParentMap
67
60
from bzrlib.tests import (
68
 
    test_server,
 
61
    condition_isinstance,
 
62
    split_suite_by_condition,
 
63
    multiply_tests,
 
64
    KnownFailure,
69
65
    )
70
 
from bzrlib.tests.scenarios import load_tests_apply_scenarios
 
66
from bzrlib.transport import get_transport, http
71
67
from bzrlib.transport.memory import MemoryTransport
72
68
from bzrlib.transport.remote import (
73
69
    RemoteTransport,
74
70
    RemoteSSHTransport,
75
71
    RemoteTCPTransport,
76
 
    )
77
 
 
78
 
 
79
 
load_tests = load_tests_apply_scenarios
80
 
 
81
 
 
82
 
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
83
 
 
84
 
    scenarios = [
 
72
)
 
73
 
 
74
def load_tests(standard_tests, module, loader):
 
75
    to_adapt, result = split_suite_by_condition(
 
76
        standard_tests, condition_isinstance(BasicRemoteObjectTests))
 
77
    smart_server_version_scenarios = [
85
78
        ('HPSS-v2',
86
 
            {'transport_server': test_server.SmartTCPServer_for_testing_v2_only}),
 
79
            {'transport_server': server.SmartTCPServer_for_testing_v2_only}),
87
80
        ('HPSS-v3',
88
 
            {'transport_server': test_server.SmartTCPServer_for_testing})]
89
 
 
 
81
            {'transport_server': server.SmartTCPServer_for_testing})]
 
82
    return multiply_tests(to_adapt, smart_server_version_scenarios, result)
 
83
 
 
84
 
 
85
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
90
86
 
91
87
    def setUp(self):
92
88
        super(BasicRemoteObjectTests, self).setUp()
93
89
        self.transport = self.get_transport()
94
90
        # make a branch that can be opened over the smart transport
95
91
        self.local_wt = BzrDir.create_standalone_workingtree('.')
96
 
        self.addCleanup(self.transport.disconnect)
 
92
 
 
93
    def tearDown(self):
 
94
        self.transport.disconnect()
 
95
        tests.TestCaseWithTransport.tearDown(self)
97
96
 
98
97
    def test_create_remote_bzrdir(self):
99
 
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
 
98
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
100
99
        self.assertIsInstance(b, BzrDir)
101
100
 
102
101
    def test_open_remote_branch(self):
103
102
        # open a standalone branch in the working directory
104
 
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
 
103
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
105
104
        branch = b.open_branch()
106
105
        self.assertIsInstance(branch, Branch)
107
106
 
123
122
    def test_find_correct_format(self):
124
123
        """Should open a RemoteBzrDir over a RemoteTransport"""
125
124
        fmt = BzrDirFormat.find_format(self.transport)
126
 
        self.assertTrue(bzrdir.RemoteBzrProber
127
 
                        in controldir.ControlDirFormat._server_probers)
128
 
        self.assertIsInstance(fmt, RemoteBzrDirFormat)
 
125
        self.assertTrue(RemoteBzrDirFormat
 
126
                        in BzrDirFormat._control_server_formats)
 
127
        self.assertIsInstance(fmt, remote.RemoteBzrDirFormat)
129
128
 
130
129
    def test_open_detected_smart_format(self):
131
130
        fmt = BzrDirFormat.find_format(self.transport)
136
135
        b = BzrDir.open_from_transport(self.transport).open_branch()
137
136
        self.assertStartsWith(str(b), 'RemoteBranch(')
138
137
 
139
 
    def test_remote_bzrdir_repr(self):
140
 
        b = BzrDir.open_from_transport(self.transport)
141
 
        self.assertStartsWith(str(b), 'RemoteBzrDir(')
142
 
 
143
138
    def test_remote_branch_format_supports_stacking(self):
144
139
        t = self.transport
145
140
        self.make_branch('unstackable', format='pack-0.92')
285
280
        self.expecting_body = True
286
281
        return result[1], FakeProtocol(result[2], self)
287
282
 
288
 
    def call_with_body_bytes(self, method, args, body):
289
 
        self._check_call(method, args)
290
 
        self._calls.append(('call_with_body_bytes', method, args, body))
291
 
        result = self._get_next_response()
292
 
        return result[1], FakeProtocol(result[2], self)
293
 
 
294
283
    def call_with_body_bytes_expecting_body(self, method, args, body):
295
284
        self._check_call(method, args)
296
285
        self._calls.append(('call_with_body_bytes_expecting_body', method,
360
349
        a given client_base and transport_base.
361
350
        """
362
351
        client_medium = medium.SmartClientMedium(client_base)
363
 
        t = transport.get_transport(transport_base)
364
 
        result = client_medium.remote_path_from_transport(t)
 
352
        transport = get_transport(transport_base)
 
353
        result = client_medium.remote_path_from_transport(transport)
365
354
        self.assertEqual(expected, result)
366
355
 
367
356
    def test_remote_path_from_transport(self):
378
367
        a given transport_base and relpath of that transport.  (Note that
379
368
        HttpTransportBase is a subclass of SmartClientMedium)
380
369
        """
381
 
        base_transport = transport.get_transport(transport_base)
 
370
        base_transport = get_transport(transport_base)
382
371
        client_medium = base_transport.get_smart_medium()
383
372
        cloned_transport = base_transport.clone(relpath)
384
373
        result = client_medium.remote_path_from_transport(cloned_transport)
419
408
        # Calling _remember_remote_is_before again with a lower value works.
420
409
        client_medium._remember_remote_is_before((1, 5))
421
410
        self.assertTrue(client_medium._is_remote_before((1, 5)))
422
 
        # If you call _remember_remote_is_before with a higher value it logs a
423
 
        # warning, and continues to remember the lower value.
424
 
        self.assertNotContainsRe(self.get_log(), '_remember_remote_is_before')
425
 
        client_medium._remember_remote_is_before((1, 9))
426
 
        self.assertContainsRe(self.get_log(), '_remember_remote_is_before')
427
 
        self.assertTrue(client_medium._is_remote_before((1, 5)))
 
411
        # You cannot call _remember_remote_is_before with a larger value.
 
412
        self.assertRaises(
 
413
            AssertionError, client_medium._remember_remote_is_before, (1, 9))
428
414
 
429
415
 
430
416
class TestBzrDirCloningMetaDir(TestRemote):
449
435
            'BzrDir.cloning_metadir', ('quack/', 'False'),
450
436
            'error', ('BranchReference',)),
451
437
        client.add_expected_call(
452
 
            'BzrDir.open_branchV3', ('quack/',),
 
438
            'BzrDir.open_branchV2', ('quack/',),
453
439
            'success', ('ref', self.get_url('referenced'))),
454
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
440
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
455
441
            _client=client)
456
442
        result = a_bzrdir.cloning_metadir()
457
443
        # We should have got a control dir matching the referenced branch.
470
456
        client.add_expected_call(
471
457
            'BzrDir.cloning_metadir', ('quack/', 'False'),
472
458
            'success', (control_name, '', ('branch', ''))),
473
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
459
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
474
460
            _client=client)
475
461
        result = a_bzrdir.cloning_metadir()
476
462
        # We should have got a reference control dir with default branch and
482
468
        self.assertFinished(client)
483
469
 
484
470
 
485
 
class TestBzrDirOpen(TestRemote):
486
 
 
487
 
    def make_fake_client_and_transport(self, path='quack'):
488
 
        transport = MemoryTransport()
489
 
        transport.mkdir(path)
490
 
        transport = transport.clone(path)
491
 
        client = FakeClient(transport.base)
492
 
        return client, transport
493
 
 
494
 
    def test_absent(self):
495
 
        client, transport = self.make_fake_client_and_transport()
496
 
        client.add_expected_call(
497
 
            'BzrDir.open_2.1', ('quack/',), 'success', ('no',))
498
 
        self.assertRaises(errors.NotBranchError, RemoteBzrDir, transport,
499
 
                RemoteBzrDirFormat(), _client=client, _force_probe=True)
500
 
        self.assertFinished(client)
501
 
 
502
 
    def test_present_without_workingtree(self):
503
 
        client, transport = self.make_fake_client_and_transport()
504
 
        client.add_expected_call(
505
 
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'no'))
506
 
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
507
 
            _client=client, _force_probe=True)
508
 
        self.assertIsInstance(bd, RemoteBzrDir)
509
 
        self.assertFalse(bd.has_workingtree())
510
 
        self.assertRaises(errors.NoWorkingTree, bd.open_workingtree)
511
 
        self.assertFinished(client)
512
 
 
513
 
    def test_present_with_workingtree(self):
514
 
        client, transport = self.make_fake_client_and_transport()
515
 
        client.add_expected_call(
516
 
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'yes'))
517
 
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
518
 
            _client=client, _force_probe=True)
519
 
        self.assertIsInstance(bd, RemoteBzrDir)
520
 
        self.assertTrue(bd.has_workingtree())
521
 
        self.assertRaises(errors.NotLocalUrl, bd.open_workingtree)
522
 
        self.assertFinished(client)
523
 
 
524
 
    def test_backwards_compat(self):
525
 
        client, transport = self.make_fake_client_and_transport()
526
 
        client.add_expected_call(
527
 
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
528
 
        client.add_expected_call(
529
 
            'BzrDir.open', ('quack/',), 'success', ('yes',))
530
 
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
531
 
            _client=client, _force_probe=True)
532
 
        self.assertIsInstance(bd, RemoteBzrDir)
533
 
        self.assertFinished(client)
534
 
 
535
 
    def test_backwards_compat_hpss_v2(self):
536
 
        client, transport = self.make_fake_client_and_transport()
537
 
        # Monkey-patch fake client to simulate real-world behaviour with v2
538
 
        # server: upon first RPC call detect the protocol version, and because
539
 
        # the version is 2 also do _remember_remote_is_before((1, 6)) before
540
 
        # continuing with the RPC.
541
 
        orig_check_call = client._check_call
542
 
        def check_call(method, args):
543
 
            client._medium._protocol_version = 2
544
 
            client._medium._remember_remote_is_before((1, 6))
545
 
            client._check_call = orig_check_call
546
 
            client._check_call(method, args)
547
 
        client._check_call = check_call
548
 
        client.add_expected_call(
549
 
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
550
 
        client.add_expected_call(
551
 
            'BzrDir.open', ('quack/',), 'success', ('yes',))
552
 
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
553
 
            _client=client, _force_probe=True)
554
 
        self.assertIsInstance(bd, RemoteBzrDir)
555
 
        self.assertFinished(client)
556
 
 
557
 
 
558
471
class TestBzrDirOpenBranch(TestRemote):
559
472
 
560
473
    def test_backwards_compat(self):
562
475
        self.make_branch('.')
563
476
        a_dir = BzrDir.open(self.get_url('.'))
564
477
        self.reset_smart_call_log()
565
 
        verb = 'BzrDir.open_branchV3'
 
478
        verb = 'BzrDir.open_branchV2'
566
479
        self.disable_verb(verb)
567
480
        format = a_dir.open_branch()
568
481
        call_count = len([call for call in self.hpss_calls if
578
491
        transport = transport.clone('quack')
579
492
        client = FakeClient(transport.base)
580
493
        client.add_expected_call(
581
 
            'BzrDir.open_branchV3', ('quack/',),
 
494
            'BzrDir.open_branchV2', ('quack/',),
582
495
            'success', ('branch', branch_network_name))
583
496
        client.add_expected_call(
584
497
            'BzrDir.find_repositoryV3', ('quack/',),
586
499
        client.add_expected_call(
587
500
            'Branch.get_stacked_on_url', ('quack/',),
588
501
            'error', ('NotStacked',))
589
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
502
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
590
503
            _client=client)
591
504
        result = bzrdir.open_branch()
592
505
        self.assertIsInstance(result, RemoteBranch)
599
512
        transport = transport.clone('quack')
600
513
        client = FakeClient(transport.base)
601
514
        client.add_error_response('nobranch')
602
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
515
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
603
516
            _client=client)
604
517
        self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
605
518
        self.assertEqual(
606
 
            [('call', 'BzrDir.open_branchV3', ('quack/',))],
 
519
            [('call', 'BzrDir.open_branchV2', ('quack/',))],
607
520
            client._calls)
608
521
 
609
522
    def test__get_tree_branch(self):
610
523
        # _get_tree_branch is a form of open_branch, but it should only ask for
611
524
        # branch opening, not any other network requests.
612
525
        calls = []
613
 
        def open_branch(name=None):
 
526
        def open_branch():
614
527
            calls.append("Called")
615
528
            return "a-branch"
616
529
        transport = MemoryTransport()
617
530
        # no requests on the network - catches other api calls being made.
618
531
        client = FakeClient(transport.base)
619
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
532
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
620
533
            _client=client)
621
534
        # patch the open_branch call to record that it was called.
622
535
        bzrdir.open_branch = open_branch
633
546
        network_name = reference_format.network_name()
634
547
        branch_network_name = self.get_branch_format().network_name()
635
548
        client.add_expected_call(
636
 
            'BzrDir.open_branchV3', ('~hello/',),
 
549
            'BzrDir.open_branchV2', ('~hello/',),
637
550
            'success', ('branch', branch_network_name))
638
551
        client.add_expected_call(
639
552
            'BzrDir.find_repositoryV3', ('~hello/',),
641
554
        client.add_expected_call(
642
555
            'Branch.get_stacked_on_url', ('~hello/',),
643
556
            'error', ('NotStacked',))
644
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
557
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
645
558
            _client=client)
646
559
        result = bzrdir.open_branch()
647
560
        self.assertFinished(client)
664
577
        client.add_success_response(
665
578
            'ok', '', rich_response, subtree_response, external_lookup,
666
579
            network_name)
667
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
580
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
668
581
            _client=client)
669
582
        result = bzrdir.open_repository()
670
583
        self.assertEqual(
687
600
        old.
688
601
        """
689
602
        self.assertRaises(errors.NotBranchError,
690
 
            RemoteBzrProber.probe_transport, OldServerTransport())
 
603
            RemoteBzrDirFormat.probe_transport, OldServerTransport())
691
604
 
692
605
 
693
606
class TestBzrDirCreateBranch(TestRemote):
716
629
            'BzrDir.create_branch', ('quack/', network_name),
717
630
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
718
631
            reference_repo_name))
719
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
632
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
720
633
            _client=client)
721
634
        branch = a_bzrdir.create_branch()
722
635
        # We should have got a remote branch
725
638
        format = branch._format
726
639
        self.assertEqual(network_name, format.network_name())
727
640
 
728
 
    def test_already_open_repo_and_reused_medium(self):
729
 
        """Bug 726584: create_branch(..., repository=repo) should work
730
 
        regardless of what the smart medium's base URL is.
731
 
        """
732
 
        self.transport_server = test_server.SmartTCPServer_for_testing
733
 
        transport = self.get_transport('.')
734
 
        repo = self.make_repository('quack')
735
 
        # Client's medium rooted a transport root (not at the bzrdir)
736
 
        client = FakeClient(transport.base)
737
 
        transport = transport.clone('quack')
738
 
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
739
 
        reference_format = reference_bzrdir_format.get_branch_format()
740
 
        network_name = reference_format.network_name()
741
 
        reference_repo_fmt = reference_bzrdir_format.repository_format
742
 
        reference_repo_name = reference_repo_fmt.network_name()
743
 
        client.add_expected_call(
744
 
            'BzrDir.create_branch', ('extra/quack/', network_name),
745
 
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
746
 
            reference_repo_name))
747
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
748
 
            _client=client)
749
 
        branch = a_bzrdir.create_branch(repository=repo)
750
 
        # We should have got a remote branch
751
 
        self.assertIsInstance(branch, remote.RemoteBranch)
752
 
        # its format should have the settings from the response
753
 
        format = branch._format
754
 
        self.assertEqual(network_name, format.network_name())
755
 
 
756
641
 
757
642
class TestBzrDirCreateRepository(TestRemote):
758
643
 
779
664
                'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
780
665
                'False'),
781
666
            'success', ('ok', 'yes', 'yes', 'yes', network_name))
782
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
667
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
783
668
            _client=client)
784
669
        repo = a_bzrdir.create_repository()
785
670
        # We should have got a remote repository
798
683
        # fallback all the way to the first version.
799
684
        reference_format = self.get_repo_format()
800
685
        network_name = reference_format.network_name()
801
 
        server_url = 'bzr://example.com/'
802
 
        self.permit_url(server_url)
803
 
        client = FakeClient(server_url)
 
686
        client = FakeClient('bzr://example.com/')
804
687
        client.add_unknown_method_response('BzrDir.find_repositoryV3')
805
688
        client.add_unknown_method_response('BzrDir.find_repositoryV2')
806
689
        client.add_success_response('ok', '', 'no', 'no')
812
695
            reference_format.get_format_string(), 'ok')
813
696
        # PackRepository wants to do a stat
814
697
        client.add_success_response('stat', '0', '65535')
815
 
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
 
698
        remote_transport = RemoteTransport('bzr://example.com/quack/', medium=False,
816
699
            _client=client)
817
 
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
 
700
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
818
701
            _client=client)
819
702
        repo = bzrdir.open_repository()
820
703
        self.assertEqual(
832
715
        # fallback to find_repositoryV2
833
716
        reference_format = self.get_repo_format()
834
717
        network_name = reference_format.network_name()
835
 
        server_url = 'bzr://example.com/'
836
 
        self.permit_url(server_url)
837
 
        client = FakeClient(server_url)
 
718
        client = FakeClient('bzr://example.com/')
838
719
        client.add_unknown_method_response('BzrDir.find_repositoryV3')
839
720
        client.add_success_response('ok', '', 'no', 'no', 'no')
840
721
        # A real repository instance will be created to determine the network
845
726
            reference_format.get_format_string(), 'ok')
846
727
        # PackRepository wants to do a stat
847
728
        client.add_success_response('stat', '0', '65535')
848
 
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
 
729
        remote_transport = RemoteTransport('bzr://example.com/quack/', medium=False,
849
730
            _client=client)
850
 
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
 
731
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
851
732
            _client=client)
852
733
        repo = bzrdir.open_repository()
853
734
        self.assertEqual(
868
749
        transport = transport.clone('quack')
869
750
        client = FakeClient(transport.base)
870
751
        client.add_success_response('ok', '', 'no', 'no', 'no', network_name)
871
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
752
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
872
753
            _client=client)
873
754
        repo = bzrdir.open_repository()
874
755
        self.assertEqual(
881
762
 
882
763
    def test_success(self):
883
764
        """Simple test for typical successful call."""
884
 
        fmt = RemoteBzrDirFormat()
 
765
        fmt = bzrdir.RemoteBzrDirFormat()
885
766
        default_format_name = BzrDirFormat.get_default_format().network_name()
886
767
        transport = self.get_transport()
887
768
        client = FakeClient(transport.base)
903
784
        """Error responses are translated, e.g. 'PermissionDenied' raises the
904
785
        corresponding error from the client.
905
786
        """
906
 
        fmt = RemoteBzrDirFormat()
 
787
        fmt = bzrdir.RemoteBzrDirFormat()
907
788
        default_format_name = BzrDirFormat.get_default_format().network_name()
908
789
        transport = self.get_transport()
909
790
        client = FakeClient(transport.base)
927
808
        """Integration test for error translation."""
928
809
        transport = self.make_smart_server('foo')
929
810
        transport = transport.clone('no-such-path')
930
 
        fmt = RemoteBzrDirFormat()
 
811
        fmt = bzrdir.RemoteBzrDirFormat()
931
812
        err = self.assertRaises(errors.NoSuchFile,
932
813
            fmt.initialize_on_transport_ex, transport, create_prefix=False)
933
814
 
964
845
 
965
846
    def make_remote_bzrdir(self, transport, client):
966
847
        """Make a RemotebzrDir using 'client' as the _client."""
967
 
        return RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
848
        return RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
968
849
            _client=client)
969
850
 
970
851
 
971
852
class RemoteBranchTestCase(RemoteBzrDirTestCase):
972
853
 
973
 
    def lock_remote_branch(self, branch):
974
 
        """Trick a RemoteBranch into thinking it is locked."""
975
 
        branch._lock_mode = 'w'
976
 
        branch._lock_count = 2
977
 
        branch._lock_token = 'branch token'
978
 
        branch._repo_lock_token = 'repo token'
979
 
        branch.repository._lock_mode = 'w'
980
 
        branch.repository._lock_count = 2
981
 
        branch.repository._lock_token = 'repo token'
982
 
 
983
854
    def make_remote_branch(self, transport, client):
984
855
        """Make a RemoteBranch using 'client' as its _SmartClient.
985
856
 
1124
995
        self.assertEqual({}, result)
1125
996
 
1126
997
 
1127
 
class TestBranchSetTagsBytes(RemoteBranchTestCase):
1128
 
 
1129
 
    def test_trivial(self):
1130
 
        transport = MemoryTransport()
1131
 
        client = FakeClient(transport.base)
1132
 
        client.add_expected_call(
1133
 
            'Branch.get_stacked_on_url', ('quack/',),
1134
 
            'error', ('NotStacked',))
1135
 
        client.add_expected_call(
1136
 
            'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
1137
 
            'success', ('',))
1138
 
        transport.mkdir('quack')
1139
 
        transport = transport.clone('quack')
1140
 
        branch = self.make_remote_branch(transport, client)
1141
 
        self.lock_remote_branch(branch)
1142
 
        branch._set_tags_bytes('tags bytes')
1143
 
        self.assertFinished(client)
1144
 
        self.assertEqual('tags bytes', client._calls[-1][-1])
1145
 
 
1146
 
    def test_backwards_compatible(self):
1147
 
        transport = MemoryTransport()
1148
 
        client = FakeClient(transport.base)
1149
 
        client.add_expected_call(
1150
 
            'Branch.get_stacked_on_url', ('quack/',),
1151
 
            'error', ('NotStacked',))
1152
 
        client.add_expected_call(
1153
 
            'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
1154
 
            'unknown', ('Branch.set_tags_bytes',))
1155
 
        transport.mkdir('quack')
1156
 
        transport = transport.clone('quack')
1157
 
        branch = self.make_remote_branch(transport, client)
1158
 
        self.lock_remote_branch(branch)
1159
 
        class StubRealBranch(object):
1160
 
            def __init__(self):
1161
 
                self.calls = []
1162
 
            def _set_tags_bytes(self, bytes):
1163
 
                self.calls.append(('set_tags_bytes', bytes))
1164
 
        real_branch = StubRealBranch()
1165
 
        branch._real_branch = real_branch
1166
 
        branch._set_tags_bytes('tags bytes')
1167
 
        # Call a second time, to exercise the 'remote version already inferred'
1168
 
        # code path.
1169
 
        branch._set_tags_bytes('tags bytes')
1170
 
        self.assertFinished(client)
1171
 
        self.assertEqual(
1172
 
            [('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
1173
 
 
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
 
 
1240
998
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
1241
999
 
1242
1000
    def test_empty_branch(self):
1297
1055
        client.add_expected_call(
1298
1056
            'Branch.get_stacked_on_url', ('stacked/',),
1299
1057
            'success', ('ok', vfs_url))
1300
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
1058
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1301
1059
            _client=client)
1302
1060
        repo_fmt = remote.RemoteRepositoryFormat()
1303
1061
        repo_fmt._custom_format = stacked_branch.repository._format
1314
1072
        client = FakeClient(self.get_url())
1315
1073
        branch_network_name = self.get_branch_format().network_name()
1316
1074
        client.add_expected_call(
1317
 
            'BzrDir.open_branchV3', ('stacked/',),
 
1075
            'BzrDir.open_branchV2', ('stacked/',),
1318
1076
            'success', ('branch', branch_network_name))
1319
1077
        client.add_expected_call(
1320
1078
            'BzrDir.find_repositoryV3', ('stacked/',),
1330
1088
        # this will also do vfs access, but that goes direct to the transport
1331
1089
        # and isn't seen by the FakeClient.
1332
1090
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1333
 
            RemoteBzrDirFormat(), _client=client)
 
1091
            remote.RemoteBzrDirFormat(), _client=client)
1334
1092
        branch = bzrdir.open_branch()
1335
1093
        result = branch.get_stacked_on_url()
1336
1094
        self.assertEqual('../base', result)
1342
1100
            len(branch.repository._real_repository._fallback_repositories))
1343
1101
 
1344
1102
    def test_get_stacked_on_real_branch(self):
1345
 
        base_branch = self.make_branch('base')
1346
 
        stacked_branch = self.make_branch('stacked')
 
1103
        base_branch = self.make_branch('base', format='1.6')
 
1104
        stacked_branch = self.make_branch('stacked', format='1.6')
1347
1105
        stacked_branch.set_stacked_on_url('../base')
1348
1106
        reference_format = self.get_repo_format()
1349
1107
        network_name = reference_format.network_name()
1350
1108
        client = FakeClient(self.get_url())
1351
1109
        branch_network_name = self.get_branch_format().network_name()
1352
1110
        client.add_expected_call(
1353
 
            'BzrDir.open_branchV3', ('stacked/',),
 
1111
            'BzrDir.open_branchV2', ('stacked/',),
1354
1112
            'success', ('branch', branch_network_name))
1355
1113
        client.add_expected_call(
1356
1114
            'BzrDir.find_repositoryV3', ('stacked/',),
1357
 
            'success', ('ok', '', 'yes', 'no', 'yes', network_name))
 
1115
            'success', ('ok', '', 'no', 'no', 'yes', network_name))
1358
1116
        # called twice, once from constructor and then again by us
1359
1117
        client.add_expected_call(
1360
1118
            'Branch.get_stacked_on_url', ('stacked/',),
1363
1121
            'Branch.get_stacked_on_url', ('stacked/',),
1364
1122
            'success', ('ok', '../base'))
1365
1123
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1366
 
            RemoteBzrDirFormat(), _client=client)
 
1124
            remote.RemoteBzrDirFormat(), _client=client)
1367
1125
        branch = bzrdir.open_branch()
1368
1126
        result = branch.get_stacked_on_url()
1369
1127
        self.assertEqual('../base', result)
1377
1135
class TestBranchSetLastRevision(RemoteBranchTestCase):
1378
1136
 
1379
1137
    def test_set_empty(self):
1380
 
        # _set_last_revision_info('null:') is translated to calling
 
1138
        # set_revision_history([]) is translated to calling
1381
1139
        # Branch.set_last_revision(path, '') on the wire.
1382
1140
        transport = MemoryTransport()
1383
1141
        transport.mkdir('branch')
1405
1163
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1406
1164
        branch._ensure_real = lambda: None
1407
1165
        branch.lock_write()
1408
 
        result = branch._set_last_revision(NULL_REVISION)
 
1166
        result = branch.set_revision_history([])
1409
1167
        branch.unlock()
1410
1168
        self.assertEqual(None, result)
1411
1169
        self.assertFinished(client)
1412
1170
 
1413
1171
    def test_set_nonempty(self):
1414
 
        # set_last_revision_info(N, rev-idN) is translated to calling
 
1172
        # set_revision_history([rev-id1, ..., rev-idN]) is translated to calling
1415
1173
        # Branch.set_last_revision(path, rev-idN) on the wire.
1416
1174
        transport = MemoryTransport()
1417
1175
        transport.mkdir('branch')
1443
1201
        branch._ensure_real = lambda: None
1444
1202
        # Lock the branch, reset the record of remote calls.
1445
1203
        branch.lock_write()
1446
 
        result = branch._set_last_revision('rev-id2')
 
1204
        result = branch.set_revision_history(['rev-id1', 'rev-id2'])
1447
1205
        branch.unlock()
1448
1206
        self.assertEqual(None, result)
1449
1207
        self.assertFinished(client)
1479
1237
        branch = self.make_remote_branch(transport, client)
1480
1238
        branch.lock_write()
1481
1239
        self.assertRaises(
1482
 
            errors.NoSuchRevision, branch._set_last_revision, 'rev-id')
 
1240
            errors.NoSuchRevision, branch.set_revision_history, ['rev-id'])
1483
1241
        branch.unlock()
1484
1242
        self.assertFinished(client)
1485
1243
 
1516
1274
        branch._ensure_real = lambda: None
1517
1275
        branch.lock_write()
1518
1276
        # The 'TipChangeRejected' error response triggered by calling
1519
 
        # set_last_revision_info causes a TipChangeRejected exception.
 
1277
        # set_revision_history causes a TipChangeRejected exception.
1520
1278
        err = self.assertRaises(
1521
 
            errors.TipChangeRejected,
1522
 
            branch._set_last_revision, 'rev-id')
 
1279
            errors.TipChangeRejected, branch.set_revision_history, ['rev-id'])
1523
1280
        # The UTF-8 message from the response has been decoded into a unicode
1524
1281
        # object.
1525
1282
        self.assertIsInstance(err.msg, unicode)
1585
1342
            errors.NoSuchRevision, branch.set_last_revision_info, 123, 'revid')
1586
1343
        branch.unlock()
1587
1344
 
 
1345
    def lock_remote_branch(self, branch):
 
1346
        """Trick a RemoteBranch into thinking it is locked."""
 
1347
        branch._lock_mode = 'w'
 
1348
        branch._lock_count = 2
 
1349
        branch._lock_token = 'branch token'
 
1350
        branch._repo_lock_token = 'repo token'
 
1351
        branch.repository._lock_mode = 'w'
 
1352
        branch.repository._lock_count = 2
 
1353
        branch.repository._lock_token = 'repo token'
 
1354
 
1588
1355
    def test_backwards_compatibility(self):
1589
1356
        """If the server does not support the Branch.set_last_revision_info
1590
1357
        verb (which is new in 1.4), then the client falls back to VFS methods.
1713
1480
    def test_get_multi_line_branch_conf(self):
1714
1481
        # Make sure that multiple-line branch.conf files are supported
1715
1482
        #
1716
 
        # https://bugs.launchpad.net/bzr/+bug/354075
 
1483
        # https://bugs.edge.launchpad.net/bzr/+bug/354075
1717
1484
        client = FakeClient()
1718
1485
        client.add_expected_call(
1719
1486
            'Branch.get_stacked_on_url', ('memory:///',),
1747
1514
        branch.unlock()
1748
1515
        self.assertFinished(client)
1749
1516
 
1750
 
    def test_set_option_with_dict(self):
1751
 
        client = FakeClient()
1752
 
        client.add_expected_call(
1753
 
            'Branch.get_stacked_on_url', ('memory:///',),
1754
 
            'error', ('NotStacked',),)
1755
 
        client.add_expected_call(
1756
 
            'Branch.lock_write', ('memory:///', '', ''),
1757
 
            'success', ('ok', 'branch token', 'repo token'))
1758
 
        encoded_dict_value = 'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde'
1759
 
        client.add_expected_call(
1760
 
            'Branch.set_config_option_dict', ('memory:///', 'branch token',
1761
 
            'repo token', encoded_dict_value, 'foo', ''),
1762
 
            'success', ())
1763
 
        client.add_expected_call(
1764
 
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
1765
 
            'success', ('ok',))
1766
 
        transport = MemoryTransport()
1767
 
        branch = self.make_remote_branch(transport, client)
1768
 
        branch.lock_write()
1769
 
        config = branch._get_config()
1770
 
        config.set_option(
1771
 
            {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'},
1772
 
            'foo')
1773
 
        branch.unlock()
1774
 
        self.assertFinished(client)
1775
 
 
1776
1517
    def test_backwards_compat_set_option(self):
1777
1518
        self.setup_smart_server_with_call_log()
1778
1519
        branch = self.make_branch('.')
1785
1526
        self.assertLength(10, self.hpss_calls)
1786
1527
        self.assertEqual('value', branch._get_config().get_option('name'))
1787
1528
 
1788
 
    def test_backwards_compat_set_option_with_dict(self):
1789
 
        self.setup_smart_server_with_call_log()
1790
 
        branch = self.make_branch('.')
1791
 
        verb = 'Branch.set_config_option_dict'
1792
 
        self.disable_verb(verb)
1793
 
        branch.lock_write()
1794
 
        self.addCleanup(branch.unlock)
1795
 
        self.reset_smart_call_log()
1796
 
        config = branch._get_config()
1797
 
        value_dict = {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
1798
 
        config.set_option(value_dict, 'name')
1799
 
        self.assertLength(10, self.hpss_calls)
1800
 
        self.assertEqual(value_dict, branch._get_config().get_option('name'))
1801
 
 
1802
1529
 
1803
1530
class TestBranchLockWrite(RemoteBranchTestCase):
1804
1531
 
1940
1667
        client = FakeClient(transport.base)
1941
1668
        transport = transport.clone(transport_path)
1942
1669
        # we do not want bzrdir to make any remote calls
1943
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
1670
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1944
1671
            _client=False)
1945
1672
        repo = RemoteRepository(bzrdir, None, _client=client)
1946
1673
        return repo, client
1947
1674
 
1948
1675
 
1949
 
def remoted_description(format):
1950
 
    return 'Remote: ' + format.get_format_description()
1951
 
 
1952
 
 
1953
 
class TestBranchFormat(tests.TestCase):
1954
 
 
1955
 
    def test_get_format_description(self):
1956
 
        remote_format = RemoteBranchFormat()
1957
 
        real_format = branch.format_registry.get_default()
1958
 
        remote_format._network_name = real_format.network_name()
1959
 
        self.assertEqual(remoted_description(real_format),
1960
 
            remote_format.get_format_description())
1961
 
 
1962
 
 
1963
1676
class TestRepositoryFormat(TestRemoteRepository):
1964
1677
 
1965
1678
    def test_fast_delta(self):
1966
 
        true_name = groupcompress_repo.RepositoryFormat2a().network_name()
 
1679
        true_name = groupcompress_repo.RepositoryFormatCHK1().network_name()
1967
1680
        true_format = RemoteRepositoryFormat()
1968
1681
        true_format._network_name = true_name
1969
1682
        self.assertEqual(True, true_format.fast_deltas)
1970
 
        false_name = knitpack_repo.RepositoryFormatKnitPack1().network_name()
 
1683
        false_name = pack_repo.RepositoryFormatKnitPack1().network_name()
1971
1684
        false_format = RemoteRepositoryFormat()
1972
1685
        false_format._network_name = false_name
1973
1686
        self.assertEqual(False, false_format.fast_deltas)
1974
1687
 
1975
 
    def test_get_format_description(self):
1976
 
        remote_repo_format = RemoteRepositoryFormat()
1977
 
        real_format = repository.format_registry.get_default()
1978
 
        remote_repo_format._network_name = real_format.network_name()
1979
 
        self.assertEqual(remoted_description(real_format),
1980
 
            remote_repo_format.get_format_description())
1981
 
 
1982
1688
 
1983
1689
class TestRepositoryGatherStats(TestRemoteRepository):
1984
1690
 
2169
1875
        self.assertLength(1, self.hpss_calls)
2170
1876
 
2171
1877
    def disableExtraResults(self):
2172
 
        self.overrideAttr(SmartServerRepositoryGetParentMap,
2173
 
                          'no_extra_results', True)
 
1878
        old_flag = SmartServerRepositoryGetParentMap.no_extra_results
 
1879
        SmartServerRepositoryGetParentMap.no_extra_results = True
 
1880
        def reset_values():
 
1881
            SmartServerRepositoryGetParentMap.no_extra_results = old_flag
 
1882
        self.addCleanup(reset_values)
2174
1883
 
2175
1884
    def test_null_cached_missing_and_stop_key(self):
2176
1885
        self.setup_smart_server_with_call_log()
2235
1944
 
2236
1945
    def test_allows_new_revisions(self):
2237
1946
        """get_parent_map's results can be updated by commit."""
2238
 
        smart_server = test_server.SmartTCPServer_for_testing()
 
1947
        smart_server = server.SmartTCPServer_for_testing()
2239
1948
        self.start_server(smart_server)
2240
1949
        self.make_branch('branch')
2241
1950
        branch = Branch.open(smart_server.get_url() + '/branch')
2351
2060
        """
2352
2061
        # Make a repo with a fallback repo, both using a FakeClient.
2353
2062
        format = remote.response_tuple_to_repo_format(
2354
 
            ('yes', 'no', 'yes', self.get_repo_format().network_name()))
 
2063
            ('yes', 'no', 'yes', 'fake-network-name'))
2355
2064
        repo, client = self.setup_fake_client_and_repository('quack')
2356
2065
        repo._format = format
2357
2066
        fallback_repo, ignored = self.setup_fake_client_and_repository(
2358
2067
            'fallback')
2359
2068
        fallback_repo._client = client
2360
 
        fallback_repo._format = format
2361
2069
        repo.add_fallback_repository(fallback_repo)
2362
2070
        # First the client should ask the primary repo
2363
2071
        client.add_expected_call(
2384
2092
            repo.get_rev_id_for_revno, 5, (42, 'rev-foo'))
2385
2093
        self.assertFinished(client)
2386
2094
 
2387
 
    def test_branch_fallback_locking(self):
2388
 
        """RemoteBranch.get_rev_id takes a read lock, and tries to call the
2389
 
        get_rev_id_for_revno verb.  If the verb is unknown the VFS fallback
2390
 
        will be invoked, which will fail if the repo is unlocked.
2391
 
        """
2392
 
        self.setup_smart_server_with_call_log()
2393
 
        tree = self.make_branch_and_memory_tree('.')
2394
 
        tree.lock_write()
2395
 
        tree.add('')
2396
 
        rev1 = tree.commit('First')
2397
 
        rev2 = tree.commit('Second')
2398
 
        tree.unlock()
2399
 
        branch = tree.branch
2400
 
        self.assertFalse(branch.is_locked())
2401
 
        self.reset_smart_call_log()
2402
 
        verb = 'Repository.get_rev_id_for_revno'
2403
 
        self.disable_verb(verb)
2404
 
        self.assertEqual(rev1, branch.get_rev_id(1))
2405
 
        self.assertLength(1, [call for call in self.hpss_calls if
2406
 
                              call.call.method == verb])
2407
 
 
2408
2095
 
2409
2096
class TestRepositoryIsShared(TestRemoteRepository):
2410
2097
 
2437
2124
        transport_path = 'quack'
2438
2125
        repo, client = self.setup_fake_client_and_repository(transport_path)
2439
2126
        client.add_success_response('ok', 'a token')
2440
 
        token = repo.lock_write().repository_token
 
2127
        result = repo.lock_write()
2441
2128
        self.assertEqual(
2442
2129
            [('call', 'Repository.lock_write', ('quack/', ''))],
2443
2130
            client._calls)
2444
 
        self.assertEqual('a token', token)
 
2131
        self.assertEqual('a token', result)
2445
2132
 
2446
2133
    def test_lock_write_already_locked(self):
2447
2134
        transport_path = 'quack'
2538
2225
        the client is finished.
2539
2226
        """
2540
2227
        sink = repo._get_sink()
2541
 
        fmt = repository.format_registry.get_default()
 
2228
        fmt = repository.RepositoryFormat.get_default_format()
2542
2229
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2543
2230
        self.assertEqual([], resume_tokens)
2544
2231
        self.assertEqual(set(), missing_keys)
2638
2325
        class FakeRealRepository:
2639
2326
            def _get_sink(self):
2640
2327
                return fake_real_sink
2641
 
            def is_in_write_group(self):
2642
 
                return False
2643
 
            def refresh_data(self):
2644
 
                return True
2645
2328
        repo._real_repository = FakeRealRepository()
2646
2329
        sink = repo._get_sink()
2647
 
        fmt = repository.format_registry.get_default()
 
2330
        fmt = repository.RepositoryFormat.get_default_format()
2648
2331
        stream = self.make_stream_with_inv_deltas(fmt)
2649
2332
        resume_tokens, missing_keys = sink.insert_stream(stream, fmt, [])
2650
2333
        # Every record from the first inventory delta should have been sent to
2785
2468
    """RemoteRepository.copy_content_into optimizations"""
2786
2469
 
2787
2470
    def test_copy_content_remote_to_local(self):
2788
 
        self.transport_server = test_server.SmartTCPServer_for_testing
 
2471
        self.transport_server = server.SmartTCPServer_for_testing
2789
2472
        src_repo = self.make_repository('repo1')
2790
2473
        src_repo = repository.Repository.open(self.get_url('repo1'))
2791
2474
        # At the moment the tarball-based copy_content_into can't write back
2870
2553
             ('pack collection autopack',)],
2871
2554
            client._calls)
2872
2555
 
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
 
 
2883
2556
 
2884
2557
class TestErrorTranslationBase(tests.TestCaseWithMemoryTransport):
2885
2558
    """Base class for unit tests for bzrlib.remote._translate_error."""
2949
2622
        expected_error = errors.NotBranchError(path=bzrdir.root_transport.base)
2950
2623
        self.assertEqual(expected_error, translated_error)
2951
2624
 
2952
 
    def test_nobranch_one_arg(self):
2953
 
        bzrdir = self.make_bzrdir('')
2954
 
        translated_error = self.translateTuple(
2955
 
            ('nobranch', 'extra detail'), bzrdir=bzrdir)
2956
 
        expected_error = errors.NotBranchError(
2957
 
            path=bzrdir.root_transport.base,
2958
 
            detail='extra detail')
2959
 
        self.assertEqual(expected_error, translated_error)
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
 
 
2968
2625
    def test_LockContention(self):
2969
2626
        translated_error = self.translateTuple(('LockContention',))
2970
2627
        expected_error = errors.LockContention('(remote lock)')
2998
2655
        expected_error = errors.DivergedBranches(branch, other_branch)
2999
2656
        self.assertEqual(expected_error, translated_error)
3000
2657
 
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
 
 
3007
2658
    def test_ReadError_no_args(self):
3008
2659
        path = 'a path'
3009
2660
        translated_error = self.translateTuple(('ReadError',), path=path)
3025
2676
 
3026
2677
    def test_PermissionDenied_no_args(self):
3027
2678
        path = 'a path'
3028
 
        translated_error = self.translateTuple(('PermissionDenied',),
3029
 
            path=path)
 
2679
        translated_error = self.translateTuple(('PermissionDenied',), path=path)
3030
2680
        expected_error = errors.PermissionDenied(path)
3031
2681
        self.assertEqual(expected_error, translated_error)
3032
2682
 
3055
2705
        expected_error = errors.PermissionDenied(path, extra)
3056
2706
        self.assertEqual(expected_error, translated_error)
3057
2707
 
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
 
 
3097
2708
 
3098
2709
class TestErrorTranslationRobustness(TestErrorTranslationBase):
3099
2710
    """Unit tests for bzrlib.remote._translate_error's robustness.
3129
2740
        # In addition to re-raising ErrorFromSmartServer, some debug info has
3130
2741
        # been muttered to the log file for developer to look at.
3131
2742
        self.assertContainsRe(
3132
 
            self.get_log(),
 
2743
            self._get_log(keep_log_file=True),
3133
2744
            "Missing key 'branch' in context")
3134
2745
 
3135
2746
    def test_path_missing(self):
3143
2754
        self.assertEqual(server_error, translated_error)
3144
2755
        # In addition to re-raising ErrorFromSmartServer, some debug info has
3145
2756
        # been muttered to the log file for developer to look at.
3146
 
        self.assertContainsRe(self.get_log(), "Missing key 'path' in context")
 
2757
        self.assertContainsRe(
 
2758
            self._get_log(keep_log_file=True), "Missing key 'path' in context")
3147
2759
 
3148
2760
 
3149
2761
class TestStacking(tests.TestCaseWithTransport):
3167
2779
        stacked_branch = self.make_branch('stacked', format='1.9')
3168
2780
        stacked_branch.set_stacked_on_url('../base')
3169
2781
        # start a server looking at this
3170
 
        smart_server = test_server.SmartTCPServer_for_testing()
 
2782
        smart_server = server.SmartTCPServer_for_testing()
3171
2783
        self.start_server(smart_server)
3172
2784
        remote_bzrdir = BzrDir.open(smart_server.get_url() + '/stacked')
3173
2785
        # can get its branch and repository
3277
2889
            local_tree.commit('more local changes are better')
3278
2890
            branch = Branch.open(self.get_url('tree3'))
3279
2891
            branch.lock_read()
3280
 
            self.addCleanup(branch.unlock)
3281
2892
            return None, branch
3282
2893
        rev_ord, expected_revs = self.get_ordered_revs('1.9', 'unordered',
3283
2894
            branch_factory=make_stacked_stacked)
3329
2940
        super(TestRemoteBranchEffort, self).setUp()
3330
2941
        # Create a smart server that publishes whatever the backing VFS server
3331
2942
        # does.
3332
 
        self.smart_server = test_server.SmartTCPServer_for_testing()
 
2943
        self.smart_server = server.SmartTCPServer_for_testing()
3333
2944
        self.start_server(self.smart_server, self.get_server())
3334
2945
        # Log all HPSS calls into self.hpss_calls.
3335
2946
        _SmartClient.hooks.install_named_hook(
3341
2952
 
3342
2953
    def test_copy_content_into_avoids_revision_history(self):
3343
2954
        local = self.make_branch('local')
3344
 
        builder = self.make_branch_builder('remote')
3345
 
        builder.build_commit(message="Commit.")
 
2955
        remote_backing_tree = self.make_branch_and_tree('remote')
 
2956
        remote_backing_tree.commit("Commit.")
3346
2957
        remote_branch_url = self.smart_server.get_url() + 'remote'
3347
2958
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3348
2959
        local.repository.fetch(remote_branch.repository)
3349
2960
        self.hpss_calls = []
3350
2961
        remote_branch.copy_content_into(local)
3351
2962
        self.assertFalse('Branch.revision_history' in self.hpss_calls)
3352
 
 
3353
 
    def test_fetch_everything_needs_just_one_call(self):
3354
 
        local = self.make_branch('local')
3355
 
        builder = self.make_branch_builder('remote')
3356
 
        builder.build_commit(message="Commit.")
3357
 
        remote_branch_url = self.smart_server.get_url() + 'remote'
3358
 
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3359
 
        self.hpss_calls = []
3360
 
        local.repository.fetch(remote_branch.repository,
3361
 
                fetch_spec=graph.EverythingResult(remote_branch.repository))
3362
 
        self.assertEqual(['Repository.get_stream_1.19'], self.hpss_calls)
3363
 
 
3364
 
    def override_verb(self, verb_name, verb):
3365
 
        request_handlers = request.request_handlers
3366
 
        orig_verb = request_handlers.get(verb_name)
3367
 
        request_handlers.register(verb_name, verb, override_existing=True)
3368
 
        self.addCleanup(request_handlers.register, verb_name, orig_verb,
3369
 
                override_existing=True)
3370
 
 
3371
 
    def test_fetch_everything_backwards_compat(self):
3372
 
        """Can fetch with EverythingResult even with pre 2.4 servers.
3373
 
        
3374
 
        Pre-2.4 do not support 'everything' searches with the
3375
 
        Repository.get_stream_1.19 verb.
3376
 
        """
3377
 
        verb_log = []
3378
 
        class OldGetStreamVerb(SmartServerRepositoryGetStream_1_19):
3379
 
            """A version of the Repository.get_stream_1.19 verb patched to
3380
 
            reject 'everything' searches the way 2.3 and earlier do.
3381
 
            """
3382
 
            def recreate_search(self, repository, search_bytes, discard_excess=False):
3383
 
                verb_log.append(search_bytes.split('\n', 1)[0])
3384
 
                if search_bytes == 'everything':
3385
 
                    return (None, request.FailedSmartServerResponse(('BadSearch',)))
3386
 
                return super(OldGetStreamVerb,
3387
 
                        self).recreate_search(repository, search_bytes,
3388
 
                            discard_excess=discard_excess)
3389
 
        self.override_verb('Repository.get_stream_1.19', OldGetStreamVerb)
3390
 
        local = self.make_branch('local')
3391
 
        builder = self.make_branch_builder('remote')
3392
 
        builder.build_commit(message="Commit.")
3393
 
        remote_branch_url = self.smart_server.get_url() + 'remote'
3394
 
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3395
 
        self.hpss_calls = []
3396
 
        local.repository.fetch(remote_branch.repository,
3397
 
                fetch_spec=graph.EverythingResult(remote_branch.repository))
3398
 
        # make sure the overridden verb was used
3399
 
        self.assertLength(1, verb_log)
3400
 
        # more than one HPSS call is needed, but because it's a VFS callback
3401
 
        # its hard to predict exactly how many.
3402
 
        self.assertTrue(len(self.hpss_calls) > 1)
3403