/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
1
# Copyright (C) 2006, 2007 Canonical Ltd
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Tests for remote bzrdir/branch/repo/etc
18
19
These are proxy objects which act on remote objects by sending messages
20
through a smart client.  The proxies are to be created when attempting to open
21
the object given a transport that supports smartserver rpc operations. 
22
"""
23
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
24
from cStringIO import StringIO
25
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
26
from bzrlib import bzrdir, remote, tests
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
27
from bzrlib.branch import Branch
28
from bzrlib.bzrdir import BzrDir, BzrDirFormat
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
29
from bzrlib.errors import NoSuchRevision
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
30
from bzrlib.remote import (
31
    RemoteBranch,
32
    RemoteBzrDir,
33
    RemoteBzrDirFormat,
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
34
    RemoteRepository,
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
35
    )
36
from bzrlib.revision import NULL_REVISION
37
from bzrlib.smart import server
38
from bzrlib.smart.client import SmartClient
2018.5.20 by Andrew Bennetts
Move bzrlib/transport/smart/_smart.py to bzrlib/transport/remote.py and rename SmartTransport to RemoteTransport (Robert Collins, Andrew Bennetts)
39
from bzrlib.transport import remote as remote_transport
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
40
from bzrlib.transport.memory import MemoryTransport
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
41
2018.5.24 by Andrew Bennetts
Setting NO_SMART_VFS in environment will disable VFS methods in the smart server. (Robert Collins, John Arbash Meinel, Andrew Bennetts)
42
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
43
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
44
45
    def setUp(self):
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
46
        super(BasicRemoteObjectTests, self).setUp()
47
        self.transport_server = server.SmartTCPServer_for_testing
48
        self.transport = self.get_transport()
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
49
        self.client = self.transport.get_smart_client()
50
        # make a branch that can be opened over the smart transport
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
51
        self.local_wt = BzrDir.create_standalone_workingtree('.')
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
52
53
    def test_create_remote_bzrdir(self):
54
        b = remote.RemoteBzrDir(self.transport)
55
        self.assertIsInstance(b, BzrDir)
56
57
    def test_open_remote_branch(self):
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
58
        # open a standalone branch in the working directory
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
59
        b = remote.RemoteBzrDir(self.transport)
60
        branch = b.open_branch()
61
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
62
    def test_remote_repository(self):
63
        b = BzrDir.open_from_transport(self.transport)
64
        repo = b.open_repository()
2018.5.40 by Robert Collins
Implement a remote Repository.has_revision method.
65
        revid = u'\xc823123123'
66
        self.assertFalse(repo.has_revision(revid))
67
        self.local_wt.commit(message='test commit', rev_id=revid)
68
        self.assertTrue(repo.has_revision(revid))
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
69
70
    def test_remote_branch_revision_history(self):
71
        b = BzrDir.open_from_transport(self.transport).open_branch()
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
72
        self.assertEqual([], b.revision_history())
73
        r1 = self.local_wt.commit('1st commit')
74
        r2 = self.local_wt.commit('1st commit', rev_id=u'\xc8')
75
        self.assertEqual([r1, r2], b.revision_history())
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
76
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
77
    def test_find_correct_format(self):
2018.5.20 by Andrew Bennetts
Move bzrlib/transport/smart/_smart.py to bzrlib/transport/remote.py and rename SmartTransport to RemoteTransport (Robert Collins, Andrew Bennetts)
78
        """Should open a RemoteBzrDir over a RemoteTransport"""
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
79
        fmt = BzrDirFormat.find_format(self.transport)
2018.5.25 by Andrew Bennetts
Make sure RemoteBzrDirFormat is always registered (John Arbash Meinel, Robert Collins, Andrew Bennetts).
80
        self.assertTrue(RemoteBzrDirFormat in BzrDirFormat._control_formats)
1752.2.30 by Martin Pool
Start adding a RemoteBzrDir, etc
81
        self.assertIsInstance(fmt, remote.RemoteBzrDirFormat)
82
83
    def test_open_detected_smart_format(self):
84
        fmt = BzrDirFormat.find_format(self.transport)
85
        d = fmt.open(self.transport)
86
        self.assertIsInstance(d, BzrDir)
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
87
88
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
89
class FakeProtocol(object):
90
    """Lookalike SmartClientRequestProtocolOne allowing body reading tests."""
91
92
    def __init__(self, body):
93
        self._body_buffer = StringIO(body)
94
95
    def read_body_bytes(self, count=-1):
96
        return self._body_buffer.read(count)
97
98
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
99
class FakeClient(SmartClient):
100
    """Lookalike for SmartClient allowing testing."""
101
    
102
    def __init__(self, responses):
103
        # We don't call the super init because there is no medium.
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
104
        """create a FakeClient.
105
106
        :param respones: A list of response-tuple, body-data pairs to be sent
107
            back to callers.
