001: /*
002: * ====================================================================
003: *
004: * The Apache Software License, Version 1.1
005: *
006: * Copyright (c) 1999-2003 The Apache Software Foundation.
007: * All rights reserved.
008: *
009: * Redistribution and use in source and binary forms, with or without
010: * modification, are permitted provided that the following conditions
011: * are met:
012: *
013: * 1. Redistributions of source code must retain the above copyright
014: * notice, this list of conditions and the following disclaimer.
015: *
016: * 2. Redistributions in binary form must reproduce the above copyright
017: * notice, this list of conditions and the following disclaimer in
018: * the documentation and/or other materials provided with the
019: * distribution.
020: *
021: * 3. The end-user documentation included with the redistribution, if
022: * any, must include the following acknowledgement:
023: * "This product includes software developed by the
024: * Apache Software Foundation (http://www.apache.org/)."
025: * Alternately, this acknowledgement may appear in the software itself,
026: * if and wherever such third-party acknowledgements normally appear.
027: *
028: * 4. The names "The Jakarta Project", "Commons", and "Apache Software
029: * Foundation" must not be used to endorse or promote products derived
030: * from this software without prior written permission. For written
031: * permission, please contact apache@apache.org.
032: *
033: * 5. Products derived from this software may not be called "Apache"
034: * nor may "Apache" appear in their names without prior written
035: * permission of the Apache Software Foundation.
036: *
037: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
038: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
039: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
040: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
041: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
042: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
043: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
044: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
045: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
046: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
047: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
048: * SUCH DAMAGE.
049: * ====================================================================
050: *
051: * This software consists of voluntary contributions made by many
052: * individuals on behalf of the Apache Software Foundation. For more
053: * information on the Apache Software Foundation, please see
054: * <http://www.apache.org/>.
055: *
056: */
057:
058: package org.apache.commons.jrcs.diff;
059:
060: import junit.framework.Test;
061: import junit.framework.TestCase;
062: import junit.framework.TestSuite;
063:
064: public abstract class DiffTest extends TestCase {
065: static final int LARGE = 2 * 1024;
066:
067: protected DiffAlgorithm algorithm;
068:
069: public DiffTest(String testName, DiffAlgorithm algorithm) {
070: super (testName);
071: this .algorithm = algorithm;
072: }
073:
074: public static Test suite() {
075: return new TestSuite(DiffTest.class);
076: }
077:
078: Object[] empty = new Object[] {};
079:
080: Object[] original = new String[] { "[1] one", "[2] two",
081: "[3] three", "[4] four", "[5] five", "[6] six",
082: "[7] seven", "[8] eight", "[9] nine" };
083:
084: // lines 3 and 9 deleted
085: Object[] rev1 = new String[] { "[1] one", "[2] two", "[4] four",
086: "[5] five", "[6] six", "[7] seven", "[8] eight", };
087:
088: // lines 7 and 8 changed, 9 deleted
089: Object[] rev2 = new String[] { "[1] one", "[2] two", "[3] three",
090: "[4] four", "[5] five", "[6] six", "[7] seven revised",
091: "[8] eight revised", };
092:
093: public void testCompare() {
094: assertTrue(!Diff.compare(original, empty));
095: assertTrue(!Diff.compare(empty, original));
096: assertTrue(Diff.compare(empty, empty));
097: assertTrue(Diff.compare(original, original));
098: }
099:
100: public void testEmptySequences()
101: throws DifferentiationFailedException {
102: String[] emptyOrig = {};
103: String[] emptyRev = {};
104: Revision revision = Diff.diff(emptyOrig, emptyRev, algorithm);
105:
106: assertEquals("revision size is not zero", 0, revision.size());
107: }
108:
109: public void testOriginalEmpty()
110: throws DifferentiationFailedException {
111: String[] emptyOrig = {};
112: String[] rev = { "1", "2", "3" };
113: Revision revision = Diff.diff(emptyOrig, rev, algorithm);
114:
115: assertEquals("revision size should be one", 1, revision.size());
116: assertTrue(revision.getDelta(0) instanceof AddDelta);
117: }
118:
119: public void testRevisedEmpty()
120: throws DifferentiationFailedException {
121: String[] orig = { "1", "2", "3" };
122: String[] emptyRev = {};
123: Revision revision = Diff.diff(orig, emptyRev, algorithm);
124:
125: assertEquals("revision size should be one", 1, revision.size());
126: assertTrue(revision.getDelta(0) instanceof DeleteDelta);
127: }
128:
129: public void testDeleteAll() throws DifferentiationFailedException,
130: PatchFailedException {
131: Revision revision = Diff.diff(original, empty, algorithm);
132: assertEquals(1, revision.size());
133: assertEquals(DeleteDelta.class, revision.getDelta(0).getClass());
134: assertTrue(Diff.compare(revision.patch(original), empty));
135: }
136:
137: public void testTwoDeletes() throws DifferentiationFailedException,
138: PatchFailedException {
139: Revision revision = Diff.diff(original, rev1, algorithm);
140: assertEquals(2, revision.size());
141: assertEquals(DeleteDelta.class, revision.getDelta(0).getClass());
142: assertEquals(DeleteDelta.class, revision.getDelta(1).getClass());
143: assertTrue(Diff.compare(revision.patch(original), rev1));
144: assertEquals("3d2" + Diff.NL + "< [3] three" + Diff.NL + "9d7"
145: + Diff.NL + "< [9] nine" + Diff.NL, revision.toString());
146: }
147:
148: public void testChangeAtTheEnd()
149: throws DifferentiationFailedException, PatchFailedException {
150: Revision revision = Diff.diff(original, rev2, algorithm);
151: assertEquals(1, revision.size());
152: assertEquals(ChangeDelta.class, revision.getDelta(0).getClass());
153: assertTrue(Diff.compare(revision.patch(original), rev2));
154: assertEquals("d7 3" + Diff.NL + "a9 2" + Diff.NL
155: + "[7] seven revised" + Diff.NL + "[8] eight revised"
156: + Diff.NL, revision.toRCSString());
157: }
158:
159: public void testPatchFailed() throws DifferentiationFailedException {
160: try {
161: Revision revision = Diff.diff(original, rev2, algorithm);
162: assertTrue(!Diff.compare(revision.patch(rev1), rev2));
163: fail("PatchFailedException not thrown");
164: } catch (PatchFailedException e) {
165: }
166: }
167:
168: public void testPreviouslyFailedShuffle()
169: throws DifferentiationFailedException, PatchFailedException {
170: Object[] orig = new String[] { "[1] one", "[2] two",
171: "[3] three", "[4] four", "[5] five", "[6] six" };
172:
173: Object[] rev = new String[] { "[3] three", "[1] one",
174: "[5] five", "[2] two", "[6] six", "[4] four" };
175: Revision revision = Diff.diff(orig, rev, algorithm);
176: Object[] patched = revision.patch(orig);
177: assertTrue(Diff.compare(patched, rev));
178: }
179:
180: public void testEdit5() throws DifferentiationFailedException,
181: PatchFailedException {
182: Object[] orig = new String[] { "[1] one", "[2] two",
183: "[3] three", "[4] four", "[5] five", "[6] six" };
184:
185: Object[] rev = new String[] { "one revised", "two revised",
186: "[2] two", "[3] three", "five revised", "six revised",
187: "[5] five" };
188: Revision revision = Diff.diff(orig, rev, algorithm);
189: Object[] patched = revision.patch(orig);
190: assertTrue(Diff.compare(patched, rev));
191: }
192:
193: public void testShuffle() throws DifferentiationFailedException,
194: PatchFailedException {
195: Object[] orig = new String[] { "[1] one", "[2] two",
196: "[3] three", "[4] four", "[5] five", "[6] six" };
197:
198: for (int seed = 0; seed < 10; seed++) {
199: Object[] shuffle = Diff.shuffle(orig);
200: Revision revision = Diff.diff(orig, shuffle, algorithm);
201: Object[] patched = revision.patch(orig);
202: if (!Diff.compare(patched, shuffle)) {
203: fail("iter " + seed + " revisions differ after patch");
204: }
205: }
206: }
207:
208: public void testRandomEdit() throws DifferentiationFailedException,
209: PatchFailedException {
210: Object[] orig = original;
211: for (int seed = 0; seed < 10; seed++) {
212: Object[] random = Diff.randomEdit(orig, seed);
213: Revision revision = Diff.diff(orig, random, algorithm);
214: Object[] patched = revision.patch(orig);
215: if (!Diff.compare(patched, random)) {
216: fail("iter " + seed + " revisions differ after patch");
217: }
218: orig = random;
219: }
220: }
221:
222: public void testVisitor() {
223: Object[] orig = new String[] { "[1] one", "[2] two",
224: "[3] three", "[4] four", "[5] five", "[6] six" };
225: Object[] rev = new String[] { "[1] one", "[2] two revised",
226: "[3] three", "[4] four revised", "[5] five", "[6] six" };
227:
228: class Visitor implements RevisionVisitor {
229:
230: StringBuffer sb = new StringBuffer();
231:
232: public void visit(Revision revision) {
233: sb.append("visited Revision\n");
234: }
235:
236: public void visit(DeleteDelta delta) {
237: visit((Delta) delta);
238: }
239:
240: public void visit(ChangeDelta delta) {
241: visit((Delta) delta);
242: }
243:
244: public void visit(AddDelta delta) {
245: visit((Delta) delta);
246: }
247:
248: public void visit(Delta delta) {
249: sb.append(delta.getRevised());
250: sb.append("\n");
251: }
252:
253: public String toString() {
254: return sb.toString();
255: }
256: }
257:
258: Visitor visitor = new Visitor();
259: try {
260: Diff.diff(orig, rev, algorithm).accept(visitor);
261: assertEquals(visitor.toString(), "visited Revision\n"
262: + "[2] two revised\n" + "[4] four revised\n");
263: } catch (Exception e) {
264: fail(e.toString());
265: }
266: }
267:
268: public void testAlternativeAlgorithm()
269: throws DifferentiationFailedException, PatchFailedException {
270: Revision revision = Diff.diff(original, rev2, new SimpleDiff());
271: assertEquals(1, revision.size());
272: assertEquals(ChangeDelta.class, revision.getDelta(0).getClass());
273: assertTrue(Diff.compare(revision.patch(original), rev2));
274: assertEquals("d7 3" + Diff.NL + "a9 2" + Diff.NL
275: + "[7] seven revised" + Diff.NL + "[8] eight revised"
276: + Diff.NL, revision.toRCSString());
277: }
278:
279: public void testLargeShuffles()
280: throws DifferentiationFailedException, PatchFailedException {
281: Object[] orig = Diff.randomSequence(LARGE);
282: for (int seed = 0; seed < 3; seed++) {
283: Object[] rev = Diff.shuffle(orig);
284: Revision revision = Diff.diff(orig, rev, algorithm);
285: Object[] patched = revision.patch(orig);
286: if (!Diff.compare(patched, rev)) {
287: fail("iter " + seed + " revisions differ after patch");
288: }
289: orig = rev;
290: }
291: }
292:
293: public void testLargeShuffleEdits()
294: throws DifferentiationFailedException, PatchFailedException {
295: Object[] orig = Diff.randomSequence(LARGE);
296: for (int seed = 0; seed < 3; seed++) {
297: Object[] rev = Diff.randomEdit(orig, seed);
298: Revision revision = Diff.diff(orig, rev, algorithm);
299: Object[] patched = revision.patch(orig);
300: if (!Diff.compare(patched, rev)) {
301: fail("iter " + seed + " revisions differ after patch");
302: }
303: }
304: }
305:
306: public void testLargeAllEdited()
307: throws DifferentiationFailedException, PatchFailedException {
308: Object[] orig = Diff.randomSequence(LARGE);
309: Object[] rev = Diff.editAll(orig);
310: Revision revision = Diff.diff(orig, rev, algorithm);
311: Object[] patched = revision.patch(orig);
312: if (!Diff.compare(patched, rev)) {
313: fail("revisions differ after patch");
314: }
315:
316: }
317: }
|