~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_smart.py

  • Committer: Martin Pool
  • Date: 2008-10-20 23:58:12 UTC
  • mto: This revision was merged to the branch mainline in revision 3787.
  • Revision ID: mbp@sourcefrog.net-20081020235812-itg90mk0u4dez92z
lp-upload-release now handles names like bzr-1.8.tar.gz

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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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,
33
32
    bzrdir,
34
33
    errors,
35
34
    pack,
36
35
    smart,
37
36
    tests,
38
37
    urlutils,
39
 
    versionedfile,
40
38
    )
41
39
from bzrlib.branch import Branch, BranchReferenceFormat
42
40
import bzrlib.smart.branch
43
 
import bzrlib.smart.bzrdir, bzrlib.smart.bzrdir as smart_dir
44
 
import bzrlib.smart.packrepository
 
41
import bzrlib.smart.bzrdir
45
42
import bzrlib.smart.repository
46
 
import bzrlib.smart.vfs
47
43
from bzrlib.smart.request import (
48
44
    FailedSmartServerResponse,
49
45
    SmartServerRequest,
51
47
    SuccessfulSmartServerResponse,
52
48
    )
53
49
from bzrlib.tests import (
 
50
    iter_suite_tests,
54
51
    split_suite_by_re,
 
52
    TestScenarioApplier,
55
53
    )
56
 
from bzrlib.transport import chroot, get_transport, local, memory
 
54
from bzrlib.transport import chroot, get_transport
 
55
from bzrlib.util import bencode
57
56
 
58
57
 
59
58
def load_tests(standard_tests, module, loader):
60
59
    """Multiply tests version and protocol consistency."""
61
60
    # FindRepository tests.
62
61
    bzrdir_mod = bzrlib.smart.bzrdir
63
 
    scenarios = [
 
62
    applier = TestScenarioApplier()
 
63
    applier.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}),
70
68
        ]
71
69
    to_adapt, result = split_suite_by_re(standard_tests,
72
70
        "TestSmartServerRequestFindRepository")
73
71
    v2_only, v1_and_2 = split_suite_by_re(to_adapt,
74
72
        "_v2")
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)
 
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))
79
78
    return result
80
79
 
81
80
 
82
81
class TestCaseWithChrootedTransport(tests.TestCaseWithTransport):
83
82
 
84
83
    def setUp(self):
85
 
        self.vfs_transport_factory = memory.MemoryServer
86
84
        tests.TestCaseWithTransport.setUp(self)
87
85
        self._chroot_server = None
88
86
 
90
88
        if self._chroot_server is None:
91
89
            backing_transport = tests.TestCaseWithTransport.get_transport(self)
92
90
            self._chroot_server = chroot.ChrootServer(backing_transport)
93
 
            self.start_server(self._chroot_server)
 
91
            self._chroot_server.setUp()
 
92
            self.addCleanup(self._chroot_server.tearDown)
94
93
        t = get_transport(self._chroot_server.get_url())
95
94
        if relpath is not None:
96
95
            t = t.clone(relpath)
97
96
        return t
98
97
 
99
98
 
100
 
class TestCaseWithSmartMedium(tests.TestCaseWithMemoryTransport):
 
99
class TestCaseWithSmartMedium(tests.TestCaseWithTransport):
101
100
 
102
101
    def setUp(self):
103
102
        super(TestCaseWithSmartMedium, self).setUp()
115
114
        return self.get_transport().get_smart_medium()
116
115
 
117
116
 
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
 
 
137
117
class TestSmartServerResponse(tests.TestCase):
138
118
 
139
119
    def test__eq__(self):
171
151
        self.assertRaises(
172
152
            errors.PathNotChild, request.translate_client_path, 'bar/')
173
153
        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))
186
154
 
187
155
    def test_transport_from_client_path(self):
188
156
        transport = self.get_transport()
192
160
            request.transport_from_client_path('foo/').base)
193
161
 
194
162
 
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
 
 
246
163
class TestSmartServerRequestFindRepository(tests.TestCaseWithMemoryTransport):
247
164
    """Tests for BzrDir.find_repository."""
