/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_remote.py

  • Committer: Jelmer Vernooij
  • Date: 2011-12-05 17:31:43 UTC
  • mto: This revision was merged to the branch mainline in revision 6348.
  • Revision ID: jelmer@samba.org-20111205173143-jwj2xtdwpgpn4ic0
Fix test.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006-2011 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
25
25
 
26
26
import bz2
27
27
from cStringIO import StringIO
 
28
import zlib
28
29
 
29
30
from bzrlib import (
30
31
    branch,
31
32
    bzrdir,
32
33
    config,
 
34
    controldir,
33
35
    errors,
34
 
    graph,
 
36
    graph as _mod_graph,
35
37
    inventory,
36
38
    inventory_delta,
37
 
    pack,
38
39
    remote,
39
40
    repository,
40
41
    tests,
 
42
    transport,
41
43
    treebuilder,
42
 
    urlutils,
43
44
    versionedfile,
 
45
    vf_search,
44
46
    )
45
47
from bzrlib.branch import Branch
46
 
from bzrlib.bzrdir import BzrDir, BzrDirFormat
 
48
from bzrlib.bzrdir import (
 
49
    BzrDir,
 
50
    BzrDirFormat,
 
51
    RemoteBzrProber,
 
52
    )
 
53
from bzrlib.chk_serializer import chk_bencode_serializer
47
54
from bzrlib.remote import (
48
55
    RemoteBranch,
49
56
    RemoteBranchFormat,
52
59
    RemoteRepository,
53
60
    RemoteRepositoryFormat,
54
61
    )
55
 
from bzrlib.repofmt import groupcompress_repo, pack_repo
56
 
from bzrlib.revision import NULL_REVISION
57
 
from bzrlib.smart import medium
 
62
from bzrlib.repofmt import groupcompress_repo, knitpack_repo
 
63
from bzrlib.revision import (
 
64
    NULL_REVISION,
 
65
    Revision,
 
66
    )
 
67
from bzrlib.smart import medium, request
58
68
from bzrlib.smart.client import _SmartClient
59
 
from bzrlib.smart.repository import SmartServerRepositoryGetParentMap
 
69
from bzrlib.smart.repository import (
 
70
    SmartServerRepositoryGetParentMap,
 
71
    SmartServerRepositoryGetStream_1_19,
 
72
    )
 
73
from bzrlib.symbol_versioning import deprecated_in
60
74
from bzrlib.tests import (
61
 
    condition_isinstance,
62
 
    split_suite_by_condition,
63
 
    multiply_tests,
64
75
    test_server,
65
76
    )
66
 
from bzrlib.transport import get_transport
 
77
from bzrlib.tests.scenarios import load_tests_apply_scenarios
67
78
from bzrlib.transport.memory import MemoryTransport
68
79
from bzrlib.transport.remote import (
69
80
    RemoteTransport,
70
81
    RemoteSSHTransport,
71
82
    RemoteTCPTransport,
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 = [
 
83
    )
 
84
 
 
85
 
 
86
load_tests = load_tests_apply_scenarios
 
87
 
 
88
 
 
89
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
 
90
 
 
91
    scenarios = [
78
92
        ('HPSS-v2',
79
 
         {'transport_server': test_server.SmartTCPServer_for_testing_v2_only}),
 
93
            {'transport_server': test_server.SmartTCPServer_for_testing_v2_only}),
80
94
        ('HPSS-v3',
81
 
         {'transport_server': test_server.SmartTCPServer_for_testing})]
82
 
    return multiply_tests(to_adapt, smart_server_version_scenarios, result)
83
 
 
84
 
 
85
 
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
 
95
            {'transport_server': test_server.SmartTCPServer_for_testing})]
 
96
 
86
97
 
87
98
    def setUp(self):
88
99
        super(BasicRemoteObjectTests, self).setUp()
89
100
        self.transport = self.get_transport()
90
101
        # make a branch that can be opened over the smart transport
91
102
        self.local_wt = BzrDir.create_standalone_workingtree('.')
92
 
 
93
 
    def tearDown(self):
94
 
        self.transport.disconnect()
95
 
        tests.TestCaseWithTransport.tearDown(self)
 
103
        self.addCleanup(self.transport.disconnect)
96
104
 
97
105
    def test_create_remote_bzrdir(self):
98
 
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
 
106
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
99
107
        self.assertIsInstance(b, BzrDir)
100
108
 
101
109
    def test_open_remote_branch(self):
102
110
        # open a standalone branch in the working directory
103
 
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
 
111
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
104
112
        branch = b.open_branch()
105
113
        self.assertIsInstance(branch, Branch)
106
114
 
114
122
 
115
123
    def test_remote_branch_revision_history(self):
116
124
        b = BzrDir.open_from_transport(self.transport).open_branch()
117
 
        self.assertEqual([], b.revision_history())
 
125
        self.assertEqual([],
 
126
            self.applyDeprecated(deprecated_in((2, 5, 0)), b.revision_history))
118
127
        r1 = self.local_wt.commit('1st commit')
119
128
        r2 = self.local_wt.commit('1st commit', rev_id=u'\xc8'.encode('utf8'))
120
 
        self.assertEqual([r1, r2], b.revision_history())
 
129
        self.assertEqual([r1, r2],
 
130
            self.applyDeprecated(deprecated_in((2, 5, 0)), b.revision_history))
121
131
 
122
132
    def test_find_correct_format(self):
123
133
        """Should open a RemoteBzrDir over a RemoteTransport"""
124
134
        fmt = BzrDirFormat.find_format(self.transport)
125
 
        self.assertTrue(RemoteBzrDirFormat
126
 
                        in BzrDirFormat._control_server_formats)
127
 
        self.assertIsInstance(fmt, remote.RemoteBzrDirFormat)
 
135
        self.assertTrue(bzrdir.RemoteBzrProber
 
136
                        in controldir.ControlDirFormat._server_probers)
 
137
        self.assertIsInstance(fmt, RemoteBzrDirFormat)
128
138
 
129
139
    def test_open_detected_smart_format(self):
130
140
        fmt = BzrDirFormat.find_format(self.transport)
359
369
        a given client_base and transport_base.
360
370
        """
361
371
        client_medium = medium.SmartClientMedium(client_base)
362
 
        transport = get_transport(transport_base)
363
 
        result = client_medium.remote_path_from_transport(transport)
 
372
        t = transport.get_transport(transport_base)
 
373
        result = client_medium.remote_path_from_transport(t)
364
374
        self.assertEqual(expected, result)
365
375
 
366
376
    def test_remote_path_from_transport(self):
377
387
        a given transport_base and relpath of that transport.  (Note that
378
388
        HttpTransportBase is a subclass of SmartClientMedium)
379
389
        """
380
 
        base_transport = get_transport(transport_base)
 
390
        base_transport = transport.get_transport(transport_base)
381
391
        client_medium = base_transport.get_smart_medium()
382
392
        cloned_transport = base_transport.clone(relpath)
383
393
        result = client_medium.remote_path_from_transport(cloned_transport)
450
460
        client.add_expected_call(
451
461
            'BzrDir.open_branchV3', ('quack/',),
452
462
            'success', ('ref', self.get_url('referenced'))),
453
 
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
463
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
454
464
            _client=client)
455
465
        result = a_bzrdir.cloning_metadir()
456
466
        # We should have got a control dir matching the referenced branch.
469
479
        client.add_expected_call(
470
480
            'BzrDir.cloning_metadir', ('quack/', 'False'),
471
481
            'success', (control_name, '', ('branch', ''))),
472
 
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
482
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
473
483
            _client=client)
474
484
        result = a_bzrdir.cloning_metadir()
475
485
        # We should have got a reference control dir with default branch and
480
490
        self.assertEqual(None, result._branch_format)
481
491
        self.assertFinished(client)
482
492
 
 
493
    def test_unknown(self):
 
494
        transport = self.get_transport('quack')
 
495
        referenced = self.make_branch('referenced')
 
496
        expected = referenced.bzrdir.cloning_metadir()
 
497
        client = FakeClient(transport.base)
 
498
        client.add_expected_call(
 
499
            'BzrDir.cloning_metadir', ('quack/', 'False'),
 
500
            'success', ('unknown', 'unknown', ('branch', ''))),
 
501
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
502
            _client=client)
 
503
        self.assertRaises(errors.UnknownFormatError, a_bzrdir.cloning_metadir)
 
504
 
 
505
 
 
506
class TestBzrDirDestroyBranch(TestRemote):
 
507
 
 
508
    def test_destroy_default(self):
 
509
        transport = self.get_transport('quack')
 
510
        referenced = self.make_branch('referenced')
 
511
        client = FakeClient(transport.base)
 
512
        client.add_expected_call(
 
513
            'BzrDir.destroy_branch', ('quack/', ),
 
514
            'success', ('ok',)),
 
515
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
516
            _client=client)
 
517
        a_bzrdir.destroy_branch()
 
518
        self.assertFinished(client)
 
519
 
 
520
    def test_destroy_named(self):
 
521
        transport = self.get_transport('quack')
 
522
        referenced = self.make_branch('referenced')
 
523
        client = FakeClient(transport.base)
 
524
        client.add_expected_call(
 
525
            'BzrDir.destroy_branch', ('quack/', "foo"),
 
526
            'success', ('ok',)),
 
527
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
528
            _client=client)
 
529
        a_bzrdir.destroy_branch("foo")
 
530
        self.assertFinished(client)
 
531
 
 
532
 
 
533
class TestBzrDirHasWorkingTree(TestRemote):
 
534
 
 
535
    def test_has_workingtree(self):
 
536
        transport = self.get_transport('quack')
 
537
        client = FakeClient(transport.base)
 
538
        client.add_expected_call(
 
539
            'BzrDir.has_workingtree', ('quack/',),
 
540
            'success', ('yes',)),
 
541
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
542
            _client=client)
 
543
        self.assertTrue(a_bzrdir.has_workingtree())
 
544
        self.assertFinished(client)
 
545
 
 
546
    def test_no_workingtree(self):
 
547
        transport = self.get_transport('quack')
 
548
        client = FakeClient(transport.base)
 
