~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_remote.py

Put in place a structure for the admin-guide

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006, 2007, 2008, 2009 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
38
38
    remote,
39
39
    repository,
40
40
    tests,
41
 
    transport,
42
41
    treebuilder,
43
42
    urlutils,
44
43
    versionedfile,
55
54
    )
56
55
from bzrlib.repofmt import groupcompress_repo, pack_repo
57
56
from bzrlib.revision import NULL_REVISION
58
 
from bzrlib.smart import medium
 
57
from bzrlib.smart import server, medium
59
58
from bzrlib.smart.client import _SmartClient
60
59
from bzrlib.smart.repository import SmartServerRepositoryGetParentMap
61
60
from bzrlib.tests import (
62
61
    condition_isinstance,
63
62
    split_suite_by_condition,
64
63
    multiply_tests,
65
 
    test_server,
66
64
    )
 
65
from bzrlib.transport import get_transport
67
66
from bzrlib.transport.memory import MemoryTransport
68
67
from bzrlib.transport.remote import (
69
68
    RemoteTransport,
76
75
        standard_tests, condition_isinstance(BasicRemoteObjectTests))
77
76
    smart_server_version_scenarios = [
78
77
        ('HPSS-v2',
79
 
         {'transport_server': test_server.SmartTCPServer_for_testing_v2_only}),
 
78
            {'transport_server': server.SmartTCPServer_for_testing_v2_only}),
80
79
        ('HPSS-v3',
81
 
         {'transport_server': test_server.SmartTCPServer_for_testing})]
 
80
            {'transport_server': server.SmartTCPServer_for_testing})]
82
81
    return multiply_tests(to_adapt, smart_server_version_scenarios, result)
83
82
 
84
83
 
89
88
        self.transport = self.get_transport()
90
89
        # make a branch that can be opened over the smart transport
91
90
        self.local_wt = BzrDir.create_standalone_workingtree('.')
92
 
        self.addCleanup(self.transport.disconnect)
 
91
 
 
92
    def tearDown(self):
 
93
        self.transport.disconnect()
 
94
        tests.TestCaseWithTransport.tearDown(self)
93
95
 
94
96
    def test_create_remote_bzrdir(self):
95
97
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
132
134
        b = BzrDir.open_from_transport(self.transport).open_branch()
133
135
        self.assertStartsWith(str(b), 'RemoteBranch(')
134
136
 
135
 
    def test_remote_bzrdir_repr(self):
136
 
        b = BzrDir.open_from_transport(self.transport)
137
 
        self.assertStartsWith(str(b), 'RemoteBzrDir(')
138
 
 
139
137
    def test_remote_branch_format_supports_stacking(self):
140
138
        t = self.transport
141
139
        self.make_branch('unstackable', format='pack-0.92')
356
354
        a given client_base and transport_base.
357
355
        """
358
356
        client_medium = medium.SmartClientMedium(client_base)
359
 
        t = transport.get_transport(transport_base)
360
 
        result = client_medium.remote_path_from_transport(t)
 
357
        transport = get_transport(transport_base)
 
358
        result = client_medium.remote_path_from_transport(transport)
361
359
        self.assertEqual(expected, result)
362
360
 
363
361
    def test_remote_path_from_transport(self):
374
372
        a given transport_base and relpath of that transport.  (Note that
375
373
        HttpTransportBase is a subclass of SmartClientMedium)
376
374
        """
377
 
        base_transport = transport.get_transport(transport_base)
 
375
        base_transport = get_transport(transport_base)
378
376
        client_medium = base_transport.get_smart_medium()
379
377
        cloned_transport = base_transport.clone(relpath)
380
378
        result = client_medium.remote_path_from_transport(cloned_transport)
415
413
        # Calling _remember_remote_is_before again with a lower value works.
416
414
        client_medium._remember_remote_is_before((1, 5))
417
415
        self.assertTrue(client_medium._is_remote_before((1, 5)))
