/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_remote.py

  • Committer: Martin Pool
  • Date: 2009-08-28 04:13:16 UTC
  • mfrom: (4634.6.8 2.0)
  • mto: This revision was merged to the branch mainline in revision 4660.
  • Revision ID: mbp@sourcefrog.net-20090828041316-adcbxfnfpc4bjtpl
Merge 2.0 back to trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
    config,
32
32
    errors,
33
33
    graph,
 
34
    inventory,
 
35
    inventory_delta,
34
36
    pack,
35
37
    remote,
36
38
    repository,
38
40
    tests,
39
41
    treebuilder,
40
42
    urlutils,
 
43
    versionedfile,
41
44
    )
42
45
from bzrlib.branch import Branch
43
46
from bzrlib.bzrdir import BzrDir, BzrDirFormat
332
335
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
333
336
        return reference_bzrdir_format.repository_format
334
337
 
335
 
    def disable_verb(self, verb):
336
 
        """Disable a verb for one test."""
337
 
        request_handlers = smart.request.request_handlers
338
 
        orig_method = request_handlers.get(verb)
339
 
        request_handlers.remove(verb)
340
 
        def restoreVerb():
341
 
            request_handlers.register(verb, orig_method)
342
 
        self.addCleanup(restoreVerb)
343
 
 
344
338
    def assertFinished(self, fake_client):
345
339
        """Assert that all of a FakeClient's expected calls have occurred."""
346
340
        fake_client.finished_test()
667
661
        network_name = reference_format.network_name()
668
662
        client.add_expected_call(
669
663
            'BzrDir.create_repository', ('quack/',
670
 
                'Bazaar pack repository format 1 (needs bzr 0.92)\n', 'False'),
671
 
            'success', ('ok', 'no', 'no', 'no', network_name))
 
664
                'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
 
665
                'False'),
 
666
            'success', ('ok', 'yes', 'yes', 'yes', network_name))
672
667
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
673
668
            _client=client)
674
669
        repo = a_bzrdir.create_repository()
676
671
        self.assertIsInstance(repo, remote.RemoteRepository)
677
672
        # its format should have the settings from the response
678
673
        format = repo._format
679
 
        self.assertFalse(format.rich_root_data)
680
 
        self.assertFalse(format.supports_tree_reference)
681
 
        self.assertFalse(format.supports_external_lookups)
 
674
        self.assertTrue(format.rich_root_data)
 
675
        self.assertTrue(format.supports_tree_reference)
 
676
        self.assertTrue(format.supports_external_lookups)
682
677
        self.assertEqual(network_name, format.network_name())
683
678
 
684
679
 
2219
2214
        self.assertEqual([], client._calls)
2220
2215
 
2221
2216
 
2222
 
class TestRepositoryInsertStream(TestRemoteRepository):
2223
 
 
2224
 
    def test_unlocked_repo(self):
2225
 
        transport_path = 'quack'
2226
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2227
 
        client.add_expected_call(
2228
 
            'Repository.insert_stream', ('quack/', ''),
2229
 
            'success', ('ok',))
2230
 
        client.add_expected_call(
2231
 
            'Repository.insert_stream', ('quack/', ''),
2232
 
            'success', ('ok',))
2233
 
        sink = repo._get_sink()
2234
 
        fmt = repository.RepositoryFormat.get_default_format()
2235
 
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2236
 
        self.assertEqual([], resume_tokens)
2237
 
        self.assertEqual(set(), missing_keys)
2238
 
        self.assertFinished(client)
2239
 
 
2240
 
    def test_locked_repo_with_no_lock_token(self):
2241
 
        transport_path = 'quack'
2242
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2243
 
        client.add_expected_call(
2244
 
            'Repository.lock_write', ('quack/', ''),
2245
 
            'success', ('ok', ''))
2246
 
        client.add_expected_call(
2247
 
            'Repository.insert_stream', ('quack/', ''),
2248
 
            'success', ('ok',))
2249
 
        client.add_expected_call(
2250
 
            'Repository.insert_stream', ('quack/', ''),
2251
 
            'success', ('ok',))
2252
 
        repo.lock_write()
2253
 
        sink = repo._get_sink()
2254
 
        fmt = repository.RepositoryFormat.get_default_format()
2255
 
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2256
 
        self.assertEqual([], resume_tokens)
2257
 
        self.assertEqual(set(), missing_keys)
2258
 
        self.assertFinished(client)
2259
 
 
2260
 
    def test_locked_repo_with_lock_token(self):
