36
36
class KnitTests(TestCaseWithTransport):
37
37
"""Class containing knit test helper routines."""
39
def make_test_knit(self, annotate=False):
39
def make_test_knit(self, annotate=False, delay_create=False):
41
41
factory = KnitPlainFactory()
44
return KnitVersionedFile('test', get_transport('.'), access_mode='w', factory=factory, create=True)
44
return KnitVersionedFile('test', get_transport('.'), access_mode='w',
45
factory=factory, create=True,
46
delay_create=delay_create)
47
49
class BasicKnitTests(KnitTests):
272
274
self.assertEquals(origins[0], ('text-c', 'z\n'))
273
275
self.assertEquals(origins[1], ('text-b', 'c\n'))
275
def test_extraction_reads_components_once(self):
276
t = MemoryTransport()
277
instrumented_t = TransportLogger(t)
278
k1 = KnitVersionedFile('id', instrumented_t, create=True, delta=True)
279
# should read the index
280
self.assertEqual([('id.kndx',)], instrumented_t._calls)
281
instrumented_t._calls = []
283
k1.add_lines('base', [], ['text\n'])
284
# should not have read at all
285
self.assertEqual([], instrumented_t._calls)
288
k1.add_lines('sub', ['base'], ['text\n', 'text2\n'])
289
# should not have read at all
290
self.assertEqual([], instrumented_t._calls)
294
# should not have read at all
295
self.assertEqual([], instrumented_t._calls)
302
# should have read a component
303
# should not have read the first component only
304
self.assertEqual([('id.knit', [(0, 87)])], instrumented_t._calls)
305
instrumented_t._calls = []
308
# should not have read at all
309
self.assertEqual([], instrumented_t._calls)
310
# and now read the other component
312
# should have read the second component
313
self.assertEqual([('id.knit', [(87, 93)])], instrumented_t._calls)
314
instrumented_t._calls = []
319
k1.add_lines('sub2', ['base'], ['text\n', 'text3\n'])
320
# should read the first component only
321
self.assertEqual([('id.knit', [(0, 87)])], instrumented_t._calls)
277
def test_get_line_delta_texts(self):
278
"""Make sure we can call get_texts on text with reused line deltas"""
279
k1 = KnitVersionedFile('test1', get_transport('.'),
280
factory=KnitPlainFactory(), create=True)
285
parents = ['%d' % (t-1)]
286
k1.add_lines('%d' % t, parents, ['hello\n'] * t)
287
k1.get_texts(('%d' % t) for t in range(3))
323
289
def test_iter_lines_reads_in_order(self):
324
290
t = MemoryTransport()
378
345
self.assertEqual(['revid', 'revid2', 'revid3'], knit.versions())
379
346
self.assertEqual(['revid2'], knit.get_parents('revid3'))
348
def test_delay_create(self):
349
"""Test that passing delay_create=True creates files late"""
350
knit = self.make_test_knit(annotate=True, delay_create=True)
351
self.failIfExists('test.knit')
352
self.failIfExists('test.kndx')
353
knit.add_lines_with_ghosts('revid', ['a_ghost'], ['a\n'])
354
self.failUnlessExists('test.knit')
355
self.assertFileEqual(
356
"# bzr knit index 8\n"
358
"revid fulltext 0 84 .a_ghost :",
361
def test_create_parent_dir(self):
362
"""create_parent_dir can create knits in nonexistant dirs"""
363
# Has no effect if we don't set 'delay_create'
364
trans = get_transport('.')
365
self.assertRaises(NoSuchFile, KnitVersionedFile, 'dir/test',
366
trans, access_mode='w', factory=None,
367
create=True, create_parent_dir=True)
368
# Nothing should have changed yet
369
knit = KnitVersionedFile('dir/test', trans, access_mode='w',
370
factory=None, create=True,
371
create_parent_dir=True,
373
self.failIfExists('dir/test.knit')
374
self.failIfExists('dir/test.kndx')
375
self.failIfExists('dir')
376
knit.add_lines('revid', [], ['a\n'])
377
self.failUnlessExists('dir')
378
self.failUnlessExists('dir/test.knit')
379
self.assertFileEqual(
380
"# bzr knit index 8\n"
382
"revid fulltext 0 84 :",
385
def test_create_mode_700(self):
386
trans = get_transport('.')
387
if not trans._can_roundtrip_unix_modebits():
388
# Can't roundtrip, so no need to run this test
390
knit = KnitVersionedFile('dir/test', trans, access_mode='w',
391
factory=None, create=True,
392
create_parent_dir=True,
396
knit.add_lines('revid', [], ['a\n'])
397
self.assertTransportMode(trans, 'dir', 0700)
398
self.assertTransportMode(trans, 'dir/test.knit', 0600)
399
self.assertTransportMode(trans, 'dir/test.kndx', 0600)
401
def test_create_mode_770(self):
402
trans = get_transport('.')
403
if not trans._can_roundtrip_unix_modebits():
404
# Can't roundtrip, so no need to run this test
406
knit = KnitVersionedFile('dir/test', trans, access_mode='w',
407
factory=None, create=True,
408
create_parent_dir=True,
412
knit.add_lines('revid', [], ['a\n'])
413
self.assertTransportMode(trans, 'dir', 0770)
414
self.assertTransportMode(trans, 'dir/test.knit', 0660)
415
self.assertTransportMode(trans, 'dir/test.kndx', 0660)
417
def test_create_mode_777(self):
418
trans = get_transport('.')
419
if not trans._can_roundtrip_unix_modebits():
420
# Can't roundtrip, so no need to run this test
422
knit = KnitVersionedFile('dir/test', trans, access_mode='w',
423
factory=None, create=True,
424
create_parent_dir=True,
428
knit.add_lines('revid', [], ['a\n'])
429
self.assertTransportMode(trans, 'dir', 0777)
430
self.assertTransportMode(trans, 'dir/test.knit', 0666)
431
self.assertTransportMode(trans, 'dir/test.kndx', 0666)
381
433
def test_plan_merge(self):
382
434
my_knit = self.make_test_knit(annotate=True)
383
435
my_knit.add_lines('text1', [], split_lines(TEXT_1))
486
538
self.failIf(WeaveToKnit.is_compatible(k, w))
487
539
self.failIf(WeaveToKnit.is_compatible(w, w))
488
540
self.failIf(WeaveToKnit.is_compatible(k, k))
543
class TestKnitCaching(KnitTests):
545
def create_knit(self, cache_add=False):
546
k = self.make_test_knit(True)
550
k.add_lines('text-1', [], split_lines(TEXT_1))
551
k.add_lines('text-2', [], split_lines(TEXT_2))
554
def test_no_caching(self):
555
k = self.create_knit()
556
# Nothing should be cached without setting 'enable_cache'
557
self.assertEqual({}, k._data._cache)
559
def test_cache_add_and_clear(self):
560
k = self.create_knit(True)
562
self.assertEqual(['text-1', 'text-2'], sorted(k._data._cache.keys()))
565
self.assertEqual({}, k._data._cache)
567
def test_cache_data_read_raw(self):
568
k = self.create_knit()
573
def read_one_raw(version):
574
pos_map = k._get_components_positions([version])
575
method, pos, size, next = pos_map[version]
576
lst = list(k._data.read_records_iter_raw([(version, pos, size)]))
577
self.assertEqual(1, len(lst))
580
val = read_one_raw('text-1')
581
self.assertEqual({'text-1':val[1]}, k._data._cache)
584
# After clear, new reads are not cached
585
self.assertEqual({}, k._data._cache)
587
val2 = read_one_raw('text-1')
588
self.assertEqual(val, val2)
589
self.assertEqual({}, k._data._cache)
591
def test_cache_data_read(self):
592
k = self.create_knit()
594
def read_one(version):
595
pos_map = k._get_components_positions([version])
596
method, pos, size, next = pos_map[version]
597
lst = list(k._data.read_records_iter([(version, pos, size)]))
598
self.assertEqual(1, len(lst))
604
val = read_one('text-2')
605
self.assertEqual(['text-2'], k._data._cache.keys())
606
self.assertEqual('text-2', val[0])
607
content, digest = k._data._parse_record('text-2',
608
k._data._cache['text-2'])
609
self.assertEqual(content, val[1])
610
self.assertEqual(digest, val[2])
613
self.assertEqual({}, k._data._cache)
615
val2 = read_one('text-2')
616
self.assertEqual(val, val2)
617
self.assertEqual({}, k._data._cache)
619
def test_cache_read(self):
620
k = self.create_knit()
623
text = k.get_text('text-1')
624
self.assertEqual(TEXT_1, text)
625
self.assertEqual(['text-1'], k._data._cache.keys())
628
self.assertEqual({}, k._data._cache)
630
text = k.get_text('text-1')
631
self.assertEqual(TEXT_1, text)
632
self.assertEqual({}, k._data._cache)