~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_knit.py

  • Committer: Andrew Bennetts
  • Date: 2007-06-26 06:18:07 UTC
  • mto: (2535.4.4 streaming-smart-fetch)
  • mto: This revision was merged to the branch mainline in revision 2906.
  • Revision ID: andrew.bennetts@canonical.com-20070626061807-nuxew9ioocogpqs4
Simple implementation of Knit.insert_data_stream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
675
675
class KnitTests(TestCaseWithTransport):
676
676
    """Class containing knit test helper routines."""
677
677
 
678
 
    def make_test_knit(self, annotate=False, delay_create=False):
 
678
    def make_test_knit(self, annotate=False, delay_create=False, name='test'):
679
679
        if not annotate:
680
680
            factory = KnitPlainFactory()
681
681
        else:
682
682
            factory = None
683
 
        return KnitVersionedFile('test', get_transport('.'), access_mode='w',
 
683
        return KnitVersionedFile(name, get_transport('.'), access_mode='w',
684
684
                                 factory=factory, create=True,
685
685
                                 delay_create=delay_create)
686
686
 
1233
1233
            bytes = reader_callable(length)
1234
1234
            self.assertRecordContentEqual(k1, version_id, bytes)
1235
1235
 
1236
 
    # permutations left to test:
 
1236
    # permutations left to explicitly test:
1237
1237
    #  * getting a version where all its parents are ghosts
1238
1238
    #  * reader_func edge-cases:
1239
1239
    #    * read too little
1240
1240
    #    * read too much
1241
1241
    #    * multiple read calls
1242
1242
    #    * read(None)
 
1243
    #  * reading records with other data interspersed skips interspersed data.
 
1244
    #     insert [A [], B [A], C [A]], read [A, C].
 
1245
 
1243
1246
    #
1244
1247
    # after that:
1245
1248
    #  * move callable into own class (see XXX in get_data_stream)
1246
1249
    #  * insert data stream into knits
1247
1250
 
 
1251
    def assertKnitFilesEqual(self, knit1, knit2):
 
1252
        """Assert that the contents of the index and data files of two knits are
 
1253
        equal.
 
1254
        """
 
1255
        self.assertEqual(
 
1256
            knit1.transport.get_bytes(knit1._data._filename),
 
1257
            knit2.transport.get_bytes(knit2._data._filename))
 
1258
        self.assertEqual(
 
1259
            knit1.transport.get_bytes(knit1._index._filename),
 
1260
            knit2.transport.get_bytes(knit2._index._filename))
 
1261
 
 
1262
    def test_insert_data_stream_empty(self):
 
1263
        """Inserting a data stream with no records should not put any data into
 
1264
        the knit.
 
1265
        """
 
1266
        k1 = self.make_test_knit()
 
1267
        k1.insert_data_stream(
 
1268
            (k1.get_format_signature(), [], lambda ignored: ''))
 
1269
        self.assertEqual('', k1.transport.get_bytes(k1._data._filename),
 
1270
                         "The .knit should be completely empty.")
 
1271
        self.assertEqual(k1._index.HEADER,
 
1272
                         k1.transport.get_bytes(k1._index._filename),
 
1273
                         "The .kndx should have nothing apart from the header.")
 
1274
 
 
1275
    def test_insert_data_stream_one_record(self):
 
1276
        """Inserting a data stream with one record from a knit with one record
 
1277
        results in byte-identical files.
 
1278
        """
 
1279
        source = self.make_test_knit(name='source')
 
1280
        source.add_lines('text-a', [], split_lines(TEXT_1))
 
1281
        data_stream = source.get_data_stream(['text-a'])
 
1282
        
 
1283
        target = self.make_test_knit(name='target')
 
1284
        target.insert_data_stream(data_stream)
 
1285
        
 
1286
        self.assertKnitFilesEqual(source, target)
 
1287
 
 
1288
    def test_insert_data_stream_records_already_present(self):
 
1289
        """Insert a data stream where some records are alreday present in the
 
1290
        target, and some not.  Only the new records are inserted.
 
1291
        """
 
1292
        source = self.make_test_knit(name='source')
 
1293
        target = self.make_test_knit(name='target')
 
1294
        # Insert 'text-a' into both source and target
 
1295
        source.add_lines('text-a', [], split_lines(TEXT_1))
 
1296
        target.insert_data_stream(source.get_data_stream(['text-a']))
 
1297
        # Insert 'text-b' into just the source.
 
1298
        source.add_lines('text-b', ['text-a'], split_lines(TEXT_1))
 
1299
        # Get a data stream of both text-a and text-b, and insert it.
 
1300
        data_stream = source.get_data_stream(['text-a', 'text-b'])
 
1301
        target.insert_data_stream(data_stream)
 
1302
        # The source and target will now be identical.  This means the text-a
 
1303
        # record was not added a second time.
 
1304
        self.assertKnitFilesEqual(source, target)
 
1305
 
 
1306
    def test_insert_data_stream_multiple_records(self):
 
1307
        """Inserting a data stream of all records from a knit with multiple
 
1308
        records results in byte-identical files.
 
1309
        """
 
1310
        source = self.make_test_knit(name='source')
 
1311
        source.add_lines('text-a', [], split_lines(TEXT_1))
 
1312
        source.add_lines('text-b', ['text-a'], split_lines(TEXT_1))
 
1313
        source.add_lines('text-c', [], split_lines(TEXT_1))
 
1314
        data_stream = source.get_data_stream(['text-a', 'text-b', 'text-c'])
 
1315
        
 
1316
        target = self.make_test_knit(name='target')
 
1317
        target.insert_data_stream(data_stream)
 
1318
        
 
1319
        self.assertKnitFilesEqual(source, target)
 
1320
 
 
1321
    def test_insert_data_stream_ghost_parent(self):
 
1322
        """Insert a data stream with a record that has a ghost parent."""
 
1323
        # Make a knit with a record, text-a, that has a ghost parent.
 
1324
        source = self.make_test_knit(name='source')
 
1325
        source.add_lines_with_ghosts('text-a', ['text-ghost'],
 
1326
                                     split_lines(TEXT_1))
 
1327
        data_stream = source.get_data_stream(['text-a'])
 
1328
 
 
1329
        target = self.make_test_knit(name='target')
 
1330
        target.insert_data_stream(data_stream)
 
1331
 
 
1332
        self.assertKnitFilesEqual(source, target)
 
1333
 
 
1334
        # The target knit object is in a consistent state, i.e. the record we
 
1335
        # just added is immediately visible.
 
1336
        self.assertTrue(target.has_version('text-a'))
 
1337
        self.assertTrue(target.has_ghost('text-ghost'))
 
1338
        self.assertEqual(split_lines(TEXT_1), target.get_lines('text-a'))
 
1339
 
 
1340
    def test_insert_data_stream_inconsistent_version_lines(self):
 
1341
        """Inserting a data stream which has different content for a version_id
 
1342
        than already exists in the knit will raise KnitCorrupt.
 
1343
        """
 
1344
        source = self.make_test_knit(name='source')
 
1345
        target = self.make_test_knit(name='target')
 
1346
        # Insert a different 'text-a' into both source and target
 
1347
        source.add_lines('text-a', [], split_lines(TEXT_1))
 
1348
        target.add_lines('text-a', [], split_lines(TEXT_2))
 
1349
        # Insert a data stream with conflicting content into the target
 
1350
        data_stream = source.get_data_stream(['text-a'])
 
1351
        self.assertRaises(
 
1352
            errors.KnitCorrupt, target.insert_data_stream, data_stream)
 
1353
 
 
1354
    def test_insert_data_stream_inconsistent_version_parents(self):
 
1355
        """Inserting a data stream which has different parents for a version_id
 
1356
        than already exists in the knit will raise KnitCorrupt.
 
1357
        """
 
1358
        source = self.make_test_knit(name='source')
 
1359
        target = self.make_test_knit(name='target')
 
1360
        # Insert a different 'text-a' into both source and target.  They differ
 
1361
        # only by the parents list, the content is the same.
 
1362
        source.add_lines_with_ghosts('text-a', [], split_lines(TEXT_1))
 
1363
        target.add_lines_with_ghosts('text-a', ['a-ghost'], split_lines(TEXT_1))
 
1364
        # Insert a data stream with conflicting content into the target
 
1365
        data_stream = source.get_data_stream(['text-a'])
 
1366
        self.assertRaises(
 
1367
            errors.KnitCorrupt, target.insert_data_stream, data_stream)
 
1368
 
 
1369
    def test_insert_data_stream_incompatible_format(self):
 
1370
        """A data stream in a different format to the target knit cannot be
 
1371
        inserted.
 
1372
 
 
1373
        It will raise KnitDataStreamIncompatible.
 
1374
        """
 
1375
        data_stream = ('fake-format-signature', [], lambda _: '')
 
1376
        target = self.make_test_knit(name='target')
 
1377
        self.assertRaises(
 
1378
            errors.KnitDataStreamIncompatible,
 
1379
            target.insert_data_stream, data_stream)
 
1380
 
1248
1381
 
1249
1382
TEXT_1 = """\
1250
1383
Banana cup cakes: