/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_smart.py

  • Committer: Andrew Bennetts
  • Date: 2010-01-12 03:53:21 UTC
  • mfrom: (4948 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4964.
  • Revision ID: andrew.bennetts@canonical.com-20100112035321-hofpz5p10224ryj3
Merge lp:bzr, resolving conflicts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
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
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Tests for the smart wire/domain protocol.
18
18
 
29
29
import tarfile
30
30
 
31
31
from bzrlib import (
 
32
    bencode,
32
33
    bzrdir,
33
34
    errors,
34
35
    pack,
35
36
    smart,
36
37
    tests,
37
38
    urlutils,
 
39
    versionedfile,
38
40
    )
39
41
from bzrlib.branch import Branch, BranchReferenceFormat
40
42
import bzrlib.smart.branch
41
 
import bzrlib.smart.bzrdir
 
43
import bzrlib.smart.bzrdir, bzrlib.smart.bzrdir as smart_dir
 
44
import bzrlib.smart.packrepository
42
45
import bzrlib.smart.repository
 
46
import bzrlib.smart.vfs
43
47
from bzrlib.smart.request import (
44
48
    FailedSmartServerResponse,
45
49
    SmartServerRequest,
47
51
    SuccessfulSmartServerResponse,
48
52
    )
49
53
from bzrlib.tests import (
50
 
    iter_suite_tests,
51
54
    split_suite_by_re,
52
 
    TestScenarioApplier,
53
55
    )
54
 
from bzrlib.transport import chroot, get_transport
55
 
from bzrlib.util import bencode
 
56
from bzrlib.transport import chroot, get_transport, local, memory
56
57
 
57
58
 
58
59
def load_tests(standard_tests, module, loader):
59
60
    """Multiply tests version and protocol consistency."""
60
61
    # FindRepository tests.
61
62
    bzrdir_mod = bzrlib.smart.bzrdir
62
 
    applier = TestScenarioApplier()
63
 
    applier.scenarios = [
 
63
    scenarios = [
64
64
        ("find_repository", {
65
65
            "_request_class":bzrdir_mod.SmartServerRequestFindRepositoryV1}),
66
66
        ("find_repositoryV2", {
67
67
            "_request_class":bzrdir_mod.SmartServerRequestFindRepositoryV2}),
 
68
        ("find_repositoryV3", {
 
69
            "_request_class":bzrdir_mod.SmartServerRequestFindRepositoryV3}),
68
70
        ]
69
71
    to_adapt, result = split_suite_by_re(standard_tests,
70
72
        "TestSmartServerRequestFindRepository")
71
73
    v2_only, v1_and_2 = split_suite_by_re(to_adapt,
72
74
        "_v2")
73
 
    for test in iter_suite_tests(v1_and_2):
74
 
        result.addTests(applier.adapt(test))
75
 
    del applier.scenarios[0]
76
 
    for test in iter_suite_tests(v2_only):
77
 
        result.addTests(applier.adapt(test))
 
75
    tests.multiply_tests(v1_and_2, scenarios, result)
 
76
    # The first scenario is only applicable to v1 protocols, it is deleted
 
77
    # since.
 
78
    tests.multiply_tests(v2_only, scenarios[1:], result)
78
79
    return result
79
80
 
80
81
 
81
82
class TestCaseWithChrootedTransport(tests.TestCaseWithTransport):
82
83
 
83
84
    def setUp(self):
 
85
        self.vfs_transport_factory = memory.MemoryServer
84
86
        tests.TestCaseWithTransport.setUp(self)
85
87
        self._chroot_server = None
86
88
 
88
90
        if self._chroot_server is None:
89
91
            backing_transport = tests.TestCaseWithTransport.get_transport(self)
90
92
            self._chroot_server = chroot.ChrootServer(backing_transport)
91
 
            self._chroot_server.setUp()
92
 
            self.addCleanup(self._chroot_server.tearDown)
 
93
            self.start_server(self._chroot_server)
93
94
        t = get_transport(self._chroot_server.get_url())
94
95
        if relpath is not None:
95
96
            t = t.clone(relpath)
96
97
        return t
97
98
 
98
99
 
99
 
class TestCaseWithSmartMedium(tests.TestCaseWithTransport):
 
100
class TestCaseWithSmartMedium(tests.TestCaseWithMemoryTransport):
100
101
 
101
102
    def setUp(self):
102
103
        super(TestCaseWithSmartMedium, self).setUp()
114
115
        return self.get_transport().get_smart_medium()
115
116
 
116
117
 
 
118
class TestByteStreamToStream(tests.TestCase):
 
119
 
 
120
    def test_repeated_substreams_same_kind_are_one_stream(self):
 
121
        # Make a stream - an iterable of bytestrings.
 
122
        stream = [('text', [versionedfile.FulltextContentFactory(('k1',), None,
 
123
            None, 'foo')]),('text', [
 
124
            versionedfile.FulltextContentFactory(('k2',), None, None, 'bar')])]
 
125
        fmt = bzrdir.format_registry.get('pack-0.92')().repository_format
 
126
        bytes = smart.repository._stream_to_byte_stream(stream, fmt)
 
127
        streams = []
 
128
        # Iterate the resulting iterable; checking that we get only one stream
 
129
        # out.
 
130
        fmt, stream = smart.repository._byte_stream_to_stream(bytes)
 
131
        for kind, substream in stream:
 
132
            streams.append((kind, list(substream)))
 
133
        self.assertLength(1, streams)
 
134
        self.assertLength(2, streams[0][1])
 
135
 
 
136
 
117
137
class TestSmartServerResponse(tests.TestCase):
118
138
 
119
139
    def test__eq__(self):
151
171
        self.assertRaises(
152
172
            errors.PathNotChild, request.translate_client_path, 'bar/')
153
173
        self.assertEqual('./baz', request.translate_client_path('foo/baz'))
 
174
        e_acute = u'\N{LATIN SMALL LETTER E WITH ACUTE}'.encode('utf-8')
 
175
        self.assertEqual('./' + urlutils.escape(e_acute),
 
176
                         request.translate_client_path('foo/' + e_acute))
 
177
 
 
178
    def test_translate_client_path_vfs(self):
 
179
        """VfsRequests receive escaped paths rather than raw UTF-8."""
 
180
        transport = self.get_transport()
 
181
        request = smart.vfs.VfsRequest(transport, 'foo/')
 
182
        e_acute = u'\N{LATIN SMALL LETTER E WITH ACUTE}'.encode('utf-8')
 
183
        escaped = urlutils.escape('foo/' + e_acute)
 
184
        self.assertEqual('./' + urlutils.escape(e_acute),
 
185
                         request.translate_client_path(escaped))
154
186
 
155
187
    def test_transport_from_client_path(self):
156
188
        transport = self.get_transport()
160
192
            request.transport_from_client_path('foo/').base)
161
193
 
162
194
 
 
195
class TestSmartServerBzrDirRequestCloningMetaDir(
 
196
    tests.TestCaseWithMemoryTransport):
 
197
    """Tests for BzrDir.cloning_metadir."""
 
198
 
 
199
    def test_cloning_metadir(self):
 
200
        """When there is a bzrdir present, the call succeeds."""
 
201
        backing = self.get_transport()
 
202
        dir = self.make_bzrdir('.')
 
203
        local_result = dir.cloning_metadir()
 
204
        request_class = smart_dir.SmartServerBzrDirRequestCloningMetaDir
 
205
        request = request_class(backing)
 
206
        expected = SuccessfulSmartServerResponse(
 
207
            (local_result.network_name(),
 
208
            local_result.repository_format.network_name(),
 
209
            ('branch', local_result.get_branch_format().network_name())))
 
210
        self.assertEqual(expected, request.execute('', 'False'))
 
211
 
 
212
    def test_cloning_metadir_reference(self):
 
213
        """The request fails when bzrdir contains a branch reference."""
 
214
        backing = self.get_transport()
 
215
        referenced_branch = self.make_branch('referenced')
 
216
        dir = self.make_bzrdir('.')
 
217
        local_result = dir.cloning_metadir()
 
218
        reference = BranchReferenceFormat().initialize(dir, referenced_branch)
 
219
        reference_url = BranchReferenceFormat().get_reference(dir)
 
220
        # The server shouldn't try to follow the branch reference, so it's fine
 
221
        # if the referenced branch isn't reachable.
 
222
        backing.rename('referenced', 'moved')
 
223
        request_class = smart_dir.SmartServerBzrDirRequestCloningMetaDir
 
224
        request = request_class(backing)
 
225
        expected = FailedSmartServerResponse(('BranchReference',))
 
226
        self.assertEqual(expected, request.execute('', 'False'))
 
227
 
 
228
 
 
229
class TestSmartServerRequestCreateRepository(tests.TestCaseWithMemoryTransport):
 
230
    """Tests for BzrDir.create_repository."""
 
231
 
 
232
    def test_makes_repository(self):
 
233
        """When there is a bzrdir present, the call succeeds."""
 
234
        backing = self.get_transport()
 
235
        self.make_bzrdir('.')
 
236
        request_class = bzrlib.smart.bzrdir.SmartServerRequestCreateRepository
 
237
        request = request_class(backing)
 
238
        reference_bzrdir_format = bzrdir.format_registry.get('pack-0.92')()
 
239
        reference_format = reference_bzrdir_format.repository_format
 
240
        network_name = reference_format.network_name()
 
241
        expected = SuccessfulSmartServerResponse(
 
242
            ('ok', 'no', 'no', 'no', network_name))
 
243
        self.assertEqual(expected, request.execute('', network_name, 'True'))
 
244
 
 
245
 
163
246
class TestSmartServerRequestFindRepository(tests.TestCaseWithMemoryTransport):
164
247
    """Tests for BzrDir.find_repository."""
165
248
 
172
255
            request.execute(''))
