/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2018.18.1 by Martin Pool
Add stub Repository.tarball smart method
1
# Copyright (C) 2006, 2007 Canonical Ltd
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
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
2621.3.1 by Andrew Bennetts
Log errors from the smart server in the trace file, to make debugging test failures (and live failures!) easier.
17
"""Tests for the smart wire/domain protocol."""
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
18
2018.18.2 by Martin Pool
smart method Repository.tarball actually returns the tarball
19
from StringIO import StringIO
20
import tempfile
21
import tarfile
22
2535.3.31 by Andrew Bennetts
Fix imports broken by reverting the container-format merge. I didn't notice them earlier because of .pyc files :(
23
from bzrlib import bzrdir, errors, pack, smart, tests
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
24
from bzrlib.smart.request import SmartServerResponse
25
import bzrlib.smart.bzrdir
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
26
import bzrlib.smart.branch
2018.5.40 by Robert Collins
Implement a remote Repository.has_revision method.
27
import bzrlib.smart.repository
2535.3.15 by Andrew Bennetts
Add KnitVersionedFile.get_stream_as_bytes, start smart implementation of RemoteRepository.get_data_stream.
28
from bzrlib.util import bencode
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
29
30
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
31
class TestCaseWithSmartMedium(tests.TestCaseWithTransport):
32
33
    def setUp(self):
34
        super(TestCaseWithSmartMedium, self).setUp()
35
        # We're allowed to set  the transport class here, so that we don't use
36
        # the default or a parameterized class, but rather use the
37
        # TestCaseWithTransport infrastructure to set up a smart server and
38
        # transport.
39
        self.transport_server = smart.server.SmartTCPServer_for_testing
40
41
    def get_smart_medium(self):
42
        """Get a smart medium to use in tests."""
43
        return self.get_transport().get_smart_medium()
44
45
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
46
class TestSmartServerResponse(tests.TestCase):
47
48
    def test__eq__(self):
49
        self.assertEqual(SmartServerResponse(('ok', )),
50
            SmartServerResponse(('ok', )))
51
        self.assertEqual(SmartServerResponse(('ok', ), 'body'),
52
            SmartServerResponse(('ok', ), 'body'))
53
        self.assertNotEqual(SmartServerResponse(('ok', )),
54
            SmartServerResponse(('notok', )))
55
        self.assertNotEqual(SmartServerResponse(('ok', ), 'body'),
56
            SmartServerResponse(('ok', )))
2018.5.41 by Robert Collins
Fix SmartServerResponse.__eq__ to handle None.
57
        self.assertNotEqual(None,
58
            SmartServerResponse(('ok', )))
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
59
60
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
61
class TestSmartServerRequestFindRepository(tests.TestCaseWithTransport):
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
62
    """Tests for BzrDir.find_repository."""
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
63
64
    def test_no_repository(self):
65
        """When there is no repository to be found, ('norepository', ) is returned."""
66
        backing = self.get_transport()
67
        request = smart.bzrdir.SmartServerRequestFindRepository(backing)
68
        self.make_bzrdir('.')
69
        self.assertEqual(SmartServerResponse(('norepository', )),
70
            request.execute(backing.local_abspath('')))
71
72
    def test_nonshared_repository(self):
73
        # nonshared repositorys only allow 'find' to return a handle when the 
74
        # path the repository is being searched on is the same as that that 
75
        # the repository is at.
76
        backing = self.get_transport()
77
        request = smart.bzrdir.SmartServerRequestFindRepository(backing)
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
78
        result = self._make_repository_and_result()
79
        self.assertEqual(result, request.execute(backing.local_abspath('')))
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
80
        self.make_bzrdir('subdir')
81
        self.assertEqual(SmartServerResponse(('norepository', )),
82
            request.execute(backing.local_abspath('subdir')))
83
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
84
    def _make_repository_and_result(self, shared=False, format=None):
85
        """Convenience function to setup a repository.
86
87
        :result: The SmartServerResponse to expect when opening it.
88
        """
89
        repo = self.make_repository('.', shared=shared, format=format)
90
        if repo.supports_rich_root():
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
91
            rich_root = 'yes'
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
92
        else:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
93
            rich_root = 'no'
2018.5.138 by Robert Collins
Merge bzr.dev.
94
        if repo._format.supports_tree_reference:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
95
            subtrees = 'yes'
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
96
        else:
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
97
            subtrees = 'no'
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
98
        return SmartServerResponse(('ok', '', rich_root, subtrees))
99
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
100
    def test_shared_repository(self):
101
        """When there is a shared repository, we get 'ok', 'relpath-to-repo'."""
102
        backing = self.get_transport()
103
        request = smart.bzrdir.SmartServerRequestFindRepository(backing)
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
104
        result = self._make_repository_and_result(shared=True)
105
        self.assertEqual(result, request.execute(backing.local_abspath('')))
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
106
        self.make_bzrdir('subdir')
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
107
        result2 = SmartServerResponse(result.args[0:1] + ('..', ) + result.args[2:])
108
        self.assertEqual(result2,
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
109
            request.execute(backing.local_abspath('subdir')))
110
        self.make_bzrdir('subdir/deeper')
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
111
        result3 = SmartServerResponse(result.args[0:1] + ('../..', ) + result.args[2:])
112
        self.assertEqual(result3,
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
113
            request.execute(backing.local_abspath('subdir/deeper')))
114
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
115
    def test_rich_root_and_subtree_encoding(self):
116
        """Test for the format attributes for rich root and subtree support."""
117
        backing = self.get_transport()
118
        request = smart.bzrdir.SmartServerRequestFindRepository(backing)
119
        result = self._make_repository_and_result(format='dirstate-with-subtree')
120
        # check the test will be valid
2018.5.166 by Andrew Bennetts
Small changes in response to Aaron's review.
121
        self.assertEqual('yes', result.args[2])
122
        self.assertEqual('yes', result.args[3])