248
165
 
255
172
            request.execute(''))
256
173
 
257
174
    def test_nonshared_repository(self):
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
 
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 
260
177
        # the repository is at.
261
178
        backing = self.get_transport()
262
179
        request = self._request_class(backing)
280
197
            subtrees = 'yes'
281
198
        else:
282
199
            subtrees = 'no'
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 ==
 
200
        if (smart.bzrdir.SmartServerRequestFindRepositoryV2 ==
293
201
            self._request_class):
294
202
            # All tests so far are on formats, and for non-external
295
203
            # repositories.
296
204
            return SuccessfulSmartServerResponse(
297
 
                ('ok', '', rich_root, subtrees, external))
 
205
                ('ok', '', rich_root, subtrees, 'no'))
298
206
        else:
299
207
            return SuccessfulSmartServerResponse(('ok', '', rich_root, subtrees))
300
208
 
333
241
        self.assertEqual(result, request.execute(''))
334
242
 
335
243
 
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
 
 
359
244
class TestSmartServerRequestInitializeBzrDir(tests.TestCaseWithMemoryTransport):
360
245
 
361
246
    def test_empty_dir(self):
365
250
        self.assertEqual(SmartServerResponse(('ok', )),
366
251
            request.execute(''))
367
252
        made_dir = bzrdir.BzrDir.open_from_transport(backing)
368
 
        # no branch, tree or repository is expected with the current
 
253
        # no branch, tree or repository is expected with the current 
369
254
        # default formart.
370
255
        self.assertRaises(errors.NoWorkingTree, made_dir.open_workingtree)
371
256
        self.assertRaises(errors.NotBranchError, made_dir.open_branch)
387
272
            request.execute, 'subdir')
388
273
 
389
274
 
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
 
 
497
275
class TestSmartServerRequestOpenBranch(TestCaseWithChrootedTransport):
498
276
 
499
277
    def test_no_branch(self):
514
292
 
515
293
    def test_branch_reference(self):
516
294
        """When there is a branch reference, the reference URL is returned."""
517
 
        self.vfs_transport_factory = local.LocalURLServer
518
295
        backing = self.get_transport()
519
296
        request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
520
297
        branch = self.make_branch('branch')
524
301
        self.assertEqual(SmartServerResponse(('ok', reference_url)),
525
302
            request.execute('reference'))
526
303
 
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
 
 
654
304
 
655
305
class TestSmartServerRequestRevisionHistory(tests.TestCaseWithMemoryTransport):
656
306
 
738
388
    def test_with_content(self):
739
389
        # SmartServerBranchGetConfigFile should return the content from
740
390
        # branch.control_files.get('branch.conf') for now - in the future it may
741
 
        # perform more complex processing.
 
391
        # perform more complex processing. 
742
392
        backing = self.get_transport()
743
393
        request = smart.branch.SmartServerBranchGetConfigFile(backing)
744
394
        branch = self.make_branch('.')
747
397
            request.execute(''))
748
398
 
749
399
 
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):
 
400
class SetLastRevisionTestBase(tests.TestCaseWithMemoryTransport):
826
401
    """Base test case for verbs that implement set_last_revision."""
827
402
 
828
403
    def setUp(self):
832
407
        self.tree = self.make_branch_and_memory_tree('.')
833
408
 
834
409
    def lock_branch(self):
835
 
        return self.get_lock_tokens(self.tree.branch)
 
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
836
415
 
837
416
    def unlock_branch(self):
838
417
        self.tree.branch.unlock()
839
 
 
 
418
        
840
419
    def set_last_revision(self, revision_id, revno):
841
420
        branch_token, repo_token = self.lock_branch()
