~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_smart.py

  • Committer: Robert Collins
  • Date: 2010-01-28 18:05:44 UTC
  • mto: (4797.2.5 2.1)
  • mto: This revision was merged to the branch mainline in revision 4989.
  • Revision ID: robertc@robertcollins.net-20100128180544-6l8x7o7obaq7b51x
Tweak ConfigurableFileMerger to use class variables rather than requiring __init__ wrapping as future proofing for helper functions.

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')
301
524
        self.assertEqual(SmartServerResponse(('ok', reference_url)),
302
525
            request.execute('reference'))
303
526
 
 
527
    def test_notification_on_branch_from_repository(self):
 
528
        """When there is a repository, the error should return details."""
 
529
        backing = self.get_transport()
 
530
        request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
 
531
        repo = self.make_repository('.')
 
532
        self.assertEqual(SmartServerResponse(('nobranch',)),
 
533
            request.execute(''))
 
534
 
 
535
 
 
536
class TestSmartServerRequestOpenBranchV2(TestCaseWithChrootedTransport):
 
537
 
 
538
    def test_no_branch(self):
 
539
        """When there is no branch, ('nobranch', ) is returned."""
 
540
        backing = self.get_transport()
 
541
        self.make_bzrdir('.')
 
542
        request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
 
543
        self.assertEqual(SmartServerResponse(('nobranch', )),
 
544
            request.execute(''))
 
545
 
 
546
    def test_branch(self):
 
547
        """When there is a branch, 'ok' is returned."""
 
548
        backing = self.get_transport()
 
549
        expected = self.make_branch('.')._format.network_name()
 
550
        request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
 
551
        self.assertEqual(SuccessfulSmartServerResponse(('branch', expected)),
 
552
            request.execute(''))
 
553
 
 
554
    def test_branch_reference(self):
 
555
        """When there is a branch reference, the reference URL is returned."""
 
556
        self.vfs_transport_factory = local.LocalURLServer
 
557
        backing = self.get_transport()
 
558
        request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
 
559
        branch = self.make_branch('branch')
 
560
        checkout = branch.create_checkout('reference',lightweight=True)
 
561
        reference_url = BranchReferenceFormat().get_reference(checkout.bzrdir)
 
562
        self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
 
563
        self.assertEqual(SuccessfulSmartServerResponse(('ref', reference_url)),
 
564
            request.execute('reference'))
 
565
 
 
566
    def test_stacked_branch(self):
 
567
        """Opening a stacked branch does not open the stacked-on branch."""
 
568
        trunk = self.make_branch('trunk')
 
569
        feature = self.make_branch('feature')
 
570
        feature.set_stacked_on_url(trunk.base)
 
571
        opened_branches = []
 
572
        Branch.hooks.install_named_hook('open', opened_branches.append, None)
 
573
        backing = self.get_transport()
 
574
        request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
 
575
        request.setup_jail()
 
576
        try:
 
577
            response = request.execute('feature')
 
578
        finally:
 
579
            request.teardown_jail()
 
580
        expected_format = feature._format.network_name()
 
581
        self.assertEqual(
 
582
            SuccessfulSmartServerResponse(('branch', expected_format)),
 
583
            response)
 
584
        self.assertLength(1, opened_branches)
 
585
 
 
586
    def test_notification_on_branch_from_repository(self):
 
587
        """When there is a repository, the error should return details."""
 
588
        backing = self.get_transport()
 
589
        request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
 
590
        repo = self.make_repository('.')
 
591
        self.assertEqual(SmartServerResponse(('nobranch',)),
 
592
            request.execute(''))
 
593
 
 
594
 
 
595
class TestSmartServerRequestOpenBranchV3(TestCaseWithChrootedTransport):
 
596
 
 
597
    def test_no_branch(self):
 
598
        """When there is no branch, ('nobranch', ) is returned."""
 
599
        backing = self.get_transport()
 
600
        self.make_bzrdir('.')
 
601
        request = smart.bzrdir.SmartServerRequestOpenBranchV3(backing)
 
602
        self.assertEqual(SmartServerResponse(('nobranch',)),
 
603
            request.execute(''))
 
604
 
 
605
    def test_branch(self):
 
606
        """When there is a branch, 'ok' is returned."""
 
607
        backing = self.get_transport()
 
608
        expected = self.make_branch('.')._format.network_name()
 
609
        request = smart.bzrdir.SmartServerRequestOpenBranchV3(backing)
 
610
        self.assertEqual(SuccessfulSmartServerResponse(('branch', expected)),
 
611
            request.execute(''))
 
612
 
 
613
    def test_branch_reference(self):
 
614
        """When there is a branch reference, the reference URL is returned."""
 
615
        self.vfs_transport_factory = local.LocalURLServer
 
616
        backing = self.get_transport()
 
617
        request = smart.bzrdir.SmartServerRequestOpenBranchV3(backing)
 
618
        branch = self.make_branch('branch')
 
619
        checkout = branch.create_checkout('reference',lightweight=True)
 
620
        reference_url = BranchReferenceFormat().get_reference(checkout.bzrdir)
 
621
        self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
 
622
        self.assertEqual(SuccessfulSmartServerResponse(('ref', reference_url)),
 
623
            request.execute('reference'))
 
624
 
 
625
    def test_stacked_branch(self):
 
626
        """Opening a stacked branch does not open the stacked-on branch."""
 
627
        trunk = self.make_branch('trunk')
 
628
        feature = self.make_branch('feature')
 
629
        feature.set_stacked_on_url(trunk.base)
 
630
        opened_branches = []
 
631
        Branch.hooks.install_named_hook('open', opened_branches.append, None)
 
632
        backing = self.get_transport()
 
633
        request = smart.bzrdir.SmartServerRequestOpenBranchV3(backing)
 
634
        request.setup_jail()
 
635
        try:
 
636
            response = request.execute('feature')
 
637
        finally:
 
638
            request.teardown_jail()
 
639
        expected_format = feature._format.network_name()
 
640
        self.assertEqual(
 
641
            SuccessfulSmartServerResponse(('branch', expected_format)),
 
642
            response)
 
643
        self.assertLength(1, opened_branches)
 
644
 
 
645
    def test_notification_on_branch_from_repository(self):
 
646
        """When there is a repository, the error should return details."""
 
647
        backing = self.get_transport()
 
648
        request = smart.bzrdir.SmartServerRequestOpenBranchV3(backing)
 
649
        repo = self.make_repository('.')
 
650
        self.assertEqual(
 
651
            SmartServerResponse(('nobranch', 'location is a repository')),
 
652
            request.execute(''))
 
653
 
304
654
 
305
655
class TestSmartServerRequestRevisionHistory(tests.TestCaseWithMemoryTransport):
306
656
 
388
738
    def test_with_content(self):
389
739
        # SmartServerBranchGetConfigFile should return the content from
390
740
        # branch.control_files.get('branch.conf') for now - in the future it may
391
 
        # perform more complex processing. 
 
741
        # perform more complex processing.
392
742
        backing = self.get_transport()
393
743
        request = smart.branch.SmartServerBranchGetConfigFile(backing)
394
744
        branch = self.make_branch('.')
397
747
            request.execute(''))
398
748
 
399
749
 
400
 
class SetLastRevisionTestBase(tests.TestCaseWithMemoryTransport):
 
750
class TestLockedBranch(tests.TestCaseWithMemoryTransport):
 
751
 
 
752
    def get_lock_tokens(self, branch):
 
753
        branch_token = branch.lock_write()
 
754
        repo_token = branch.repository.lock_write()
 
755
        branch.repository.unlock()
 
756
        return branch_token, repo_token
 
757
 
 
758
 
 
759
class TestSmartServerBranchRequestSetConfigOption(TestLockedBranch):
 
760
 
 
761
    def test_value_name(self):
 
762
        branch = self.make_branch('.')
 
763
        request = smart.branch.SmartServerBranchRequestSetConfigOption(
 
764
            branch.bzrdir.root_transport)
 
765
        branch_token, repo_token = self.get_lock_tokens(branch)
 
766
        config = branch._get_config()
 
767
        result = request.execute('', branch_token, repo_token, 'bar', 'foo',
 
768
            '')
 
769
        self.assertEqual(SuccessfulSmartServerResponse(()), result)
 
770
        self.assertEqual('bar', config.get_option('foo'))
 
771
        # Cleanup
 
772
        branch.unlock()
 
773
 
 
774
    def test_value_name_section(self):
 
775
        branch = self.make_branch('.')
 
776
        request = smart.branch.SmartServerBranchRequestSetConfigOption(
 
777
            branch.bzrdir.root_transport)
 
778
        branch_token, repo_token = self.get_lock_tokens(branch)
 
779
        config = branch._get_config()
 
780
        result = request.execute('', branch_token, repo_token, 'bar', 'foo',
 
781
            'gam')
 
782
        self.assertEqual(SuccessfulSmartServerResponse(()), result)
 
783
        self.assertEqual('bar', config.get_option('foo', 'gam'))
 
784
        # Cleanup
 
785
        branch.unlock()
 
786
 
 
787
 
 
788
class TestSmartServerBranchRequestSetTagsBytes(TestLockedBranch):
 
789
    # Only called when the branch format and tags match [yay factory
 
790
    # methods] so only need to test straight forward cases.
 
791
 
 
792
    def test_set_bytes(self):
 
793
        base_branch = self.make_branch('base')
 
794
        tag_bytes = base_branch._get_tags_bytes()
 
795
        # get_lock_tokens takes out a lock.
 
796
        branch_token, repo_token = self.get_lock_tokens(base_branch)
 
797
        request = smart.branch.SmartServerBranchSetTagsBytes(
 
798
            self.get_transport())
 
799
        response = request.execute('base', branch_token, repo_token)
 
800
        self.assertEqual(None, response)
 
801
        response = request.do_chunk(tag_bytes)
 
802
        self.assertEqual(None, response)
 
803
        response = request.do_end()
 
804
        self.assertEquals(
 
805
            SuccessfulSmartServerResponse(()), response)
 
806
        base_branch.unlock()
 
807
 
 
808
    def test_lock_failed(self):
 
809
        base_branch = self.make_branch('base')
 
810
        base_branch.lock_write()
 
811
        tag_bytes = base_branch._get_tags_bytes()
 
812
        request = smart.branch.SmartServerBranchSetTagsBytes(
 
813
            self.get_transport())
 
814
        self.assertRaises(errors.TokenMismatch, request.execute,
 
815
            'base', 'wrong token', 'wrong token')
 
816
        # The request handler will keep processing the message parts, so even
 
817
        # if the request fails immediately do_chunk and do_end are still
 
818
        # called.
 
819
        request.do_chunk(tag_bytes)
 
820
        request.do_end()
 