2018.5.118 by Robert Collins
Fix RemoteRepositoryFormat to have appropriate rich_root_data and support_tree_reference.
123
        self.assertEqual(result, request.execute(backing.local_abspath('')))
124
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
125
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
126
class TestSmartServerRequestInitializeBzrDir(tests.TestCaseWithTransport):
127
128
    def test_empty_dir(self):
129
        """Initializing an empty dir should succeed and do it."""
130
        backing = self.get_transport()
131
        request = smart.bzrdir.SmartServerRequestInitializeBzrDir(backing)
132
        self.assertEqual(SmartServerResponse(('ok', )),
133
            request.execute(backing.local_abspath('.')))
134
        made_dir = bzrdir.BzrDir.open_from_transport(backing)
135
        # no branch, tree or repository is expected with the current 
136
        # default formart.
137
        self.assertRaises(errors.NoWorkingTree, made_dir.open_workingtree)
138
        self.assertRaises(errors.NotBranchError, made_dir.open_branch)
139
        self.assertRaises(errors.NoRepositoryPresent, made_dir.open_repository)
140
141
    def test_missing_dir(self):
142
        """Initializing a missing directory should fail like the bzrdir api."""
143
        backing = self.get_transport()
144
        request = smart.bzrdir.SmartServerRequestInitializeBzrDir(backing)
145
        self.assertRaises(errors.NoSuchFile,
146
            request.execute, backing.local_abspath('subdir'))
147
148
    def test_initialized_dir(self):
149
        """Initializing an extant bzrdir should fail like the bzrdir api."""
150
        backing = self.get_transport()
151
        request = smart.bzrdir.SmartServerRequestInitializeBzrDir(backing)
152
        self.make_bzrdir('subdir')
153
        self.assertRaises(errors.FileExists,
154
            request.execute, backing.local_abspath('subdir'))
155
156
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
157
class TestSmartServerRequestOpenBranch(tests.TestCaseWithTransport):
158
159
    def test_no_branch(self):
160
        """When there is no branch, ('nobranch', ) is returned."""
161
        backing = self.get_transport()
162
        request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
163
        self.make_bzrdir('.')
164
        self.assertEqual(SmartServerResponse(('nobranch', )),
165
            request.execute(backing.local_abspath('')))
166
167
    def test_branch(self):
168
        """When there is a branch, 'ok' is returned."""
169
        backing = self.get_transport()
170
        request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
171
        self.make_branch('.')
172
        self.assertEqual(SmartServerResponse(('ok', '')),
173
            request.execute(backing.local_abspath('')))
174
175
    def test_branch_reference(self):
176
        """When there is a branch reference, the reference URL is returned."""
177
        backing = self.get_transport()
178
        request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
179
        branch = self.make_branch('branch')
180
        checkout = branch.create_checkout('reference',lightweight=True)
181
        # TODO: once we have an API to probe for references of any sort, we
182
        # can use it here.
183
        reference_url = backing.abspath('branch') + '/'
184
        self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
185
        self.assertEqual(SmartServerResponse(('ok', reference_url)),
186
            request.execute(backing.local_abspath('reference')))
187
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
188
189
class TestSmartServerRequestRevisionHistory(tests.TestCaseWithTransport):
190
191
    def test_empty(self):
192
        """For an empty branch, the body is empty."""
193
        backing = self.get_transport()
194
        request = smart.branch.SmartServerRequestRevisionHistory(backing)
195
        self.make_branch('.')
196
        self.assertEqual(SmartServerResponse(('ok', ), ''),
197
            request.execute(backing.local_abspath('')))
198
199
    def test_not_empty(self):
200
        """For a non-empty branch, the body is empty."""
201
        backing = self.get_transport()
202
        request = smart.branch.SmartServerRequestRevisionHistory(backing)
203
        tree = self.make_branch_and_memory_tree('.')
204
        tree.lock_write()
205
        tree.add('')
206
        r1 = tree.commit('1st commit')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
207
        r2 = tree.commit('2nd commit', rev_id=u'\xc8'.encode('utf-8'))
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
208
        tree.unlock()
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
209
        self.assertEqual(
210
            SmartServerResponse(('ok', ), ('\x00'.join([r1, r2]))),
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
211
            request.execute(backing.local_abspath('')))
212
2018.5.49 by Wouter van Heyst
Refactor SmartServerBranchRequest out from SmartServerRequestRevisionHistory to
213
214
class TestSmartServerBranchRequest(tests.TestCaseWithTransport):
215
216
    def test_no_branch(self):
217
        """When there is a bzrdir and no branch, NotBranchError is raised."""
218
        backing = self.get_transport()
219
        request = smart.branch.SmartServerBranchRequest(backing)
220
        self.make_bzrdir('.')
221
        self.assertRaises(errors.NotBranchError,
222
            request.execute, backing.local_abspath(''))
223
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
224
    def test_branch_reference(self):
225
        """When there is a branch reference, NotBranchError is raised."""
226
        backing = self.get_transport()
2018.5.49 by Wouter van Heyst
Refactor SmartServerBranchRequest out from SmartServerRequestRevisionHistory to
227
        request = smart.branch.SmartServerBranchRequest(backing)
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
228
        branch = self.make_branch('branch')
229
        checkout = branch.create_checkout('reference',lightweight=True)
230
        self.assertRaises(errors.NotBranchError,
231
            request.execute, backing.local_abspath('checkout'))
232
233
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
234
class TestSmartServerBranchRequestLastRevisionInfo(tests.TestCaseWithTransport):
235
236
    def test_empty(self):
2018.5.170 by Andrew Bennetts
Use 'null:' instead of '' to mean NULL_REVISION on the wire.
237
        """For an empty branch, the result is ('ok', '0', 'null:')."""
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
238
        backing = self.get_transport()
239
        request = smart.branch.SmartServerBranchRequestLastRevisionInfo(backing)
240
        self.make_branch('.')
2018.5.170 by Andrew Bennetts
Use 'null:' instead of '' to mean NULL_REVISION on the wire.
241
        self.assertEqual(SmartServerResponse(('ok', '0', 'null:')),
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
242
            request.execute(backing.local_abspath('')))