418
 
        # If you call _remember_remote_is_before with a higher value it logs a
419
 
        # warning, and continues to remember the lower value.
420
 
        self.assertNotContainsRe(self.get_log(), '_remember_remote_is_before')
421
 
        client_medium._remember_remote_is_before((1, 9))
422
 
        self.assertContainsRe(self.get_log(), '_remember_remote_is_before')
423
 
        self.assertTrue(client_medium._is_remote_before((1, 5)))
 
416
        # You cannot call _remember_remote_is_before with a larger value.
 
417
        self.assertRaises(
 
418
            AssertionError, client_medium._remember_remote_is_before, (1, 9))
424
419
 
425
420
 
426
421
class TestBzrDirCloningMetaDir(TestRemote):
445
440
            'BzrDir.cloning_metadir', ('quack/', 'False'),
446
441
            'error', ('BranchReference',)),
447
442
        client.add_expected_call(
448
 
            'BzrDir.open_branchV3', ('quack/',),
 
443
            'BzrDir.open_branchV2', ('quack/',),
449
444
            'success', ('ref', self.get_url('referenced'))),
450
445
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
451
446
            _client=client)
528
523
        self.assertIsInstance(bd, RemoteBzrDir)
529
524
        self.assertFinished(client)
530
525
 
531
 
    def test_backwards_compat_hpss_v2(self):
532
 
        client, transport = self.make_fake_client_and_transport()
533
 
        # Monkey-patch fake client to simulate real-world behaviour with v2
534
 
        # server: upon first RPC call detect the protocol version, and because
535
 
        # the version is 2 also do _remember_remote_is_before((1, 6)) before
536
 
        # continuing with the RPC.
537
 
        orig_check_call = client._check_call
538
 
        def check_call(method, args):
539
 
            client._medium._protocol_version = 2
540
 
            client._medium._remember_remote_is_before((1, 6))
541
 
            client._check_call = orig_check_call
542
 
            client._check_call(method, args)
543
 
        client._check_call = check_call
544
 
        client.add_expected_call(
545
 
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
546
 
        client.add_expected_call(
547
 
            'BzrDir.open', ('quack/',), 'success', ('yes',))
548
 
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
549
 
            _client=client, _force_probe=True)
550
 
        self.assertIsInstance(bd, RemoteBzrDir)
551
 
        self.assertFinished(client)
552
 
 
553
526
 
554
527
class TestBzrDirOpenBranch(TestRemote):
555
528
 
558
531
        self.make_branch('.')
559
532
        a_dir = BzrDir.open(self.get_url('.'))
560
533
        self.reset_smart_call_log()
561
 
        verb = 'BzrDir.open_branchV3'
 
534
        verb = 'BzrDir.open_branchV2'
562
535
        self.disable_verb(verb)
563
536
        format = a_dir.open_branch()