173
256
 
174
257
    def test_nonshared_repository(self):
175
 
        # nonshared repositorys only allow 'find' to return a handle when the 
176
 
        # path the repository is being searched on is the same as that that 
 
258
        # nonshared repositorys only allow 'find' to return a handle when the
 
259
        # path the repository is being searched on is the same as that that
177
260
        # the repository is at.
178
261
        backing = self.get_transport()
179
262
        request = self._request_class(backing)
197
280
            subtrees = 'yes'
198
281
        else:
199
282
            subtrees = 'no'
200
 
        if (smart.bzrdir.SmartServerRequestFindRepositoryV2 ==
 
283
        if repo._format.supports_external_lookups:
 
284
            external = 'yes'
 
285
        else:
 
286
            external = 'no'
 
287
        if (smart.bzrdir.SmartServerRequestFindRepositoryV3 ==
 
288
            self._request_class):
 
289
            return SuccessfulSmartServerResponse(
 
290
                ('ok', '', rich_root, subtrees, external,
 
291
                 repo._format.network_name()))
 
292
        elif (smart.bzrdir.SmartServerRequestFindRepositoryV2 ==
201
293
            self._request_class):
202
294
            # All tests so far are on formats, and for non-external
203
295
            # repositories.
204
296
            return SuccessfulSmartServerResponse(
205
 
                ('ok', '', rich_root, subtrees, 'no'))
 
297
                ('ok', '', rich_root, subtrees, external))
206
298
        else:
207
299
            return SuccessfulSmartServerResponse(('ok', '', rich_root, subtrees))
208
300
 
241
333
        self.assertEqual(result, request.execute(''))
242
334
 
243
335
 
 
336
class TestSmartServerBzrDirRequestGetConfigFile(
 
337
    tests.TestCaseWithMemoryTransport):
 
338
    """Tests for BzrDir.get_config_file."""
 
339
 
 
340
    def test_present(self):
 
341
        backing = self.get_transport()
 
342
        dir = self.make_bzrdir('.')
 
343
        dir.get_config().set_default_stack_on("/")
 
344
        local_result = dir._get_config()._get_config_file().read()
 
345
        request_class = smart_dir.SmartServerBzrDirRequestConfigFile
 
346
        request = request_class(backing)
 
347
        expected = SuccessfulSmartServerResponse((), local_result)
 
348
        self.assertEqual(expected, request.execute(''))
 
349
 
 
350
    def test_missing(self):
 
351
        backing = self.get_transport()
 
352
        dir = self.make_bzrdir('.')
 
353
        request_class = smart_dir.SmartServerBzrDirRequestConfigFile
 
354
        request = request_class(backing)
 
355
        expected = SuccessfulSmartServerResponse((), '')
 
356
        self.assertEqual(expected, request.execute(''))
 
357
 
 
358
 
244
359
class TestSmartServerRequestInitializeBzrDir(tests.TestCaseWithMemoryTransport):
245
360
 
246
361
    def test_empty_dir(self):
250
365
        self.assertEqual(SmartServerResponse(('ok', )),
251
366
            request.execute(''))
252
367
        made_dir = bzrdir.BzrDir.open_from_transport(backing)
253
 
        # no branch, tree or repository is expected with the current 
 
368
        # no branch, tree or repository is expected with the current
254
369
        # default formart.
255
370
        self.assertRaises(errors.NoWorkingTree, made_dir.open_workingtree)
256
371
        self.assertRaises(errors.NotBranchError, made_dir.open_branch)
272
387
            request.execute, 'subdir')
273
388
 
274
389
 
 
390
class TestSmartServerRequestBzrDirInitializeEx(tests.TestCaseWithMemoryTransport):
 
391
    """Basic tests for BzrDir.initialize_ex_1.16 in the smart server.
 
392
 
 
393
    The main unit tests in test_bzrdir exercise the API comprehensively.
 
394
    """
 
395
 
 
396
    def test_empty_dir(self):
 
397
        """Initializing an empty dir should succeed and do it."""
 
398
        backing = self.get_transport()
 
399
        name = self.make_bzrdir('reference')._format.network_name()
 
400
        request = smart.bzrdir.SmartServerRequestBzrDirInitializeEx(backing)
 
401
        self.assertEqual(SmartServerResponse(('', '', '', '', '', '', name,
 
402
            'False', '', '', '')),
 
403
            request.execute(name, '', 'True', 'False', 'False', '', '', '', '',
 
404
            'False'))
 
405
        made_dir = bzrdir.BzrDir.open_from_transport(backing)
 
406
        # no branch, tree or repository is expected with the current
 
407
        # default format.
 
408
        self.assertRaises(errors.NoWorkingTree, made_dir.open_workingtree)
 
409
        self.assertRaises(errors.NotBranchError, made_dir.open_branch)
 