821
        base_branch.unlock()
 
822
 
 
823
 
 
824
 
 
825
class SetLastRevisionTestBase(TestLockedBranch):
401
826
    """Base test case for verbs that implement set_last_revision."""
402
827
 
403
828
    def setUp(self):
407
832
        self.tree = self.make_branch_and_memory_tree('.')
408
833
 
409
834
    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
 
835
        return self.get_lock_tokens(self.tree.branch)
415
836
 
416
837
    def unlock_branch(self):
417
838
        self.tree.branch.unlock()
418
 
        
 
839
 
419
840
    def set_last_revision(self, revision_id, revno):
420
841
        branch_token, repo_token = self.lock_branch()
421
842
        response = self._set_last_revision(
427
848
        response = self.set_last_revision(revision_id, revno)
428
849
        self.assertEqual(SuccessfulSmartServerResponse(('ok',)), response)
429
850
 
430
 
        
 
851
 
431
852
class TestSetLastRevisionVerbMixin(object):
432
853
    """Mixin test case for verbs that implement set_last_revision."""
433
854
 
538
959
        self.assertEqual(
539
960
            SuccessfulSmartServerResponse(('ok', revno, revision_id)),
540
961
            response)
541
 
        
 
962
 
542
963
    def test_branch_last_revision_info_rewind(self):
543
964
        """A branch's tip can be set to a revision that is an ancestor of the
544
965
        current tip, but only if allow_overwrite_descendant is passed.
587
1008
        # child-1.
588
1009
        new_r2 = self.tree.commit('2nd commit', rev_id='child-2')
589
1010
        self.tree.unlock()
590
 
        
 
1011
 
591
1012
    def test_not_allow_diverged(self):
592
1013
        """If allow_diverged is not passed, then setting a divergent history
593
1014
        returns a Diverged error.
615
1036
        self.assertEqual('child-1', self.tree.branch.last_revision())
616
1037
 
617
1038
 
 
1039
class TestSmartServerBranchRequestGetParent(tests.TestCaseWithMemoryTransport):
 
1040
 
 
1041
    def test_get_parent_none(self):
 
1042
        base_branch = self.make_branch('base')
 
1043
        request = smart.branch.SmartServerBranchGetParent(self.get_transport())
 
1044
        response = request.execute('base')
 
1045
        self.assertEquals(
 
1046
            SuccessfulSmartServerResponse(('',)), response)
 
1047
 
 
1048
    def test_get_parent_something(self):
 
1049
        base_branch = self.make_branch('base')
 
1050
        base_branch.set_parent(self.get_url('foo'))
 
1051
        request = smart.branch.SmartServerBranchGetParent(self.get_transport())
 
1052
        response = request.execute('base')
 
1053
        self.assertEquals(
 
1054
            SuccessfulSmartServerResponse(("../foo",)),
 
1055
            response)
 
1056
 
 
1057
 
 
1058
class TestSmartServerBranchRequestSetParent(tests.TestCaseWithMemoryTransport):
 
1059
 
 
1060
    def test_set_parent_none(self):
 
1061
        branch = self.make_branch('base', format="1.9")
 
1062
        branch.lock_write()
 
1063
        branch._set_parent_location('foo')
 
1064
        branch.unlock()
 
1065
        request = smart.branch.SmartServerBranchRequestSetParentLocation(
 
1066
            self.get_transport())
 
1067
        branch_token = branch.lock_write()
 
1068
        repo_token = branch.repository.lock_write()
 
1069
        try:
 
1070
            response = request.execute('base', branch_token, repo_token, '')
 
1071
        finally:
 
1072
            branch.repository.unlock()
 
1073
            branch.unlock()
 
1074
        self.assertEqual(SuccessfulSmartServerResponse(()), response)
 
1075
        self.assertEqual(None, branch.get_parent())
 
1076
 
 
1077
    def test_set_parent_something(self):
 
1078
        branch = self.make_branch('base', format="1.9")
 
1079
        request = smart.branch.SmartServerBranchRequestSetParentLocation(
 
1080
            self.get_transport())
 
1081
        branch_token = branch.lock_write()
 
1082
        repo_token = branch.repository.lock_write()
 
1083
        try:
 
1084
            response = request.execute('base', branch_token, repo_token,
 
1085
            'http://bar/')
 
1086
        finally:
 
1087
            branch.repository.unlock()
 
1088
            branch.unlock()
 
1089
        self.assertEqual(SuccessfulSmartServerResponse(()), response)
 
1090
        self.assertEqual('http://bar/', branch.get_parent())
 
1091
 
 
1092
 
 
1093
class TestSmartServerBranchRequestGetTagsBytes(tests.TestCaseWithMemoryTransport):
 
1094
    # Only called when the branch format and tags match [yay factory
 
1095
    # methods] so only need to test straight forward cases.
 
1096
 
 
1097
    def test_get_bytes(self):
 
1098
        base_branch = self.make_branch('base')
 
1099
        request = smart.branch.SmartServerBranchGetTagsBytes(
 
1100
            self.get_transport())
 
1101
        response = request.execute('base')
 
1102
        self.assertEquals(
 
1103
            SuccessfulSmartServerResponse(('',)), response)
 
1104
 
 
1105
 
618
1106
class TestSmartServerBranchRequestGetStackedOnURL(tests.TestCaseWithMemoryTransport):
619
1107
 
620
1108
    def test_get_stacked_on_url(self):
650
1138
        # with a new branch object.
651
1139
        new_branch = repository.bzrdir.open_branch()
652
1140
        self.assertRaises(errors.LockContention, new_branch.lock_write)
 
1141
        # Cleanup
 
1142
        request = smart.branch.SmartServerBranchRequestUnlock(backing)
 
1143
        response = request.execute('', branch_nonce, repository_nonce)
653
1144
 
654
1145
    def test_lock_write_on_locked_branch(self):
655
1146
        backing = self.get_transport()
656
1147
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
657
1148
        branch = self.make_branch('.')
658
 
        branch.lock_write()
 
1149
        branch_token = branch.lock_write()
659
1150
        branch.leave_lock_in_place()
660
1151
        branch.unlock()
661
1152
        response = request.execute('')
662
1153
        self.assertEqual(
663
1154
            SmartServerResponse(('LockContention',)), response)
 
1155
        # Cleanup
 
1156
        branch.lock_write(branch_token)
 
1157
        branch.dont_leave_lock_in_place()
 
1158
        branch.unlock()
664
1159
 
665
1160
    def test_lock_write_with_tokens_on_locked_branch(self):
666
1161
        backing = self.get_transport()
676
1171
                                   branch_token, repo_token)