243
244
    def test_not_empty(self):
245
        """For a non-empty branch, the result is ('ok', 'revno', 'revid')."""
246
        backing = self.get_transport()
247
        request = smart.branch.SmartServerBranchRequestLastRevisionInfo(backing)
248
        tree = self.make_branch_and_memory_tree('.')
249
        tree.lock_write()
250
        tree.add('')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
251
        rev_id_utf8 = u'\xc8'.encode('utf-8')
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
252
        r1 = tree.commit('1st commit')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
253
        r2 = tree.commit('2nd commit', rev_id=rev_id_utf8)
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
254
        tree.unlock()
255
        self.assertEqual(
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
256
            SmartServerResponse(('ok', '2', rev_id_utf8)),
2018.5.50 by Wouter van Heyst
Add SmartServerBranchRequestLastRevisionInfo method.
257
            request.execute(backing.local_abspath('')))
258
259
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
260
class TestSmartServerBranchRequestGetConfigFile(tests.TestCaseWithTransport):
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
261
262
    def test_default(self):
263
        """With no file, we get empty content."""
264
        backing = self.get_transport()
265
        request = smart.branch.SmartServerBranchGetConfigFile(backing)
266
        branch = self.make_branch('.')
267
        # there should be no file by default
268
        content = ''
269
        self.assertEqual(SmartServerResponse(('ok', ), content),
270
            request.execute(backing.local_abspath('')))
271
272
    def test_with_content(self):
273
        # SmartServerBranchGetConfigFile should return the content from
274
        # branch.control_files.get('branch.conf') for now - in the future it may
275
        # perform more complex processing. 
276
        backing = self.get_transport()
277
        request = smart.branch.SmartServerBranchGetConfigFile(backing)
278
        branch = self.make_branch('.')
279
        branch.control_files.put_utf8('branch.conf', 'foo bar baz')
280
        self.assertEqual(SmartServerResponse(('ok', ), 'foo bar baz'),
281
            request.execute(backing.local_abspath('')))
282
283
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
284
class TestSmartServerBranchRequestSetLastRevision(tests.TestCaseWithTransport):
285
286
    def test_empty(self):
287
        backing = self.get_transport()
288
        request = smart.branch.SmartServerBranchRequestSetLastRevision(backing)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
289
        b = self.make_branch('.')
2018.5.144 by Andrew Bennetts
Fix four tests I broke with the Branch.lock_write changes.
290
        branch_token = b.lock_write()
291
        repo_token = b.repository.lock_write()
292
        b.repository.unlock()
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
293
        try:
294
            self.assertEqual(SmartServerResponse(('ok',)),
295
                request.execute(
2018.5.170 by Andrew Bennetts
Use 'null:' instead of '' to mean NULL_REVISION on the wire.
296
                    backing.local_abspath(''), branch_token, repo_token,
297
                    'null:'))
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
298
        finally:
299
            b.unlock()
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
300
301
    def test_not_present_revision_id(self):
302
        backing = self.get_transport()
303
        request = smart.branch.SmartServerBranchRequestSetLastRevision(backing)
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
304
        b = self.make_branch('.')
2018.5.144 by Andrew Bennetts
Fix four tests I broke with the Branch.lock_write changes.
305
        branch_token = b.lock_write()
306
        repo_token = b.repository.lock_write()
307
        b.repository.unlock()
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
308
        try:
309
            revision_id = 'non-existent revision'
310
            self.assertEqual(
311
                SmartServerResponse(('NoSuchRevision', revision_id)),
312
                request.execute(
313
                    backing.local_abspath(''), branch_token, repo_token,
314
                    revision_id))
315
        finally:
316
            b.unlock()
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
317
318
    def test_revision_id_present(self):
319
        backing = self.get_transport()
320
        request = smart.branch.SmartServerBranchRequestSetLastRevision(backing)
321
        tree = self.make_branch_and_memory_tree('.')
322
        tree.lock_write()
323
        tree.add('')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
324
        rev_id_utf8 = u'\xc8'.encode('utf-8')
325
        r1 = tree.commit('1st commit', rev_id=rev_id_utf8)
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
326
        r2 = tree.commit('2nd commit')
327
        tree.unlock()
2018.5.144 by Andrew Bennetts
Fix four tests I broke with the Branch.lock_write changes.
328
        branch_token = tree.branch.lock_write()
329
        repo_token = tree.branch.repository.lock_write()
330
        tree.branch.repository.unlock()
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
331
        try:
332
            self.assertEqual(
333
                SmartServerResponse(('ok',)),
334
                request.execute(
335
                    backing.local_abspath(''), branch_token, repo_token,
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
336
                    rev_id_utf8))
337
            self.assertEqual([rev_id_utf8], tree.branch.revision_history())
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
338
        finally:
339
            tree.branch.unlock()
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
340
341
    def test_revision_id_present2(self):
342
        backing = self.get_transport()
343
        request = smart.branch.SmartServerBranchRequestSetLastRevision(backing)
344
        tree = self.make_branch_and_memory_tree('.')
345
        tree.lock_write()
346
        tree.add('')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
347
        rev_id_utf8 = u'\xc8'.encode('utf-8')
348
        r1 = tree.commit('1st commit', rev_id=rev_id_utf8)
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
349
        r2 = tree.commit('2nd commit')
350
        tree.unlock()
351
        tree.branch.set_revision_history([])
2018.5.144 by Andrew Bennetts
Fix four tests I broke with the Branch.lock_write changes.
352
        branch_token = tree.branch.lock_write()
353
        repo_token = tree.branch.repository.lock_write()
354
        tree.branch.repository.unlock()
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
355
        try:
356
            self.assertEqual(
357
                SmartServerResponse(('ok',)),
358
                request.execute(
359
                    backing.local_abspath(''), branch_token, repo_token,
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
360
                    rev_id_utf8))