2261
 
        transport_path = 'quack'
2262
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2263
 
        client.add_expected_call(
2264
 
            'Repository.lock_write', ('quack/', ''),
2265
 
            'success', ('ok', 'a token'))
2266
 
        client.add_expected_call(
2267
 
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
2268
 
            'success', ('ok',))
2269
 
        client.add_expected_call(
2270
 
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
2271
 
            'success', ('ok',))
2272
 
        repo.lock_write()
2273
 
        sink = repo._get_sink()
2274
 
        fmt = repository.RepositoryFormat.get_default_format()
2275
 
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2276
 
        self.assertEqual([], resume_tokens)
2277
 
        self.assertEqual(set(), missing_keys)
2278
 
        self.assertFinished(client)
 
2217
class TestRepositoryInsertStreamBase(TestRemoteRepository):
 
2218
    """Base class for Repository.insert_stream and .insert_stream_1.19
 
2219
    tests.
 
2220
    """
 
2221
    
 
2222
    def checkInsertEmptyStream(self, repo, client):
 
2223
        """Insert an empty stream, checking the result.
 
2224
 
 
2225
        This checks that there are no resume_tokens or missing_keys, and that
 
2226
        the client is finished.
 
2227
        """
 
2228
        sink = repo._get_sink()
 
2229
        fmt = repository.RepositoryFormat.get_default_format()
 
2230
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
 
2231
        self.assertEqual([], resume_tokens)
 
2232
        self.assertEqual(set(), missing_keys)
 
2233
        self.assertFinished(client)
 
2234
 
 
2235
 
 
2236
class TestRepositoryInsertStream(TestRepositoryInsertStreamBase):
 
2237
    """Tests for using Repository.insert_stream verb when the _1.19 variant is
 
2238
    not available.
 
2239
 
 
2240
    This test case is very similar to TestRepositoryInsertStream_1_19.
 
2241
    """
 
2242
 
 
2243
    def setUp(self):
 
2244
        TestRemoteRepository.setUp(self)
 
2245
        self.disable_verb('Repository.insert_stream_1.19')
 
2246
 
 
2247
    def test_unlocked_repo(self):
 
2248
        transport_path = 'quack'
 
2249
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2250
        client.add_expected_call(
 
2251
            'Repository.insert_stream_1.19', ('quack/', ''),
 
2252
            'unknown', ('Repository.insert_stream_1.19',))
 
2253
        client.add_expected_call(
 
2254
            'Repository.insert_stream', ('quack/', ''),
 
2255
            'success', ('ok',))
 
2256
        client.add_expected_call(
 
2257
            'Repository.insert_stream', ('quack/', ''),
 
2258
            'success', ('ok',))
 
2259
        self.checkInsertEmptyStream(repo, client)
 
2260
 
 
2261
    def test_locked_repo_with_no_lock_token(self):
 
2262
        transport_path = 'quack'
 
2263
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2264
        client.add_expected_call(
 
2265
            'Repository.lock_write', ('quack/', ''),
 
2266
            'success', ('ok', ''))
 
2267
        client.add_expected_call(
 
2268
            'Repository.insert_stream_1.19', ('quack/', ''),
 
2269
            'unknown', ('Repository.insert_stream_1.19',))
 
2270
        client.add_expected_call(
 
2271
            'Repository.insert_stream', ('quack/', ''),
 
2272
            'success', ('ok',))
 
2273
        client.add_expected_call(
 
2274
            'Repository.insert_stream', ('quack/', ''),
 
2275
            'success', ('ok',))
 
2276
        repo.lock_write()
 
2277
        self.checkInsertEmptyStream(repo, client)
 
2278
 
 
2279
    def test_locked_repo_with_lock_token(self):
 
2280
        transport_path = 'quack'
 
2281
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2282
        client.add_expected_call(
 
2283
            'Repository.lock_write', ('quack/', ''),
 
2284
            'success', ('ok', 'a token'))
 
2285
        client.add_expected_call(
 
2286
            'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
 
2287
            'unknown', ('Repository.insert_stream_1.19',))
 
2288
        client.add_expected_call(
 
2289
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
 
2290
            'success', ('ok',))
 
2291
        client.add_expected_call(
 
2292
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
 
2293
            'success', ('ok',))
 
2294
        repo.lock_write()
 
2295
        self.checkInsertEmptyStream(repo, client)
 
2296
 
 
2297
    def test_stream_with_inventory_deltas(self):
 