677
1172
        self.assertEqual(
678
1173
            SmartServerResponse(('ok', branch_token, repo_token)), response)
 
1174
        # Cleanup
 
1175
        branch.repository.lock_write(repo_token)
 
1176
        branch.repository.dont_leave_lock_in_place()
 
1177
        branch.repository.unlock()
 
1178
        branch.lock_write(branch_token)
 
1179
        branch.dont_leave_lock_in_place()
 
1180
        branch.unlock()
679
1181
 
680
1182
    def test_lock_write_with_mismatched_tokens_on_locked_branch(self):
681
1183
        backing = self.get_transport()
691
1193
                                   branch_token+'xxx', repo_token)
692
1194
        self.assertEqual(
693
1195
            SmartServerResponse(('TokenMismatch',)), response)
 
1196
        # Cleanup
 
1197
        branch.repository.lock_write(repo_token)
 
1198
        branch.repository.dont_leave_lock_in_place()
 
1199
        branch.repository.unlock()
 
1200
        branch.lock_write(branch_token)
 
1201
        branch.dont_leave_lock_in_place()
 
1202
        branch.unlock()
694
1203
 
695
1204
    def test_lock_write_on_locked_repo(self):
696
1205
        backing = self.get_transport()
697
1206
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
698
1207
        branch = self.make_branch('.', format='knit')
699
 
        branch.repository.lock_write()
700
 
        branch.repository.leave_lock_in_place()
701
 
        branch.repository.unlock()
 
1208
        repo = branch.repository
 
1209
        repo_token = repo.lock_write()
 
1210
        repo.leave_lock_in_place()
 
1211
        repo.unlock()
702
1212
        response = request.execute('')
703
1213
        self.assertEqual(
704
1214
            SmartServerResponse(('LockContention',)), response)
 
1215
        # Cleanup
 
1216
        repo.lock_write(repo_token)
 
1217
        repo.dont_leave_lock_in_place()
 
1218
        repo.unlock()
705
1219
 
706
1220
    def test_lock_write_on_readonly_transport(self):
707
1221
        backing = self.get_readonly_transport()
766
1280
            '', 'branch token', repo_token)
767
1281
        self.assertEqual(
768
1282
            SmartServerResponse(('TokenMismatch',)), response)
 
1283
        # Cleanup
 
1284
        branch.repository.lock_write(repo_token)
 
1285
        branch.repository.dont_leave_lock_in_place()
 
1286
        branch.repository.unlock()
769
1287
 
770
1288
 
771
1289
class TestSmartServerRepositoryRequest(tests.TestCaseWithMemoryTransport):
794
1312
 
795
1313
        self.assertEqual(None,
796
1314
            request.execute('', 'missing-id'))
797
 
        # Note that it returns a body (of '' bzipped).
 
1315
        # Note that it returns a body that is bzipped.
798
1316
        self.assertEqual(
799
1317
            SuccessfulSmartServerResponse(('ok', ), bz2.compress('')),
800
1318
            request.do_body('\n\n0\n'))
801
1319
 
 
1320
    def test_trivial_include_missing(self):
 
1321
        backing = self.get_transport()
 
1322
        request = smart.repository.SmartServerRepositoryGetParentMap(backing)
 
1323
        tree = self.make_branch_and_memory_tree('.')
 
1324
 
 
1325
        self.assertEqual(None,
 
1326
            request.execute('', 'missing-id', 'include-missing:'))
 
1327
        self.assertEqual(
 
1328
            SuccessfulSmartServerResponse(('ok', ),
 
1329
                bz2.compress('missing:missing-id')),
 
1330
            request.do_body('\n\n0\n'))
 
1331
 
802
1332
 
803
1333
class TestSmartServerRepositoryGetRevisionGraph(tests.TestCaseWithMemoryTransport):
804
1334
 
834
1364
 
835
1365
        self.assertEqual(SmartServerResponse(('ok', ), rev_id_utf8),
836
1366
            request.execute('', rev_id_utf8))
837
 
    
 
1367
 
838
1368
    def test_no_such_revision(self):
839
1369
        backing = self.get_transport()
840
1370
        request = smart.repository.SmartServerRepositoryGetRevisionGraph(backing)
850
1380
            request.execute('', 'missingrevision'))
851
1381
 