361
            self.assertEqual([rev_id_utf8], tree.branch.revision_history())
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
362
        finally:
363
            tree.branch.unlock()
2018.12.3 by Andrew Bennetts
Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it.
364
365
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
366
class TestSmartServerBranchRequestLockWrite(tests.TestCaseWithTransport):
367
368
    def setUp(self):
369
        tests.TestCaseWithTransport.setUp(self)
370
        self.reduceLockdirTimeout()
371
372
    def test_lock_write_on_unlocked_branch(self):
373
        backing = self.get_transport()
374
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
375
        branch = self.make_branch('.')
376
        repository = branch.repository
377
        response = request.execute(backing.local_abspath(''))
378
        branch_nonce = branch.control_files._lock.peek().get('nonce')
379
        repository_nonce = repository.control_files._lock.peek().get('nonce')
380
        self.assertEqual(
381
            SmartServerResponse(('ok', branch_nonce, repository_nonce)),
382
            response)
383
        # The branch (and associated repository) is now locked.  Verify that
384
        # with a new branch object.
385
        new_branch = repository.bzrdir.open_branch()
386
        self.assertRaises(errors.LockContention, new_branch.lock_write)
387
388
    def test_lock_write_on_locked_branch(self):
389
        backing = self.get_transport()
390
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
391
        branch = self.make_branch('.')
392
        branch.lock_write()
393
        branch.leave_lock_in_place()
394
        branch.unlock()
395
        response = request.execute(backing.local_abspath(''))
396
        self.assertEqual(
397
            SmartServerResponse(('LockContention',)), response)
398
399
    def test_lock_write_with_tokens_on_locked_branch(self):
400
        backing = self.get_transport()
401
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
402
        branch = self.make_branch('.')
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
403
        branch_token = branch.lock_write()
404
        repo_token = branch.repository.lock_write()
405
        branch.repository.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
406
        branch.leave_lock_in_place()
407
        branch.repository.leave_lock_in_place()
408
        branch.unlock()
409
        response = request.execute(backing.local_abspath(''),
410
                                   branch_token, repo_token)
411
        self.assertEqual(
412
            SmartServerResponse(('ok', branch_token, repo_token)), response)
413
414
    def test_lock_write_with_mismatched_tokens_on_locked_branch(self):
415
        backing = self.get_transport()
416
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
417
        branch = self.make_branch('.')
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
418
        branch_token = branch.lock_write()
419
        repo_token = branch.repository.lock_write()
420
        branch.repository.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
421
        branch.leave_lock_in_place()
422
        branch.repository.leave_lock_in_place()
423
        branch.unlock()
424
        response = request.execute(backing.local_abspath(''),
425
                                   branch_token+'xxx', repo_token)
426
        self.assertEqual(
427
            SmartServerResponse(('TokenMismatch',)), response)
428
429
    def test_lock_write_on_locked_repo(self):
430
        backing = self.get_transport()
431
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
432
        branch = self.make_branch('.')
433
        branch.repository.lock_write()
434
        branch.repository.leave_lock_in_place()
435
        branch.repository.unlock()
436
        response = request.execute(backing.local_abspath(''))
437
        self.assertEqual(
438
            SmartServerResponse(('LockContention',)), response)
439
2018.5.95 by Andrew Bennetts
Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes.
440
    def test_lock_write_on_readonly_transport(self):
441
        backing = self.get_readonly_transport()
442
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
443
        branch = self.make_branch('.')
444
        response = request.execute('')
2872.5.3 by Martin Pool
Pass back LockFailed from smart server lock methods
445
        error_name, lock_str, why_str = response.args
446
        self.assertFalse(response.is_successful())
447
        self.assertEqual('LockFailed', error_name)
2018.5.95 by Andrew Bennetts
Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes.
448
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
449
450
class TestSmartServerBranchRequestUnlock(tests.TestCaseWithTransport):
451
452
    def setUp(self):
453
        tests.TestCaseWithTransport.setUp(self)
454
        self.reduceLockdirTimeout()
455
456
    def test_unlock_on_locked_branch_and_repo(self):
457
        backing = self.get_transport()
458
        request = smart.branch.SmartServerBranchRequestUnlock(backing)
459
        branch = self.make_branch('.')
460
        # Lock the branch
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
461
        branch_token = branch.lock_write()
462
        repo_token = branch.repository.lock_write()
463
        branch.repository.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
464
        # Unlock the branch (and repo) object, leaving the physical locks
465
        # in place.
466
        branch.leave_lock_in_place()
467
        branch.repository.leave_lock_in_place()
468
        branch.unlock()
469
        response = request.execute(backing.local_abspath(''),
470
                                   branch_token, repo_token)
471
        self.assertEqual(
472
            SmartServerResponse(('ok',)), response)
473
        # The branch is now unlocked.  Verify that with a new branch
474
        # object.
475
        new_branch = branch.bzrdir.open_branch()
476
        new_branch.lock_write()
477
        new_branch.unlock()
478
479
    def test_unlock_on_unlocked_branch_unlocked_repo(self):
480
        backing = self.get_transport()
481
        request = smart.branch.SmartServerBranchRequestUnlock(backing)
482
        branch = self.make_branch('.')
483
        response = request.execute(
484
            backing.local_abspath(''), 'branch token', 'repo token')
485
        self.assertEqual(
486
            SmartServerResponse(('TokenMismatch',)), response)
487
488
    def test_unlock_on_unlocked_branch_locked_repo(self):
489
        backing = self.get_transport()
490
        request = smart.branch.SmartServerBranchRequestUnlock(backing)
491
        branch = self.make_branch('.')
492
        # Lock the repository.
493
        repo_token = branch.repository.lock_write()
494
        branch.repository.leave_lock_in_place()
495
        branch.repository.unlock()
496
        # Issue branch lock_write request on the unlocked branch (with locked
497
        # repo).
498
        response = request.execute(
499
            backing.local_abspath(''), 'branch token', repo_token)
500
        self.assertEqual(
501
            SmartServerResponse(('TokenMismatch',)), response)