108
        """
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
109
        self.responses = responses
110
        self._calls = []
111
112
    def call(self, method, *args):
113
        self._calls.append(('call', method, args))
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
114
        return self.responses.pop(0)[0]
115
116
    def call2(self, method, *args):
117
        self._calls.append(('call2', method, args))
118
        result = self.responses.pop(0)
119
        return result[0], FakeProtocol(result[1])
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
120
121
122
class TestBranchLastRevisionInfo(tests.TestCase):
123
124
    def test_empty_branch(self):
125
        # in an empty branch we decode the response properly
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
126
        client = FakeClient([(('ok', '0', ''), )])
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
127
        transport = MemoryTransport()
128
        transport.mkdir('quack')
129
        transport = transport.clone('quack')
130
        # we do not want bzrdir to make any remote calls
131
        bzrdir = RemoteBzrDir(transport, _client=False)
132
        branch = RemoteBranch(bzrdir, None, _client=client)
133
        result = branch.last_revision_info()
134
135
        self.assertEqual(
136
            [('call', 'Branch.last_revision_info', ('///quack/',))],
137
            client._calls)
138
        self.assertEqual((0, NULL_REVISION), result)
139
140
    def test_non_empty_branch(self):
141
        # in a non-empty branch we also decode the response properly
142
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
143
        client = FakeClient([(('ok', '2', u'\xc8'.encode('utf8')), )])
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
144
        transport = MemoryTransport()
145
        transport.mkdir('kwaak')
146
        transport = transport.clone('kwaak')
147
        # we do not want bzrdir to make any remote calls
148
        bzrdir = RemoteBzrDir(transport, _client=False)
149
        branch = RemoteBranch(bzrdir, None, _client=client)
150
        result = branch.last_revision_info()
151
152
        self.assertEqual(
153
            [('call', 'Branch.last_revision_info', ('///kwaak/',))],
154
            client._calls)
155
        self.assertEqual((2, u'\xc8'), result)
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
156
157
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
158
class TestBranchControlGetBranchConf(tests.TestCase):
159
    """Test branch.control_files api munging...
160
161
    we special case RemoteBranch.control_files.get('branch.conf') to 
162
    call a specific API so that RemoteBranch's can intercept configuration
163
    file reading, allowing them to signal to the client about things like
164
    'email is configured for commits'.