549
        client.add_expected_call(
 
550
            'BzrDir.has_workingtree', ('quack/',),
 
551
            'success', ('no',)),
 
552
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
553
            _client=client)
 
554
        self.assertFalse(a_bzrdir.has_workingtree())
 
555
        self.assertFinished(client)
 
556
 
 
557
 
 
558
class TestBzrDirDestroyRepository(TestRemote):
 
559
 
 
560
    def test_destroy_repository(self):
 
561
        transport = self.get_transport('quack')
 
562
        client = FakeClient(transport.base)
 
563
        client.add_expected_call(
 
564
            'BzrDir.destroy_repository', ('quack/',),
 
565
            'success', ('ok',)),
 
566
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
567
            _client=client)
 
568
        a_bzrdir.destroy_repository()
 
569
        self.assertFinished(client)
 
570
 
483
571
 
484
572
class TestBzrDirOpen(TestRemote):
485
573
 
495
583
        client.add_expected_call(
496
584
            'BzrDir.open_2.1', ('quack/',), 'success', ('no',))
497
585
        self.assertRaises(errors.NotBranchError, RemoteBzrDir, transport,
498
 
                remote.RemoteBzrDirFormat(), _client=client, _force_probe=True)
 
586
                RemoteBzrDirFormat(), _client=client, _force_probe=True)
499
587
        self.assertFinished(client)
500
588
 
501
589
    def test_present_without_workingtree(self):
502
590
        client, transport = self.make_fake_client_and_transport()
503
591
        client.add_expected_call(
504
592
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'no'))
505
 
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
593
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
506
594
            _client=client, _force_probe=True)
507
595
        self.assertIsInstance(bd, RemoteBzrDir)
508
596
        self.assertFalse(bd.has_workingtree())
513
601
        client, transport = self.make_fake_client_and_transport()
514
602
        client.add_expected_call(
515
603
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'yes'))
516
 
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
604
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
517
605
            _client=client, _force_probe=True)
518
606
        self.assertIsInstance(bd, RemoteBzrDir)
519
607
        self.assertTrue(bd.has_workingtree())
526
614
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
527
615
        client.add_expected_call(
528
616
            'BzrDir.open', ('quack/',), 'success', ('yes',))
529
 
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
617
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
530
618
            _client=client, _force_probe=True)
531
619
        self.assertIsInstance(bd, RemoteBzrDir)
532
620
        self.assertFinished(client)
548
636
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
549
637
        client.add_expected_call(
550
638
            'BzrDir.open', ('quack/',), 'success', ('yes',))
551
 
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
639
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
552
640
            _client=client, _force_probe=True)
553
641
        self.assertIsInstance(bd, RemoteBzrDir)
554
642
        self.assertFinished(client)
585
673
        client.add_expected_call(
586
674
            'Branch.get_stacked_on_url', ('quack/',),
587
675
            'error', ('NotStacked',))
588
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
676
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
589
677
            _client=client)
590
678
        result = bzrdir.open_branch()
591
679
        self.assertIsInstance(result, RemoteBranch)
598
686
        transport = transport.clone('quack')
599
687
        client = FakeClient(transport.base)
600
688
        client.add_error_response('nobranch')
601
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
689
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
602
690
            _client=client)
603
691
        self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
604
692
        self.assertEqual(
609
697
        # _get_tree_branch is a form of open_branch, but it should only ask for
610
698
        # branch opening, not any other network requests.
611
699
        calls = []
612
 
        def open_branch():
 
700
        def open_branch(name=None, possible_transports=None):
613
701
            calls.append("Called")
614
702
            return "a-branch"
615
703
        transport = MemoryTransport()
616
704
        # no requests on the network - catches other api calls being made.
617
705
        client = FakeClient(transport.base)
618
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
706
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
619
707
            _client=client)
620
708
        # patch the open_branch call to record that it was called.
621
709
        bzrdir.open_branch = open_branch
640
728
        client.add_expected_call(
641
729
            'Branch.get_stacked_on_url', ('~hello/',),
642
730
            'error', ('NotStacked',))
643
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
731
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
644
732
            _client=client)
645
733
        result = bzrdir.open_branch()
646
734
        self.assertFinished(client)
663
751
        client.add_success_response(
664
752
            'ok', '', rich_response, subtree_response, external_lookup,
665
753
            network_name)
666
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
754
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
667
755
            _client=client)
668
756
        result = bzrdir.open_repository()