502
503
2018.5.56 by Robert Collins
Factor out code we expect to be common in SmartServerRequestHasRevision to SmartServerRepositoryRequest (Robert Collins, Vincent Ladeuil).
504
class TestSmartServerRepositoryRequest(tests.TestCaseWithTransport):
505
506
    def test_no_repository(self):
507
        """Raise NoRepositoryPresent when there is a bzrdir and no repo."""
508
        # we test this using a shared repository above the named path,
509
        # thus checking the right search logic is used - that is, that
510
        # its the exact path being looked at and the server is not
511
        # searching.
512
        backing = self.get_transport()
2018.5.58 by Wouter van Heyst
Small test fixes to reflect naming and documentation
513
        request = smart.repository.SmartServerRepositoryRequest(backing)
2018.5.56 by Robert Collins
Factor out code we expect to be common in SmartServerRequestHasRevision to SmartServerRepositoryRequest (Robert Collins, Vincent Ladeuil).
514
        self.make_repository('.', shared=True)
515
        self.make_bzrdir('subdir')
516
        self.assertRaises(errors.NoRepositoryPresent,
2018.5.58 by Wouter van Heyst
Small test fixes to reflect naming and documentation
517
            request.execute, backing.local_abspath('subdir'))
2018.5.56 by Robert Collins
Factor out code we expect to be common in SmartServerRequestHasRevision to SmartServerRepositoryRequest (Robert Collins, Vincent Ladeuil).
518
519
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
520
class TestSmartServerRepositoryGetRevisionGraph(tests.TestCaseWithTransport):
521
522
    def test_none_argument(self):
523
        backing = self.get_transport()
524
        request = smart.repository.SmartServerRepositoryGetRevisionGraph(backing)
525
        tree = self.make_branch_and_memory_tree('.')
526
        tree.lock_write()
527
        tree.add('')
528
        r1 = tree.commit('1st commit')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
529
        r2 = tree.commit('2nd commit', rev_id=u'\xc8'.encode('utf-8'))
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
530
        tree.unlock()
531
532
        # the lines of revision_id->revision_parent_list has no guaranteed
533
        # order coming out of a dict, so sort both our test and response
534
        lines = sorted([' '.join([r2, r1]), r1])
535
        response = request.execute(backing.local_abspath(''), '')
536
        response.body = '\n'.join(sorted(response.body.split('\n')))
537
2018.5.83 by Andrew Bennetts
Fix some test failures caused by the switch from unicode to UTF-8-encoded strs for revision IDs.
538
        self.assertEqual(
539
            SmartServerResponse(('ok', ), '\n'.join(lines)), response)
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
540
541
    def test_specific_revision_argument(self):
542
        backing = self.get_transport()
543
        request = smart.repository.SmartServerRepositoryGetRevisionGraph(backing)
544
        tree = self.make_branch_and_memory_tree('.')
545
        tree.lock_write()
546
        tree.add('')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
547
        rev_id_utf8 = u'\xc9'.encode('utf-8')
548
        r1 = tree.commit('1st commit', rev_id=rev_id_utf8)
549
        r2 = tree.commit('2nd commit', rev_id=u'\xc8'.encode('utf-8'))
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
550
        tree.unlock()
551
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
552
        self.assertEqual(SmartServerResponse(('ok', ), rev_id_utf8),
553
            request.execute(backing.local_abspath(''), rev_id_utf8))
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
554
    
555
    def test_no_such_revision(self):
556
        backing = self.get_transport()
557
        request = smart.repository.SmartServerRepositoryGetRevisionGraph(backing)
558
        tree = self.make_branch_and_memory_tree('.')
559
        tree.lock_write()
560
        tree.add('')
561
        r1 = tree.commit('1st commit')
562
        tree.unlock()
563
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
564
        # Note that it still returns body (of zero bytes).
565
        self.assertEqual(
566
            SmartServerResponse(('nosuchrevision', 'missingrevision', ), ''),
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
567
            request.execute(backing.local_abspath(''), 'missingrevision'))
568
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
569
2018.5.56 by Robert Collins
Factor out code we expect to be common in SmartServerRequestHasRevision to SmartServerRepositoryRequest (Robert Collins, Vincent Ladeuil).
570
class TestSmartServerRequestHasRevision(tests.TestCaseWithTransport):
571
572
    def test_missing_revision(self):
573
        """For a missing revision, ('no', ) is returned."""
574
        backing = self.get_transport()
575
        request = smart.repository.SmartServerRequestHasRevision(backing)
576
        self.make_repository('.')
577
        self.assertEqual(SmartServerResponse(('no', )),
578
            request.execute(backing.local_abspath(''), 'revid'))
579
580
    def test_present_revision(self):
2018.5.158 by Andrew Bennetts
Return 'yes'/'no' rather than 'ok'/'no' from the Repository.has_revision smart command.
581
        """For a present revision, ('yes', ) is returned."""
2018.5.56 by Robert Collins
Factor out code we expect to be common in SmartServerRequestHasRevision to SmartServerRepositoryRequest (Robert Collins, Vincent Ladeuil).
582
        backing = self.get_transport()
583
        request = smart.repository.SmartServerRequestHasRevision(backing)
584
        tree = self.make_branch_and_memory_tree('.')
585
        tree.lock_write()
586
        tree.add('')
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
587
        rev_id_utf8 = u'\xc8abc'.encode('utf-8')
588
        r1 = tree.commit('a commit', rev_id=rev_id_utf8)
2018.5.56 by Robert Collins
Factor out code we expect to be common in SmartServerRequestHasRevision to SmartServerRepositoryRequest (Robert Collins, Vincent Ladeuil).
589
        tree.unlock()
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
590
        self.assertTrue(tree.branch.repository.has_revision(rev_id_utf8))
2018.5.158 by Andrew Bennetts
Return 'yes'/'no' rather than 'ok'/'no' from the Repository.has_revision smart command.
591
        self.assertEqual(SmartServerResponse(('yes', )),
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
592
            request.execute(backing.local_abspath(''), rev_id_utf8))
