~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_remote.py

  • Committer: Aaron Bentley
  • Date: 2008-04-24 04:58:42 UTC
  • mfrom: (3377 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3380.
  • Revision ID: aaron@aaronbentley.com-20080424045842-0cajl9v6s4u52kaw
Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
136
136
        """Create a FakeClient.
137
137
 
138
138
        :param responses: A list of response-tuple, body-data pairs to be sent
139
 
            back to callers.
 
139
            back to callers.  A special case is if the response-tuple is
 
140
            'unknown verb', then a UnknownSmartMethod will be raised for that
 
141
            call, using the second element of the tuple as the verb in the
 
142
            exception.
140
143
        """
141
144
        self.responses = responses
142
145
        self._calls = []
143
146
        self.expecting_body = False
144
147
        _SmartClient.__init__(self, FakeMedium(self._calls), fake_medium_base)
145
148
 
 
149
    def _get_next_response(self):
 
150
        response_tuple = self.responses.pop(0)
 
151
        if response_tuple[0][0] == 'unknown verb':
 
152
            raise errors.UnknownSmartMethod(response_tuple[0][1])
 
153
        return response_tuple
 
154
 
146
155
    def call(self, method, *args):
147
156
        self._calls.append(('call', method, args))
148
 
        return self.responses.pop(0)[0]
 
157
        return self._get_next_response()[0]
149
158
 
150
159
    def call_expecting_body(self, method, *args):
151
160
        self._calls.append(('call_expecting_body', method, args))
152
 
        result = self.responses.pop(0)
 
161
        result = self._get_next_response()
153
162
        self.expecting_body = True
154
163
        return result[0], FakeProtocol(result[1], self)
155
164
 
156
165
    def call_with_body_bytes_expecting_body(self, method, args, body):
157
166
        self._calls.append(('call_with_body_bytes_expecting_body', method,
158
167
            args, body))
159
 
        result = self.responses.pop(0)
 
168
        result = self._get_next_response()
160
169
        self.expecting_body = True
161
170
        return result[0], FakeProtocol(result[1], self)
162
171
 
315
324
            RemoteBzrDirFormat.probe_transport, OldServerTransport())
316
325
 
317
326
 
 
327
class TestBzrDirOpenRepository(tests.TestCase):
 
328
 
 
329
    def test_backwards_compat_1_2(self):
 
330
        transport = MemoryTransport()
 
331
        transport.mkdir('quack')
 
332
        transport = transport.clone('quack')
 
333
        client = FakeClient([
 
334
            (('unknown verb', 'RemoteRepository.find_repositoryV2'), ''),
 
335
            (('ok', '', 'no', 'no'), ''),],
 
336
            transport.base)
 
337
        bzrdir = RemoteBzrDir(transport, _client=client)
 
338
        repo = bzrdir.open_repository()
 
339
        self.assertEqual(
 
340
            [('call', 'BzrDir.find_repositoryV2', ('quack/',)),
 
341
             ('call', 'BzrDir.find_repository', ('quack/',))],
 
342
            client._calls)
 
343
 
 
344
 