410
        self.assertRaises(errors.NoRepositoryPresent, made_dir.open_repository)
 
411
 
 
412
    def test_missing_dir(self):
 
413
        """Initializing a missing directory should fail like the bzrdir api."""
 
414
        backing = self.get_transport()
 
415
        name = self.make_bzrdir('reference')._format.network_name()
 
416
        request = smart.bzrdir.SmartServerRequestBzrDirInitializeEx(backing)
 
417
        self.assertRaises(errors.NoSuchFile, request.execute, name,
 
418
            'subdir/dir', 'False', 'False', 'False', '', '', '', '', 'False')
 
419
 
 
420
    def test_initialized_dir(self):
 
421
        """Initializing an extant directory should fail like the bzrdir api."""
 
422
        backing = self.get_transport()
 
423
        name = self.make_bzrdir('reference')._format.network_name()
 
424
        request = smart.bzrdir.SmartServerRequestBzrDirInitializeEx(backing)
 
425
        self.make_bzrdir('subdir')
 
426
        self.assertRaises(errors.FileExists, request.execute, name, 'subdir',
 
427
            'False', 'False', 'False', '', '', '', '', 'False')
 
428
 
 
429
 
 
430
class TestSmartServerRequestOpenBzrDir(tests.TestCaseWithMemoryTransport):
 
431
    
 
432
    def test_no_directory(self):
 
433
        backing = self.get_transport()
 
434
        request = smart.bzrdir.SmartServerRequestOpenBzrDir(backing)
 
435
        self.assertEqual(SmartServerResponse(('no', )),
 
436
            request.execute('does-not-exist'))
 
437
 
 
438
    def test_empty_directory(self):
 
439
        backing = self.get_transport()
 
440
        backing.mkdir('empty')
 
441
        request = smart.bzrdir.SmartServerRequestOpenBzrDir(backing)
 
442
        self.assertEqual(SmartServerResponse(('no', )),
 
443
            request.execute('empty'))
 
444
 
 
445
    def test_outside_root_client_path(self):
 
446
        backing = self.get_transport()
 
447
        request = smart.bzrdir.SmartServerRequestOpenBzrDir(backing,
 
448
            root_client_path='root')
 
449
        self.assertEqual(SmartServerResponse(('no', )),
 
450
            request.execute('not-root'))
 
451
 
 
452
    
 
453
class TestSmartServerRequestOpenBzrDir_2_1(tests.TestCaseWithMemoryTransport):
 
454
    
 
455
    def test_no_directory(self):
 
456
        backing = self.get_transport()
 
457
        request = smart.bzrdir.SmartServerRequestOpenBzrDir_2_1(backing)
 
458
        self.assertEqual(SmartServerResponse(('no', )),
 
459
            request.execute('does-not-exist'))
 
460
 
 
461
    def test_empty_directory(self):
 
462
        backing = self.get_transport()
 
463
        backing.mkdir('empty')
 
464
        request = smart.bzrdir.SmartServerRequestOpenBzrDir_2_1(backing)
 
465
        self.assertEqual(SmartServerResponse(('no', )),
 
466
            request.execute('empty'))
 
467
 
 
468
    def test_present_without_workingtree(self):
 
469
        backing = self.get_transport()
 
470
        request = smart.bzrdir.SmartServerRequestOpenBzrDir_2_1(backing)
 
471
        self.make_bzrdir('.')
 
472
        self.assertEqual(SmartServerResponse(('yes', 'no')),
 
473
            request.execute(''))
 
474
 
 
475
    def test_outside_root_client_path(self):
 
476
        backing = self.get_transport()
 
477
        request = smart.bzrdir.SmartServerRequestOpenBzrDir_2_1(backing,
 
478
            root_client_path='root')
 
479
        self.assertEqual(SmartServerResponse(('no',)),
 
480
            request.execute('not-root'))
 
481
 
 
482
    
 
483
class TestSmartServerRequestOpenBzrDir_2_1_disk(TestCaseWithChrootedTransport):
 
484
 
 
485
    def test_present_with_workingtree(self):
 
486
        self.vfs_transport_factory = local.LocalURLServer
 
487
        backing = self.get_transport()
 
488
        request = smart.bzrdir.SmartServerRequestOpenBzrDir_2_1(backing)
 
489
        bd = self.make_bzrdir('.')
 
490
        bd.create_repository()
 
491
        bd.create_branch()
 
492
        bd.create_workingtree()
 
493
        self.assertEqual(SmartServerResponse(('yes', 'yes')),
 
494
            request.execute(''))
 
495
 
 
496
 
275
497
class TestSmartServerRequestOpenBranch(TestCaseWithChrootedTransport):
276
498
 
277
499
    def test_no_branch(self):
292
514
 
293
515
    def test_branch_reference(self):
294
516
        """When there is a branch reference, the reference URL is returned."""
 
517
        self.vfs_transport_factory = local.LocalURLServer
295
518
        backing = self.get_transport()
296
519
        request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
297
520
        branch = self.make_branch('branch')
302
525
            request.execute('reference'))
303
526
 
304
527
 
 
528
class TestSmartServerRequestOpenBranchV2(TestCaseWithChrootedTransport):
 
529
 
 
530
    def test_no_branch(self):
 
531
        """When there is no branch, ('nobranch', ) is returned."""
 
532
        backing = self.get_transport()
 
533
        self.make_bzrdir('.')
 
534
        request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
 
535
        self.assertEqual(SmartServerResponse(('nobranch', )),
 
536
            request.execute(''))
 
537
 
 
538
    def test_branch(self):
 
539
        """When there is a branch, 'ok' is returned."""
 
540
        backing = self.get_transport()
 
541
        expected = self.make_branch('.')._format.network_name()
 
542
        request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
 
543
        self.assertEqual(SuccessfulSmartServerResponse(('branch', expected)),
 
544
            request.execute(''))
 
545
 
 
546
    def test_branch_reference(self):
 
547
        """When there is a branch reference, the reference URL is returned."""
 
548
        self.vfs_transport_factory = local.LocalURLServer
 
549
        backing = self.get_transport()
 
550
        request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
 
551
        branch = self.make_branch('branch')
 
552
        checkout = branch.create_checkout('reference',lightweight=True)
 
553
        reference_url = BranchReferenceFormat().get_reference(checkout.bzrdir)
 
554
        self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
 
555
        self.assertEqual(SuccessfulSmartServerResponse(('ref', reference_url)),
 
556
            request.execute('reference'))
 
557
 
 
558
    def test_stacked_branch(self):
 
559
        """Opening a stacked branch does not open the stacked-on branch."""
 
560
        trunk = self.make_branch('trunk')
 
561
        feature = self.make_branch('feature')
 
562
        feature.set_stacked_on_url(trunk.base)
 
563
        opened_branches = []
 
564
        Branch.hooks.install_named_hook('open', opened_branches.append, None)
 
565
        backing = self.get_transport()
 
566
        request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
 
567
        request.setup_jail()
 
568
        try:
 
569
            response = request.execute('feature')
 
570
        finally:
 
571
            request.teardown_jail()
 
572
        expected_format = feature._format.network_name()
 
573
        self.assertEqual(
 
574
            SuccessfulSmartServerResponse(('branch', expected_format)),
 
575
            response)
 
576
        self.assertLength(1, opened_branches)
 
577
 
 
578
 