852
1382
 
 
1383
class TestSmartServerRepositoryGetRevIdForRevno(tests.TestCaseWithMemoryTransport):
 
1384
 
 
1385
    def test_revno_found(self):
 
1386
        backing = self.get_transport()
 
1387
        request = smart.repository.SmartServerRepositoryGetRevIdForRevno(backing)
 
1388
        tree = self.make_branch_and_memory_tree('.')
 
1389
        tree.lock_write()
 
1390
        tree.add('')
 
1391
        rev1_id_utf8 = u'\xc8'.encode('utf-8')
 
1392
        rev2_id_utf8 = u'\xc9'.encode('utf-8')
 
1393
        tree.commit('1st commit', rev_id=rev1_id_utf8)
 
1394
        tree.commit('2nd commit', rev_id=rev2_id_utf8)
 
1395
        tree.unlock()
 
1396
 
 
1397
        self.assertEqual(SmartServerResponse(('ok', rev1_id_utf8)),
 
1398
            request.execute('', 1, (2, rev2_id_utf8)))
 
1399
 
 
1400
    def test_known_revid_missing(self):
 
1401
        backing = self.get_transport()
 
1402
        request = smart.repository.SmartServerRepositoryGetRevIdForRevno(backing)
 
1403
        repo = self.make_repository('.')
 
1404
        self.assertEqual(
 
1405
            FailedSmartServerResponse(('nosuchrevision', 'ghost')),
 
1406
            request.execute('', 1, (2, 'ghost')))
 
1407
 
 
1408
    def test_history_incomplete(self):
 
1409
        backing = self.get_transport()
 
1410
        request = smart.repository.SmartServerRepositoryGetRevIdForRevno(backing)
 
1411
        parent = self.make_branch_and_memory_tree('parent', format='1.9')
 
1412
        parent.lock_write()
 
1413
        parent.add([''], ['TREE_ROOT'])
 
1414
        r1 = parent.commit(message='first commit')
 
1415
        r2 = parent.commit(message='second commit')
 
1416
        parent.unlock()
 
1417
        local = self.make_branch_and_memory_tree('local', format='1.9')
 
1418
        local.branch.pull(parent.branch)
 
1419
        local.set_parent_ids([r2])
 
1420
        r3 = local.commit(message='local commit')
 
1421
        local.branch.create_clone_on_transport(
 
1422
            self.get_transport('stacked'), stacked_on=self.get_url('parent'))
 
1423
        self.assertEqual(
 
1424
            SmartServerResponse(('history-incomplete', 2, r2)),
 
1425
            request.execute('stacked', 1, (3, r3)))
 
1426
 
 
1427
 
 
1428
class TestSmartServerRepositoryGetStream(tests.TestCaseWithMemoryTransport):
 
1429
 
 
1430
    def make_two_commit_repo(self):
 
1431
        tree = self.make_branch_and_memory_tree('.')
 
1432
        tree.lock_write()
 
1433
        tree.add('')
 
1434
        r1 = tree.commit('1st commit')
 
1435
        r2 = tree.commit('2nd commit', rev_id=u'\xc8'.encode('utf-8'))
 
1436
        tree.unlock()
 
1437
        repo = tree.branch.repository
 
1438
        return repo, r1, r2
 
1439
 
 
1440
    def test_ancestry_of(self):
 
1441
        """The search argument may be a 'ancestry-of' some heads'."""
 
1442
        backing = self.get_transport()
 
1443
        request = smart.repository.SmartServerRepositoryGetStream(backing)
 
1444
        repo, r1, r2 = self.make_two_commit_repo()
 
1445
        fetch_spec = ['ancestry-of', r2]
 
1446
        lines = '\n'.join(fetch_spec)
 
1447
        request.execute('', repo._format.network_name())
 
1448
        response = request.do_body(lines)
 
1449
        self.assertEqual(('ok',), response.args)
 
1450
        stream_bytes = ''.join(response.body_stream)
 
1451
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
 
1452
 
 
1453
    def test_search(self):
 
1454
        """The search argument may be a 'search' of some explicit keys."""
 
1455
        backing = self.get_transport()
 
1456
        request = smart.repository.SmartServerRepositoryGetStream(backing)
 
1457
        repo, r1, r2 = self.make_two_commit_repo()
 
1458
        fetch_spec = ['search', '%s %s' % (r1, r2), 'null:', '2']
 
1459
        lines = '\n'.join(fetch_spec)
 
1460
        request.execute('', repo._format.network_name())
 
1461
        response = request.do_body(lines)
 
1462
        self.assertEqual(('ok',), response.args)
 
1463
        stream_bytes = ''.join(response.body_stream)
 
1464
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
 
1465
 
 
1466
 
853
1467
class TestSmartServerRequestHasRevision(tests.TestCaseWithMemoryTransport):
854
1468
 
855
1469
    def test_missing_revision(self):
955
1569
 
956
1570
class TestSmartServerRepositoryLockWrite(tests.TestCaseWithMemoryTransport):
957
1571
 
958
 
    def setUp(self):
959
 
        tests.TestCaseWithMemoryTransport.setUp(self)
960
 
 
961
1572
    def test_lock_write_on_unlocked_repo(self):
962
1573
        backing = self.get_transport()
963
1574
        request = smart.repository.SmartServerRepositoryLockWrite(backing)
969
1580
        # object.
970
1581
        new_repo = repository.bzrdir.open_repository()