318
345
class OldSmartClient(object):
319
346
    """A fake smart client for test_old_version that just returns a version one
320
347
    response to the 'hello' (query version) command.
467
494
        branch.unlock()
468
495
 
469
496
 
 
497
class TestBranchSetLastRevisionInfo(tests.TestCase):
 
498
 
 
499
    def test_set_last_revision_info(self):
 
500
        # set_last_revision_info(num, 'rev-id') is translated to calling
 
501
        # Branch.set_last_revision_info(num, 'rev-id') on the wire.
 
502
        transport = MemoryTransport()
 
503
        transport.mkdir('branch')
 
504
        transport = transport.clone('branch')
 
505
        client = FakeClient([
 
506
            # lock_write
 
507
            (('ok', 'branch token', 'repo token'), ),
 
508
            # set_last_revision_info
 
509
            (('ok',), ),
 
510
            # unlock
 
511
            (('ok',), )], transport.base)
 
512
 
 
513
        bzrdir = RemoteBzrDir(transport, _client=False)
 
514
        branch = RemoteBranch(bzrdir, None, _client=client)
 
515
        # This is a hack to work around the problem that RemoteBranch currently
 
516
        # unnecessarily invokes _ensure_real upon a call to lock_write.
 
517
        branch._ensure_real = lambda: None
 
518
        # Lock the branch, reset the record of remote calls.
 
519
        branch.lock_write()
 
520
        client._calls = []
 
521
        result = branch.set_last_revision_info(1234, 'a-revision-id')
 
522
        self.assertEqual(
 
523
            [('call', 'Branch.set_last_revision_info',
 
524
                ('branch/', 'branch token', 'repo token',
 
525
                 '1234', 'a-revision-id'))],
 
526
            client._calls)
 
527
        self.assertEqual(None, result)
 
528
 
 
529
    def test_no_such_revision(self):
 
530
        # A response of 'NoSuchRevision' is translated into an exception.
 
531
        client = FakeClient([
 
532
            # lock_write
 
533
            (('ok', 'branch token', 'repo token'), ),
 
534
            # set_last_revision_info
 
535
            (('NoSuchRevision', 'revid'), ),
 
536
            # unlock
 
537
            (('ok',), ),
 
538
            ])
 
539
        transport = MemoryTransport()
 
540
        transport.mkdir('branch')
 
541
        transport = transport.clone('branch')
 
542
 
 
543
        bzrdir = RemoteBzrDir(transport, _client=False)
 
544
        branch = RemoteBranch(bzrdir, None, _client=client)
 
545
        # This is a hack to work around the problem that RemoteBranch currently
 
546
        # unnecessarily invokes _ensure_real upon a call to lock_write.
 
547
        branch._ensure_real = lambda: None
 
548
        # Lock the branch, reset the record of remote calls.
 
549
        branch.lock_write()
 
550
        client._calls = []
 
551
 
 
552
        self.assertRaises(
 
553
            errors.NoSuchRevision, branch.set_last_revision_info, 123, 'revid')
 
554
        branch.unlock()
 
555
 
 
556
    def lock_remote_branch(self, branch):
 
557
        """Trick a RemoteBranch into thinking it is locked."""
 
558
        branch._lock_mode = 'w'
 
559
        branch._lock_count = 2
 
560
        branch._lock_token = 'branch token'
 
561
        branch._repo_lock_token = 'repo token'
 
562
 
 
563
    def test_backwards_compatibility(self):
 
564
        """If the server does not support the Branch.set_last_revision_info
 
565
        verb (which is new in 1.4), then the client falls back to VFS methods.
 
566
        """
 
567
        # This test is a little messy.  Unlike most tests in this file, it
 
568
        # doesn't purely test what a Remote* object sends over the wire, and
 
569
        # how it reacts to responses from the wire.  It instead relies partly
 
570
        # on asserting that the RemoteBranch will call
 
571
        # self._real_branch.set_last_revision_info(...).
 
572
 
 
573
        # First, set up our RemoteBranch with a FakeClient that raises
 
574
        # UnknownSmartMethod, and a StubRealBranch that logs how it is called.
 
575
        transport = MemoryTransport()
 
576
        transport.mkdir('branch')
 
577
        transport = transport.clone('branch')
 
578
        client = FakeClient(
 
579
            [(('unknown verb', 'Branch.set_last_revision_info',), ),],
 
580
            transport.base)
 
581
        bzrdir = RemoteBzrDir(transport, _client=False)
 
582
        branch = RemoteBranch(bzrdir, None, _client=client)
 
583
        class StubRealBranch(object):
 
584
            def __init__(self):
 
585
                self.calls = []
 
586
            def set_last_revision_info(self, revno, revision_id):
 
587
                self.calls.append(
 
588
                    ('set_last_revision_info', revno, revision_id))
 
589
        real_branch = StubRealBranch()
 
590
        branch._real_branch = real_branch
 
591
        self.lock_remote_branch(branch)
 
592
 
 
593
        # Call set_last_revision_info, and verify it behaved as expected.
 
594
        result = branch.set_last_revision_info(1234, 'a-revision-id')
 
595
        self.assertEqual(
 
596
            [('call', 'Branch.set_last_revision_info',
 
597
                ('branch/', 'branch token', 'repo token',
 
598
                 '1234', 'a-revision-id')),],
 
599
            client._calls)
 
600
        self.assertEqual(
 
601
            [('set_last_revision_info', 1234, 'a-revision-id')],
 
602
            real_branch.calls)
 
603
 
 
604
 
470
605
class TestBranchControlGetBranchConf(tests.TestCaseWithMemoryTransport):
471
606
    """Test branch.control_files api munging...
