/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.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
158
class TestBranchSetLastRevision(tests.TestCase):
159
160
    def test_set_empty(self):
161
        # set_revision_history([]) is translated to calling
162
        # Branch.set_last_revision(path, '') on the wire.
163
        client = FakeClient([(('ok',), )])
164
        transport = MemoryTransport()
165
        transport.mkdir('branch')
166
        transport = transport.clone('branch')
167
168
        bzrdir = RemoteBzrDir(transport, _client=False)
169
        branch = RemoteBranch(bzrdir, None, _client=client)
170
171
        result = branch.set_revision_history([])
172
        self.assertEqual(
173
            [('call', 'Branch.set_last_revision', ('///branch/', ''))],
174
            client._calls)
175
        self.assertEqual(None, result)
176
177
    def test_set_nonempty(self):
178
        # set_revision_history([rev-id1, ..., rev-idN]) is translated to calling
179
        # Branch.set_last_revision(path, rev-idN) on the wire.
180
        client = FakeClient([(('ok',), )])
181
        transport = MemoryTransport()
182
        transport.mkdir('branch')
183
        transport = transport.clone('branch')
184
185
        bzrdir = RemoteBzrDir(transport, _client=False)
186
        branch = RemoteBranch(bzrdir, None, _client=client)
187
188
        result = branch.set_revision_history(['rev-id1', 'rev-id2'])
189
        self.assertEqual(
190
            [('call', 'Branch.set_last_revision', ('///branch/', 'rev-id2'))],
191
            client._calls)
192
        self.assertEqual(None, result)
193
194
    def test_no_such_revision(self):
195
        # A response of 'NoSuchRevision' is translated into an exception.
196
        client = FakeClient([(('NoSuchRevision', 'rev-id'), )])
197
        transport = MemoryTransport()
198
        transport.mkdir('branch')
199
        transport = transport.clone('branch')
200
201
        bzrdir = RemoteBzrDir(transport, _client=False)
202
        branch = RemoteBranch(bzrdir, None, _client=client)
203
204
        self.assertRaises(
205
            NoSuchRevision, branch.set_revision_history, ['rev-id'])
206
207
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
208
class TestBranchControlGetBranchConf(tests.TestCase):
209
    """Test branch.control_files api munging...
210
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
211
    we special case RemoteBranch.control_files.get('branch.conf') to
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
212
    call a specific API so that RemoteBranch's can intercept configuration
213
    file reading, allowing them to signal to the client about things like
214
    'email is configured for commits'.
215
    """
216
217
    def test_get_branch_conf(self):
218
        # in an empty branch we decode the response properly
219
        client = FakeClient([(('ok', ), 'config file body')])
220
        transport = MemoryTransport()
221
        transport.mkdir('quack')
222
        transport = transport.clone('quack')
223
        # we do not want bzrdir to make any remote calls
224
        bzrdir = RemoteBzrDir(transport, _client=False)
225
        branch = RemoteBranch(bzrdir, None, _client=client)
226
        result = branch.control_files.get('branch.conf')
227
        self.assertEqual(
228
            [('call2', 'Branch.get_config_file', ('///quack/',))],
229
            client._calls)
230
        self.assertEqual('config file body', result.read())
231
232
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
233
class TestRemoteRepository(tests.TestCase):
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
234
235
    def setup_fake_client_and_repository(self, responses, transport_path):
236
        """Create the fake client and repository for testing with."""
237
        client = FakeClient(responses)
238
        transport = MemoryTransport()
239
        transport.mkdir(transport_path)
240
        transport = transport.clone(transport_path)
241
        # we do not want bzrdir to make any remote calls
242
        bzrdir = RemoteBzrDir(transport, _client=False)
243
        repo = RemoteRepository(bzrdir, None, _client=client)
244
        return repo, client
245
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
246
2018.12.2 by Andrew Bennetts
Remove some duplicate code in test_remote
247
class TestRepositoryGatherStats(TestRemoteRepository):
2018.10.3 by v.ladeuil+lp at free
more tests for gather_stats
248
249
    def test_revid_none(self):
250
        # ('ok',), body with revisions and size
251
        responses = [(('ok', ), 'revisions: 2\nsize: 18\n')]
252
        transport_path = 'quack'
253
        repo, client = self.setup_fake_client_and_repository(
254
            responses, transport_path)
255
        result = repo.gather_stats(None)
256
        self.assertEqual(
257
            [('call2', 'Repository.gather_stats', ('///quack/','','no'))],
258
            client._calls)
259
        self.assertEqual({'revisions': 2, 'size': 18}, result)
260
261
    def test_revid_no_committers(self):
262
        # ('ok',), body without committers
263
        responses = [(('ok', ),
264
                      'firstrev: 123456.300 3600\n'
265
                      'latestrev: 654231.400 0\n'
266
                      'revisions: 2\n'
267
                      'size: 18\n')]
268
        transport_path = 'quick'
269
        revid = u'\xc8'
270
        repo, client = self.setup_fake_client_and_repository(
271
            responses, transport_path)
272
        result = repo.gather_stats(revid)