971
1582
        self.assertRaises(errors.LockContention, new_repo.lock_write)
 
1583
        # Cleanup
 
1584
        request = smart.repository.SmartServerRepositoryUnlock(backing)
 
1585
        response = request.execute('', nonce)
972
1586
 
973
1587
    def test_lock_write_on_locked_repo(self):
974
1588
        backing = self.get_transport()
975
1589
        request = smart.repository.SmartServerRepositoryLockWrite(backing)
976
1590
        repository = self.make_repository('.', format='knit')
977
 
        repository.lock_write()
 
1591
        repo_token = repository.lock_write()
978
1592
        repository.leave_lock_in_place()
979
1593
        repository.unlock()
980
1594
        response = request.execute('')
981
1595
        self.assertEqual(
982
1596
            SmartServerResponse(('LockContention',)), response)
 
1597
        # Cleanup
 
1598
        repository.lock_write(repo_token)
 
1599
        repository.dont_leave_lock_in_place()
 
1600
        repository.unlock()
983
1601
 
984
1602
    def test_lock_write_on_readonly_transport(self):
985
1603
        backing = self.get_readonly_transport()
990
1608
        self.assertEqual('LockFailed', response.args[0])
991
1609
 
992
1610
 
 
1611
class TestInsertStreamBase(tests.TestCaseWithMemoryTransport):
 
1612
 
 
1613
    def make_empty_byte_stream(self, repo):
 
1614
        byte_stream = smart.repository._stream_to_byte_stream([], repo._format)
 
1615
        return ''.join(byte_stream)
 
1616
 
 
1617
 
 
1618
class TestSmartServerRepositoryInsertStream(TestInsertStreamBase):
 
1619
 
 
1620
    def test_insert_stream_empty(self):
 
1621
        backing = self.get_transport()
 
1622
        request = smart.repository.SmartServerRepositoryInsertStream(backing)
 
1623
        repository = self.make_repository('.')
 
1624
        response = request.execute('', '')
 
1625
        self.assertEqual(None, response)
 
1626
        response = request.do_chunk(self.make_empty_byte_stream(repository))
 
1627
        self.assertEqual(None, response)
 
1628
        response = request.do_end()
 
1629
        self.assertEqual(SmartServerResponse(('ok', )), response)
 
1630
        
 
1631
 
 
1632
class TestSmartServerRepositoryInsertStreamLocked(TestInsertStreamBase):
 
1633
 
 
1634
    def test_insert_stream_empty(self):
 
1635
        backing = self.get_transport()
 
1636
        request = smart.repository.SmartServerRepositoryInsertStreamLocked(
 
1637
            backing)
 
1638
        repository = self.make_repository('.', format='knit')
 
1639
        lock_token = repository.lock_write()
 
1640
        response = request.execute('', '', lock_token)
 
1641
        self.assertEqual(None, response)
 
1642
        response = request.do_chunk(self.make_empty_byte_stream(repository))
 
1643
        self.assertEqual(None, response)
 
1644
        response = request.do_end()
 
1645
        self.assertEqual(SmartServerResponse(('ok', )), response)
 
1646
        repository.unlock()
 
1647
 
 
1648
    def test_insert_stream_with_wrong_lock_token(self):
 
1649
        backing = self.get_transport()
 
1650
        request = smart.repository.SmartServerRepositoryInsertStreamLocked(
 
1651
            backing)
 
1652
        repository = self.make_repository('.', format='knit')
 
1653
        lock_token = repository.lock_write()
 
1654
        self.assertRaises(
 
1655
            errors.TokenMismatch, request.execute, '', '', 'wrong-token')
 
1656
        repository.unlock()
 
1657
 
 
1658
 
993
1659
class TestSmartServerRepositoryUnlock(tests.TestCaseWithMemoryTransport):
994
1660
 
995
1661
    def setUp(self):
1037
1703
            SmartServerResponse(('yes',)), response)
1038
1704
 
1039
1705
 
 
1706
class TestSmartServerRepositorySetMakeWorkingTrees(tests.TestCaseWithMemoryTransport):
 
1707
 
 
1708
    def test_set_false(self):
 
1709
        backing = self.get_transport()
 
1710
        repo = self.make_repository('.', shared=True)
 
1711
        repo.set_make_working_trees(True)
 
1712
        request_class = smart.repository.SmartServerRepositorySetMakeWorkingTrees
 
1713
        request = request_class(backing)
 
1714
        self.assertEqual(SuccessfulSmartServerResponse(('ok',)),
 
1715
            request.execute('', 'False'))
 
1716
        repo = repo.bzrdir.open_repository()
 
1717
        self.assertFalse(repo.make_working_trees())
 
1718
 
 
1719
    def test_set_true(self):
 
1720
        backing = self.get_transport()
 
1721
        repo = self.make_repository('.', shared=True)
 
1722
        repo.set_make_working_trees(False)
 
1723
        request_class = smart.repository.SmartServerRepositorySetMakeWorkingTrees
 
1724
        request = request_class(backing)
 
1725
        self.assertEqual(SuccessfulSmartServerResponse(('ok',)),
 
1726
            request.execute('', 'True'))
 
1727
        repo = repo.bzrdir.open_repository()
 
1728
        self.assertTrue(repo.make_working_trees())
 
1729
 
 
1730
 
1040
1731
class TestSmartServerPackRepositoryAutopack(tests.TestCaseWithTransport):
1041
1732
 
1042
1733
    def make_repo_needing_autopacking(self, path='.'):