2298
        """'inventory-deltas' substreams cannot be sent to the
 
2299
        Repository.insert_stream verb, because not all servers that implement
 
2300
        that verb will accept them.  So when one is encountered the RemoteSink
 
2301
        immediately stops using that verb and falls back to VFS insert_stream.
 
2302
        """
 
2303
        transport_path = 'quack'
 
2304
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2305
        client.add_expected_call(
 
2306
            'Repository.insert_stream_1.19', ('quack/', ''),
 
2307
            'unknown', ('Repository.insert_stream_1.19',))
 
2308
        client.add_expected_call(
 
2309
            'Repository.insert_stream', ('quack/', ''),
 
2310
            'success', ('ok',))
 
2311
        client.add_expected_call(
 
2312
            'Repository.insert_stream', ('quack/', ''),
 
2313
            'success', ('ok',))
 
2314
        # Create a fake real repository for insert_stream to fall back on, so
 
2315
        # that we can directly see the records the RemoteSink passes to the
 
2316
        # real sink.
 
2317
        class FakeRealSink:
 
2318
            def __init__(self):
 
2319
                self.records = []
 
2320
            def insert_stream(self, stream, src_format, resume_tokens):
 
2321
                for substream_kind, substream in stream:
 
2322
                    self.records.append(
 
2323
                        (substream_kind, [record.key for record in substream]))
 
2324
                return ['fake tokens'], ['fake missing keys']
 
2325
        fake_real_sink = FakeRealSink()
 
2326
        class FakeRealRepository:
 
2327
            def _get_sink(self):
 
2328
                return fake_real_sink
 
2329
        repo._real_repository = FakeRealRepository()
 
2330
        sink = repo._get_sink()
 
2331
        fmt = repository.RepositoryFormat.get_default_format()
 
2332
        stream = self.make_stream_with_inv_deltas(fmt)
 
2333
        resume_tokens, missing_keys = sink.insert_stream(stream, fmt, [])
 
2334
        # Every record from the first inventory delta should have been sent to
 
2335
        # the VFS sink.
 
2336
        expected_records = [
 
2337
            ('inventory-deltas', [('rev2',), ('rev3',)]),
 
2338
            ('texts', [('some-rev', 'some-file')])]
 
2339
        self.assertEqual(expected_records, fake_real_sink.records)
 
2340
        # The return values from the real sink's insert_stream are propagated
 
2341
        # back to the original caller.
 
2342
        self.assertEqual(['fake tokens'], resume_tokens)
 
2343
        self.assertEqual(['fake missing keys'], missing_keys)
 
2344
        self.assertFinished(client)
 
2345
 
 
2346
    def make_stream_with_inv_deltas(self, fmt):
 
2347
        """Make a simple stream with an inventory delta followed by more
 
2348
        records and more substreams to test that all records and substreams
 
2349
        from that point on are used.
 
2350
 
 
2351
        This sends, in order:
 
2352
           * inventories substream: rev1, rev2, rev3.  rev2 and rev3 are
 
2353
             inventory-deltas.
 
2354
           * texts substream: (some-rev, some-file)
 
2355
        """
 
2356
        # Define a stream using generators so that it isn't rewindable.
 
2357
        inv = inventory.Inventory(revision_id='rev1')
 
2358
        inv.root.revision = 'rev1'
 
2359
        def stream_with_inv_delta():
 
2360
            yield ('inventories', inventories_substream())
 
2361
            yield ('inventory-deltas', inventory_delta_substream())
 
2362
            yield ('texts', [
 
2363
                versionedfile.FulltextContentFactory(
 
2364
                    ('some-rev', 'some-file'), (), None, 'content')])
 
2365
        def inventories_substream():
 
2366
            # An empty inventory fulltext.  This will be streamed normally.
 
2367
            text = fmt._serializer.write_inventory_to_string(inv)
 
2368
            yield versionedfile.FulltextContentFactory(
 
2369
                ('rev1',), (), None, text)
 
2370
        def inventory_delta_substream():
 
2371
            # An inventory delta.  This can't be streamed via this verb, so it
 
2372
            # will trigger a fallback to VFS insert_stream.
 
2373
            entry = inv.make_entry(
 
2374
                'directory', 'newdir', inv.root.file_id, 'newdir-id')
 
2375
            entry.revision = 'ghost'
 
2376
            delta = [(None, 'newdir', 'newdir-id', entry)]
 