564
537
        call_count = len([call for call in self.hpss_calls if
574
547
        transport = transport.clone('quack')
575
548
        client = FakeClient(transport.base)
576
549
        client.add_expected_call(
577
 
            'BzrDir.open_branchV3', ('quack/',),
 
550
            'BzrDir.open_branchV2', ('quack/',),
578
551
            'success', ('branch', branch_network_name))
579
552
        client.add_expected_call(
580
553
            'BzrDir.find_repositoryV3', ('quack/',),
599
572
            _client=client)
600
573
        self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
601
574
        self.assertEqual(
602
 
            [('call', 'BzrDir.open_branchV3', ('quack/',))],
 
575
            [('call', 'BzrDir.open_branchV2', ('quack/',))],
603
576
            client._calls)
604
577
 
605
578
    def test__get_tree_branch(self):
606
579
        # _get_tree_branch is a form of open_branch, but it should only ask for
607
580
        # branch opening, not any other network requests.
608
581
        calls = []
609
 
        def open_branch(name=None):
 
582
        def open_branch():
610
583
            calls.append("Called")
611
584
            return "a-branch"
612
585
        transport = MemoryTransport()
629
602
        network_name = reference_format.network_name()
630
603
        branch_network_name = self.get_branch_format().network_name()
631
604
        client.add_expected_call(
632
 
            'BzrDir.open_branchV3', ('~hello/',),
 
605
            'BzrDir.open_branchV2', ('~hello/',),
633
606
            'success', ('branch', branch_network_name))
634
607
        client.add_expected_call(
635
608
            'BzrDir.find_repositoryV3', ('~hello/',),
1217
1190
        client = FakeClient(self.get_url())
1218
1191
        branch_network_name = self.get_branch_format().network_name()
1219
1192
        client.add_expected_call(
1220
 
            'BzrDir.open_branchV3', ('stacked/',),
 
1193
            'BzrDir.open_branchV2', ('stacked/',),
1221
1194
            'success', ('branch', branch_network_name))
1222
1195
        client.add_expected_call(
1223
1196
            'BzrDir.find_repositoryV3', ('stacked/',),
1245
1218
            len(branch.repository._real_repository._fallback_repositories))
1246
1219
 
1247
1220
    def test_get_stacked_on_real_branch(self):
1248
 
        base_branch = self.make_branch('base')
1249
 
        stacked_branch = self.make_branch('stacked')
 
1221
        base_branch = self.make_branch('base', format='1.6')
 
1222
        stacked_branch = self.make_branch('stacked', format='1.6')
1250
1223
        stacked_branch.set_stacked_on_url('../base')
1251
1224
        reference_format = self.get_repo_format()
1252
1225
        network_name = reference_format.network_name()
1253
1226
        client = FakeClient(self.get_url())
1254
1227
        branch_network_name = self.get_branch_format().network_name()
1255
1228
        client.add_expected_call(
1256
 
            'BzrDir.open_branchV3', ('stacked/',),
 
1229
            'BzrDir.open_branchV2', ('stacked/',),
1257
1230
            'success', ('branch', branch_network_name))
1258
1231
        client.add_expected_call(
1259
1232
            'BzrDir.find_repositoryV3', ('stacked/',),
1260
 
            'success', ('ok', '', 'yes', 'no', 'yes', network_name))
 
1233
            'success', ('ok', '', 'no', 'no', 'yes', network_name))
1261
1234
        # called twice, once from constructor and then again by us
1262
1235
        client.add_expected_call(
1263
1236
            'Branch.get_stacked_on_url', ('stacked/',),
1615
1588
    def test_get_multi_line_branch_conf(self):
1616
1589
        # Make sure that multiple-line branch.conf files are supported
1617
1590
        #
1618
 
        # https://bugs.launchpad.net/bzr/+bug/354075
 
1591
        # https://bugs.edge.launchpad.net/bzr/+bug/354075
1619
1592
        client = FakeClient()
1620
1593
        client.add_expected_call(
1621
1594
            'Branch.get_stacked_on_url', ('memory:///',),
1649
1622
        branch.unlock()
1650
1623
        self.assertFinished(client)
1651
1624
 
1652
 
    def test_set_option_with_dict(self):
1653
 
        client = FakeClient()
1654
 
        client.add_expected_call(
1655
 
            'Branch.get_stacked_on_url', ('memory:///',),
1656
 
            'error', ('NotStacked',),)
1657
 
        client.add_expected_call(
1658
 
            'Branch.lock_write', ('memory:///', '', ''),
1659
 
            'success', ('ok', 'branch token', 'repo token'))
1660
 
        encoded_dict_value = 'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde'
1661
 
        client.add_expected_call(
1662
 
            'Branch.set_config_option_dict', ('memory:///', 'branch token',
1663
 
            'repo token', encoded_dict_value, 'foo', ''),
1664
 
            'success', ())
1665
 
        client.add_expected_call(
1666
 
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
1667
 
            'success', ('ok',))
1668
 
        transport = MemoryTransport()
1669
 
        branch = self.make_remote_branch(transport, client)
1670
 
        branch.lock_write()
1671
 
        config = branch._get_config()
1672
 
        config.set_option(
1673
 
            {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'},
1674
 
            'foo')
1675
 
        branch.unlock()
1676
 
        self.assertFinished(client)
1677
 
 
1678
1625
    def test_backwards_compat_set_option(self):
1679
1626
        self.setup_smart_server_with_call_log()
1680
1627
        branch = self.make_branch('.')
1687
1634
        self.assertLength(10, self.hpss_calls)
1688
1635
        self.assertEqual('value', branch._get_config().get_option('name'))
1689
1636
 
1690
 
    def test_backwards_compat_set_option_with_dict(self):
1691
 
        self.setup_smart_server_with_call_log()
1692
 
        branch = self.make_branch('.')
1693
 
        verb = 'Branch.set_config_option_dict'
1694
 
        self.disable_verb(verb)
1695
 
        branch.lock_write()
1696
 
        self.addCleanup(branch.unlock)
1697
 
        self.reset_smart_call_log()
1698
 
        config = branch._get_config()
1699
 
        value_dict = {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
1700
 
        config.set_option(value_dict, 'name')
1701
 
        self.assertLength(10, self.hpss_calls)
1702
 
        self.assertEqual(value_dict, branch._get_config().get_option('name'))
1703
 
 
1704
1637
 
1705
1638
class TestBranchLockWrite(RemoteBranchTestCase):
1706
1639
 
2071
2004
        self.assertLength(1, self.hpss_calls)
2072
2005
 
2073
2006
    def disableExtraResults(self):
2074
 
        self.overrideAttr(SmartServerRepositoryGetParentMap,
2075
 
                          'no_extra_results', True)
 
2007
        old_flag = SmartServerRepositoryGetParentMap.no_extra_results
 
2008
        SmartServerRepositoryGetParentMap.no_extra_results = True
 
2009
        def reset_values():
 
2010
            SmartServerRepositoryGetParentMap.no_extra_results = old_flag
 
2011
        self.addCleanup(reset_values)
2076
2012
 
2077
2013
    def test_null_cached_missing_and_stop_key(self):
2078
2014
        self.setup_smart_server_with_call_log()
2137
2073
 
2138
2074
    def test_allows_new_revisions(self):
2139
2075
        """get_parent_map's results can be updated by commit."""
2140
 
        smart_server = test_server.SmartTCPServer_for_testing()
 
2076
        smart_server = server.SmartTCPServer_for_testing()
2141
2077
        self.start_server(smart_server)
2142
2078
        self.make_branch('branch')
2143
2079
        branch = Branch.open(smart_server.get_url() + '/branch')
2253
2189
        """
2254
2190
        # Make a repo with a fallback repo, both using a FakeClient.
2255
2191
        format = remote.response_tuple_to_repo_format(
2256
 
            ('yes', 'no', 'yes', self.get_repo_format().network_name()))
 
2192
            ('yes', 'no', 'yes', 'fake-network-name'))
2257
2193
        repo, client = self.setup_fake_client_and_repository('quack')
2258
2194
        repo._format = format
2259
2195
        fallback_repo, ignored = self.setup_fake_client_and_repository(
2260
2196
            'fallback')
2261
2197
        fallback_repo._client = client
2262
 
        fallback_repo._format = format
2263
2198
        repo.add_fallback_repository(fallback_repo)
2264
2199
        # First the client should ask the primary repo
2265
2200
        client.add_expected_call(
2294
2229
        self.setup_smart_server_with_call_log()
2295
2230
        tree = self.make_branch_and_memory_tree('.')
2296
2231
        tree.lock_write()
2297
 
        tree.add('')
2298
2232
        rev1 = tree.commit('First')
2299
2233
        rev2 = tree.commit('Second')
2300
2234
        tree.unlock()
2339
2273
        transport_path = 'quack'
2340
2274
        repo, client = self.setup_fake_client_and_repository(transport_path)
2341
2275
        client.add_success_response('ok', 'a token')
2342
 
        token = repo.lock_write().repository_token
 
2276
        result = repo.lock_write()
2343
2277
        self.assertEqual(
2344
2278
            [('call', 'Repository.lock_write', ('quack/', ''))],
2345
2279
            client._calls)
2346
 
        self.assertEqual('a token', token)
 
2280
        self.assertEqual('a token', result)
2347
2281
 
2348
2282
    def test_lock_write_already_locked(self):
2349
2283
        transport_path = 'quack'
2687
2621
    """RemoteRepository.copy_content_into optimizations"""
2688
2622
 
2689
2623
    def test_copy_content_remote_to_local(self):
2690
 
        self.transport_server = test_server.SmartTCPServer_for_testing
 
2624
        self.transport_server = server.SmartTCPServer_for_testing
2691
2625
        src_repo = self.make_repository('repo1')
2692
2626
        src_repo = repository.Repository.open(self.get_url('repo1'))
2693
2627
        # At the moment the tarball-based copy_content_into can't write back
2841
2775
        expected_error = errors.NotBranchError(path=bzrdir.root_transport.base)
2842
2776
        self.assertEqual(expected_error, translated_error)
2843
2777
 
2844
 
    def test_nobranch_one_arg(self):
2845
 
        bzrdir = self.make_bzrdir('')
2846
 
        translated_error = self.translateTuple(
2847
 
            ('nobranch', 'extra detail'), bzrdir=bzrdir)
2848
 
        expected_error = errors.NotBranchError(
2849
 
            path=bzrdir.root_transport.base,
2850
 
            detail='extra detail')
2851
 
        self.assertEqual(expected_error, translated_error)
2852
 
 
2853
2778
    def test_LockContention(self):
2854
2779
        translated_error = self.translateTuple(('LockContention',))
2855
2780
        expected_error = errors.LockContention('(remote lock)')
2968
2893
        # In addition to re-raising ErrorFromSmartServer, some debug info has
2969
2894
        # been muttered to the log file for developer to look at.
2970
2895
        self.assertContainsRe(
2971
 
            self.get_log(),
 
2896
            self._get_log(keep_log_file=True),
2972
2897
            "Missing key 'branch' in context")
2973
2898
 
2974
2899
    def test_path_missing(self):
2982
2907
        self.assertEqual(server_error, translated_error)
2983
2908
        # In addition to re-raising ErrorFromSmartServer, some debug info has
2984
2909
        # been muttered to the log file for developer to look at.
2985
 
        self.assertContainsRe(self.get_log(), "Missing key 'path' in context")
 
2910
        self.assertContainsRe(
 
2911
            self._get_log(keep_log_file=True), "Missing key 'path' in context")
2986
2912
 
2987
2913
 
2988
2914
class TestStacking(tests.TestCaseWithTransport):
3006
2932
        stacked_branch = self.make_branch('stacked', format='1.9')
3007
2933
        stacked_branch.set_stacked_on_url('../base')
3008
2934
        # start a server looking at this
3009
 
        smart_server = test_server.SmartTCPServer_for_testing()
 
2935
        smart_server = server.SmartTCPServer_for_testing()
3010
2936
        self.start_server(smart_server)
3011
2937
        remote_bzrdir = BzrDir.open(smart_server.get_url() + '/stacked')
3012
2938
        # can get its branch and repository
3168
3094
        super(TestRemoteBranchEffort, self).setUp()
3169
3095
        # Create a smart server that publishes whatever the backing VFS server
3170
3096
        # does.
3171
 
        self.smart_server = test_server.SmartTCPServer_for_testing()
 
3097
        self.smart_server = server.SmartTCPServer_for_testing()
3172
3098
        self.start_server(self.smart_server, self.get_server())
3173
3099
        # Log all HPSS calls into self.hpss_calls.
3174
3100
        _SmartClient.hooks.install_named_hook(