165
    """
166
167
    def test_get_branch_conf(self):
168
        # in an empty branch we decode the response properly
169
        client = FakeClient([(('ok', ), 'config file body')])
170
        transport = MemoryTransport()
171
        transport.mkdir('quack')
172
        transport = transport.clone('quack')
173
        # we do not want bzrdir to make any remote calls
174
        bzrdir = RemoteBzrDir(transport, _client=False)
175
        branch = RemoteBranch(bzrdir, None, _client=client)
176
        result = branch.control_files.get('branch.conf')
177
        self.assertEqual(
178
            [('call2', 'Branch.get_config_file', ('///quack/',))],
179
            client._calls)
180
        self.assertEqual('config file body', result.read())
181
182
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
183
class TestRemoteRepository(tests.TestCase):
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
184
185
    def setup_fake_client_and_repository(self, responses, transport_path):
186
        """Create the fake client and repository for testing with."""
187
        client = FakeClient(responses)
188
        transport = MemoryTransport()
189
        transport.mkdir(transport_path)
190
        transport = transport.clone(transport_path)
191
        # we do not want bzrdir to make any remote calls
192
        bzrdir = RemoteBzrDir(transport, _client=False)
193
        repo = RemoteRepository(bzrdir, None, _client=client)
194
        return repo, client
195
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
196
2018.12.2 by Andrew Bennetts
Remove some duplicate code in test_remote
197
class TestRepositoryGatherStats(TestRemoteRepository):
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
198
199
    def test_revid_none(self):
200
        # ('ok',), body with revisions and size
201
        responses = [(('ok', ), 'revisions: 2\nsize: 18\n')]
202
        transport_path = 'quack'
203
        repo, client = self.setup_fake_client_and_repository(
204
            responses, transport_path)
205
        result = repo.gather_stats(None)
206
        self.assertEqual(
207
            [('call2', 'Repository.gather_stats', ('///quack/','','no'))],
208
            client._calls)
209
        self.assertEqual({'revisions': 2, 'size': 18}, result)
210
211
    def test_revid_no_committers(self):
212
        # ('ok',), body without committers
213
        responses = [(('ok', ),
214
                      'firstrev: 123456.300 3600\n'
215
                      'latestrev: 654231.400 0\n'
216
                      'revisions: 2\n'
217
                      'size: 18\n')]
218
        transport_path = 'quick'
219
        revid = u'\xc8'
220
        repo, client = self.setup_fake_client_and_repository(
221
            responses, transport_path)
222
        result = repo.gather_stats(revid)
223
        self.assertEqual(
224
            [('call2', 'Repository.gather_stats',
225
              ('///quick/', revid.encode('utf8'), 'no'))],
226
            client._calls)
227
        self.assertEqual({'revisions': 2, 'size': 18,
228
                          'firstrev': (123456.300, 3600),
229
                          'latestrev': (654231.400, 0),},
230
                         result)
231
232
    def test_revid_with_committers(self):
233
        # ('ok',), body with committers
234
        responses = [(('ok', ),
235
                      'committers: 128\n'
236
                      'firstrev: 123456.300 3600\n'
237
                      'latestrev: 654231.400 0\n'
238
                      'revisions: 2\n'
239
                      'size: 18\n')]
240
        transport_path = 'buick'
241
        revid = u'\xc8'
242
        repo, client = self.setup_fake_client_and_repository(
243
            responses, transport_path)
244
        result = repo.gather_stats(revid, True)
245
        self.assertEqual(
246
            [('call2', 'Repository.gather_stats',
247
              ('///buick/', revid.encode('utf8'), 'yes'))],
248
            client._calls)
249
        self.assertEqual({'revisions': 2, 'size': 18,
250
                          'committers': 128,
251
                          'firstrev': (123456.300, 3600),
252
                          'latestrev': (654231.400, 0),},
253
                         result)
254
255
2018.5.68 by Wouter van Heyst
Merge RemoteRepository.gather_stats.
256
class TestRepositoryGetRevisionGraph(TestRemoteRepository):
257
    
258
    def test_null_revision(self):
259
        # a null revision has the predictable result {}, we should have no wire
260
        # traffic when calling it with this argument
261
        responses = [(('notused', ), '')]
262
        transport_path = 'empty'
263
        repo, client = self.setup_fake_client_and_repository(
264
            responses, transport_path)
265
        result = repo.get_revision_graph(NULL_REVISION)
266
        self.assertEqual([], client._calls)
267
        self.assertEqual({}, result)
268
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
269
    def test_none_revision(self):
270
        # with none we want the entire graph
271
        r1 = u'\u0e33'
272
        r2 = u'\u0dab'
273
        lines = [' '.join([r2, r1]), r1]
274
        encoded_body = '\n'.join(lines).encode('utf8')
275
276
        responses = [(('ok', ), encoded_body)]
277
        transport_path = 'sinhala'
278
        repo, client = self.setup_fake_client_and_repository(
279
            responses, transport_path)
280
        result = repo.get_revision_graph()
281
        self.assertEqual(
282
            [('call2', 'Repository.get_revision_graph', ('///sinhala/', ''))],
283
            client._calls)
284
        self.assertEqual({r1: [], r2: [r1]}, result)
285
286
    def test_specific_revision(self):
287
        # with a specific revision we want the graph for that
288
        # with none we want the entire graph
289
        r11 = u'\u0e33'
290
        r12 = u'\xc9'
291
        r2 = u'\u0dab'
292
        lines = [' '.join([r2, r11, r12]), r11, r12]
293
        encoded_body = '\n'.join(lines).encode('utf8')
294
295
        responses = [(('ok', ), encoded_body)]
296
        transport_path = 'sinhala'
297
        repo, client = self.setup_fake_client_and_repository(
298
            responses, transport_path)
299
        result = repo.get_revision_graph(r2)
300
        self.assertEqual(
301
            [('call2', 'Repository.get_revision_graph', ('///sinhala/', r2.encode('utf8')))],
302
            client._calls)
303
        self.assertEqual({r11: [], r12: [], r2: [r11, r12], }, result)
304
305
    def test_no_such_revision(self):
306
        revid = '123'
307
        responses = [(('nosuchrevision', revid), '')]
308
        transport_path = 'sinhala'
309
        repo, client = self.setup_fake_client_and_repository(
310
            responses, transport_path)
311
        # also check that the right revision is reported in the error
312
        self.assertRaises(NoSuchRevision,
313
            repo.get_revision_graph, revid)
314
        self.assertEqual(
315
            [('call2', 'Repository.get_revision_graph', ('///sinhala/', revid))],
316
            client._calls)
317
318
        
319
class TestRepositoryIsShared(TestRemoteRepository):
320
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
321
    def test_is_shared(self):
322
        # ('yes', ) for Repository.is_shared -> 'True'.
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
323
        responses = [(('yes', ), )]
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
324
        transport_path = 'quack'
325
        repo, client = self.setup_fake_client_and_repository(
326
            responses, transport_path)
327
        result = repo.is_shared()
328
        self.assertEqual(
329
            [('call', 'Repository.is_shared', ('///quack/',))],
330
            client._calls)
331
        self.assertEqual(True, result)
332
333
    def test_is_not_shared(self):
334
        # ('no', ) for Repository.is_shared -> 'False'.
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
335
        responses = [(('no', ), )]
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
336
        transport_path = 'qwack'
337
        repo, client = self.setup_fake_client_and_repository(
338
            responses, transport_path)
339
        result = repo.is_shared()
340
        self.assertEqual(
341
            [('call', 'Repository.is_shared', ('///qwack/',))],
342
            client._calls)
343
        self.assertEqual(False, result)