1053
1744
 
1054
1745
    def test_autopack_needed(self):
1055
1746
        repo = self.make_repo_needing_autopacking()
 
1747
        repo.lock_write()
 
1748
        self.addCleanup(repo.unlock)
1056
1749
        backing = self.get_transport()
1057
1750
        request = smart.packrepository.SmartServerPackRepositoryAutopack(
1058
1751
            backing)
1060
1753
        self.assertEqual(SmartServerResponse(('ok',)), response)
1061
1754
        repo._pack_collection.reload_pack_names()
1062
1755
        self.assertEqual(1, len(repo._pack_collection.names()))
1063
 
    
 
1756
 
1064
1757
    def test_autopack_not_needed(self):
1065
1758
        tree = self.make_branch_and_tree('.', format='pack-0.92')
1066
1759
        repo = tree.branch.repository
 
1760
        repo.lock_write()
 
1761
        self.addCleanup(repo.unlock)
1067
1762
        for x in range(9):
1068
1763
            tree.commit('commit %s' % x)
1069
1764
        backing = self.get_transport()
1073
1768
        self.assertEqual(SmartServerResponse(('ok',)), response)
1074
1769
        repo._pack_collection.reload_pack_names()
1075
1770
        self.assertEqual(9, len(repo._pack_collection.names()))
1076
 
    
 
1771
 
1077
1772
    def test_autopack_on_nonpack_format(self):
1078
1773
        """A request to autopack a non-pack repo is a no-op."""
1079
1774
        repo = self.make_repository('.', format='knit')
1082
1777
            backing)
1083
1778
        response = request.execute('')
1084
1779
        self.assertEqual(SmartServerResponse(('ok',)), response)
1085
 
        
 
1780
 
 
1781
 
 
1782
class TestSmartServerVfsGet(tests.TestCaseWithMemoryTransport):
 
1783
 
 
1784
    def test_unicode_path(self):
 
1785
        """VFS requests expect unicode paths to be escaped."""
 
1786
        filename = u'foo\N{INTERROBANG}'
 
1787
        filename_escaped = urlutils.escape(filename)
 
1788
        backing = self.get_transport()
 
1789
        request = smart.vfs.GetRequest(backing)
 
1790
        backing.put_bytes_non_atomic(filename_escaped, 'contents')
 
1791
        self.assertEqual(SmartServerResponse(('ok', ), 'contents'),
 
1792
            request.execute(filename_escaped))
 
1793
 
1086
1794
 
1087
1795
class TestHandlers(tests.TestCase):
1088
1796
    """Tests for the request.request_handlers object."""
1094
1802
        for key, item in smart.request.request_handlers.iteritems():
1095
1803
            pass
1096
1804
 
 
1805
    def assertHandlerEqual(self, verb, handler):
 
1806
        self.assertEqual(smart.request.request_handlers.get(verb), handler)
 
1807
 
1097
1808
    def test_registered_methods(self):
1098
1809
        """Test that known methods are registered to the correct object."""