305
579
class TestSmartServerRequestRevisionHistory(tests.TestCaseWithMemoryTransport):
306
580
 
307
581
    def test_empty(self):
388
662
    def test_with_content(self):
389
663
        # SmartServerBranchGetConfigFile should return the content from
390
664
        # branch.control_files.get('branch.conf') for now - in the future it may
391
 
        # perform more complex processing. 
 
665
        # perform more complex processing.
392
666
        backing = self.get_transport()
393
667
        request = smart.branch.SmartServerBranchGetConfigFile(backing)
394
668
        branch = self.make_branch('.')
397
671
            request.execute(''))
398
672
 
399
673
 
400
 
class SetLastRevisionTestBase(tests.TestCaseWithMemoryTransport):
 
674
class TestLockedBranch(tests.TestCaseWithMemoryTransport):
 
675
 
 
676
    def get_lock_tokens(self, branch):
 
677
        branch_token = branch.lock_write()
 
678
        repo_token = branch.repository.lock_write()
 
679
        branch.repository.unlock()
 
680
        return branch_token, repo_token
 
681
 
 
682
 
 
683
class TestSmartServerBranchRequestSetConfigOption(TestLockedBranch):
 
684
 
 
685
    def test_value_name(self):
 
686
        branch = self.make_branch('.')
 
687
        request = smart.branch.SmartServerBranchRequestSetConfigOption(
 
688
            branch.bzrdir.root_transport)
 
689
        branch_token, repo_token = self.get_lock_tokens(branch)
 
690
        config = branch._get_config()
 
691
        result = request.execute('', branch_token, repo_token, 'bar', 'foo',
 
692
            '')
 
693
        self.assertEqual(SuccessfulSmartServerResponse(()), result)
 
694
        self.assertEqual('bar', config.get_option('foo'))
 
695
        # Cleanup
 
696
        branch.unlock()
 
697
 
 
698
    def test_value_name_section(self):
 
699
        branch = self.make_branch('.')
 
700
        request = smart.branch.SmartServerBranchRequestSetConfigOption(
 
701
            branch.bzrdir.root_transport)
 
702
        branch_token, repo_token = self.get_lock_tokens(branch)
 
703
        config = branch._get_config()
 
704
        result = request.execute('', branch_token, repo_token, 'bar', 'foo',
 
705
            'gam')
 
706
        self.assertEqual(SuccessfulSmartServerResponse(()), result)
 
707
        self.assertEqual('bar', config.get_option('foo', 'gam'))
 
708
        # Cleanup
 
709
        branch.unlock()
 
710
 
 
711
 
 
712
class TestSmartServerBranchRequestSetTagsBytes(TestLockedBranch):
 
713
    # Only called when the branch format and tags match [yay factory
 
714
    # methods] so only need to test straight forward cases.
 
715
 
 
716
    def test_set_bytes(self):
 
717
        base_branch = self.make_branch('base')
 
718
        tag_bytes = base_branch._get_tags_bytes()
 
719
        # get_lock_tokens takes out a lock.
 
720
        branch_token, repo_token = self.get_lock_tokens(base_branch)
 
721
        request = smart.branch.SmartServerBranchSetTagsBytes(
 
722
            self.get_transport())
 
723
        response = request.execute('base', branch_token, repo_token)
 
724
        self.assertEqual(None, response)
 
725
        response = request.do_chunk(tag_bytes)
 
726
        self.assertEqual(None, response)
 
727
        response = request.do_end()
 
728
        self.assertEquals(
 
729
            SuccessfulSmartServerResponse(()), response)
 
730
        base_branch.unlock()
 
731
 
 
732
    def test_lock_failed(self):
 
733
        base_branch = self.make_branch('base')
 
734
        base_branch.lock_write()
 
735
        tag_bytes = base_branch._get_tags_bytes()
 
736
        request = smart.branch.SmartServerBranchSetTagsBytes(
 
737
            self.get_transport())
 
738
        self.assertRaises(errors.TokenMismatch, request.execute,
 
739
            'base', 'wrong token', 'wrong token')
 
740
        # The request handler will keep processing the message parts, so even
 
741
        # if the request fails immediately do_chunk and do_end are still
 
742
        # called.
 
743
        request.do_chunk(tag_bytes)
 
744
        request.do_end()
 
745
        base_branch.unlock()
 
746
 
 
747
 
 
748
 
 
749
class SetLastRevisionTestBase(TestLockedBranch):
401
750
    """Base test case for verbs that implement set_last_revision."""
402
751
 
403
752
    def setUp(self):
407
756
        self.tree = self.make_branch_and_memory_tree('.')
408
757
 
409
758
    def lock_branch(self):
410
 
        b = self.tree.branch
411
 
        branch_token = b.lock_write()
412
 
        repo_token = b.repository.lock_write()
413
 
        b.repository.unlock()
414
 
        return branch_token, repo_token
 
759
        return self.get_lock_tokens(self.tree.branch)
415
760
 
416
761
    def unlock_branch(self):
417
762
        self.tree.branch.unlock()
418
 
        
 
763
 
419
764
    def set_last_revision(self, revision_id, revno):
420
765
        branch_token, repo_token = self.lock_branch()