842
421
        response = self._set_last_revision(
848
427
        response = self.set_last_revision(revision_id, revno)
849
428
        self.assertEqual(SuccessfulSmartServerResponse(('ok',)), response)
850
429
 
851
 
 
 
430
        
852
431
class TestSetLastRevisionVerbMixin(object):
853
432
    """Mixin test case for verbs that implement set_last_revision."""
854
433
 
959
538
        self.assertEqual(
960
539
            SuccessfulSmartServerResponse(('ok', revno, revision_id)),
961
540
            response)
962
 
 
 
541
        
963
542
    def test_branch_last_revision_info_rewind(self):
964
543
        """A branch's tip can be set to a revision that is an ancestor of the
965
544
        current tip, but only if allow_overwrite_descendant is passed.
1008
587
        # child-1.
1009
588
        new_r2 = self.tree.commit('2nd commit', rev_id='child-2')
1010
589
        self.tree.unlock()
1011
 
 
 
590
        
1012
591
    def test_not_allow_diverged(self):
1013
592
        """If allow_diverged is not passed, then setting a divergent history
1014
593
        returns a Diverged error.
1036
615
        self.assertEqual('child-1', self.tree.branch.last_revision())
1037
616
 
1038
617
 
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
 
 
1106
618
class TestSmartServerBranchRequestGetStackedOnURL(tests.TestCaseWithMemoryTransport):
1107
619
 
1108
620
    def test_get_stacked_on_url(self):
1138
650
        # with a new branch object.
1139
651
        new_branch = repository.bzrdir.open_branch()
1140
652
        self.assertRaises(errors.LockContention, new_branch.lock_write)
1141
 
        # Cleanup
1142
 
        request = smart.branch.SmartServerBranchRequestUnlock(backing)
1143
 
        response = request.execute('', branch_nonce, repository_nonce)
1144
653
 
1145
654
    def test_lock_write_on_locked_branch(self):
1146
655
        backing = self.get_transport()
1147
656
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
1148
657
        branch = self.make_branch('.')
1149
 
        branch_token = branch.lock_write()
 
658
        branch.lock_write()
1150
659
        branch.leave_lock_in_place()
1151
660
        branch.unlock()
1152
661
        response = request.execute('')
1153
662
        self.assertEqual(
1154
663
            SmartServerResponse(('LockContention',)), response)
1155
 
        # Cleanup
1156
 
        branch.lock_write(branch_token)
1157
 
        branch.dont_leave_lock_in_place()
1158
 
        branch.unlock()
1159
664
 
1160
665
    def test_lock_write_with_tokens_on_locked_branch(self):
1161
666
        backing = self.get_transport()
1171
676
                                   branch_token, repo_token)
1172
677
        self.assertEqual(
1173
678
            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()
1181
679
 
1182
680
    def test_lock_write_with_mismatched_tokens_on_locked_branch(self):
1183
681
        backing = self.get_transport()
1193
691
                                   branch_token+'xxx', repo_token)
1194
692
        self.assertEqual(
1195
693
            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()
1203
694
 
1204
695
    def test_lock_write_on_locked_repo(self):
1205
696
        backing = self.get_transport()
1206
697
        request = smart.branch.SmartServerBranchRequestLockWrite(backing)
1207
698
        branch = self.make_branch('.', format='knit')
1208
 
        repo = branch.repository
1209
 
        repo_token = repo.lock_write()
1210
 
        repo.leave_lock_in_place()
1211
 
        repo.unlock()
 
699
        branch.repository.lock_write()
 
700
        branch.repository.leave_lock_in_place()
 
701
        branch.repository.unlock()
1212
702
        response = request.execute('')
1213
703
        self.assertEqual(
1214
704
            SmartServerResponse(('LockContention',)), response)
1215
 
        # Cleanup
1216
 
        repo.lock_write(repo_token)
1217
 
        repo.dont_leave_lock_in_place()
1218
 
        repo.unlock()
1219
705
 
1220
706
    def test_lock_write_on_readonly_transport(self):
1221
707
        backing = self.get_readonly_transport()
1280
766
            '', 'branch token', repo_token)
1281
767
        self.assertEqual(
1282
768
            SmartServerResponse(('TokenMismatch',)), response)
1283
 
        # Cleanup
1284
 
        branch.repository.lock_write(repo_token)
1285
 
        branch.repository.dont_leave_lock_in_place()
1286
 
        branch.repository.unlock()
1287
769
 
1288
770
 
1289
771
class TestSmartServerRepositoryRequest(tests.TestCaseWithMemoryTransport):
1312
794
 