2377
            serializer = inventory_delta.InventoryDeltaSerializer(
 
2378
                versioned_root=True, tree_references=False)
 
2379
            lines = serializer.delta_to_lines('rev1', 'rev2', delta)
 
2380
            yield versionedfile.ChunkedContentFactory(
 
2381
                ('rev2',), (('rev1',)), None, lines)
 
2382
            # Another delta.
 
2383
            lines = serializer.delta_to_lines('rev1', 'rev3', delta)
 
2384
            yield versionedfile.ChunkedContentFactory(
 
2385
                ('rev3',), (('rev1',)), None, lines)
 
2386
        return stream_with_inv_delta()
 
2387
 
 
2388
 
 
2389
class TestRepositoryInsertStream_1_19(TestRepositoryInsertStreamBase):
 
2390
 
 
2391
    def test_unlocked_repo(self):
 
2392
        transport_path = 'quack'
 
2393
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2394
        client.add_expected_call(
 
2395
            'Repository.insert_stream_1.19', ('quack/', ''),
 
2396
            'success', ('ok',))
 
2397
        client.add_expected_call(
 
2398
            'Repository.insert_stream_1.19', ('quack/', ''),
 
2399
            'success', ('ok',))
 
2400
        self.checkInsertEmptyStream(repo, client)
 
2401
 
 
2402
    def test_locked_repo_with_no_lock_token(self):
 
2403
        transport_path = 'quack'
 
2404
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2405
        client.add_expected_call(
 
2406
            'Repository.lock_write', ('quack/', ''),
 
2407
            'success', ('ok', ''))
 
2408
        client.add_expected_call(
 
2409
            'Repository.insert_stream_1.19', ('quack/', ''),
 
2410
            'success', ('ok',))
 
2411
        client.add_expected_call(
 
2412
            'Repository.insert_stream_1.19', ('quack/', ''),
 
2413
            'success', ('ok',))
 
2414
        repo.lock_write()
 
2415
        self.checkInsertEmptyStream(repo, client)
 
2416
 
 
2417
    def test_locked_repo_with_lock_token(self):
 
2418
        transport_path = 'quack'
 
2419
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2420
        client.add_expected_call(
 
2421
            'Repository.lock_write', ('quack/', ''),
 
2422
            'success', ('ok', 'a token'))
 
2423
        client.add_expected_call(
 
2424
            'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
 
2425
            'success', ('ok',))
 
2426
        client.add_expected_call(
 
2427
            'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
 
2428
            'success', ('ok',))
 
2429
        repo.lock_write()
 
2430
        self.checkInsertEmptyStream(repo, client)
2279
2431
 
2280
2432
 
2281
2433
class TestRepositoryTarball(TestRemoteRepository):
2651
2803
        tree1.commit('rev1', rev_id='rev1')
2652
2804
        tree2 = tree1.branch.bzrdir.sprout('tree2', stacked=True
2653
2805
            ).open_workingtree()
2654
 
        tree2.commit('local changes make me feel good.')
 
2806
        local_tree = tree2.branch.create_checkout('local')
 
2807
        local_tree.commit('local changes make me feel good.')
2655
2808
        branch2 = Branch.open(self.get_url('tree2'))
2656
2809
        branch2.lock_read()
2657
2810
        self.addCleanup(branch2.unlock)
2727
2880
            _, stacked = self.prepare_stacked_remote_branch()
2728
2881
            tree = stacked.bzrdir.sprout('tree3', stacked=True
2729
2882
                ).open_workingtree()
2730
 
            tree.commit('more local changes are better')
 
2883
            local_tree = tree.branch.create_checkout('local-tree3')
 
2884
            local_tree.commit('more local changes are better')
2731
2885
            branch = Branch.open(self.get_url('tree3'))
2732
2886
            branch.lock_read()
2733
2887
            return None, branch
2744
2898
        # stacked upon sources in topological order.
2745
2899
        rev_ord, expected_revs = self.get_ordered_revs('knit', 'topological')
2746
2900
        self.assertEqual(expected_revs, rev_ord)
2747
 
        # Getting topological sort requires VFS calls still
2748
 
        self.assertLength(12, self.hpss_calls)
 
2901
        # Getting topological sort requires VFS calls still - one of which is
 
2902
        # pushing up from the bound branch.
 
2903
        self.assertLength(13, self.hpss_calls)
2749
2904
 
2750
2905
    def test_stacked_get_stream_groupcompress(self):
2751
2906
        # Repository._get_source.get_stream() from a stacked repository with