421
766
        response = self._set_last_revision(
427
772
        response = self.set_last_revision(revision_id, revno)
428
773
        self.assertEqual(SuccessfulSmartServerResponse(('ok',)), response)
429
774
 
430
 
        
 
775
 
431
776
class TestSetLastRevisionVerbMixin(object):
432
777
    """Mixin test case for verbs that implement set_last_revision."""
433
778
 
538
883
        self.assertEqual(
539
884
            SuccessfulSmartServerResponse(('ok', revno, revision_id)),
540
885
            response)
541
 
        
 
886
 
542
887
    def test_branch_last_revision_info_rewind(self):
543
888
        """A branch's tip can be set to a revision that is an ancestor of the
544
889
        current tip, but only if allow_overwrite_descendant is passed.
587
932
        # child-1.
588
933
        new_r2 = self.tree.commit('2nd commit', rev_id='child-2')
589
934
        self.tree.unlock()
590
 
        
 
935
 
591
936
    def test_not_allow_diverged(self):
592
937
        """If allow_diverged is not passed, then setting a divergent history
593
938
        returns a Diverged error.
615
960
        self.assertEqual('child-1', self.tree.branch.last_revision())
616
961
 
617
962
 
 
963
class TestSmartServerBranchRequestGetParent(tests.TestCaseWithMemoryTransport):
 
964
 
 
965
    def test_get_parent_none(self):
 
966
        base_branch = self.make_branch('base')
 
967
        request = smart.branch.SmartServerBranchGetParent(self.get_transport())
 
968
        response = request.execute('base')
 
969
        self.assertEquals(
 
970
            SuccessfulSmartServerResponse(('',)), response)
 
971
 
 
972
    def test_get_parent_something(self):
 
973
        base_branch = self.make_branch('base')
 
974
        base_branch.set_parent(self.get_url('foo'))
 
975
        request = smart.branch.SmartServerBranchGetParent(self.get_transport())
 
976
        response = request.execute('base')
 
977
        self.assertEquals(
 
978
            SuccessfulSmartServerResponse(("../foo",)),
 
979
            response)
 
980
 
 
981
 
 
982
class TestSmartServerBranchRequestSetParent(tests.TestCaseWithMemoryTransport):
 
983
 
 
984
    def test_set_parent_none(self):
 
985
        branch = self.make_branch('base', format="1.9")
 
986
        branch.lock_write()
 
987
        branch._set_parent_location('foo')
 
988
        branch.unlock()
 
989
        request = smart.branch.SmartServerBranchRequestSetParentLocation(
 
990
            self.get_transport())
 
991
        branch_token = branch.lock_write()
 
992
        repo_token = branch.repository.lock_write()
 
993
        try:
 
994
            response = request.execute('base', branch_token, repo_token, '')
 
995
        finally:
 
996
            branch.repository.unlock()
 
997
            branch.unlock()
 
998
        self.assertEqual(SuccessfulSmartServerResponse(()), response)
 
999
        self.assertEqual(None, branch.get_parent())
 
1000
 
 
1001
    def test_set_parent_something(self):
 
1002
        branch = self.make_branch('base', format="1.9")
 
1003
        request = smart.branch.SmartServerBranchRequestSetParentLocation(
 
1004
            self.get_transport())
 
1005
        branch_token = branch.lock_write()
 
1006
        repo_token = branch.repository.lock_write()
 
1007
        try:
 
1008
            response = request.execute('base', branch_token, repo_token,
 
1009
            'http://bar/')
 
1010
        finally:
 
1011
            branch.repository.unlock()
 
1012
            branch.unlock()
 
1013
        self.assertEqual(SuccessfulSmartServerResponse(()), response)
 
1014
        self.assertEqual('http://bar/', branch.get_parent())
 
1015
 
 
1016
 
 
1017
class TestSmartServerBranchRequestGetTagsBytes(tests.TestCaseWithMemoryTransport):
 
1018
    # Only called when the branch format and tags match [yay factory
 
1019
    # methods] so only need to test straight forward cases.
 
1020
 
 
1021
    def test_get_bytes(self):
 
1022
        base_branch = self.make_branch('base')
 
1023
        request = smart.branch.SmartServerBranchGetTagsBytes(
 
1024
            self.get_transport())
 
1025
        response = request.execute('base')
 
1026
        self.assertEquals(
 
1027
            SuccessfulSmartServerResponse(('',)), response)
 
1028
 
 
1029
 
618
1030
class TestSmartServerBranchRequestGetStackedOnURL(tests.TestCaseWithMemoryTransport):
619
1031
 
620
1032
    def test_get_stacked_on_url(self):
650
1062
        # with a new branch object.
651
1063
        new_branch = repository.bzrdir.open_branch()
652
1064
        self.assertRaises(errors.LockContention, new_branch.lock_write)
 
1065
        # Cleanup
 
1066
        request = smart.branch.SmartServerBranchRequestUnlock(backing)
 
1067
        response = request.execute('', branch_nonce, repository_nonce)
653
1068
 
654
1069
    def test_lock_write_on_locked_branch(self):
655
1070
        backing = self.get_transport()
656
1071
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
657
1072
        branch = self.make_branch('.')
658
 
        branch.lock_write()
 
1073
        branch_token = branch.lock_write()
659
1074
        branch.leave_lock_in_place()
660
1075
        branch.unlock()
661
1076
        response = request.execute('')
662
1077
        self.assertEqual(
663
1078
            SmartServerResponse(('LockContention',)), response)
 
1079
        # Cleanup
 
1080
        branch.lock_write(branch_token)
 
1081
        branch.dont_leave_lock_in_place()
 
1082
        branch.unlock()
664
1083
 
665
1084
    def test_lock_write_with_tokens_on_locked_branch(self):
666
1085
        backing = self.get_transport()
676
1095
                                   branch_token, repo_token)
677
1096
        self.assertEqual(
678
1097
            SmartServerResponse(('ok', branch_token, repo_token)), response)
 
1098
        # Cleanup
 
1099
        branch.repository.lock_write(repo_token)
 
1100
        branch.repository.dont_leave_lock_in_place()
 
1101
        branch.repository.unlock()
 
1102
        branch.lock_write(branch_token)
 
1103
        branch.dont_leave_lock_in_place()
 
1104
        branch.unlock()
679
1105
 
680
1106
    def test_lock_write_with_mismatched_tokens_on_locked_branch(self):
681
1107
        backing = self.get_transport()
691
1117
                                   branch_token+'xxx', repo_token)
692
1118
        self.assertEqual(
693
1119
            SmartServerResponse(('TokenMismatch',)), response)
 
1120
        # Cleanup
 
1121
        branch.repository.lock_write(repo_token)
 
1122
        branch.repository.dont_leave_lock_in_place()
 
1123
        branch.repository.unlock()
 
1124
        branch.lock_write(branch_token)
 
1125
        branch.dont_leave_lock_in_place()
 
1126
        branch.unlock()
694
1127
 
695
1128
    def test_lock_write_on_locked_repo(self):
696
1129
        backing = self.get_transport()
697
1130
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
698
1131
        branch = self.make_branch('.', format='knit')
699
 
        branch.repository.lock_write()
700
 
        branch.repository.leave_lock_in_place()
701
 
        branch.repository.unlock()
 
1132
        repo = branch.repository
 
1133
        repo_token = repo.lock_write()
 
1134
        repo.leave_lock_in_place()
 
1135
        repo.unlock()
702
1136
        response = request.execute('')
703
1137
        self.assertEqual(
704
1138
            SmartServerResponse(('LockContention',)), response)
 
1139
        # Cleanup
 
1140
        repo.lock_write(repo_token)
 
1141
        repo.dont_leave_lock_in_place()
 
1142
        repo.unlock()
705
1143
 
706
1144
    def test_lock_write_on_readonly_transport(self):
707
1145
        backing = self.get_readonly_transport()
766
1204
            '', 'branch token', repo_token)
767
1205
        self.assertEqual(
768
1206
            SmartServerResponse(('TokenMismatch',)), response)
 
1207
        # Cleanup
 
1208
        branch.repository.lock_write(repo_token)
 
1209
        branch.repository.dont_leave_lock_in_place()
 
1210
        branch.repository.unlock()
769
1211
 
770
1212
 
771
1213
class TestSmartServerRepositoryRequest(tests.TestCaseWithMemoryTransport):
794
1236
 
795
1237
        self.assertEqual(None,
796
1238
            request.execute('', 'missing-id'))
797
 
        # Note that it returns a body (of '' bzipped).
 
1239
        # Note that it returns a body that is bzipped.
798
1240
        self.assertEqual(
799
1241
            SuccessfulSmartServerResponse(('ok', ), bz2.compress('')),
800
1242
            request.do_body('\n\n0\n'))
801
1243
 
 
1244
    def test_trivial_include_missing(self):
 
1245
        backing = self.get_transport()
 
1246
        request = smart.repository.SmartServerRepositoryGetParentMap(backing)
 
1247
        tree = self.make_branch_and_memory_tree('.')
 
1248
 
 
1249
        self.assertEqual(None,
 
1250
            request.execute('', 'missing-id', 'include-missing:'))
 
1251
        self.assertEqual(
 
1252
            SuccessfulSmartServerResponse(('ok', ),
 
1253
                bz2.compress('missing:missing-id')),
 
1254
            request.do_body('\n\n0\n'))
 
1255
 
802
1256
 
803
1257
class TestSmartServerRepositoryGetRevisionGraph(tests.TestCaseWithMemoryTransport):
804
1258
 