2018.5.56 by Robert Collins
Factor out code we expect to be common in SmartServerRequestHasRevision to SmartServerRepositoryRequest (Robert Collins, Vincent Ladeuil).
593
594
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
595
class TestSmartServerRepositoryGatherStats(tests.TestCaseWithTransport):
596
597
    def test_empty_revid(self):
598
        """With an empty revid, we get only size an number and revisions"""
599
        backing = self.get_transport()
600
        request = smart.repository.SmartServerRepositoryGatherStats(backing)
601
        repository = self.make_repository('.')
602
        stats = repository.gather_stats()
603
        size = stats['size']
604
        expected_body = 'revisions: 0\nsize: %d\n' % size
605
        self.assertEqual(SmartServerResponse(('ok', ), expected_body),
606
                         request.execute(backing.local_abspath(''), '', 'no'))
607
608
    def test_revid_with_committers(self):
609
        """For a revid we get more infos."""
610
        backing = self.get_transport()
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
611
        rev_id_utf8 = u'\xc8abc'.encode('utf-8')
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
612
        request = smart.repository.SmartServerRepositoryGatherStats(backing)
613
        tree = self.make_branch_and_memory_tree('.')
614
        tree.lock_write()
615
        tree.add('')
616
        # Let's build a predictable result
617
        tree.commit('a commit', timestamp=123456.2, timezone=3600)
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
618
        tree.commit('a commit', timestamp=654321.4, timezone=0,
619
                    rev_id=rev_id_utf8)
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
620
        tree.unlock()
621
622
        stats = tree.branch.repository.gather_stats()
623
        size = stats['size']
624
        expected_body = ('firstrev: 123456.200 3600\n'
625
                         'latestrev: 654321.400 0\n'
626
                         'revisions: 2\n'
627
                         'size: %d\n' % size)
628
        self.assertEqual(SmartServerResponse(('ok', ), expected_body),
629
                         request.execute(backing.local_abspath(''),
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
630
                                         rev_id_utf8, 'no'))
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
631
632
    def test_not_empty_repository_with_committers(self):
633
        """For a revid and requesting committers we get the whole thing."""
634
        backing = self.get_transport()
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
635
        rev_id_utf8 = u'\xc8abc'.encode('utf-8')
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
636
        request = smart.repository.SmartServerRepositoryGatherStats(backing)
637
        tree = self.make_branch_and_memory_tree('.')
638
        tree.lock_write()
639
        tree.add('')
640
        # Let's build a predictable result
641
        tree.commit('a commit', timestamp=123456.2, timezone=3600,
642
                    committer='foo')
643
        tree.commit('a commit', timestamp=654321.4, timezone=0,
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
644
                    committer='bar', rev_id=rev_id_utf8)
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
645
        tree.unlock()
646
        stats = tree.branch.repository.gather_stats()
647
648
        size = stats['size']
649
        expected_body = ('committers: 2\n'
650
                         'firstrev: 123456.200 3600\n'
651
                         'latestrev: 654321.400 0\n'
652
                         'revisions: 2\n'
653
                         'size: %d\n' % size)
654
        self.assertEqual(SmartServerResponse(('ok', ), expected_body),
655
                         request.execute(backing.local_abspath(''),
2018.5.148 by Andrew Bennetts
Fix all the DeprecationWarnings in test_smart caused by unicode revision IDs.
656
                                         rev_id_utf8, 'yes'))
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
657
658
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
659
class TestSmartServerRepositoryIsShared(tests.TestCaseWithTransport):
660
661
    def test_is_shared(self):
662
        """For a shared repository, ('yes', ) is returned."""
663
        backing = self.get_transport()
664
        request = smart.repository.SmartServerRepositoryIsShared(backing)
665
        self.make_repository('.', shared=True)
666
        self.assertEqual(SmartServerResponse(('yes', )),
667
            request.execute(backing.local_abspath(''), ))
668
669
    def test_is_not_shared(self):
2018.5.58 by Wouter van Heyst
Small test fixes to reflect naming and documentation
670
        """For a shared repository, ('no', ) is returned."""
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
671
        backing = self.get_transport()
672
        request = smart.repository.SmartServerRepositoryIsShared(backing)
673
        self.make_repository('.', shared=False)
674
        self.assertEqual(SmartServerResponse(('no', )),
675
            request.execute(backing.local_abspath(''), ))
676
2018.5.56 by Robert Collins
Factor out code we expect to be common in SmartServerRequestHasRevision to SmartServerRepositoryRequest (Robert Collins, Vincent Ladeuil).
677
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
678
class TestSmartServerRepositoryLockWrite(tests.TestCaseWithTransport):
679
680
    def setUp(self):
681
        tests.TestCaseWithTransport.setUp(self)
682
        self.reduceLockdirTimeout()
683
684
    def test_lock_write_on_unlocked_repo(self):
685
        backing = self.get_transport()
686
        request = smart.repository.SmartServerRepositoryLockWrite(backing)
687
        repository = self.make_repository('.')
688
        response = request.execute(backing.local_abspath(''))
689
        nonce = repository.control_files._lock.peek().get('nonce')
690
        self.assertEqual(SmartServerResponse(('ok', nonce)), response)
691
        # The repository is now locked.  Verify that with a new repository
692
        # object.
693
        new_repo = repository.bzrdir.open_repository()
694
        self.assertRaises(errors.LockContention, new_repo.lock_write)
695
696
    def test_lock_write_on_locked_repo(self):
697
        backing = self.get_transport()
698
        request = smart.repository.SmartServerRepositoryLockWrite(backing)
699
        repository = self.make_repository('.')
700
        repository.lock_write()
701
        repository.leave_lock_in_place()
702
        repository.unlock()
703
        response = request.execute(backing.local_abspath(''))
704
        self.assertEqual(
705
            SmartServerResponse(('LockContention',)), response)