669
757
        self.assertEqual(
686
774
        old.
687
775
        """
688
776
        self.assertRaises(errors.NotBranchError,
689
 
            RemoteBzrDirFormat.probe_transport, OldServerTransport())
 
777
            RemoteBzrProber.probe_transport, OldServerTransport())
690
778
 
691
779
 
692
780
class TestBzrDirCreateBranch(TestRemote):
715
803
            'BzrDir.create_branch', ('quack/', network_name),
716
804
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
717
805
            reference_repo_name))
718
 
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
806
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
719
807
            _client=client)
720
808
        branch = a_bzrdir.create_branch()
721
809
        # We should have got a remote branch
724
812
        format = branch._format
725
813
        self.assertEqual(network_name, format.network_name())
726
814
 
 
815
    def test_already_open_repo_and_reused_medium(self):
 
816
        """Bug 726584: create_branch(..., repository=repo) should work
 
817
        regardless of what the smart medium's base URL is.
 
818
        """
 
819
        self.transport_server = test_server.SmartTCPServer_for_testing
 
820
        transport = self.get_transport('.')
 
821
        repo = self.make_repository('quack')
 
822
        # Client's medium rooted a transport root (not at the bzrdir)
 
823
        client = FakeClient(transport.base)
 
824
        transport = transport.clone('quack')
 
825
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
 
826
        reference_format = reference_bzrdir_format.get_branch_format()
 
827
        network_name = reference_format.network_name()
 
828
        reference_repo_fmt = reference_bzrdir_format.repository_format
 
829
        reference_repo_name = reference_repo_fmt.network_name()
 
830
        client.add_expected_call(
 
831
            'BzrDir.create_branch', ('extra/quack/', network_name),
 
832
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
 
833
            reference_repo_name))
 
834
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
835
            _client=client)
 
836
        branch = a_bzrdir.create_branch(repository=repo)
 
837
        # We should have got a remote branch
 
838
        self.assertIsInstance(branch, remote.RemoteBranch)
 
839
        # its format should have the settings from the response
 
840
        format = branch._format
 
841
        self.assertEqual(network_name, format.network_name())
 
842
 
727
843
 
728
844
class TestBzrDirCreateRepository(TestRemote):
729
845
 
750
866
                'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
751
867
                'False'),
752
868
            'success', ('ok', 'yes', 'yes', 'yes', network_name))
753
 
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
869
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
754
870
            _client=client)
755
871
        repo = a_bzrdir.create_repository()
756
872
        # We should have got a remote repository
785
901
        client.add_success_response('stat', '0', '65535')
786
902
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
787
903
            _client=client)
788
 
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
 
904
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
789
905
            _client=client)
790
906
        repo = bzrdir.open_repository()
791
907
        self.assertEqual(
818
934
        client.add_success_response('stat', '0', '65535')
819
935
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
820
936
            _client=client)
821
 
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
 
937
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
822
938
            _client=client)
823
939
        repo = bzrdir.open_repository()
824
940
        self.assertEqual(
839
955
        transport = transport.clone('quack')
840
956
        client = FakeClient(transport.base)
841
957
        client.add_success_response('ok', '', 'no', 'no', 'no', network_name)
842
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
958
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
843
959
            _client=client)
844
960
        repo = bzrdir.open_repository()
845
961
        self.assertEqual(
852
968
 
853
969
    def test_success(self):
854
970
        """Simple test for typical successful call."""
855
 
        fmt = bzrdir.RemoteBzrDirFormat()
 
971
        fmt = RemoteBzrDirFormat()
856
972
        default_format_name = BzrDirFormat.get_default_format().network_name()
857
973
        transport = self.get_transport()
858
974
        client = FakeClient(transport.base)
874
990
        """Error responses are translated, e.g. 'PermissionDenied' raises the
875
991
        corresponding error from the client.
876
992
        """
877
 
        fmt = bzrdir.RemoteBzrDirFormat()
 
993
        fmt = RemoteBzrDirFormat()
878
994
        default_format_name = BzrDirFormat.get_default_format().network_name()
879
995
        transport = self.get_transport()
880
996
        client = FakeClient(transport.base)
898
1014
        """Integration test for error translation."""
899
1015
        transport = self.make_smart_server('foo')
900
1016
        transport = transport.clone('no-such-path')
901
 
        fmt = bzrdir.RemoteBzrDirFormat()
 
1017
        fmt = RemoteBzrDirFormat()
902
1018
        err = self.assertRaises(errors.NoSuchFile,
903
1019
            fmt.initialize_on_transport_ex, transport, create_prefix=False)
904
1020
 
935
1051
 
936
1052
    def make_remote_bzrdir(self, transport, client):
937
1053
        """Make a RemotebzrDir using 'client' as the _client."""
938
 
        return RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
1054
        return RemoteBzrDir(transport, RemoteBzrDirFormat(),
939
1055
            _client=client)
940
1056
 
941
1057
 
967
1083
        return RemoteBranch(bzrdir, repo, _client=client, format=format)
968
1084
 
969
1085
 
 
1086
class TestBranchBreakLock(RemoteBranchTestCase):
 
1087
 
 
1088
    def test_break_lock(self):
 
1089
        transport_path = 'quack'
 
1090
        transport = MemoryTransport()
 
1091
        client = FakeClient(transport.base)
 
1092
        client.add_expected_call(
 
1093
            'Branch.get_stacked_on_url', ('quack/',),
 
1094
            'error', ('NotStacked',))
 
1095
        client.add_expected_call(
 
1096
            'Branch.break_lock', ('quack/',),
 
1097
            'success', ('ok',))
 
1098
        transport.mkdir('quack')
 
1099
        transport = transport.clone('quack')
 
1100
        branch = self.make_remote_branch(transport, client)
 
1101
        branch.break_lock()
 
1102
        self.assertFinished(client)
 
1103
 
 
1104
 
 
1105
class TestBranchGetPhysicalLockStatus(RemoteBranchTestCase):
 
1106
 
 
1107
    def test_get_physical_lock_status_yes(self):
 
1108
        transport = MemoryTransport()
 
1109
        client = FakeClient(transport.base)
 
1110
        client.add_expected_call(
 
1111
            'Branch.get_stacked_on_url', ('quack/',),
 
1112
            'error', ('NotStacked',))
 
1113
        client.add_expected_call(
 
1114
            'Branch.get_physical_lock_status', ('quack/',),
 
1115
            'success', ('yes',))
 
1116
        transport.mkdir('quack')
 
1117
        transport = transport.clone('quack')
 
1118
        branch = self.make_remote_branch(transport, client)
 
1119
        result = branch.get_physical_lock_status()
 
1120
        self.assertFinished(client)
 
1121
        self.assertEqual(True, result)
 
1122
 
 
1123
    def test_get_physical_lock_status_no(self):
 
1124
        transport = MemoryTransport()
 
1125
        client = FakeClient(transport.base)
 
1126
        client.add_expected_call(
 
1127
            'Branch.get_stacked_on_url', ('quack/',),
 
1128
            'error', ('NotStacked',))
 
1129
        client.add_expected_call(
 
1130
            'Branch.get_physical_lock_status', ('quack/',),
 
1131
            'success', ('no',))
 
1132
        transport.mkdir('quack')
 
1133
        transport = transport.clone('quack')
 
1134
        branch = self.make_remote_branch(transport, client)
 
1135
        result = branch.get_physical_lock_status()
 
1136
        self.assertFinished(client)
 
1137
        self.assertEqual(False, result)
 
1138
 
 
1139
 
970
1140
class TestBranchGetParent(RemoteBranchTestCase):
971
1141
 
972
1142
    def test_no_parent(self):
1143
1313
            [('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
1144
1314
 
1145
1315
 
 
1316
class TestBranchHeadsToFetch(RemoteBranchTestCase):
 
1317
 
 
1318
    def test_uses_last_revision_info_and_tags_by_default(self):
 
1319
        transport = MemoryTransport()
 
1320
        client = FakeClient(transport.base)
 
1321
        client.add_expected_call(
 
1322
            'Branch.get_stacked_on_url', ('quack/',),
 
1323
            'error', ('NotStacked',))
 
1324
        client.add_expected_call(
 
1325
            'Branch.last_revision_info', ('quack/',),
 
1326
            'success', ('ok', '1', 'rev-tip'))
 
1327
        client.add_expected_call(
 
1328
            'Branch.get_config_file', ('quack/',),
 
1329
            'success', ('ok',), '')
 
1330
        transport.mkdir('quack')
 
1331
        transport = transport.clone('quack')
 
1332
        branch = self.make_remote_branch(transport, client)
 
1333
        result = branch.heads_to_fetch()
 
1334
        self.assertFinished(client)
 
1335
        self.assertEqual((set(['rev-tip']), set()), result)
 
1336
 
 
1337
    def test_uses_last_revision_info_and_tags_when_set(self):
 
1338
        transport = MemoryTransport()
 
1339
        client = FakeClient(transport.base)
 
1340
        client.add_expected_call(
 
1341
            'Branch.get_stacked_on_url', ('quack/',),
 
1342
            'error', ('NotStacked',))
 
1343
        client.add_expected_call(
 
1344
            'Branch.last_revision_info', ('quack/',),
 
1345
            'success', ('ok', '1', 'rev-tip'))
 
1346
        client.add_expected_call(
 
1347
            'Branch.get_config_file', ('quack/',),
 
1348
            'success', ('ok',), 'branch.fetch_tags = True')
 
1349
        # XXX: this will break if the default format's serialization of tags
 
1350
        # changes, or if the RPC for fetching tags changes from get_tags_bytes.
 
1351
        client.add_expected_call(
 
1352
            'Branch.get_tags_bytes', ('quack/',),
 
1353
            'success', ('d5:tag-17:rev-foo5:tag-27:rev-bare',))
 
1354
        transport.mkdir('quack')
 
1355
        transport = transport.clone('quack')
 
1356
        branch = self.make_remote_branch(transport, client)
 
1357
        result = branch.heads_to_fetch()
 
1358
        self.assertFinished(client)
 
1359
        self.assertEqual(
 
1360
            (set(['rev-tip']), set(['rev-foo', 'rev-bar'])), result)
 
1361
 
 
1362
    def test_uses_rpc_for_formats_with_non_default_heads_to_fetch(self):
 
1363
        transport = MemoryTransport()
 
1364
        client = FakeClient(transport.base)
 
1365
        client.add_expected_call(
 
1366
            'Branch.get_stacked_on_url', ('quack/',),
 
1367
            'error', ('NotStacked',))
 
1368
        client.add_expected_call(
 
1369
            'Branch.heads_to_fetch', ('quack/',),
 
1370
            'success', (['tip'], ['tagged-1', 'tagged-2']))
 
1371
        transport.mkdir('quack')
 
1372
        transport = transport.clone('quack')
 
1373
        branch = self.make_remote_branch(transport, client)
 
1374
        branch._format._use_default_local_heads_to_fetch = lambda: False
 
1375
        result = branch.heads_to_fetch()
 
1376
        self.assertFinished(client)
 
1377
        self.assertEqual((set(['tip']), set(['tagged-1', 'tagged-2'])), result)
 
1378
 
 
1379
    def make_branch_with_tags(self):
 
1380
        self.setup_smart_server_with_call_log()
 
1381
        # Make a branch with a single revision.
 
1382
        builder = self.make_branch_builder('foo')
 
1383
        builder.start_series()
 
1384
        builder.build_snapshot('tip', None, [
 
1385
            ('add', ('', 'root-id', 'directory', ''))])
 
1386
        builder.finish_series()
 
1387
        branch = builder.get_branch()
 
1388
        # Add two tags to that branch
 
1389
        branch.tags.set_tag('tag-1', 'rev-1')
 
1390
        branch.tags.set_tag('tag-2', 'rev-2')
 
1391
        return branch
 
1392
 
 
1393
    def test_backwards_compatible(self):
 
1394
        branch = self.make_branch_with_tags()
 
1395
        c = branch.get_config()
 
1396
        c.set_user_option('branch.fetch_tags', 'True')
 
1397
        self.addCleanup(branch.lock_read().unlock)
 
1398
        # Disable the heads_to_fetch verb
 
1399
        verb = 'Branch.heads_to_fetch'
 
1400
        self.disable_verb(verb)
 
1401
        self.reset_smart_call_log()
 
1402
        result = branch.heads_to_fetch()
 
1403
        self.assertEqual((set(['tip']), set(['rev-1', 'rev-2'])), result)
 
1404
        self.assertEqual(
 
1405
            ['Branch.last_revision_info', 'Branch.get_config_file',
 
1406
             'Branch.get_tags_bytes'],
 
1407
            [call.call.method for call in self.hpss_calls])
 
1408
 
 
1409
    def test_backwards_compatible_no_tags(self):
 
1410
        branch = self.make_branch_with_tags()
 
1411
        c = branch.get_config()
 
1412
        c.set_user_option('branch.fetch_tags', 'False')
 
1413
        self.addCleanup(branch.lock_read().unlock)
 
1414
        # Disable the heads_to_fetch verb
 
1415
        verb = 'Branch.heads_to_fetch'
 
1416
        self.disable_verb(verb)
 
1417
        self.reset_smart_call_log()
 
1418
        result = branch.heads_to_fetch()
 
1419
        self.assertEqual((set(['tip']), set()), result)
 
1420
        self.assertEqual(
 
1421
            ['Branch.last_revision_info', 'Branch.get_config_file'],
 
1422
            [call.call.method for call in self.hpss_calls])
 
1423
 
 
1424
 
1146
1425
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
1147
1426
 
1148
1427
    def test_empty_branch(self):
1203
1482
        client.add_expected_call(
1204
1483
            'Branch.get_stacked_on_url', ('stacked/',),
1205
1484
            'success', ('ok', vfs_url))
1206
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
1485
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1207
1486
            _client=client)
1208
1487
        repo_fmt = remote.RemoteRepositoryFormat()
1209
1488
        repo_fmt._custom_format = stacked_branch.repository._format
1236
1515
        # this will also do vfs access, but that goes direct to the transport
1237
1516
        # and isn't seen by the FakeClient.
1238
1517
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1239
 
            remote.RemoteBzrDirFormat(), _client=client)
 
1518
            RemoteBzrDirFormat(), _client=client)
1240
1519
        branch = bzrdir.open_branch()
1241
1520
        result = branch.get_stacked_on_url()
1242
1521
        self.assertEqual('../base', result)
1269
1548
            'Branch.get_stacked_on_url', ('stacked/',),
1270
1549
            'success', ('ok', '../base'))
1271
1550
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1272
 
            remote.RemoteBzrDirFormat(), _client=client)
 
1551
            RemoteBzrDirFormat(), _client=client)
1273
1552
        branch = bzrdir.open_branch()
1274
1553
        result = branch.get_stacked_on_url()
1275
1554
        self.assertEqual('../base', result)
1283
1562
class TestBranchSetLastRevision(RemoteBranchTestCase):
1284
1563
 
1285
1564
    def test_set_empty(self):
1286
 
        # set_revision_history([]) is translated to calling
 
1565
        # _set_last_revision_info('null:') is translated to calling
1287
1566
        # Branch.set_last_revision(path, '') on the wire.
1288
1567
        transport = MemoryTransport()
1289
1568
        transport.mkdir('branch')
1307
1586
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1308
1587
            'success', ('ok',))
1309
1588
        branch = self.make_remote_branch(transport, client)
1310
 
        # This is a hack to work around the problem that RemoteBranch currently
1311
 
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1312
 
        branch._ensure_real = lambda: None
1313
1589
        branch.lock_write()
1314
 
        result = branch.set_revision_history([])
 
1590
        result = branch._set_last_revision(NULL_REVISION)
1315
1591
        branch.unlock()
1316
1592
        self.assertEqual(None, result)
1317
1593
        self.assertFinished(client)
1318
1594
 
1319
1595
    def test_set_nonempty(self):
1320
 
        # set_revision_history([rev-id1, ..., rev-idN]) is translated to calling
 
1596
        # set_last_revision_info(N, rev-idN) is translated to calling
1321
1597
        # Branch.set_last_revision(path, rev-idN) on the wire.
1322
1598
        transport = MemoryTransport()
1323
1599
        transport.mkdir('branch')
1344
1620
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1345
1621
            'success', ('ok',))
1346
1622
        branch = self.make_remote_branch(transport, client)
1347
 
        # This is a hack to work around the problem that RemoteBranch currently
1348
 
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1349
 
        branch._ensure_real = lambda: None
1350
1623
        # Lock the branch, reset the record of remote calls.
1351
1624
        branch.lock_write()
1352
 
        result = branch.set_revision_history(['rev-id1', 'rev-id2'])
 
1625
        result = branch._set_last_revision('rev-id2')
1353
1626
        branch.unlock()
1354
1627
        self.assertEqual(None, result)
1355
1628
        self.assertFinished(client)
1385
1658
        branch = self.make_remote_branch(transport, client)
1386
1659
        branch.lock_write()
1387
1660
        self.assertRaises(
1388
 
            errors.NoSuchRevision, branch.set_revision_history, ['rev-id'])
 
1661
            errors.NoSuchRevision, branch._set_last_revision, 'rev-id')
1389
1662
        branch.unlock()
1390
1663
        self.assertFinished(client)
1391
1664
 
1419
1692
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1420
1693
            'success', ('ok',))
1421
1694
        branch = self.make_remote_branch(transport, client)
1422
 
        branch._ensure_real = lambda: None
1423
1695
        branch.lock_write()
1424
1696
        # The 'TipChangeRejected' error response triggered by calling
1425
 
        # set_revision_history causes a TipChangeRejected exception.
 
1697
        # set_last_revision_info causes a TipChangeRejected exception.
1426
1698
        err = self.assertRaises(
1427
 
            errors.TipChangeRejected, branch.set_revision_history, ['rev-id'])
 
1699
            errors.TipChangeRejected,
 
1700
            branch._set_last_revision, 'rev-id')
1428
1701
        # The UTF-8 message from the response has been decoded into a unicode
1429
1702
        # object.
1430
1703
        self.assertIsInstance(err.msg, unicode)
1618
1891
    def test_get_multi_line_branch_conf(self):
1619
1892
        # Make sure that multiple-line branch.conf files are supported
1620
1893
        #
1621
 
        # https://bugs.edge.launchpad.net/bzr/+bug/354075
 
1894
        # https://bugs.launchpad.net/bzr/+bug/354075
1622
1895
        client = FakeClient()
1623
1896
        client.add_expected_call(
1624
1897
            'Branch.get_stacked_on_url', ('memory:///',),
1652
1925
        branch.unlock()
1653
1926
        self.assertFinished(client)
1654
1927
 
 
1928
    def test_set_option_with_dict(self):
 
1929
        client = FakeClient()
 
1930
        client.add_expected_call(
 
1931
            'Branch.get_stacked_on_url', ('memory:///',),
 
1932
            'error', ('NotStacked',),)
 
1933
        client.add_expected_call(
 
1934
            'Branch.lock_write', ('memory:///', '', ''),
 
1935
            'success', ('ok', 'branch token', 'repo token'))
 
1936
        encoded_dict_value = 'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde'
 
1937
        client.add_expected_call(
 
1938
            'Branch.set_config_option_dict', ('memory:///', 'branch token',
 
1939
            'repo token', encoded_dict_value, 'foo', ''),
 
1940
            'success', ())
 
1941
        client.add_expected_call(
 
1942
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
 
1943
            'success', ('ok',))
 
1944
        transport = MemoryTransport()
 
1945
        branch = self.make_remote_branch(transport, client)
 
1946
        branch.lock_write()
 
1947
        config = branch._get_config()
 
1948
        config.set_option(
 
1949
            {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'},
 
1950
            'foo')
 
1951
        branch.unlock()
 
1952
        self.assertFinished(client)
 
1953
 
1655
1954
    def test_backwards_compat_set_option(self):
1656
1955
        self.setup_smart_server_with_call_log()
1657
1956
        branch = self.make_branch('.')
1664
1963
        self.assertLength(10, self.hpss_calls)
1665
1964
        self.assertEqual('value', branch._get_config().get_option('name'))
1666
1965
 
 
1966
    def test_backwards_compat_set_option_with_dict(self):
 
1967
        self.setup_smart_server_with_call_log()
 
1968
        branch = self.make_branch('.')
 
1969
        verb = 'Branch.set_config_option_dict'
 
1970
        self.disable_verb(verb)
 
1971
        branch.lock_write()
 
1972
        self.addCleanup(branch.unlock)
 
1973
        self.reset_smart_call_log()
 
1974
        config = branch._get_config()
 
1975
        value_dict = {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
 
1976
        config.set_option(value_dict, 'name')
 
1977
        self.assertLength(10, self.hpss_calls)
 
1978
        self.assertEqual(value_dict, branch._get_config().get_option('name'))
 
1979
 
 
1980
 
 
1981
class TestBranchGetPutConfigStore(RemoteBranchTestCase):
 
1982
 
 
1983
    def test_get_branch_conf(self):
 
1984
        # in an empty branch we decode the response properly
 
1985
        client = FakeClient()
 
1986
        client.add_expected_call(
 
1987
            'Branch.get_stacked_on_url', ('memory:///',),
 
1988
            'error', ('NotStacked',),)
 
1989
        client.add_success_response_with_body('# config file body', 'ok')
 
1990
        transport = MemoryTransport()
 
1991
        branch = self.make_remote_branch(transport, client)
 
1992
        config = branch.get_config_stack()
 
1993
        config.get("email")
 
1994
        config.get("log_format")
 
1995
        self.assertEqual(
 
1996
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
 
1997
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',))],
 
1998
            client._calls)
 
1999
 
 
2000
    def test_set_branch_conf(self):
 
2001
        client = FakeClient()
 
2002
        client.add_expected_call(
 
2003
            'Branch.get_stacked_on_url', ('memory:///',),
 
2004
            'error', ('NotStacked',),)
 
2005
        client.add_expected_call(
 
2006
            'Branch.lock_write', ('memory:///', '', ''),
 
2007
            'success', ('ok', 'branch token', 'repo token'))
 
2008
        client.add_expected_call(
 
2009
            'Branch.get_config_file', ('memory:///', ),
 
2010
            'success', ('ok', ), "# line 1\n")
 
2011
        client.add_expected_call(
 
2012
            'Branch.put_config_file', ('memory:///', 'branch token',
 
2013
            'repo token'),
 
2014
            'success', ('ok',))
 
2015
        client.add_expected_call(
 
2016
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
 
2017
            'success', ('ok',))
 
2018
        transport = MemoryTransport()
 
2019
        branch = self.make_remote_branch(transport, client)
 
2020
        branch.lock_write()
 
2021
        config = branch.get_config_stack()
 
2022
        config.set('email', 'The Dude <lebowski@example.com>')
 
2023
        branch.unlock()
 
2024
        self.assertFinished(client)
 
2025
        self.assertEqual(
 
2026
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
 
2027
             ('call', 'Branch.lock_write', ('memory:///', '', '')),
 
2028
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',)),
 
2029
             ('call_with_body_bytes_expecting_body', 'Branch.put_config_file',
 
2030
                 ('memory:///', 'branch token', 'repo token'),
 
2031
                 '# line 1\nemail = The Dude <lebowski@example.com>\n'),
 
2032
             ('call', 'Branch.unlock', ('memory:///', 'branch token', 'repo token'))],
 
2033
            client._calls)
 
2034
 
1667
2035
 
1668
2036
class TestBranchLockWrite(RemoteBranchTestCase):
1669
2037
 
1683
2051
        self.assertFinished(client)
1684
2052
 
1685
2053
 
 
2054
class TestBranchRevisionIdToRevno(RemoteBranchTestCase):
 
2055
 
 
2056
    def test_simple(self):
 
2057
        transport = MemoryTransport()
 
2058
        client = FakeClient(transport.base)
 
2059
        client.add_expected_call(
 
2060
            'Branch.get_stacked_on_url', ('quack/',),
 
2061
            'error', ('NotStacked',),)
 
2062
        client.add_expected_call(
 
2063
            'Branch.revision_id_to_revno', ('quack/', 'null:'),
 
2064
            'success', ('ok', '0',),)
 
2065
        client.add_expected_call(
 
2066
            'Branch.revision_id_to_revno', ('quack/', 'unknown'),
 
2067
            'error', ('NoSuchRevision', 'unknown',),)
 
2068
        transport.mkdir('quack')
 
2069
        transport = transport.clone('quack')
 
2070
        branch = self.make_remote_branch(transport, client)
 
2071
        self.assertEquals(0, branch.revision_id_to_revno('null:'))
 
2072
        self.assertRaises(errors.NoSuchRevision,
 
2073
            branch.revision_id_to_revno, 'unknown')
 
2074
        self.assertFinished(client)
 
2075
 
 
2076
    def test_dotted(self):
 
2077
        transport = MemoryTransport()
 
2078
        client = FakeClient(transport.base)
 
2079
        client.add_expected_call(
 
2080
            'Branch.get_stacked_on_url', ('quack/',),
 
2081
            'error', ('NotStacked',),)
 
2082
        client.add_expected_call(
 
2083
            'Branch.revision_id_to_revno', ('quack/', 'null:'),
 
2084
            'success', ('ok', '0',),)
 
2085
        client.add_expected_call(
 
2086
            'Branch.revision_id_to_revno', ('quack/', 'unknown'),
 
2087
            'error', ('NoSuchRevision', 'unknown',),)
 
2088
        transport.mkdir('quack')
 
2089
        transport = transport.clone('quack')
 
2090
        branch = self.make_remote_branch(transport, client)
 
2091
        self.assertEquals((0, ), branch.revision_id_to_dotted_revno('null:'))
 
2092
        self.assertRaises(errors.NoSuchRevision,
 
2093
            branch.revision_id_to_dotted_revno, 'unknown')
 
2094
        self.assertFinished(client)
 
2095
 
 
2096
    def test_dotted_no_smart_verb(self):
 
2097
        self.setup_smart_server_with_call_log()
 
2098
        branch = self.make_branch('.')
 
2099
        self.disable_verb('Branch.revision_id_to_revno')
 
2100
        self.reset_smart_call_log()
 
2101
        self.assertEquals((0, ),
 
2102
            branch.revision_id_to_dotted_revno('null:'))
 
2103
        self.assertLength(7, self.hpss_calls)
 
2104
 
 
2105
 
1686
2106
class TestBzrDirGetSetConfig(RemoteBzrDirTestCase):
1687
2107
 
1688
2108
    def test__get_config(self):
1805
2225
        client = FakeClient(transport.base)
1806
2226
        transport = transport.clone(transport_path)
1807
2227
        # we do not want bzrdir to make any remote calls
1808
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
2228
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1809
2229
            _client=False)
1810
2230
        repo = RemoteRepository(bzrdir, None, _client=client)
1811
2231
        return repo, client
1819
2239
 
1820
2240
    def test_get_format_description(self):
1821
2241
        remote_format = RemoteBranchFormat()
1822
 
        real_format = branch.BranchFormat.get_default_format()
 
2242
        real_format = branch.format_registry.get_default()
1823
2243
        remote_format._network_name = real_format.network_name()
1824
2244
        self.assertEqual(remoted_description(real_format),
1825
2245
            remote_format.get_format_description())
1828
2248
class TestRepositoryFormat(TestRemoteRepository):
1829
2249
 
1830
2250
    def test_fast_delta(self):
1831
 
        true_name = groupcompress_repo.RepositoryFormatCHK1().network_name()
 
2251
        true_name = groupcompress_repo.RepositoryFormat2a().network_name()
1832
2252
        true_format = RemoteRepositoryFormat()
1833
2253
        true_format._network_name = true_name
1834
2254
        self.assertEqual(True, true_format.fast_deltas)
1835
 
        false_name = pack_repo.RepositoryFormatKnitPack1().network_name()
 
2255
        false_name = knitpack_repo.RepositoryFormatKnitPack1().network_name()
1836
2256
        false_format = RemoteRepositoryFormat()
1837
2257
        false_format._network_name = false_name
1838
2258
        self.assertEqual(False, false_format.fast_deltas)
1839
2259
 
1840
2260
    def test_get_format_description(self):
1841
2261
        remote_repo_format = RemoteRepositoryFormat()
1842
 
        real_format = repository.RepositoryFormat.get_default_format()
 
2262
        real_format = repository.format_registry.get_default()
1843
2263
        remote_repo_format._network_name = real_format.network_name()
1844
2264
        self.assertEqual(remoted_description(real_format),
1845
2265
            remote_repo_format.get_format_description())
1846
2266
 
1847
2267
 
 
2268
class TestRepositoryAllRevisionIds(TestRemoteRepository):
 
2269
 
 
2270
    def test_empty(self):
 
2271
        transport_path = 'quack'
 
2272
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2273
        client.add_success_response_with_body('', 'ok')
 
2274
        self.assertEquals([], repo.all_revision_ids())
 
2275
        self.assertEqual(
 
2276
            [('call_expecting_body', 'Repository.all_revision_ids',
 
2277
             ('quack/',))],
 
2278
            client._calls)
 
2279
 
 
2280
    def test_with_some_content(self):
 
2281
        transport_path = 'quack'
 
2282
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2283
        client.add_success_response_with_body(
 
2284
            'rev1\nrev2\nanotherrev\n', 'ok')
 
2285
        self.assertEquals(["rev1", "rev2", "anotherrev"],
 
2286
            repo.all_revision_ids())
 
2287
        self.assertEqual(
 
2288
            [('call_expecting_body', 'Repository.all_revision_ids',
 
2289
             ('quack/',))],
 
2290
            client._calls)
 
2291
 
 
2292
 
1848
2293
class TestRepositoryGatherStats(TestRemoteRepository):
1849
2294
 
1850
2295
    def test_revid_none(self):
1903
2348
                         result)
1904
2349
 
1905
2350
 
 
2351
class TestRepositoryBreakLock(TestRemoteRepository):
 
2352
 
 
2353
    def test_break_lock(self):
 
2354
        transport_path = 'quack'
 
2355
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2356
        client.add_success_response('ok')
 
2357
        repo.break_lock()
 
2358
        self.assertEqual(
 
2359
            [('call', 'Repository.break_lock', ('quack/',))],
 
2360
            client._calls)
 
2361
 
 
2362
 
 
2363
class TestRepositoryGetSerializerFormat(TestRemoteRepository):
 
2364
 
 
2365
    def test_get_serializer_format(self):
 
2366
        transport_path = 'hill'
 
2367
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2368
        client.add_success_response('ok', '7')
 
2369
        self.assertEquals('7', repo.get_serializer_format())
 
2370
        self.assertEqual(
 
2371
            [('call', 'VersionedFileRepository.get_serializer_format',
 
2372
              ('hill/', ))],
 
2373
            client._calls)
 
2374
 
 
2375
 
 
2376
class TestRepositoryGetRevisionSignatureText(TestRemoteRepository):
 
2377
 
 
2378
    def test_text(self):
 
2379
        # ('ok',), body with signature text
 
2380
        transport_path = 'quack'
 
2381
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2382
        client.add_success_response_with_body(
 
2383
            'THETEXT', 'ok')
 
2384
        self.assertEquals("THETEXT", repo.get_signature_text("revid"))
 
2385
        self.assertEqual(
 
2386
            [('call_expecting_body', 'Repository.get_revision_signature_text',
 
2387
             ('quack/', 'revid'))],
 
2388
            client._calls)
 
2389
 
 
2390
    def test_no_signature(self):
 
2391
        transport_path = 'quick'
 
2392
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2393
        client.add_error_response('nosuchrevision', 'unknown')
 
2394
        self.assertRaises(errors.NoSuchRevision, repo.get_signature_text,
 
2395
                "unknown")
 
2396
        self.assertEqual(
 
2397
            [('call_expecting_body', 'Repository.get_revision_signature_text',
 
2398
              ('quick/', 'unknown'))],
 
2399
            client._calls)
 
2400
 
 
2401
 
1906
2402
class TestRepositoryGetGraph(TestRemoteRepository):
1907
2403
 
1908
2404
    def test_get_graph(self):
1913
2409
        self.assertNotEqual(graph._parents_provider, repo)
1914
2410
 
1915
2411
 
 
2412
class TestRepositoryAddSignatureText(TestRemoteRepository):
 
2413
 
 
2414
    def test_add_signature_text(self):
 
2415
        transport_path = 'quack'
 
2416
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2417
        client.add_expected_call(
 
2418
            'Repository.lock_write', ('quack/', ''),
 
2419
            'success', ('ok', 'a token'))
 
2420
        client.add_expected_call(
 
2421
            'Repository.start_write_group', ('quack/', 'a token'),
 
2422
            'success', ('ok', ('token1', )))
 
2423
        client.add_expected_call(
 
2424
            'Repository.add_signature_text', ('quack/', 'a token', 'rev1',
 
2425
                'token1'),
 
2426
            'success', ('ok', ), None)
 
2427
        repo.lock_write()
 
2428
        repo.start_write_group()
 
2429
        self.assertIs(None,
 
2430
            repo.add_signature_text("rev1", "every bloody emperor"))
 
2431
        self.assertEqual(
 
2432
            ('call_with_body_bytes_expecting_body',
 
2433
              'Repository.add_signature_text',
 
2434
                ('quack/', 'a token', 'rev1', 'token1'),
 
2435
              'every bloody emperor'),
 
2436
            client._calls[-1])
 
2437
 
 
2438
 
1916
2439
class TestRepositoryGetParentMap(TestRemoteRepository):
1917
2440
 
1918
2441
    def test_get_parent_map_caching(self):
1968
2491
        parents = repo.get_parent_map([rev_id])
1969
2492
        self.assertEqual(
1970
2493
            [('call_with_body_bytes_expecting_body',
1971
 
              'Repository.get_parent_map', ('quack/', 'include-missing:',
1972
 
              rev_id), '\n\n0'),
 
2494
              'Repository.get_parent_map',
 
2495
              ('quack/', 'include-missing:', rev_id), '\n\n0'),
1973
2496
             ('disconnect medium',),
1974
2497
             ('call_expecting_body', 'Repository.get_revision_graph',
1975
2498
              ('quack/', ''))],
2095
2618
        self.assertEqual({}, repo.get_parent_map(['non-existant']))
2096
2619
        self.assertLength(0, self.hpss_calls)
2097
2620
 
 
2621
    def test_exposes_get_cached_parent_map(self):
 
2622
        """RemoteRepository exposes get_cached_parent_map from
 
2623
        _unstacked_provider
 
2624
        """
 
2625
        r1 = u'\u0e33'.encode('utf8')
 
2626
        r2 = u'\u0dab'.encode('utf8')
 
2627
        lines = [' '.join([r2, r1]), r1]
 
2628
        encoded_body = bz2.compress('\n'.join(lines))
 
2629
 
 
2630
        transport_path = 'quack'
 
2631
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2632
        client.add_success_response_with_body(encoded_body, 'ok')
 
2633
        repo.lock_read()
 
2634
        # get_cached_parent_map should *not* trigger an RPC
 
2635
        self.assertEqual({}, repo.get_cached_parent_map([r1]))
 
2636
        self.assertEqual([], client._calls)
 
2637
        self.assertEqual({r2: (r1,)}, repo.get_parent_map([r2]))
 
2638
        self.assertEqual({r1: (NULL_REVISION,)},
 
2639
            repo.get_cached_parent_map([r1]))
 
2640
        self.assertEqual(
 
2641
            [('call_with_body_bytes_expecting_body',
 
2642
              'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
 
2643
              '\n\n0')],
 
2644
            client._calls)
 
2645
        repo.unlock()
 
2646
 
2098
2647
 
2099
2648
class TestGetParentMapAllowsNew(tests.TestCaseWithTransport):
2100
2649
 
2115
2664
        self.assertEqual({'rev1': ('null:',)}, graph.get_parent_map(['rev1']))
2116
2665
 
2117
2666
 
 
2667
class TestRepositoryGetRevisions(TestRemoteRepository):
 
2668
 
 
2669
    def test_hpss_missing_revision(self):
 
2670
        transport_path = 'quack'
 
2671
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2672
        client.add_success_response_with_body(
 
2673
            '', 'ok', '10')
 
2674
        self.assertRaises(errors.NoSuchRevision, repo.get_revisions,
 
2675
            ['somerev1', 'anotherrev2'])
 
2676
        self.assertEqual(
 
2677
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
 
2678
             ('quack/', ), "somerev1\nanotherrev2")],
 
2679
            client._calls)
 
2680
 
 
2681
    def test_hpss_get_single_revision(self):
 
2682
        transport_path = 'quack'
 
2683
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2684
        somerev1 = Revision("somerev1")
 
2685
        somerev1.committer = "Joe Committer <joe@example.com>"
 
2686
        somerev1.timestamp = 1321828927
 
2687
        somerev1.timezone = -60
 
2688
        somerev1.inventory_sha1 = "691b39be74c67b1212a75fcb19c433aaed903c2b"
 
2689
        somerev1.message = "Message"
 
2690
        body = zlib.compress(chk_bencode_serializer.write_revision_to_string(
 
2691
            somerev1))
 
2692
        # Split up body into two bits to make sure the zlib compression object
 
2693
        # gets data fed twice.
 
2694
        client.add_success_response_with_body(
 
2695
                [body[:10], body[10:]], 'ok', '10')
 
2696
        revs = repo.get_revisions(['somerev1'])
 
2697
        self.assertEquals(revs, [somerev1])
 
2698
        self.assertEqual(
 
2699
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
 
2700
             ('quack/', ), "somerev1")],
 
2701
            client._calls)
 
2702
 
 
2703
 
2118
2704
class TestRepositoryGetRevisionGraph(TestRemoteRepository):
2119
2705
 
2120
2706
    def test_null_revision(self):
2257
2843
        self.setup_smart_server_with_call_log()
2258
2844
        tree = self.make_branch_and_memory_tree('.')
2259
2845
        tree.lock_write()
 
2846
        tree.add('')
2260
2847
        rev1 = tree.commit('First')
2261
2848
        rev2 = tree.commit('Second')
2262
2849
        tree.unlock()
2270
2857
                              call.call.method == verb])
2271
2858
 
2272
2859
 
 
2860
class TestRepositoryHasSignatureForRevisionId(TestRemoteRepository):
 
2861
 
 
2862
    def test_has_signature_for_revision_id(self):
 
2863
        # ('yes', ) for Repository.has_signature_for_revision_id -> 'True'.
 
2864
        transport_path = 'quack'
 
2865
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2866
        client.add_success_response('yes')
 
2867
        result = repo.has_signature_for_revision_id('A')
 
2868
        self.assertEqual(
 
2869
            [('call', 'Repository.has_signature_for_revision_id',
 
2870
              ('quack/', 'A'))],
 
2871
            client._calls)
 
2872
        self.assertEqual(True, result)
 
2873
 
 
2874
    def test_is_not_shared(self):
 
2875
        # ('no', ) for Repository.has_signature_for_revision_id -> 'False'.
 
2876
        transport_path = 'qwack'
 
2877
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2878
        client.add_success_response('no')
 
2879
        result = repo.has_signature_for_revision_id('A')
 
2880
        self.assertEqual(
 
2881
            [('call', 'Repository.has_signature_for_revision_id',
 
2882
              ('qwack/', 'A'))],
 
2883
            client._calls)
 
2884
        self.assertEqual(False, result)
 
2885
 
 
2886
 
 
2887
class TestRepositoryPhysicalLockStatus(TestRemoteRepository):
 
2888
 
 
2889
    def test_get_physical_lock_status_yes(self):
 
2890
        transport_path = 'qwack'
 
2891
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2892
        client.add_success_response('yes')
 
2893
        result = repo.get_physical_lock_status()
 
2894
        self.assertEqual(
 
2895
            [('call', 'Repository.get_physical_lock_status',
 
2896
              ('qwack/', ))],
 
2897
            client._calls)
 
2898
        self.assertEqual(True, result)
 
2899
 
 
2900
    def test_get_physical_lock_status_no(self):
 
2901
        transport_path = 'qwack'
 
2902
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2903
        client.add_success_response('no')
 
2904
        result = repo.get_physical_lock_status()
 
2905
        self.assertEqual(
 
2906
            [('call', 'Repository.get_physical_lock_status',
 
2907
              ('qwack/', ))],
 
2908
            client._calls)
 
2909
        self.assertEqual(False, result)
 
2910
 
 
2911
 
2273
2912
class TestRepositoryIsShared(TestRemoteRepository):
2274
2913
 
2275
2914
    def test_is_shared(self):
2295
2934
        self.assertEqual(False, result)
2296
2935
 
2297
2936
 
 
2937
class TestRepositoryMakeWorkingTrees(TestRemoteRepository):
 
2938
 
 
2939
    def test_make_working_trees(self):
 
2940
        # ('yes', ) for Repository.make_working_trees -> 'True'.
 
2941
        transport_path = 'quack'
 
2942
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2943
        client.add_success_response('yes')
 
2944
        result = repo.make_working_trees()
 
2945
        self.assertEqual(
 
2946
            [('call', 'Repository.make_working_trees', ('quack/',))],
 
2947
            client._calls)
 
2948
        self.assertEqual(True, result)
 
2949
 
 
2950
    def test_no_working_trees(self):
 
2951
        # ('no', ) for Repository.make_working_trees -> 'False'.
 
2952
        transport_path = 'qwack'
 
2953
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2954
        client.add_success_response('no')
 
2955
        result = repo.make_working_trees()
 
2956
        self.assertEqual(
 
2957
            [('call', 'Repository.make_working_trees', ('qwack/',))],
 
2958
            client._calls)
 
2959
        self.assertEqual(False, result)
 
2960
 
 
2961
 
2298
2962
class TestRepositoryLockWrite(TestRemoteRepository):
2299
2963
 
2300
2964
    def test_lock_write(self):
2301
2965
        transport_path = 'quack'
2302
2966
        repo, client = self.setup_fake_client_and_repository(transport_path)
2303
2967
        client.add_success_response('ok', 'a token')
2304
 
        result = repo.lock_write()
 
2968
        token = repo.lock_write().repository_token
2305
2969
        self.assertEqual(
2306
2970
            [('call', 'Repository.lock_write', ('quack/', ''))],
2307
2971
            client._calls)
2308
 
        self.assertEqual('a token', result)
 
2972
        self.assertEqual('a token', token)
2309
2973
 
2310
2974
    def test_lock_write_already_locked(self):
2311
2975
        transport_path = 'quack'
2326
2990
            client._calls)
2327
2991
 
2328
2992
 
 
2993
class TestRepositoryWriteGroups(TestRemoteRepository):
 
2994
 
 
2995
    def test_start_write_group(self):
 
2996
        transport_path = 'quack'
 
2997
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2998
        client.add_expected_call(
 
2999
            'Repository.lock_write', ('quack/', ''),
 
3000
            'success', ('ok', 'a token'))
 
3001
        client.add_expected_call(
 
3002
            'Repository.start_write_group', ('quack/', 'a token'),
 
3003
            'success', ('ok', ('token1', )))
 
3004
        repo.lock_write()
 
3005
        repo.start_write_group()
 
3006
 
 
3007
    def test_start_write_group_unsuspendable(self):
 
3008
        # Some repositories do not support suspending write
 
3009
        # groups. For those, fall back to the "real" repository.
 
3010
        transport_path = 'quack'
 
3011
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3012
        def stub_ensure_real():
 
3013
            client._calls.append(('_ensure_real',))
 
3014
            repo._real_repository = _StubRealPackRepository(client._calls)
 
3015
        repo._ensure_real = stub_ensure_real
 
3016
        client.add_expected_call(
 
3017
            'Repository.lock_write', ('quack/', ''),
 
3018
            'success', ('ok', 'a token'))
 
3019
        client.add_expected_call(
 
3020
            'Repository.start_write_group', ('quack/', 'a token'),
 
3021
            'error', ('UnsuspendableWriteGroup',))
 
3022
        repo.lock_write()
 
3023
        repo.start_write_group()
 
3024
        self.assertEquals(client._calls[-2:], [ 
 
3025
            ('_ensure_real',),
 
3026
            ('start_write_group',)])
 
3027
 
 
3028
    def test_commit_write_group(self):
 
3029
        transport_path = 'quack'
 
3030
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3031
        client.add_expected_call(
 
3032
            'Repository.lock_write', ('quack/', ''),
 
3033
            'success', ('ok', 'a token'))
 
3034
        client.add_expected_call(
 
3035
            'Repository.start_write_group', ('quack/', 'a token'),
 
3036
            'success', ('ok', ['token1']))
 
3037
        client.add_expected_call(
 
3038
            'Repository.commit_write_group', ('quack/', 'a token', ['token1']),
 
3039
            'success', ('ok',))
 
3040
        repo.lock_write()
 
3041
        repo.start_write_group()
 
3042
        repo.commit_write_group()
 
3043
 
 
3044
    def test_abort_write_group(self):
 
3045
        transport_path = 'quack'
 
3046
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3047
        client.add_expected_call(
 
3048
            'Repository.lock_write', ('quack/', ''),
 
3049
            'success', ('ok', 'a token'))
 
3050
        client.add_expected_call(
 
3051
            'Repository.start_write_group', ('quack/', 'a token'),
 
3052
            'success', ('ok', ['token1']))
 
3053
        client.add_expected_call(
 
3054
            'Repository.abort_write_group', ('quack/', 'a token', ['token1']),
 
3055
            'success', ('ok',))
 
3056
        repo.lock_write()
 
3057
        repo.start_write_group()
 
3058
        repo.abort_write_group(False)
 
3059
 
 
3060
    def test_suspend_write_group(self):
 
3061
        transport_path = 'quack'
 
3062
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3063
        self.assertEquals([], repo.suspend_write_group())
 
3064
 
 
3065
    def test_resume_write_group(self):
 
3066
        transport_path = 'quack'
 
3067
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3068
        client.add_expected_call(
 
3069
            'Repository.lock_write', ('quack/', ''),
 
3070
            'success', ('ok', 'a token'))
 
3071
        client.add_expected_call(
 
3072
            'Repository.check_write_group', ('quack/', 'a token', ['token1']),
 
3073
            'success', ('ok',))
 
3074
        repo.lock_write()
 
3075
        repo.resume_write_group(['token1'])
 
3076
 
 
3077
 
2329
3078
class TestRepositorySetMakeWorkingTrees(TestRemoteRepository):
2330
3079
 
2331
3080
    def test_backwards_compat(self):
2390
3139
        self.assertEqual([], client._calls)
2391
3140
 
2392
3141
 
 
3142
class TestRepositoryIterFilesBytes(TestRemoteRepository):
 
3143
    """Test Repository.iter_file_bytes."""
 
3144
 
 
3145
    def test_single(self):
 
3146
        transport_path = 'quack'
 
3147
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3148
        client.add_expected_call(
 
3149
            'Repository.iter_files_bytes', ('quack/', ),
 
3150
            'success', ('ok',), iter(["ok\x000", "\n", zlib.compress("mydata" * 10)]))
 
3151
        for (identifier, byte_stream) in repo.iter_files_bytes([("somefile",
 
3152
                "somerev", "myid")]):
 
3153
            self.assertEquals("myid", identifier)
 
3154
            self.assertEquals("".join(byte_stream), "mydata" * 10)
 
3155
 
 
3156
    def test_missing(self):
 
3157
        transport_path = 'quack'
 
3158
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3159
        client.add_expected_call(
 
3160
            'Repository.iter_files_bytes',
 
3161
                ('quack/', ),
 
3162
            'error', ('RevisionNotPresent', 'somefile', 'somerev'),
 
3163
            iter(["absent\0somefile\0somerev\n"]))
 
3164
        self.assertRaises(errors.RevisionNotPresent, list,
 
3165
                repo.iter_files_bytes(
 
3166
                [("somefile", "somerev", "myid")]))
 
3167
 
 
3168
 
2393
3169
class TestRepositoryInsertStreamBase(TestRemoteRepository):
2394
3170
    """Base class for Repository.insert_stream and .insert_stream_1.19
2395
3171
    tests.
2402
3178
        the client is finished.
2403
3179
        """
2404
3180
        sink = repo._get_sink()
2405
 
        fmt = repository.RepositoryFormat.get_default_format()
 
3181
        fmt = repository.format_registry.get_default()
2406
3182
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2407
3183
        self.assertEqual([], resume_tokens)
2408
3184
        self.assertEqual(set(), missing_keys)
2508
3284
                return True
2509
3285
        repo._real_repository = FakeRealRepository()
2510
3286
        sink = repo._get_sink()
2511
 
        fmt = repository.RepositoryFormat.get_default_format()
 
3287
        fmt = repository.format_registry.get_default()
2512
3288
        stream = self.make_stream_with_inv_deltas(fmt)
2513
3289
        resume_tokens, missing_keys = sink.insert_stream(stream, fmt, [])
2514
3290
        # Every record from the first inventory delta should have been sent to
2670
3446
        self.calls = calls
2671
3447
        self._pack_collection = _StubPackCollection(calls)
2672
3448
 
 
3449
    def start_write_group(self):
 
3450
        self.calls.append(('start_write_group',))
 
3451
 
2673
3452
    def is_in_write_group(self):
2674
3453
        return False
2675
3454
 
2734
3513
             ('pack collection autopack',)],
2735
3514
            client._calls)
2736
3515
 
 
3516
    def test_oom_error_reporting(self):
 
3517
        """An out-of-memory condition on the server is reported clearly"""
 
3518
        transport_path = 'quack'
 
3519
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3520
        client.add_expected_call(
 
3521
            'PackRepository.autopack', ('quack/',),
 
3522
            'error', ('MemoryError',))
 
3523
        err = self.assertRaises(errors.BzrError, repo.autopack)
 
3524
        self.assertContainsRe(str(err), "^remote server out of mem")
 
3525
 
2737
3526
 
2738
3527
class TestErrorTranslationBase(tests.TestCaseWithMemoryTransport):
2739
3528
    """Base class for unit tests for bzrlib.remote._translate_error."""
2812
3601
            detail='extra detail')
2813
3602
        self.assertEqual(expected_error, translated_error)
2814
3603
 
 
3604
    def test_norepository(self):
 
3605
        bzrdir = self.make_bzrdir('')
 
3606
        translated_error = self.translateTuple(('norepository',),
 
3607
            bzrdir=bzrdir)
 
3608
        expected_error = errors.NoRepositoryPresent(bzrdir)
 
3609
        self.assertEqual(expected_error, translated_error)
 
3610
 
2815
3611
    def test_LockContention(self):
2816
3612
        translated_error = self.translateTuple(('LockContention',))
2817
3613
        expected_error = errors.LockContention('(remote lock)')
2845
3641
        expected_error = errors.DivergedBranches(branch, other_branch)
2846
3642
        self.assertEqual(expected_error, translated_error)
2847
3643
 
 
3644
    def test_NotStacked(self):
 
3645
        branch = self.make_branch('')
 
3646
        translated_error = self.translateTuple(('NotStacked',), branch=branch)
 
3647
        expected_error = errors.NotStacked(branch)
 
3648
        self.assertEqual(expected_error, translated_error)
 
3649
 
2848
3650
    def test_ReadError_no_args(self):
2849
3651
        path = 'a path'
2850
3652
        translated_error = self.translateTuple(('ReadError',), path=path)
2866
3668
 
2867
3669
    def test_PermissionDenied_no_args(self):
2868
3670
        path = 'a path'
2869
 
        translated_error = self.translateTuple(('PermissionDenied',), path=path)
 
3671
        translated_error = self.translateTuple(('PermissionDenied',),
 
3672
            path=path)
2870
3673
        expected_error = errors.PermissionDenied(path)
2871
3674
        self.assertEqual(expected_error, translated_error)
2872
3675
 
2895
3698
        expected_error = errors.PermissionDenied(path, extra)
2896
3699
        self.assertEqual(expected_error, translated_error)
2897
3700
 
 
3701
    # GZ 2011-03-02: TODO test for PermissionDenied with non-ascii 'extra'
 
3702
 
 
3703
    def test_NoSuchFile_context_path(self):
 
3704
        local_path = "local path"
 
3705
        translated_error = self.translateTuple(('ReadError', "remote path"),
 
3706
            path=local_path)
 
3707
        expected_error = errors.ReadError(local_path)
 
3708
        self.assertEqual(expected_error, translated_error)
 
3709
 
 
3710
    def test_NoSuchFile_without_context(self):
 
3711
        remote_path = "remote path"
 
3712
        translated_error = self.translateTuple(('ReadError', remote_path))
 
3713
        expected_error = errors.ReadError(remote_path)
 
3714
        self.assertEqual(expected_error, translated_error)
 
3715
 
 
3716
    def test_ReadOnlyError(self):
 
3717
        translated_error = self.translateTuple(('ReadOnlyError',))
 
3718
        expected_error = errors.TransportNotPossible("readonly transport")
 
3719
        self.assertEqual(expected_error, translated_error)
 
3720
 
 
3721
    def test_MemoryError(self):
 
3722
        translated_error = self.translateTuple(('MemoryError',))
 
3723
        self.assertStartsWith(str(translated_error),
 
3724
            "remote server out of memory")
 
3725
 
 
3726
    def test_generic_IndexError_no_classname(self):
 
3727
        err = errors.ErrorFromSmartServer(('error', "list index out of range"))
 
3728
        translated_error = self.translateErrorFromSmartServer(err)
 
3729
        expected_error = errors.UnknownErrorFromSmartServer(err)
 
3730
        self.assertEqual(expected_error, translated_error)
 
3731
 
 
3732
    # GZ 2011-03-02: TODO test generic non-ascii error string
 
3733
 
 
3734
    def test_generic_KeyError(self):
 
3735
        err = errors.ErrorFromSmartServer(('error', 'KeyError', "1"))
 
3736
        translated_error = self.translateErrorFromSmartServer(err)
 
3737
        expected_error = errors.UnknownErrorFromSmartServer(err)
 
3738
        self.assertEqual(expected_error, translated_error)
 
3739
 
2898
3740
 
2899
3741
class TestErrorTranslationRobustness(TestErrorTranslationBase):
2900
3742
    """Unit tests for bzrlib.remote._translate_error's robustness.
3045
3887
        _, stacked = branch_factory()
3046
3888
        source = stacked.repository._get_source(target_repository_format)
3047
3889
        tip = stacked.last_revision()
3048
 
        revs = stacked.repository.get_ancestry(tip)
3049
 
        search = graph.PendingAncestryResult([tip], stacked.repository)
 
3890
        stacked.repository._ensure_real()
 
3891
        graph = stacked.repository.get_graph()
 
3892
        revs = [r for (r,ps) in graph.iter_ancestry([tip])
 
3893
                if r != NULL_REVISION]
 
3894
        revs.reverse()
 
3895
        search = vf_search.PendingAncestryResult([tip], stacked.repository)
3050
3896
        self.reset_smart_call_log()
3051
3897
        stream = source.get_stream(search)
3052
 
        if None in revs:
3053
 
            revs.remove(None)
3054
3898
        # We trust that if a revision is in the stream the rest of the new
3055
3899
        # content for it is too, as per our main fetch tests; here we are
3056
3900
        # checking that the revisions are actually included at all, and their
3095
3939
        self.assertEqual(expected_revs, rev_ord)
3096
3940
        # Getting topological sort requires VFS calls still - one of which is
3097
3941
        # pushing up from the bound branch.
3098
 
        self.assertLength(13, self.hpss_calls)
 
3942
        self.assertLength(14, self.hpss_calls)
3099
3943
 
3100
3944
    def test_stacked_get_stream_groupcompress(self):
3101
3945
        # Repository._get_source.get_stream() from a stacked repository with
3142
3986
 
3143
3987
    def test_copy_content_into_avoids_revision_history(self):
3144
3988
        local = self.make_branch('local')
3145
 
        remote_backing_tree = self.make_branch_and_tree('remote')
3146
 
        remote_backing_tree.commit("Commit.")
 
3989
        builder = self.make_branch_builder('remote')
 
3990
        builder.build_commit(message="Commit.")
3147
3991
        remote_branch_url = self.smart_server.get_url() + 'remote'
3148
3992
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3149
3993
        local.repository.fetch(remote_branch.repository)
3150
3994
        self.hpss_calls = []
3151
3995
        remote_branch.copy_content_into(local)
3152
3996
        self.assertFalse('Branch.revision_history' in self.hpss_calls)
 
3997
 
 
3998
    def test_fetch_everything_needs_just_one_call(self):
 
3999
        local = self.make_branch('local')
 
4000
        builder = self.make_branch_builder('remote')
 
4001
        builder.build_commit(message="Commit.")
 
4002
        remote_branch_url = self.smart_server.get_url() + 'remote'
 
4003
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
 
4004
        self.hpss_calls = []
 
4005
        local.repository.fetch(
 
4006
            remote_branch.repository,
 
4007
            fetch_spec=vf_search.EverythingResult(remote_branch.repository))
 
4008
        self.assertEqual(['Repository.get_stream_1.19'], self.hpss_calls)
 
4009
 
 
4010
    def override_verb(self, verb_name, verb):
 
4011
        request_handlers = request.request_handlers
 
4012
        orig_verb = request_handlers.get(verb_name)
 
4013
        orig_info = request_handlers.get_info(verb_name)
 
4014
        request_handlers.register(verb_name, verb, override_existing=True)
 
4015
        self.addCleanup(request_handlers.register, verb_name, orig_verb,
 
4016
                override_existing=True, info=orig_info)
 
4017
 
 
4018
    def test_fetch_everything_backwards_compat(self):
 
4019
        """Can fetch with EverythingResult even with pre 2.4 servers.
 
4020
        
 
4021
        Pre-2.4 do not support 'everything' searches with the
 
4022
        Repository.get_stream_1.19 verb.
 
4023
        """
 
4024
        verb_log = []
 
4025
        class OldGetStreamVerb(SmartServerRepositoryGetStream_1_19):
 
4026
            """A version of the Repository.get_stream_1.19 verb patched to
 
4027
            reject 'everything' searches the way 2.3 and earlier do.
 
4028
            """
 
4029
            def recreate_search(self, repository, search_bytes,
 
4030
                                discard_excess=False):
 
4031
                verb_log.append(search_bytes.split('\n', 1)[0])
 
4032
                if search_bytes == 'everything':
 
4033
                    return (None,
 
4034
                            request.FailedSmartServerResponse(('BadSearch',)))
 
4035
                return super(OldGetStreamVerb,
 
4036
                        self).recreate_search(repository, search_bytes,
 
4037
                            discard_excess=discard_excess)
 
4038
        self.override_verb('Repository.get_stream_1.19', OldGetStreamVerb)
 
4039
        local = self.make_branch('local')
 
4040
        builder = self.make_branch_builder('remote')
 
4041
        builder.build_commit(message="Commit.")
 
4042
        remote_branch_url = self.smart_server.get_url() + 'remote'
 
4043
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
 
4044
        self.hpss_calls = []
 
4045
        local.repository.fetch(
 
4046
            remote_branch.repository,
 
4047
            fetch_spec=vf_search.EverythingResult(remote_branch.repository))
 
4048
        # make sure the overridden verb was used
 
4049
        self.assertLength(1, verb_log)
 
4050
        # more than one HPSS call is needed, but because it's a VFS callback
 
4051
        # its hard to predict exactly how many.
 
4052
        self.assertTrue(len(self.hpss_calls) > 1)
 
4053
 
 
4054
 
 
4055
class TestUpdateBoundBranchWithModifiedBoundLocation(
 
4056
    tests.TestCaseWithTransport):
 
4057
    """Ensure correct handling of bound_location modifications.
 
4058
 
 
4059
    This is tested against a smart server as http://pad.lv/786980 was about a
 
4060
    ReadOnlyError (write attempt during a read-only transaction) which can only
 
4061
    happen in this context.
 
4062
    """
 
4063
 
 
4064
    def setUp(self):
 
4065
        super(TestUpdateBoundBranchWithModifiedBoundLocation, self).setUp()
 
4066
        self.transport_server = test_server.SmartTCPServer_for_testing
 
4067
 
 
4068
    def make_master_and_checkout(self, master_name, checkout_name):
 
4069
        # Create the master branch and its associated checkout
 
4070
        self.master = self.make_branch_and_tree(master_name)
 
4071
        self.checkout = self.master.branch.create_checkout(checkout_name)
 
4072
        # Modify the master branch so there is something to update
 
4073
        self.master.commit('add stuff')
 
4074
        self.last_revid = self.master.commit('even more stuff')
 
4075
        self.bound_location = self.checkout.branch.get_bound_location()
 
4076
 
 
4077
    def assertUpdateSucceeds(self, new_location):
 
4078
        self.checkout.branch.set_bound_location(new_location)
 
4079
        self.checkout.update()
 
4080
        self.assertEquals(self.last_revid, self.checkout.last_revision())
 
4081
 
 
4082
    def test_without_final_slash(self):
 
4083
        self.make_master_and_checkout('master', 'checkout')
 
4084
        # For unclear reasons some users have a bound_location without a final
 
4085
        # '/', simulate that by forcing such a value
 
4086
        self.assertEndsWith(self.bound_location, '/')
 
4087
        self.assertUpdateSucceeds(self.bound_location.rstrip('/'))
 
4088
 
 
4089
    def test_plus_sign(self):
 
4090
        self.make_master_and_checkout('+master', 'checkout')
 
4091
        self.assertUpdateSucceeds(self.bound_location.replace('%2B', '+', 1))
 
4092
 
 
4093
    def test_tilda(self):
 
4094
        # Embed ~ in the middle of the path just to avoid any $HOME
 
4095
        # interpretation
 
4096
        self.make_master_and_checkout('mas~ter', 'checkout')
 
4097
        self.assertUpdateSucceeds(self.bound_location.replace('%2E', '~', 1))
 
4098
 
 
4099
 
 
4100
class TestWithCustomErrorHandler(RemoteBranchTestCase):
 
4101
 
 
4102
    def test_no_context(self):
 
4103
        class OutOfCoffee(errors.BzrError):
 
4104
            """A dummy exception for testing."""
 
4105
 
 
4106
            def __init__(self, urgency):
 
4107
                self.urgency = urgency
 
4108
        remote.no_context_error_translators.register("OutOfCoffee",
 
4109
            lambda err: OutOfCoffee(err.error_args[0]))
 
4110
        transport = MemoryTransport()
 
4111
        client = FakeClient(transport.base)
 
4112
        client.add_expected_call(
 
4113
            'Branch.get_stacked_on_url', ('quack/',),
 
4114
            'error', ('NotStacked',))
 
4115
        client.add_expected_call(
 
4116
            'Branch.last_revision_info',
 
4117
            ('quack/',),
 
4118
            'error', ('OutOfCoffee', 'low'))
 
4119
        transport.mkdir('quack')
 
4120
        transport = transport.clone('quack')
 
4121
        branch = self.make_remote_branch(transport, client)
 
4122
        self.assertRaises(OutOfCoffee, branch.last_revision_info)
 
4123
        self.assertFinished(client)
 
4124
 
 
4125
    def test_with_context(self):
 
4126
        class OutOfTea(errors.BzrError):
 
4127
            def __init__(self, branch, urgency):
 
4128
                self.branch = branch
 
4129
                self.urgency = urgency
 
4130
        remote.error_translators.register("OutOfTea",
 
4131
            lambda err, find, path: OutOfTea(err.error_args[0],
 
4132
                find("branch")))
 
4133
        transport = MemoryTransport()
 
4134
        client = FakeClient(transport.base)
 
4135
        client.add_expected_call(
 
4136
            'Branch.get_stacked_on_url', ('quack/',),
 
4137
            'error', ('NotStacked',))
 
4138
        client.add_expected_call(
 
4139
            'Branch.last_revision_info',
 
4140
            ('quack/',),
 
4141
            'error', ('OutOfTea', 'low'))
 
4142
        transport.mkdir('quack')
 
4143
        transport = transport.clone('quack')
 
4144
        branch = self.make_remote_branch(transport, client)
 
4145
        self.assertRaises(OutOfTea, branch.last_revision_info)
 
4146
        self.assertFinished(client)
 
4147
 
 
4148
 
 
4149
class TestRepositoryPack(TestRemoteRepository):
 
4150
 
 
4151
    def test_pack(self):
 
4152
        transport_path = 'quack'
 
4153
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4154
        client.add_expected_call(
 
4155
            'Repository.lock_write', ('quack/', ''),
 
4156
            'success', ('ok', 'token'))
 
4157
        client.add_expected_call(
 
4158
            'Repository.pack', ('quack/', 'token', 'False'),
 
4159
            'success', ('ok',), )
 
4160
        client.add_expected_call(
 
4161
            'Repository.unlock', ('quack/', 'token'),
 
4162
            'success', ('ok', ))
 
4163
        repo.pack()
 
4164
 
 
4165
    def test_pack_with_hint(self):
 
4166
        transport_path = 'quack'
 
4167
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4168
        client.add_expected_call(
 
4169
            'Repository.lock_write', ('quack/', ''),
 
4170
            'success', ('ok', 'token'))
 
4171
        client.add_expected_call(
 
4172
            'Repository.pack', ('quack/', 'token', 'False'),
 
4173
            'success', ('ok',), )
 
4174
        client.add_expected_call(
 
4175
            'Repository.unlock', ('quack/', 'token', 'False'),
 
4176
            'success', ('ok', ))
 
4177
        repo.pack(['hinta', 'hintb'])