834
1288
 
835
1289
        self.assertEqual(SmartServerResponse(('ok', ), rev_id_utf8),
836
1290
            request.execute('', rev_id_utf8))
837
 
    
 
1291
 
838
1292
    def test_no_such_revision(self):
839
1293
        backing = self.get_transport()
840
1294
        request = smart.repository.SmartServerRepositoryGetRevisionGraph(backing)
850
1304
            request.execute('', 'missingrevision'))
851
1305
 
852
1306
 
 
1307
class TestSmartServerRepositoryGetRevIdForRevno(tests.TestCaseWithMemoryTransport):
 
1308
 
 
1309
    def test_revno_found(self):
 
1310
        backing = self.get_transport()
 
1311
        request = smart.repository.SmartServerRepositoryGetRevIdForRevno(backing)
 
1312
        tree = self.make_branch_and_memory_tree('.')
 
1313
        tree.lock_write()
 
1314
        tree.add('')
 
1315
        rev1_id_utf8 = u'\xc8'.encode('utf-8')
 
1316
        rev2_id_utf8 = u'\xc9'.encode('utf-8')
 
1317
        tree.commit('1st commit', rev_id=rev1_id_utf8)
 
1318
        tree.commit('2nd commit', rev_id=rev2_id_utf8)
 
1319
        tree.unlock()
 
1320
 
 
1321
        self.assertEqual(SmartServerResponse(('ok', rev1_id_utf8)),
 
1322
            request.execute('', 1, (2, rev2_id_utf8)))
 
1323
 
 
1324
    def test_known_revid_missing(self):
 
1325
        backing = self.get_transport()
 
1326
        request = smart.repository.SmartServerRepositoryGetRevIdForRevno(backing)
 
1327
        repo = self.make_repository('.')
 
1328
        self.assertEqual(
 
1329
            FailedSmartServerResponse(('nosuchrevision', 'ghost')),
 
1330
            request.execute('', 1, (2, 'ghost')))
 
1331
 
 
1332
    def test_history_incomplete(self):
 
1333
        backing = self.get_transport()
 
1334
        request = smart.repository.SmartServerRepositoryGetRevIdForRevno(backing)
 
1335
        parent = self.make_branch_and_memory_tree('parent', format='1.9')
 
1336
        parent.lock_write()
 
1337
        parent.add([''], ['TREE_ROOT'])
 
1338
        r1 = parent.commit(message='first commit')
 
1339
        r2 = parent.commit(message='second commit')
 
1340
        parent.unlock()
 
1341
        local = self.make_branch_and_memory_tree('local', format='1.9')
 
1342
        local.branch.pull(parent.branch)
 
1343
        local.set_parent_ids([r2])
 
1344
        r3 = local.commit(message='local commit')
 
1345
        local.branch.create_clone_on_transport(
 
1346
            self.get_transport('stacked'), stacked_on=self.get_url('parent'))
 
1347
        self.assertEqual(
 
1348
            SmartServerResponse(('history-incomplete', 2, r2)),
 
1349
            request.execute('stacked', 1, (3, r3)))
 
1350
 
 
1351
 
 
1352
class TestSmartServerRepositoryGetStream(tests.TestCaseWithMemoryTransport):
 
1353
 
 
1354
    def make_two_commit_repo(self):
 
1355
        tree = self.make_branch_and_memory_tree('.')
 
1356
        tree.lock_write()
 
1357
        tree.add('')
 
1358
        r1 = tree.commit('1st commit')
 
1359
        r2 = tree.commit('2nd commit', rev_id=u'\xc8'.encode('utf-8'))
 
1360
        tree.unlock()
 
1361
        repo = tree.branch.repository
 
1362
        return repo, r1, r2
 
1363
 
 
1364
    def test_ancestry_of(self):
 
1365
        """The search argument may be a 'ancestry-of' some heads'."""
 
1366
        backing = self.get_transport()
 
1367
        request = smart.repository.SmartServerRepositoryGetStream(backing)
 
1368
        repo, r1, r2 = self.make_two_commit_repo()
 
1369
        fetch_spec = ['ancestry-of', r2]
 
1370
        lines = '\n'.join(fetch_spec)
 
1371
        request.execute('', repo._format.network_name())
 
1372
        response = request.do_body(lines)
 
1373
        self.assertEqual(('ok',), response.args)
 
1374
        stream_bytes = ''.join(response.body_stream)
 
1375
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
 
1376
 
 
1377
    def test_search(self):
 
1378
        """The search argument may be a 'search' of some explicit keys."""
 
1379
        backing = self.get_transport()
 
1380
        request = smart.repository.SmartServerRepositoryGetStream(backing)
 
1381
        repo, r1, r2 = self.make_two_commit_repo()
 
1382
        fetch_spec = ['search', '%s %s' % (r1, r2), 'null:', '2']
 
1383
        lines = '\n'.join(fetch_spec)
 
1384
        request.execute('', repo._format.network_name())
 
1385
        response = request.do_body(lines)
 
1386
        self.assertEqual(('ok',), response.args)
 
1387
        stream_bytes = ''.join(response.body_stream)
 
1388
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
 
1389
 
 
1390
 
853
1391
class TestSmartServerRequestHasRevision(tests.TestCaseWithMemoryTransport):
854
1392
 
855
1393
    def test_missing_revision(self):
955
1493
 
956
1494
class TestSmartServerRepositoryLockWrite(tests.TestCaseWithMemoryTransport):
957
1495
 
958
 
    def setUp(self):
959
 
        tests.TestCaseWithMemoryTransport.setUp(self)
960
 
 
961
1496
    def test_lock_write_on_unlocked_repo(self):
962
1497
        backing = self.get_transport()
963
1498
        request = smart.repository.SmartServerRepositoryLockWrite(backing)
969
1504
        # object.
970
1505
        new_repo = repository.bzrdir.open_repository()
971
1506
        self.assertRaises(errors.LockContention, new_repo.lock_write)
 
1507
        # Cleanup
 
1508
        request = smart.repository.SmartServerRepositoryUnlock(backing)
 
1509
        response = request.execute('', nonce)
972
1510
 
973
1511
    def test_lock_write_on_locked_repo(self):
974
1512
        backing = self.get_transport()
975
1513
        request = smart.repository.SmartServerRepositoryLockWrite(backing)
976
1514
        repository = self.make_repository('.', format='knit')
977
 
        repository.lock_write()
 
1515
        repo_token = repository.lock_write()
978
1516
        repository.leave_lock_in_place()
979
1517
        repository.unlock()
980
1518
        response = request.execute('')
981
1519
        self.assertEqual(
982
1520
            SmartServerResponse(('LockContention',)), response)
 
1521
        # Cleanup
 
1522
        repository.lock_write(repo_token)
 
1523
        repository.dont_leave_lock_in_place()
 
1524
        repository.unlock()
983
1525
 
984
1526
    def test_lock_write_on_readonly_transport(self):
985
1527
        backing = self.get_readonly_transport()
990
1532
        self.assertEqual('LockFailed', response.args[0])
991
1533
 
992
1534
 
 
1535
class TestInsertStreamBase(tests.TestCaseWithMemoryTransport):
 
1536
 
 
1537
    def make_empty_byte_stream(self, repo):
 