273
        self.assertEqual(
274
            [('call2', 'Repository.gather_stats',
275
              ('///quick/', revid.encode('utf8'), 'no'))],
276
            client._calls)
277
        self.assertEqual({'revisions': 2, 'size': 18,
278
                          'firstrev': (123456.300, 3600),
279
                          'latestrev': (654231.400, 0),},
280
                         result)
281
282
    def test_revid_with_committers(self):
283
        # ('ok',), body with committers
284
        responses = [(('ok', ),
285
                      'committers: 128\n'
286
                      'firstrev: 123456.300 3600\n'
287
                      'latestrev: 654231.400 0\n'
288
                      'revisions: 2\n'
289
                      'size: 18\n')]
290
        transport_path = 'buick'
291
        revid = u'\xc8'
292
        repo, client = self.setup_fake_client_and_repository(
293
            responses, transport_path)
294
        result = repo.gather_stats(revid, True)
295
        self.assertEqual(
296
            [('call2', 'Repository.gather_stats',
297
              ('///buick/', revid.encode('utf8'), 'yes'))],
298
            client._calls)
299
        self.assertEqual({'revisions': 2, 'size': 18,
300
                          'committers': 128,
301
                          'firstrev': (123456.300, 3600),
302
                          'latestrev': (654231.400, 0),},
303
                         result)
304
305
2018.5.68 by Wouter van Heyst
Merge RemoteRepository.gather_stats.
306
class TestRepositoryGetRevisionGraph(TestRemoteRepository):
307
    
308
    def test_null_revision(self):
309
        # a null revision has the predictable result {}, we should have no wire
310
        # traffic when calling it with this argument
311
        responses = [(('notused', ), '')]
312
        transport_path = 'empty'
313
        repo, client = self.setup_fake_client_and_repository(
314
            responses, transport_path)
315
        result = repo.get_revision_graph(NULL_REVISION)
316
        self.assertEqual([], client._calls)
317
        self.assertEqual({}, result)
318
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
319
    def test_none_revision(self):
320
        # with none we want the entire graph
321
        r1 = u'\u0e33'
322
        r2 = u'\u0dab'
323
        lines = [' '.join([r2, r1]), r1]
324
        encoded_body = '\n'.join(lines).encode('utf8')
325
326
        responses = [(('ok', ), encoded_body)]
327
        transport_path = 'sinhala'
328
        repo, client = self.setup_fake_client_and_repository(
329
            responses, transport_path)
330
        result = repo.get_revision_graph()
331
        self.assertEqual(
332
            [('call2', 'Repository.get_revision_graph', ('///sinhala/', ''))],
333
            client._calls)
334
        self.assertEqual({r1: [], r2: [r1]}, result)
335
336
    def test_specific_revision(self):
337
        # with a specific revision we want the graph for that
338
        # with none we want the entire graph
339
        r11 = u'\u0e33'
340
        r12 = u'\xc9'
341
        r2 = u'\u0dab'
342
        lines = [' '.join([r2, r11, r12]), r11, r12]
343
        encoded_body = '\n'.join(lines).encode('utf8')
344
345
        responses = [(('ok', ), encoded_body)]
346
        transport_path = 'sinhala'
347
        repo, client = self.setup_fake_client_and_repository(
348
            responses, transport_path)
349
        result = repo.get_revision_graph(r2)
350
        self.assertEqual(
351
            [('call2', 'Repository.get_revision_graph', ('///sinhala/', r2.encode('utf8')))],
352
            client._calls)
353
        self.assertEqual({r11: [], r12: [], r2: [r11, r12], }, result)
354
355
    def test_no_such_revision(self):
356
        revid = '123'
357
        responses = [(('nosuchrevision', revid), '')]
358
        transport_path = 'sinhala'
359
        repo, client = self.setup_fake_client_and_repository(
360
            responses, transport_path)
361
        # also check that the right revision is reported in the error
362
        self.assertRaises(NoSuchRevision,
363
            repo.get_revision_graph, revid)
364
        self.assertEqual(
365
            [('call2', 'Repository.get_revision_graph', ('///sinhala/', revid))],
366
            client._calls)
367
368
        
369
class TestRepositoryIsShared(TestRemoteRepository):
370
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
371
    def test_is_shared(self):
372
        # ('yes', ) for Repository.is_shared -> 'True'.
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
373
        responses = [(('yes', ), )]
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
374
        transport_path = 'quack'
375
        repo, client = self.setup_fake_client_and_repository(
376
            responses, transport_path)
377
        result = repo.is_shared()
378
        self.assertEqual(
379
            [('call', 'Repository.is_shared', ('///quack/',))],
380
            client._calls)
381
        self.assertEqual(True, result)
382
383
    def test_is_not_shared(self):
384
        # ('no', ) for Repository.is_shared -> 'False'.
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
385
        responses = [(('no', ), )]
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
386
        transport_path = 'qwack'
387
        repo, client = self.setup_fake_client_and_repository(
388
            responses, transport_path)
389
        result = repo.is_shared()
390
        self.assertEqual(
391
            [('call', 'Repository.is_shared', ('///qwack/',))],
392
            client._calls)
393
        self.assertEqual(False, result)