706
2018.5.95 by Andrew Bennetts
Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes.
707
    def test_lock_write_on_readonly_transport(self):
708
        backing = self.get_readonly_transport()
709
        request = smart.repository.SmartServerRepositoryLockWrite(backing)
710
        repository = self.make_repository('.')
711
        response = request.execute('')
2872.5.3 by Martin Pool
Pass back LockFailed from smart server lock methods
712
        self.assertFalse(response.is_successful())
713
        self.assertEqual('LockFailed', response.args[0])
2018.5.95 by Andrew Bennetts
Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes.
714
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
715
716
class TestSmartServerRepositoryUnlock(tests.TestCaseWithTransport):
717
718
    def setUp(self):
719
        tests.TestCaseWithTransport.setUp(self)
720
        self.reduceLockdirTimeout()
721
722
    def test_unlock_on_locked_repo(self):
723
        backing = self.get_transport()
724
        request = smart.repository.SmartServerRepositoryUnlock(backing)
725
        repository = self.make_repository('.')
726
        token = repository.lock_write()
727
        repository.leave_lock_in_place()
728
        repository.unlock()
729
        response = request.execute(backing.local_abspath(''), token)
730
        self.assertEqual(
731
            SmartServerResponse(('ok',)), response)
732
        # The repository is now unlocked.  Verify that with a new repository
733
        # object.
734
        new_repo = repository.bzrdir.open_repository()
735
        new_repo.lock_write()
736
        new_repo.unlock()
737
738
    def test_unlock_on_unlocked_repo(self):
739
        backing = self.get_transport()
740
        request = smart.repository.SmartServerRepositoryUnlock(backing)
741
        repository = self.make_repository('.')
742
        response = request.execute(backing.local_abspath(''), 'some token')
743
        self.assertEqual(
744
            SmartServerResponse(('TokenMismatch',)), response)
745
746
2018.18.1 by Martin Pool
Add stub Repository.tarball smart method
747
class TestSmartServerRepositoryTarball(tests.TestCaseWithTransport):
748
749
    def test_repository_tarball(self):
750
        backing = self.get_transport()
751
        request = smart.repository.SmartServerRepositoryTarball(backing)
752
        repository = self.make_repository('.')
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
753
        # make some extraneous junk in the repository directory which should
754
        # not be copied
755
        self.build_tree(['.bzr/repository/extra-junk'])
2018.18.2 by Martin Pool
smart method Repository.tarball actually returns the tarball
756
        response = request.execute(backing.local_abspath(''), 'bz2')
2018.18.1 by Martin Pool
Add stub Repository.tarball smart method
757
        self.assertEqual(('ok',), response.args)
758
        # body should be a tbz2
2018.18.2 by Martin Pool
smart method Repository.tarball actually returns the tarball
759
        body_file = StringIO(response.body)
760
        body_tar = tarfile.open('body_tar.tbz2', fileobj=body_file,
2018.18.25 by Martin Pool
Repository.tarball fixes for python2.4
761
            mode='r|bz2')
2018.18.2 by Martin Pool
smart method Repository.tarball actually returns the tarball
762
        # let's make sure there are some key repository components inside it.
763
        # the tarfile returns directories with trailing slashes...
764
        names = set([n.rstrip('/') for n in body_tar.getnames()])
2018.18.11 by Martin Pool
merge hpss changes
765
        self.assertTrue('.bzr/repository/lock' in names)
766
        self.assertTrue('.bzr/repository/format' in names)
767
        self.assertTrue('.bzr/repository/extra-junk' not in names,
2018.18.9 by Martin Pool
remote Repository.tarball builds a temporary directory and tars that
768
            "extraneous file present in tar file")
2018.18.1 by Martin Pool
Add stub Repository.tarball smart method
769
770
2535.3.49 by Andrew Bennetts
Rename 'Repository.fetch_revisions' smart request to 'Repository.stream_knit_data_for_revisions'.
771
class TestSmartServerRepositoryStreamKnitData(tests.TestCaseWithTransport):
2535.3.14 by Andrew Bennetts
Move serialising repo data stream to bytes into smart protocol.
772
773
    def test_fetch_revisions(self):
774
        backing = self.get_transport()
2535.3.49 by Andrew Bennetts
Rename 'Repository.fetch_revisions' smart request to 'Repository.stream_knit_data_for_revisions'.
775
        request = smart.repository.SmartServerRepositoryStreamKnitDataForRevisions(backing)
2535.3.14 by Andrew Bennetts
Move serialising repo data stream to bytes into smart protocol.
776
        tree = self.make_branch_and_memory_tree('.')
777
        tree.lock_write()
778
        tree.add('')
779
        rev_id1_utf8 = u'\xc8'.encode('utf-8')
780
        rev_id2_utf8 = u'\xc9'.encode('utf-8')
781
        r1 = tree.commit('1st commit', rev_id=rev_id1_utf8)
782
        r1 = tree.commit('2nd commit', rev_id=rev_id2_utf8)
783
        tree.unlock()
784
785
        response = request.execute(backing.local_abspath(''), rev_id2_utf8)
786
        self.assertEqual(('ok',), response.args)
787
        from cStringIO import StringIO
2535.3.31 by Andrew Bennetts
Fix imports broken by reverting the container-format merge. I didn't notice them earlier because of .pyc files :(
788
        unpacker = pack.ContainerReader(StringIO(response.body))
2535.3.14 by Andrew Bennetts
Move serialising repo data stream to bytes into smart protocol.
789
        names = []
790
        for [name], read_bytes in unpacker.iter_records():
791
            names.append(name)
2535.3.15 by Andrew Bennetts
Add KnitVersionedFile.get_stream_as_bytes, start smart implementation of RemoteRepository.get_data_stream.
792
            bytes = read_bytes(None)
793
            # The bytes should be a valid bencoded string.
794
            bencode.bdecode(bytes)
795
            # XXX: assert that the bencoded knit records have the right
796
            # contents?
2535.3.14 by Andrew Bennetts
Move serialising repo data stream to bytes into smart protocol.
797
        