1538
        byte_stream = smart.repository._stream_to_byte_stream([], repo._format)
 
1539
        return ''.join(byte_stream)
 
1540
 
 
1541
 
 
1542
class TestSmartServerRepositoryInsertStream(TestInsertStreamBase):
 
1543
 
 
1544
    def test_insert_stream_empty(self):
 
1545
        backing = self.get_transport()
 
1546
        request = smart.repository.SmartServerRepositoryInsertStream(backing)
 
1547
        repository = self.make_repository('.')
 
1548
        response = request.execute('', '')
 
1549
        self.assertEqual(None, response)
 
1550
        response = request.do_chunk(self.make_empty_byte_stream(repository))
 
1551
        self.assertEqual(None, response)
 
1552
        response = request.do_end()
 
1553
        self.assertEqual(SmartServerResponse(('ok', )), response)
 
1554
        
 
1555
 
 
1556
class TestSmartServerRepositoryInsertStreamLocked(TestInsertStreamBase):
 
1557
 
 
1558
    def test_insert_stream_empty(self):
 
1559
        backing = self.get_transport()
 
1560
        request = smart.repository.SmartServerRepositoryInsertStreamLocked(
 
1561
            backing)
 
1562
        repository = self.make_repository('.', format='knit')
 
1563
        lock_token = repository.lock_write()
 
1564
        response = request.execute('', '', lock_token)
 
1565
        self.assertEqual(None, response)
 
1566
        response = request.do_chunk(self.make_empty_byte_stream(repository))
 
1567
        self.assertEqual(None, response)
 
1568
        response = request.do_end()
 
1569
        self.assertEqual(SmartServerResponse(('ok', )), response)
 
1570
        repository.unlock()
 
1571
 
 
1572
    def test_insert_stream_with_wrong_lock_token(self):
 
1573
        backing = self.get_transport()
 
1574
        request = smart.repository.SmartServerRepositoryInsertStreamLocked(
 
1575
            backing)
 
1576
        repository = self.make_repository('.', format='knit')
 
1577
        lock_token = repository.lock_write()
 
1578
        self.assertRaises(
 
1579
            errors.TokenMismatch, request.execute, '', '', 'wrong-token')
 
1580
        repository.unlock()
 
1581
 
 
1582
 
993
1583
class TestSmartServerRepositoryUnlock(tests.TestCaseWithMemoryTransport):
994
1584
 
995
1585
    def setUp(self):
1037
1627
            SmartServerResponse(('yes',)), response)
1038
1628
 
1039
1629
 
 
1630
class TestSmartServerRepositorySetMakeWorkingTrees(tests.TestCaseWithMemoryTransport):
 
1631
 
 
1632
    def test_set_false(self):
 
1633
        backing = self.get_transport()
 
1634
        repo = self.make_repository('.', shared=True)
 
1635
        repo.set_make_working_trees(True)
 
1636
        request_class = smart.repository.SmartServerRepositorySetMakeWorkingTrees
 
1637
        request = request_class(backing)
 
1638
        self.assertEqual(SuccessfulSmartServerResponse(('ok',)),
 
1639
            request.execute('', 'False'))
 
1640
        repo = repo.bzrdir.open_repository()
 
1641
        self.assertFalse(repo.make_working_trees())
 
1642
 
 
1643
    def test_set_true(self):
 
1644
        backing = self.get_transport()
 
1645
        repo = self.make_repository('.', shared=True)
 
1646
        repo.set_make_working_trees(False)
 
1647
        request_class = smart.repository.SmartServerRepositorySetMakeWorkingTrees
 
1648
        request = request_class(backing)
 
1649
        self.assertEqual(SuccessfulSmartServerResponse(('ok',)),
 
1650
            request.execute('', 'True'))
 
1651
        repo = repo.bzrdir.open_repository()
 
1652
        self.assertTrue(repo.make_working_trees())
 
1653
 
 
1654
 
1040
1655
class TestSmartServerPackRepositoryAutopack(tests.TestCaseWithTransport):
1041
1656
 
1042
1657
    def make_repo_needing_autopacking(self, path='.'):
1053
1668
 
1054
1669
    def test_autopack_needed(self):
1055
1670
        repo = self.make_repo_needing_autopacking()
 
1671
        repo.lock_write()
 
1672
        self.addCleanup(repo.unlock)
1056
1673
        backing = self.get_transport()
1057
1674
        request = smart.packrepository.SmartServerPackRepositoryAutopack(
1058
1675
            backing)
1060
1677
        self.assertEqual(SmartServerResponse(('ok',)), response)
1061
1678
        repo._pack_collection.reload_pack_names()
1062
1679
        self.assertEqual(1, len(repo._pack_collection.names()))
1063
 
    
 
1680
 
1064
1681
    def test_autopack_not_needed(self):
1065
1682
        tree = self.make_branch_and_tree('.', format='pack-0.92')
1066
1683
        repo = tree.branch.repository
 
1684
        repo.lock_write()
 
1685
        self.addCleanup(repo.unlock)
1067
1686
        for x in range(9):
1068
1687
            tree.commit('commit %s' % x)
1069
1688
        backing = self.get_transport()
1073
1692
        self.assertEqual(SmartServerResponse(('ok',)), response)
1074
1693
        repo._pack_collection.reload_pack_names()
1075
1694
        self.assertEqual(9, len(repo._pack_collection.names()))
1076
 
    
 
1695
 
1077
1696
    def test_autopack_on_nonpack_format(self):
1078
1697
        """A request to autopack a non-pack repo is a no-op."""
1079
1698
        repo = self.make_repository('.', format='knit')
1082
1701
            backing)
1083
1702
        response = request.execute('')
1084
1703
        self.assertEqual(SmartServerResponse(('ok',)), response)
1085
 
        
 
1704
 
 
1705
 
 
1706
class TestSmartServerVfsGet(tests.TestCaseWithMemoryTransport):
 
1707
 
 
1708
    def test_unicode_path(self):
 
1709
        """VFS requests expect unicode paths to be escaped."""
 
1710
        filename = u'foo\N{INTERROBANG}'
 
1711
        filename_escaped = urlutils.escape(filename)
 
1712
        backing = self.get_transport()
 
1713
        request = smart.vfs.GetRequest(backing)
 
1714
        backing.put_bytes_non_atomic(filename_escaped, 'contents')
 
1715
        self.assertEqual(SmartServerResponse(('ok', ), 'contents'),
 
1716
            request.execute(filename_escaped))
 
1717
 
1086
1718
 
1087
1719
class TestHandlers(tests.TestCase):
1088
1720
    """Tests for the request.request_handlers object."""
1094
1726
        for key, item in smart.request.request_handlers.iteritems():
1095
1727
            pass
1096
1728
 
 
1729
    def assertHandlerEqual(self, verb, handler):
 
1730
        self.assertEqual(smart.request.request_handlers.get(verb), handler)
 
1731
 
1097
1732
    def test_registered_methods(self):
1098
1733
        """Test that known methods are registered to the correct object."""