1313
795
        self.assertEqual(None,
1314
796
            request.execute('', 'missing-id'))
1315
 
        # Note that it returns a body that is bzipped.
 
797
        # Note that it returns a body (of '' bzipped).
1316
798
        self.assertEqual(
1317
799
            SuccessfulSmartServerResponse(('ok', ), bz2.compress('')),
1318
800
            request.do_body('\n\n0\n'))
1319
801
 
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
 
 
1332
802
 
1333
803
class TestSmartServerRepositoryGetRevisionGraph(tests.TestCaseWithMemoryTransport):
1334
804
 
1364
834
 
1365
835
        self.assertEqual(SmartServerResponse(('ok', ), rev_id_utf8),
1366
836
            request.execute('', rev_id_utf8))
1367
 
 
 
837
    
1368
838
    def test_no_such_revision(self):
1369
839
        backing = self.get_transport()
1370
840
        request = smart.repository.SmartServerRepositoryGetRevisionGraph(backing)
1380
850
            request.execute('', 'missingrevision'))
1381
851
 
1382
852
 
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
 
 
1467
853
class TestSmartServerRequestHasRevision(tests.TestCaseWithMemoryTransport):
1468
854
 
1469
855
    def test_missing_revision(self):
1569
955
 
1570
956
class TestSmartServerRepositoryLockWrite(tests.TestCaseWithMemoryTransport):
1571
957
 
 
958
    def setUp(self):
 
959
        tests.TestCaseWithMemoryTransport.setUp(self)
 
960
 
1572
961
    def test_lock_write_on_unlocked_repo(self):
1573
962
        backing = self.get_transport()
1574
963
        request = smart.repository.SmartServerRepositoryLockWrite(backing)
1580
969
        # object.
1581
970
        new_repo = repository.bzrdir.open_repository()
1582
971
        self.assertRaises(errors.LockContention, new_repo.lock_write)
1583
 
        # Cleanup
1584
 
        request = smart.repository.SmartServerRepositoryUnlock(backing)
1585
 
        response = request.execute('', nonce)
1586
972
 
1587
973
    def test_lock_write_on_locked_repo(self):
1588
974
        backing = self.get_transport()
1589
975
        request = smart.repository.SmartServerRepositoryLockWrite(backing)
1590
976
        repository = self.make_repository('.', format='knit')
1591
 
        repo_token = repository.lock_write()
 
977
        repository.lock_write()
1592
978
        repository.leave_lock_in_place()
1593
979
        repository.unlock()
1594
980
        response = request.execute('')
1595
981
        self.assertEqual(
1596
982
            SmartServerResponse(('LockContention',)), response)
1597
 
        # Cleanup
1598
 
        repository.lock_write(repo_token)
1599
 
        repository.dont_leave_lock_in_place()
1600
 
        repository.unlock()
1601
983
 
1602
984
    def test_lock_write_on_readonly_transport(self):
1603
985
        backing = self.get_readonly_transport()
1608
990
        self.assertEqual('LockFailed', response.args[0])
1609
991
 
1610
992
 
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
 
 
1659
993
class TestSmartServerRepositoryUnlock(tests.TestCaseWithMemoryTransport):
1660
994
 
1661
995
    def setUp(self):
1703
1037
            SmartServerResponse(('yes',)), response)
1704
1038
 
1705
1039
 
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
 
 
1731
 
class TestSmartServerPackRepositoryAutopack(tests.TestCaseWithTransport):
1732
 
 
1733
 
    def make_repo_needing_autopacking(self, path='.'):
1734
 
        # Make a repo in need of autopacking.
1735
 
        tree = self.make_branch_and_tree('.', format='pack-0.92')
1736
 
        repo = tree.branch.repository
1737
 
        # monkey-patch the pack collection to disable autopacking
1738
 
        repo._pack_collection._max_pack_count = lambda count: count
1739
 
        for x in range(10):
1740
 
            tree.commit('commit %s' % x)
1741
 
        self.assertEqual(10, len(repo._pack_collection.names()))
1742
 
        del repo._pack_collection._max_pack_count