1099
 
        self.assertEqual(
1100
 
            smart.request.request_handlers.get('Branch.get_config_file'),
 
1810
        self.assertHandlerEqual('Branch.get_config_file',
1101
1811
            smart.branch.SmartServerBranchGetConfigFile)
1102
 
        self.assertEqual(
1103
 
            smart.request.request_handlers.get('Branch.lock_write'),
 
1812
        self.assertHandlerEqual('Branch.get_parent',
 
1813
            smart.branch.SmartServerBranchGetParent)
 
1814
        self.assertHandlerEqual('Branch.get_tags_bytes',
 
1815
            smart.branch.SmartServerBranchGetTagsBytes)
 
1816
        self.assertHandlerEqual('Branch.lock_write',
1104
1817
            smart.branch.SmartServerBranchRequestLockWrite)
1105
 
        self.assertEqual(
1106
 
            smart.request.request_handlers.get('Branch.last_revision_info'),
 
1818
        self.assertHandlerEqual('Branch.last_revision_info',
1107
1819
            smart.branch.SmartServerBranchRequestLastRevisionInfo)
1108
 
        self.assertEqual(
1109
 
            smart.request.request_handlers.get('Branch.revision_history'),
 
1820
        self.assertHandlerEqual('Branch.revision_history',
1110
1821
            smart.branch.SmartServerRequestRevisionHistory)
1111
 
        self.assertEqual(
1112
 
            smart.request.request_handlers.get('Branch.set_last_revision'),
 
1822
        self.assertHandlerEqual('Branch.set_config_option',
 
1823
            smart.branch.SmartServerBranchRequestSetConfigOption)
 
1824
        self.assertHandlerEqual('Branch.set_last_revision',
1113
1825
            smart.branch.SmartServerBranchRequestSetLastRevision)
1114
 
        self.assertEqual(
1115
 
            smart.request.request_handlers.get('Branch.set_last_revision_info'),
 
1826
        self.assertHandlerEqual('Branch.set_last_revision_info',
1116
1827
            smart.branch.SmartServerBranchRequestSetLastRevisionInfo)
1117
 
        self.assertEqual(
1118
 
            smart.request.request_handlers.get('Branch.unlock'),
 
1828
        self.assertHandlerEqual('Branch.set_last_revision_ex',
 
1829
            smart.branch.SmartServerBranchRequestSetLastRevisionEx)
 
1830
        self.assertHandlerEqual('Branch.set_parent_location',
 
1831
            smart.branch.SmartServerBranchRequestSetParentLocation)
 
1832
        self.assertHandlerEqual('Branch.unlock',
1119
1833
            smart.branch.SmartServerBranchRequestUnlock)
1120
 
        self.assertEqual(
1121
 
            smart.request.request_handlers.get('BzrDir.find_repository'),
 
1834
        self.assertHandlerEqual('BzrDir.find_repository',
1122
1835
            smart.bzrdir.SmartServerRequestFindRepositoryV1)
1123
 
        self.assertEqual(
1124
 
            smart.request.request_handlers.get('BzrDir.find_repositoryV2'),
 
1836
        self.assertHandlerEqual('BzrDir.find_repositoryV2',
1125
1837
            smart.bzrdir.SmartServerRequestFindRepositoryV2)
1126
 
        self.assertEqual(
1127
 
            smart.request.request_handlers.get('BzrDirFormat.initialize'),
 
1838
        self.assertHandlerEqual('BzrDirFormat.initialize',
1128
1839
            smart.bzrdir.SmartServerRequestInitializeBzrDir)
1129
 
        self.assertEqual(
1130
 
            smart.request.request_handlers.get('BzrDir.open_branch'),
 
1840
        self.assertHandlerEqual('BzrDirFormat.initialize_ex_1.16',
 
1841
            smart.bzrdir.SmartServerRequestBzrDirInitializeEx)
 
1842
        self.assertHandlerEqual('BzrDir.cloning_metadir',
 
1843
            smart.bzrdir.SmartServerBzrDirRequestCloningMetaDir)
 
1844
        self.assertHandlerEqual('BzrDir.get_config_file',
 
1845
            smart.bzrdir.SmartServerBzrDirRequestConfigFile)
 
1846
        self.assertHandlerEqual('BzrDir.open_branch',
1131
1847
            smart.bzrdir.SmartServerRequestOpenBranch)
1132
 
        self.assertEqual(
1133
 
            smart.request.request_handlers.get('PackRepository.autopack'),
 
1848
        self.assertHandlerEqual('BzrDir.open_branchV2',
 
1849
            smart.bzrdir.SmartServerRequestOpenBranchV2)
 
1850
        self.assertHandlerEqual('BzrDir.open_branchV3',
 
1851
            smart.bzrdir.SmartServerRequestOpenBranchV3)
 
1852
        self.assertHandlerEqual('PackRepository.autopack',
1134
1853
            smart.packrepository.SmartServerPackRepositoryAutopack)
1135
 
        self.assertEqual(
1136
 
            smart.request.request_handlers.get('Repository.gather_stats'),
 
1854
        self.assertHandlerEqual('Repository.gather_stats',
1137
1855
            smart.repository.SmartServerRepositoryGatherStats)
1138
 
        self.assertEqual(
1139
 
            smart.request.request_handlers.get('Repository.get_parent_map'),
 
1856
        self.assertHandlerEqual('Repository.get_parent_map',
1140
1857
            smart.repository.SmartServerRepositoryGetParentMap)
1141
 
        self.assertEqual(
1142
 
            smart.request.request_handlers.get(
1143
 
                'Repository.get_revision_graph'),
 
1858
        self.assertHandlerEqual('Repository.get_rev_id_for_revno',
 
1859
            smart.repository.SmartServerRepositoryGetRevIdForRevno)
 
1860
        self.assertHandlerEqual('Repository.get_revision_graph',
1144
1861
            smart.repository.SmartServerRepositoryGetRevisionGraph)
1145
 
        self.assertEqual(
1146
 
            smart.request.request_handlers.get('Repository.has_revision'),
 
1862
        self.assertHandlerEqual('Repository.get_stream',
 
1863
            smart.repository.SmartServerRepositoryGetStream)
 
1864
        self.assertHandlerEqual('Repository.has_revision',
1147
1865
            smart.repository.SmartServerRequestHasRevision)
1148
 
        self.assertEqual(
1149
 
            smart.request.request_handlers.get('Repository.is_shared'),
 
1866
        self.assertHandlerEqual('Repository.insert_stream',
 
1867
            smart.repository.SmartServerRepositoryInsertStream)
 
1868
        self.assertHandlerEqual('Repository.insert_stream_locked',
 
1869
            smart.repository.SmartServerRepositoryInsertStreamLocked)
 
1870
        self.assertHandlerEqual('Repository.is_shared',
1150
1871
            smart.repository.SmartServerRepositoryIsShared)
1151
 
        self.assertEqual(
1152
 
            smart.request.request_handlers.get('Repository.lock_write'),
 
1872
        self.assertHandlerEqual('Repository.lock_write',
1153
1873
            smart.repository.SmartServerRepositoryLockWrite)
1154
 
        self.assertEqual(
1155
 
            smart.request.request_handlers.get('Repository.tarball'),
 
1874
        self.assertHandlerEqual('Repository.tarball',
1156
1875
            smart.repository.SmartServerRepositoryTarball)
1157
 
        self.assertEqual(
1158
 
            smart.request.request_handlers.get('Repository.unlock'),
 
1876
        self.assertHandlerEqual('Repository.unlock',
1159
1877
            smart.repository.SmartServerRepositoryUnlock)
1160
 
        self.assertEqual(
1161
 
            smart.request.request_handlers.get('Transport.is_readonly'),
 
1878
        self.assertHandlerEqual('Transport.is_readonly',
1162
1879
            smart.request.SmartServerIsReadonly)