1099
 
        self.assertEqual(
1100
 
            smart.request.request_handlers.get('Branch.get_config_file'),
 
1734
        self.assertHandlerEqual('Branch.get_config_file',
1101
1735
            smart.branch.SmartServerBranchGetConfigFile)
1102
 
        self.assertEqual(
1103
 
            smart.request.request_handlers.get('Branch.lock_write'),
 
1736
        self.assertHandlerEqual('Branch.get_parent',
 
1737
            smart.branch.SmartServerBranchGetParent)
 
1738
        self.assertHandlerEqual('Branch.get_tags_bytes',
 
1739
            smart.branch.SmartServerBranchGetTagsBytes)
 
1740
        self.assertHandlerEqual('Branch.lock_write',
1104
1741
            smart.branch.SmartServerBranchRequestLockWrite)
1105
 
        self.assertEqual(
1106
 
            smart.request.request_handlers.get('Branch.last_revision_info'),
 
1742
        self.assertHandlerEqual('Branch.last_revision_info',
1107
1743
            smart.branch.SmartServerBranchRequestLastRevisionInfo)
1108
 
        self.assertEqual(
1109
 
            smart.request.request_handlers.get('Branch.revision_history'),
 
1744
        self.assertHandlerEqual('Branch.revision_history',
1110
1745
            smart.branch.SmartServerRequestRevisionHistory)
1111
 
        self.assertEqual(
1112
 
            smart.request.request_handlers.get('Branch.set_last_revision'),
 
1746
        self.assertHandlerEqual('Branch.set_config_option',
 
1747
            smart.branch.SmartServerBranchRequestSetConfigOption)
 
1748
        self.assertHandlerEqual('Branch.set_last_revision',
1113
1749
            smart.branch.SmartServerBranchRequestSetLastRevision)
1114
 
        self.assertEqual(
1115
 
            smart.request.request_handlers.get('Branch.set_last_revision_info'),
 
1750
        self.assertHandlerEqual('Branch.set_last_revision_info',
1116
1751
            smart.branch.SmartServerBranchRequestSetLastRevisionInfo)
1117
 
        self.assertEqual(
1118
 
            smart.request.request_handlers.get('Branch.unlock'),
 
1752
        self.assertHandlerEqual('Branch.set_last_revision_ex',
 
1753
            smart.branch.SmartServerBranchRequestSetLastRevisionEx)
 
1754
        self.assertHandlerEqual('Branch.set_parent_location',
 
1755
            smart.branch.SmartServerBranchRequestSetParentLocation)
 
1756
        self.assertHandlerEqual('Branch.unlock',
1119
1757
            smart.branch.SmartServerBranchRequestUnlock)
1120
 
        self.assertEqual(
1121
 
            smart.request.request_handlers.get('BzrDir.find_repository'),
 
1758
        self.assertHandlerEqual('BzrDir.find_repository',
1122
1759
            smart.bzrdir.SmartServerRequestFindRepositoryV1)
1123
 
        self.assertEqual(
1124
 
            smart.request.request_handlers.get('BzrDir.find_repositoryV2'),
 
1760
        self.assertHandlerEqual('BzrDir.find_repositoryV2',
1125
1761
            smart.bzrdir.SmartServerRequestFindRepositoryV2)
1126
 
        self.assertEqual(
1127
 
            smart.request.request_handlers.get('BzrDirFormat.initialize'),
 
1762
        self.assertHandlerEqual('BzrDirFormat.initialize',
1128
1763
            smart.bzrdir.SmartServerRequestInitializeBzrDir)
1129
 
        self.assertEqual(
1130
 
            smart.request.request_handlers.get('BzrDir.open_branch'),
 
1764
        self.assertHandlerEqual('BzrDirFormat.initialize_ex_1.16',
 
1765
            smart.bzrdir.SmartServerRequestBzrDirInitializeEx)
 
1766
        self.assertHandlerEqual('BzrDir.cloning_metadir',
 
1767
            smart.bzrdir.SmartServerBzrDirRequestCloningMetaDir)
 
1768
        self.assertHandlerEqual('BzrDir.get_config_file',
 
1769
            smart.bzrdir.SmartServerBzrDirRequestConfigFile)
 
1770
        self.assertHandlerEqual('BzrDir.open_branch',
1131
1771
            smart.bzrdir.SmartServerRequestOpenBranch)
1132
 
        self.assertEqual(
1133
 
            smart.request.request_handlers.get('PackRepository.autopack'),
 
1772
        self.assertHandlerEqual('BzrDir.open_branchV2',
 
1773
            smart.bzrdir.SmartServerRequestOpenBranchV2)
 
1774
        self.assertHandlerEqual('PackRepository.autopack',
1134
1775
            smart.packrepository.SmartServerPackRepositoryAutopack)
1135
 
        self.assertEqual(
1136
 
            smart.request.request_handlers.get('Repository.gather_stats'),
 
1776
        self.assertHandlerEqual('Repository.gather_stats',
1137
1777
            smart.repository.SmartServerRepositoryGatherStats)
1138
 
        self.assertEqual(
1139
 
            smart.request.request_handlers.get('Repository.get_parent_map'),
 
1778
        self.assertHandlerEqual('Repository.get_parent_map',
1140
1779
            smart.repository.SmartServerRepositoryGetParentMap)
1141
 
        self.assertEqual(
1142
 
            smart.request.request_handlers.get(
1143
 
                'Repository.get_revision_graph'),
 
1780
        self.assertHandlerEqual('Repository.get_rev_id_for_revno',
 
1781
            smart.repository.SmartServerRepositoryGetRevIdForRevno)
 
1782
        self.assertHandlerEqual('Repository.get_revision_graph',
1144
1783
            smart.repository.SmartServerRepositoryGetRevisionGraph)
1145
 
        self.assertEqual(
1146
 
            smart.request.request_handlers.get('Repository.has_revision'),
 
1784
        self.assertHandlerEqual('Repository.get_stream',
 
1785
            smart.repository.SmartServerRepositoryGetStream)
 
1786
        self.assertHandlerEqual('Repository.has_revision',
1147
1787
            smart.repository.SmartServerRequestHasRevision)
1148
 
        self.assertEqual(
1149
 
            smart.request.request_handlers.get('Repository.is_shared'),
 
1788
        self.assertHandlerEqual('Repository.insert_stream',
 
1789
            smart.repository.SmartServerRepositoryInsertStream)
 
1790
        self.assertHandlerEqual('Repository.insert_stream_locked',
 
1791
            smart.repository.SmartServerRepositoryInsertStreamLocked)
 
1792
        self.assertHandlerEqual('Repository.is_shared',
1150
1793
            smart.repository.SmartServerRepositoryIsShared)
1151
 
        self.assertEqual(
1152
 
            smart.request.request_handlers.get('Repository.lock_write'),
 
1794
        self.assertHandlerEqual('Repository.lock_write',
1153
1795
            smart.repository.SmartServerRepositoryLockWrite)
1154
 
        self.assertEqual(
1155
 
            smart.request.request_handlers.get('Repository.tarball'),
 
1796
        self.assertHandlerEqual('Repository.tarball',
1156
1797
            smart.repository.SmartServerRepositoryTarball)
1157
 
        self.assertEqual(
1158
 
            smart.request.request_handlers.get('Repository.unlock'),
 
1798
        self.assertHandlerEqual('Repository.unlock',
1159
1799
            smart.repository.SmartServerRepositoryUnlock)
1160
 
        self.assertEqual(
1161
 
            smart.request.request_handlers.get('Transport.is_readonly'),
 
1800
        self.assertHandlerEqual('Transport.is_readonly',
1162
1801
            smart.request.SmartServerIsReadonly)