2535.3.40 by Andrew Bennetts
Tidy up more XXXs.
798
    def test_no_such_revision_error(self):
799
        backing = self.get_transport()
2535.3.49 by Andrew Bennetts
Rename 'Repository.fetch_revisions' smart request to 'Repository.stream_knit_data_for_revisions'.
800
        request = smart.repository.SmartServerRepositoryStreamKnitDataForRevisions(backing)
2535.3.40 by Andrew Bennetts
Tidy up more XXXs.
801
        repo = self.make_repository('.')
802
        rev_id1_utf8 = u'\xc8'.encode('utf-8')
803
        response = request.execute(backing.local_abspath(''), rev_id1_utf8)
804
        self.assertEqual(
805
            SmartServerResponse(('NoSuchRevision', rev_id1_utf8)),
806
            response)
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
807
808
2018.5.95 by Andrew Bennetts
Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes.
809
class TestSmartServerIsReadonly(tests.TestCaseWithTransport):
810
811
    def test_is_readonly_no(self):
812
        backing = self.get_transport()
813
        request = smart.request.SmartServerIsReadonly(backing)
814
        response = request.execute()
815
        self.assertEqual(
816
            SmartServerResponse(('no',)), response)
817
818
    def test_is_readonly_yes(self):
819
        backing = self.get_readonly_transport()
820
        request = smart.request.SmartServerIsReadonly(backing)
821
        response = request.execute()
822
        self.assertEqual(
823
            SmartServerResponse(('yes',)), response)
824
825
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
826
class TestHandlers(tests.TestCase):
827
    """Tests for the request.request_handlers object."""
828
829
    def test_registered_methods(self):
830
        """Test that known methods are registered to the correct object."""
831
        self.assertEqual(
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
832
            smart.request.request_handlers.get('Branch.get_config_file'),
833
            smart.branch.SmartServerBranchGetConfigFile)
834
        self.assertEqual(
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
835
            smart.request.request_handlers.get('Branch.lock_write'),
836
            smart.branch.SmartServerBranchRequestLockWrite)
837
        self.assertEqual(
2018.5.51 by Wouter van Heyst
Test and implement RemoteBranch.last_revision_info()
838
            smart.request.request_handlers.get('Branch.last_revision_info'),
839
            smart.branch.SmartServerBranchRequestLastRevisionInfo)
840
        self.assertEqual(
2018.5.38 by Robert Collins
Implement RemoteBranch.revision_history().
841
            smart.request.request_handlers.get('Branch.revision_history'),
842
            smart.branch.SmartServerRequestRevisionHistory)
843
        self.assertEqual(
2018.5.77 by Wouter van Heyst
Fix typo in request_handlers registration of Branch.set_last_revision, and test that registration
844
            smart.request.request_handlers.get('Branch.set_last_revision'),
845
            smart.branch.SmartServerBranchRequestSetLastRevision)
846
        self.assertEqual(
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
847
            smart.request.request_handlers.get('Branch.unlock'),
848
            smart.branch.SmartServerBranchRequestUnlock)
849
        self.assertEqual(
2018.5.34 by Robert Collins
Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository.
850
            smart.request.request_handlers.get('BzrDir.find_repository'),
851
            smart.bzrdir.SmartServerRequestFindRepository)
852
        self.assertEqual(
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
853
            smart.request.request_handlers.get('BzrDirFormat.initialize'),
854
            smart.bzrdir.SmartServerRequestInitializeBzrDir)
855
        self.assertEqual(
2018.6.1 by Robert Collins
Implement a BzrDir.open_branch smart server method for opening a branch without VFS.
856
            smart.request.request_handlers.get('BzrDir.open_branch'),
857
            smart.bzrdir.SmartServerRequestOpenBranch)
2018.5.40 by Robert Collins
Implement a remote Repository.has_revision method.
858
        self.assertEqual(
2018.10.2 by v.ladeuil+lp at free
gather_stats server side and request registration
859
            smart.request.request_handlers.get('Repository.gather_stats'),
860
            smart.repository.SmartServerRepositoryGatherStats)
861
        self.assertEqual(
2535.3.69 by Andrew Bennetts
Add check for Repository.stream_knit_data_for_revisions to TestHandlers.test_registered_methods.
862
            smart.request.request_handlers.get(
863
                'Repository.get_revision_graph'),
2018.5.67 by Wouter van Heyst
Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins)
864
            smart.repository.SmartServerRepositoryGetRevisionGraph)
865
        self.assertEqual(
2018.5.40 by Robert Collins
Implement a remote Repository.has_revision method.
866
            smart.request.request_handlers.get('Repository.has_revision'),
867
            smart.repository.SmartServerRequestHasRevision)
2018.5.57 by Robert Collins
Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil).
868
        self.assertEqual(
869
            smart.request.request_handlers.get('Repository.is_shared'),
870
            smart.repository.SmartServerRepositoryIsShared)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
871
        self.assertEqual(
872
            smart.request.request_handlers.get('Repository.lock_write'),
873
            smart.repository.SmartServerRepositoryLockWrite)
874
        self.assertEqual(
2535.3.69 by Andrew Bennetts
Add check for Repository.stream_knit_data_for_revisions to TestHandlers.test_registered_methods.
875
            smart.request.request_handlers.get(
876
                'Repository.stream_knit_data_for_revisions'),
877
            smart.repository.SmartServerRepositoryStreamKnitDataForRevisions)
878
        self.assertEqual(
879
            smart.request.request_handlers.get('Repository.tarball'),
880
            smart.repository.SmartServerRepositoryTarball)
881
        self.assertEqual(
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
882
            smart.request.request_handlers.get('Repository.unlock'),
883
            smart.repository.SmartServerRepositoryUnlock)
2018.5.95 by Andrew Bennetts
Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes.
884
        self.assertEqual(
885
            smart.request.request_handlers.get('Transport.is_readonly'),
886
            smart.request.SmartServerIsReadonly)