472
607
 
536
671
        advisory anyway (a transport could be read-write, but then the
537
672
        underlying filesystem could be readonly anyway).
538
673
        """
539
 
        client = FakeClient([(
540
 
            ('error', "Generic bzr smart protocol error: "
541
 
                      "bad request 'Transport.is_readonly'"), '')])
542
 
        transport = RemoteTransport('bzr://example.com/', medium=False,
543
 
                                    _client=client)
544
 
        self.assertEqual(False, transport.is_readonly())
545
 
        self.assertEqual(
546
 
            [('call', 'Transport.is_readonly', ())],
547
 
            client._calls)
548
 
 
549
 
    def test_error_from_old_0_11_server(self):
550
 
        """Same as test_error_from_old_server, but with the slightly different
551
 
        error message from bzr 0.11 servers.
552
 
        """
553
 
        client = FakeClient([(
554
 
            ('error', "Generic bzr smart protocol error: "
555
 
                      "bad request u'Transport.is_readonly'"), '')])
 
674
        client = FakeClient([(('unknown verb', 'Transport.is_readonly'), '')])
556
675
        transport = RemoteTransport('bzr://example.com/', medium=False,
557
676
                                    _client=client)
558
677
        self.assertEqual(False, transport.is_readonly())
704
823
        repo.unlock()
705
824
 
706
825
    def test_get_parent_map_reconnects_if_unknown_method(self):
707
 
        error_msg = (
708
 
            "Generic bzr smart protocol error: "
709
 
            "bad request 'Repository.get_parent_map'")
710
826
        responses = [
711
 
            (('error', error_msg), ''),
 
827
            (('unknown verb', 'Repository.get_parent_map'), ''),
712
828
            (('ok',), '')]
713
829
        transport_path = 'quack'
714
830
        repo, client = self.setup_fake_client_and_repository(
715
831
            responses, transport_path)
716
832
        rev_id = 'revision-id'
717
 
        parents = repo.get_parent_map([rev_id])
 
833
        expected_deprecations = [
 
834
            'bzrlib.remote.RemoteRepository.get_revision_graph was deprecated '
 
835
            'in version 1.4.']
 
836
        parents = self.callDeprecated(
 
837
            expected_deprecations, repo.get_parent_map, [rev_id])
718
838
        self.assertEqual(
719
839
            [('call_with_body_bytes_expecting_body',
720
840
              'Repository.get_parent_map', ('quack/', rev_id), '\n\n0'),
723
843
              ('quack/', ''))],
724
844
            client._calls)
725
845
 
 
846
    def test_get_parent_map_unexpected_response(self):
 
847
        responses = [
 
848
            (('something unexpected!',), '')]
 
849
        repo, client = self.setup_fake_client_and_repository(responses, 'path')
 
850
        self.assertRaises(
 
851
            errors.UnexpectedSmartServerResponse,
 
852
            repo.get_parent_map, ['a-revision-id'])
726
853
 
727
854
 
728
855
class TestRepositoryGetRevisionGraph(TestRemoteRepository):
989
1116
    
990
1117
    def test_backwards_compatibility(self):
991
1118
        """If the server doesn't recognise this request, fallback to VFS."""
992
 
        error_msg = (
993
 
            "Generic bzr smart protocol error: "
994
 
            "bad request 'Repository.stream_revisions_chunked'")
995
1119
        responses = [
996
 
            (('error', error_msg), '')]
 
1120
            (('unknown verb', 'Repository.stream_revisions_chunked'), '')]
997
1121
        repo, client = self.setup_fake_client_and_repository(
998
1122
            responses, 'path')
999
1123
        self.mock_called = False