3
# Copyright (C) 2005 by Canonical Ltd
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
"""test suite for weave algorithm"""
25
from testsweet import TestBase
26
from weave import Weave, VerInfo, WeaveFormatError
27
from pprint import pformat
35
from sets import Set, ImmutableSet
37
frozenset = ImmutableSet
42
# texts for use in testing
43
TEXT_0 = ["Hello world"]
44
TEXT_1 = ["Hello world",
53
class StoreText(TestBase):
54
"""Store and retrieve a simple text."""
57
idx = k.add([], TEXT_0)
58
self.assertEqual(k.get(idx), TEXT_0)
59
self.assertEqual(idx, 0)
63
class AnnotateOne(TestBase):
67
self.assertEqual(k.annotate(0),
71
class StoreTwo(TestBase):
75
idx = k.add([], TEXT_0)
76
self.assertEqual(idx, 0)
78
idx = k.add([], TEXT_1)
79
self.assertEqual(idx, 1)
81
self.assertEqual(k.get(0), TEXT_0)
82
self.assertEqual(k.get(1), TEXT_1)
88
class DeltaAdd(TestBase):
89
"""Detection of changes prior to inserting new revision."""
94
self.assertEqual(k._l,
100
changes = list(k._delta(set([0]),
104
self.log('raw changes: ' + pformat(changes))
106
# currently there are 3 lines in the weave, and we insert after them
107
self.assertEquals(changes,
108
[(3, 3, ['new line'])])
110
changes = k._delta(set([0]),
114
self.assertEquals(list(changes),
115
[(1, 1, ['top line'])])
119
class InvalidAdd(TestBase):
120
"""Try to use invalid version number during add."""
124
self.assertRaises(IndexError,
130
class InsertLines(TestBase):
131
"""Store a revision that adds one line to the original.
133
Look at the annotations to make sure that the first line is matched
134
and not stored repeatedly."""
138
k.add([], ['line 1'])
139
k.add([0], ['line 1', 'line 2'])
141
self.assertEqual(k.annotate(0),
144
self.assertEqual(k.get(1),
148
self.assertEqual(k.annotate(1),
152
k.add([0], ['line 1', 'diverged line'])
154
self.assertEqual(k.annotate(2),
156
(2, 'diverged line')])
158
text3 = ['line 1', 'middle line', 'line 2']
162
self.log("changes to text3: " + pformat(list(k._delta(set([0, 1]), text3))))
164
self.log("k._l=" + pformat(k._l))
166
self.assertEqual(k.annotate(3),
171
# now multiple insertions at different places
173
['line 1', 'aaa', 'middle line', 'bbb', 'line 2', 'ccc'])
175
self.assertEqual(k.annotate(4),
185
class DeleteLines(TestBase):
186
"""Deletion of lines from existing text.
188
Try various texts all based on a common ancestor."""
192
base_text = ['one', 'two', 'three', 'four']
196
texts = [['one', 'two', 'three'],
197
['two', 'three', 'four'],
199
['one', 'two', 'three', 'four'],
205
self.log('final weave:')
206
self.log('k._l=' + pformat(k._l))
208
for i in range(len(texts)):
209
self.assertEqual(k.get(i+1),
215
class SuicideDelete(TestBase):
216
"""Invalid weave which tries to add and delete simultaneously."""
230
self.assertRaises(WeaveFormatError,
236
class CannedDelete(TestBase):
237
"""Unpack canned weave with deleted lines."""
247
'line to be deleted',
253
self.assertEqual(k.get(0),
255
'line to be deleted',
259
self.assertEqual(k.get(1),
266
class CannedReplacement(TestBase):
267
"""Unpack canned weave with deleted lines."""
277
'line to be deleted',
286
self.assertEqual(k.get(0),
288
'line to be deleted',
292
self.assertEqual(k.get(1),
300
class BadWeave(TestBase):
301
"""Test that we trap an insert which should not occur."""
311
' added in version 1',
320
self.assertRaises(WeaveFormatError,
325
class BadInsert(TestBase):
326
"""Test that we trap an insert which should not occur."""
338
' added in version 1',
345
self.assertRaises(WeaveFormatError,
349
self.assertRaises(WeaveFormatError,
354
class InsertNested(TestBase):
355
"""Insertion with nested instructions."""
367
' added in version 1',
376
self.assertEqual(k.get(0),
380
self.assertEqual(k.get(1),
382
' added in version 1',
386
self.assertEqual(k.get(2),
391
self.assertEqual(k.get(3),
393
' added in version 1',
400
class DeleteLines2(TestBase):
401
"""Test recording revisions that delete lines.
403
This relies on the weave having a way to represent lines knocked
404
out by a later revision."""
408
k.add([], ["line the first",
413
self.assertEqual(len(k.get(0)), 4)
415
k.add([0], ["line the first",
418
self.assertEqual(k.get(1),
422
self.assertEqual(k.annotate(1),
423
[(0, "line the first"),
428
class IncludeVersions(TestBase):
429
"""Check texts that are stored across multiple revisions.
431
Here we manually create a weave with particular encoding and make
432
sure it unpacks properly.
434
Text 0 includes nothing; text 1 includes text 0 and adds some
441
k._v = [VerInfo(), VerInfo(included=[0])]
449
self.assertEqual(k.get(1),
453
self.assertEqual(k.get(0),
456
k.dump(self.TEST_LOG)
459
class DivergedIncludes(TestBase):
460
"""Weave with two diverged texts based on version 0.
466
VerInfo(included=[0]),
467
VerInfo(included=[0]),
476
"alternative second line",
480
self.assertEqual(k.get(0),
483
self.assertEqual(k.get(1),
487
self.assertEqual(k.get(2),
489
"alternative second line"])
493
class ReplaceLine(TestBase):
497
text0 = ['cheddar', 'stilton', 'gruyere']
498
text1 = ['cheddar', 'blue vein', 'neufchatel', 'chevre']
503
self.log('k._l=' + pformat(k._l))
505
self.assertEqual(k.get(0), text0)
506
self.assertEqual(k.get(1), text1)
510
class Merge(TestBase):
511
"""Versions that merge diverged parents"""
516
['header', '', 'line from 1'],
517
['header', '', 'line from 2', 'more from 2'],
518
['header', '', 'line from 1', 'fixup line', 'line from 2'],
524
k.add([0, 1, 2], texts[3])
526
for i, t in enumerate(texts):
527
self.assertEqual(k.get(i), t)
529
self.assertEqual(k.annotate(3),
537
self.log('k._l=' + pformat(k._l))
541
class AutoMerge(TestBase):
545
texts = [['header', 'aaa', 'bbb'],
546
['header', 'aaa', 'line from 1', 'bbb'],
547
['header', 'aaa', 'bbb', 'line from 2', 'more from 2'],
554
self.log('k._l=' + pformat(k._l))
556
m = list(k.merge_iter([0, 1, 2]))
562
'line from 2', 'more from 2'])
566
class Khayyam(TestBase):
569
"""A Book of Verses underneath the Bough,
570
A Jug of Wine, a Loaf of Bread, -- and Thou
571
Beside me singing in the Wilderness --
572
Oh, Wilderness were Paradise enow!""",
574
"""A Book of Verses underneath the Bough,
575
A Jug of Wine, a Loaf of Bread, -- and Thou
576
Beside me singing in the Wilderness --
577
Oh, Wilderness were Paradise now!""",
579
"""A Book of poems underneath the tree,
580
A Jug of Wine, a Loaf of Bread,
582
Beside me singing in the Wilderness --
583
Oh, Wilderness were Paradise now!
587
"""A Book of Verses underneath the Bough,
588
A Jug of Wine, a Loaf of Bread,
590
Beside me singing in the Wilderness --
591
Oh, Wilderness were Paradise now!
594
texts = [[l.strip() for l in t.split('\n')] for t in rawtexts]
599
ver = k.add(parents, t)
602
self.log("k._l=" + pformat(k._l))
604
for i, t in enumerate(texts):
605
self.assertEqual(k.get(i),
612
from unittest import TestSuite, TestLoader
617
suite.addTest(tl.loadTestsFromModule(testweave))
619
return int(not testsweet.run_suite(suite)) # for shell 0=true
622
if __name__ == '__main__':
624
sys.exit(testweave())