1743
 
        return repo
1744
 
 
1745
 
    def test_autopack_needed(self):
1746
 
        repo = self.make_repo_needing_autopacking()
1747
 
        repo.lock_write()
1748
 
        self.addCleanup(repo.unlock)
1749
 
        backing = self.get_transport()
1750
 
        request = smart.packrepository.SmartServerPackRepositoryAutopack(
1751
 
            backing)
1752
 
        response = request.execute('')
1753
 
        self.assertEqual(SmartServerResponse(('ok',)), response)
1754
 
        repo._pack_collection.reload_pack_names()
1755
 
        self.assertEqual(1, len(repo._pack_collection.names()))
1756
 
 
1757
 
    def test_autopack_not_needed(self):
1758
 
        tree = self.make_branch_and_tree('.', format='pack-0.92')
1759
 
        repo = tree.branch.repository
1760
 
        repo.lock_write()
1761
 
        self.addCleanup(repo.unlock)
1762
 
        for x in range(9):
1763
 
            tree.commit('commit %s' % x)
1764
 
        backing = self.get_transport()
1765
 
        request = smart.packrepository.SmartServerPackRepositoryAutopack(
1766
 
            backing)
1767
 
        response = request.execute('')
1768
 
        self.assertEqual(SmartServerResponse(('ok',)), response)
1769
 
        repo._pack_collection.reload_pack_names()
1770
 
        self.assertEqual(9, len(repo._pack_collection.names()))
1771
 
 
1772
 
    def test_autopack_on_nonpack_format(self):
1773
 
        """A request to autopack a non-pack repo is a no-op."""
1774
 
        repo = self.make_repository('.', format='knit')
1775
 
        backing = self.get_transport()
1776
 
        request = smart.packrepository.SmartServerPackRepositoryAutopack(
1777
 
            backing)
1778
 
        response = request.execute('')
1779
 
        self.assertEqual(SmartServerResponse(('ok',)), response)
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
 
 
1794
 
 
1795
1040
class TestHandlers(tests.TestCase):
1796
1041
    """Tests for the request.request_handlers object."""
1797
1042
 
1802
1047
        for key, item in smart.request.request_handlers.iteritems():
1803
1048
            pass
1804
1049
 
1805
 
    def assertHandlerEqual(self, verb, handler):
1806
 
        self.assertEqual(smart.request.request_handlers.get(verb), handler)
1807
 
 
1808
1050
    def test_registered_methods(self):
1809
1051
        """Test that known methods are registered to the correct object."""
