run-tests.py: Only pass the --svnadmin option to cvs2svn when needed.
[cvs2svn.git] / cvs2svn_lib / test / rcs_stream_test.py
blob964ce521b3077cde70ea5bdf1fa674c822442611
1 #!/usr/bin/env python
2 # (Be in -*- python -*- mode.)
4 # ====================================================================
5 # Copyright (c) 2010 CollabNet. All rights reserved.
7 # This software is licensed as described in the file COPYING, which
8 # you should have received as part of this distribution. The terms
9 # are also available at http://subversion.tigris.org/license-1.html.
10 # If newer versions of this license are posted there, you may use a
11 # newer version instead, at your option.
13 # This software consists of voluntary contributions made by many
14 # individuals. For exact contribution history, see the revision
15 # history and logs, available at http://cvs2svn.tigris.org/.
16 # ====================================================================
18 """This program tests the RCSStream class.
20 When executed, this class conducts a number of unit tests of the
21 RCSStream class. It requires RCS's 'ci' program to be installed."""
23 import sys
24 import os
25 import shutil
26 import unittest
27 import subprocess
29 SRCPATH = os.path.normpath(os.path.join(os.path.dirname(__file__), '..', '..'))
30 sys.path.insert(0, SRCPATH)
32 import unittest
34 from cvs2svn_lib.rcsparser import Sink
35 from cvs2svn_lib.rcsparser import parse
36 from cvs2svn_lib.rcs_stream import RCSStream
38 TMPDIR = os.path.join(SRCPATH, 'cvs2svn-tmp')
41 # Do we require that the inverse of an inverse delta is identical to
42 # the original delta? (This is not really required; it would be
43 # enough if the deltas were functionally the same.)
44 STRICT_INVERSES = True
47 class RCSRecorder(Sink):
48 def __init__(self):
49 self.texts = {}
51 def set_revision_info(self, rev, log, text):
52 self.texts[rev] = text
55 class RCSStreamTestCase(unittest.TestCase):
56 def __init__(self, name, doc, v1, v2):
57 unittest.TestCase.__init__(self)
58 self.name = name
59 self.doc = doc
60 self.v1 = v1
61 self.v2 = v2
62 self.filename = os.path.join(TMPDIR, 'rcsstream-%s' % self.name, 'a.txt')
64 def shortDescription(self):
65 return self.doc
67 def call(self, *args, **kwargs):
68 retcode = subprocess.call(*args, **kwargs)
69 self.assertEqual(retcode, 0)
71 def setUp(self):
72 if not os.path.isdir(os.path.dirname(self.filename)):
73 os.makedirs(os.path.dirname(self.filename))
74 open(self.filename, 'wb').write(self.v1)
75 self.call(
76 ['ci', '-q', '-i', '-t-' + self.name, '-mv1', '-l', self.filename],
78 open(self.filename, 'wb').write(self.v2)
79 self.call(
80 ['ci', '-q', '-f', '-mv2', self.filename],
83 def applyTest(self, old, delta, new):
84 s1 = RCSStream(old)
85 self.assertEqual(s1.get_text(), old)
86 s1.apply_diff(delta)
87 self.assertEqual(s1.get_text(), new)
89 s2 = RCSStream(old)
90 self.assertEqual(s2.get_text(), old)
91 s2.invert_diff(delta)
92 self.assertEqual(s2.get_text(), new)
94 def runTest(self):
95 self.assert_(os.path.isfile(self.filename + ',v'))
96 recorder = RCSRecorder()
97 parse(open(self.filename + ',v', 'rb'), recorder)
98 v2 = recorder.texts['1.2']
99 self.assertEqual(v2, self.v2)
100 delta = recorder.texts['1.1']
101 s = RCSStream(v2)
102 self.assertEqual(s.get_text(), self.v2)
103 invdelta = s.invert_diff(delta)
104 self.assertEqual(s.get_text(), self.v1)
105 delta2 = s.invert_diff(invdelta)
107 self.applyTest(self.v2, delta, self.v1)
108 self.applyTest(self.v1, invdelta, self.v2)
110 if STRICT_INVERSES:
111 self.assertEqual(delta2, delta)
112 elif delta2 != delta:
113 self.applyTest(self.v2, delta2, self.v1)
115 def tearDown(self):
116 shutil.rmtree(os.path.dirname(self.filename))
119 suite = unittest.TestSuite()
122 def add_test_pair(name, v1, v2):
123 suite.addTest(RCSStreamTestCase(name, name, v1, v2))
124 if v1 != v2:
125 suite.addTest(RCSStreamTestCase(name + '-reverse', name + '-reverse', v2, v1))
128 def add_test(name, v1, v2):
129 add_test_pair(name, v1, v2)
130 if v1.endswith('\n'):
131 add_test_pair(name + '-1', v1[:-1], v2)
132 if v2.endswith('\n'):
133 add_test_pair(name + '-2', v1, v2[:-1])
134 if v1.endswith('\n') and v2.endswith('\n'):
135 add_test_pair(name + '-3', v1[:-1], v2[:-1])
138 add_test('empty', '', '')
139 add_test('ab-initio', '', 'blah\n')
141 add_test('delete-at-start', 'a\nb\nc\n', 'b\nc\n')
142 add_test('delete-in-middle', 'a\nb\nc\n', 'a\nc\n')
143 add_test('delete-at-end', 'a\nb\nc\n', 'a\nb\n')
145 add_test('replace-at-start', 'a\nb\nc\n', 'a1\nb\nc\n')
146 add_test('replace-in-middle', 'a\nb\nc\n', 'a\nb1\nc\n')
147 add_test('replace-at-end', 'a\nb\nc\n', 'a\nb\nc1\n')
149 add_test('enlarge-at-start', 'a\nb\nc\n', 'a1\na2\nb\nc\n')
150 add_test('enlarge-in-middle', 'a\nb\nc\n', 'a\nb1\nb2\nc\n')
151 add_test('enlarge-at-end', 'a\nb\nc\n', 'a\nb\nc1\nc2\n')
154 unittest.TextTestRunner(verbosity=2).run(suite)