1810
 
        self.assertHandlerEqual('Branch.get_config_file',
 
1052
        self.assertEqual(
 
1053
            smart.request.request_handlers.get('Branch.get_config_file'),
1811
1054
            smart.branch.SmartServerBranchGetConfigFile)
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',
 
1055
        self.assertEqual(
 
1056
            smart.request.request_handlers.get('Branch.lock_write'),
1817
1057
            smart.branch.SmartServerBranchRequestLockWrite)
1818
 
        self.assertHandlerEqual('Branch.last_revision_info',
 
1058
        self.assertEqual(
 
1059
            smart.request.request_handlers.get('Branch.last_revision_info'),
1819
1060
            smart.branch.SmartServerBranchRequestLastRevisionInfo)
1820
 
        self.assertHandlerEqual('Branch.revision_history',
 
1061
        self.assertEqual(
 
1062
            smart.request.request_handlers.get('Branch.revision_history'),
1821
1063
            smart.branch.SmartServerRequestRevisionHistory)
1822
 
        self.assertHandlerEqual('Branch.set_config_option',
1823
 
            smart.branch.SmartServerBranchRequestSetConfigOption)
1824
 
        self.assertHandlerEqual('Branch.set_last_revision',
 
1064
        self.assertEqual(
 
1065
            smart.request.request_handlers.get('Branch.set_last_revision'),
1825
1066
            smart.branch.SmartServerBranchRequestSetLastRevision)
1826
 
        self.assertHandlerEqual('Branch.set_last_revision_info',
 
1067
        self.assertEqual(
 
1068
            smart.request.request_handlers.get('Branch.set_last_revision_info'),
1827
1069
            smart.branch.SmartServerBranchRequestSetLastRevisionInfo)
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',
 
1070
        self.assertEqual(
 
1071
            smart.request.request_handlers.get('Branch.unlock'),
1833
1072
            smart.branch.SmartServerBranchRequestUnlock)
1834
 
        self.assertHandlerEqual('BzrDir.find_repository',
 
1073
        self.assertEqual(
 
1074
            smart.request.request_handlers.get('BzrDir.find_repository'),
1835
1075
            smart.bzrdir.SmartServerRequestFindRepositoryV1)
1836
 
        self.assertHandlerEqual('BzrDir.find_repositoryV2',
 
1076
        self.assertEqual(
 
1077
            smart.request.request_handlers.get('BzrDir.find_repositoryV2'),
1837
1078
            smart.bzrdir.SmartServerRequestFindRepositoryV2)
1838
 
        self.assertHandlerEqual('BzrDirFormat.initialize',
 
1079
        self.assertEqual(
 
1080
            smart.request.request_handlers.get('BzrDirFormat.initialize'),
1839
1081
            smart.bzrdir.SmartServerRequestInitializeBzrDir)
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',
 
1082
        self.assertEqual(
 
1083
            smart.request.request_handlers.get('BzrDir.open_branch'),
1847
1084
            smart.bzrdir.SmartServerRequestOpenBranch)
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',
1853
 
            smart.packrepository.SmartServerPackRepositoryAutopack)
1854
 
        self.assertHandlerEqual('Repository.gather_stats',
 
1085
        self.assertEqual(
 
1086
            smart.request.request_handlers.get('Repository.gather_stats'),
1855
1087
            smart.repository.SmartServerRepositoryGatherStats)
1856
 
        self.assertHandlerEqual('Repository.get_parent_map',
 
1088
        self.assertEqual(
 
1089
            smart.request.request_handlers.get('Repository.get_parent_map'),
1857
1090
            smart.repository.SmartServerRepositoryGetParentMap)
1858
 
        self.assertHandlerEqual('Repository.get_rev_id_for_revno',
1859
 
            smart.repository.SmartServerRepositoryGetRevIdForRevno)
1860
 
        self.assertHandlerEqual('Repository.get_revision_graph',
 
1091
        self.assertEqual(
 
1092
            smart.request.request_handlers.get(
 
1093
                'Repository.get_revision_graph'),
1861
1094
            smart.repository.SmartServerRepositoryGetRevisionGraph)
1862
 
        self.assertHandlerEqual('Repository.get_stream',
1863
 
            smart.repository.SmartServerRepositoryGetStream)
1864
 
        self.assertHandlerEqual('Repository.has_revision',
 
1095
        self.assertEqual(
 
1096
            smart.request.request_handlers.get('Repository.has_revision'),
1865
1097
            smart.repository.SmartServerRequestHasRevision)
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',
 
1098
        self.assertEqual(
 
1099
            smart.request.request_handlers.get('Repository.is_shared'),
1871
1100
            smart.repository.SmartServerRepositoryIsShared)
1872
 
        self.assertHandlerEqual('Repository.lock_write',
 
1101
        self.assertEqual(
 
1102
            smart.request.request_handlers.get('Repository.lock_write'),
1873
1103
            smart.repository.SmartServerRepositoryLockWrite)
1874
 
        self.assertHandlerEqual('Repository.tarball',
 
1104
        self.assertEqual(
 
1105
            smart.request.request_handlers.get('Repository.tarball'),
1875
1106
            smart.repository.SmartServerRepositoryTarball)
1876
 
        self.assertHandlerEqual('Repository.unlock',
 
1107
        self.assertEqual(
 
1108
            smart.request.request_handlers.get('Repository.unlock'),
1877
1109
            smart.repository.SmartServerRepositoryUnlock)
1878
 
        self.assertHandlerEqual('Transport.is_readonly',
 
1110
        self.assertEqual(
 
1111
            smart.request.request_handlers.get('Transport.is_readonly'),
1879
1112
            smart.request.SmartServerIsReadonly)