summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.test
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit.test')
-rw-r--r--org.eclipse.jgit.test/.settings/org.eclipse.jdt.ui.prefs6
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/.gitattributes3
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffTestDataGenerator.java90
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/MyersDiffPerformanceTest.java196
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/MyersDiffTest.java109
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergeAlgorithmTest.java187
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/CPUTimeStopWatch.java111
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/IntListTest.java21
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/UnionInputStreamTest.java217
9 files changed, 937 insertions, 3 deletions
diff --git a/org.eclipse.jgit.test/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.jgit.test/.settings/org.eclipse.jdt.ui.prefs
index 9adc9b1d31..476f78fa9f 100644
--- a/org.eclipse.jgit.test/.settings/org.eclipse.jdt.ui.prefs
+++ b/org.eclipse.jgit.test/.settings/org.eclipse.jdt.ui.prefs
@@ -1,8 +1,8 @@
-#Sat Oct 31 14:53:06 PDT 2009
+#Tue Jan 05 11:30:06 PST 2010
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
-formatter_profile=_JGit
-formatter_settings_version=10
+formatter_profile=_JGit Format
+formatter_settings_version=11
internal.default.compliance=default
org.eclipse.jdt.ui.ignorelowercasenames=true
org.eclipse.jdt.ui.importorder=java;javax;org;com;
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/.gitattributes b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/.gitattributes
new file mode 100644
index 0000000000..c5831d9a8b
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/.gitattributes
@@ -0,0 +1,3 @@
+*.patch -crlf
+*Image -crlf
+*.out -crlf
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffTestDataGenerator.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffTestDataGenerator.java
new file mode 100644
index 0000000000..c403112149
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffTestDataGenerator.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2009, Christian Halstrick <christian.halstrick@sap.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.diff;
+
+public class DiffTestDataGenerator {
+ /**
+ * Generate sequence of characters in ascending order. The first character
+ * is a space. All subsequent characters have an ASCII code one greater then
+ * the ASCII code of the preceding character. On exception: the character
+ * following which follows '~' is again a ' '.
+ *
+ * @param len
+ * length of the String to be returned
+ * @return the sequence of characters as String
+ */
+ public static String generateSequence(int len) {
+ return generateSequence(len, 0, 0);
+ }
+
+ /**
+ * Generate sequence of characters similar to the one returned by
+ * {@link #generateSequence(int)}. But this time in each chunk of
+ * <skipPeriod> characters the last <skipLength> characters are left out. By
+ * calling this method twice with two different prime skipPeriod values and
+ * short skipLength values you create test data which is similar to what
+ * programmers do to their source code - huge files with only few
+ * insertions/deletions/changes.
+ *
+ * @param len
+ * length of the String to be returned
+ * @param skipPeriod
+ * @param skipLength
+ * @return the sequence of characters as String
+ */
+ public static String generateSequence(int len, int skipPeriod,
+ int skipLength) {
+ StringBuilder text = new StringBuilder(len);
+ int skipStart = skipPeriod - skipLength;
+ int skippedChars = 0;
+ for (int i = 0; i - skippedChars < len; ++i) {
+ if (skipPeriod == 0 || i % skipPeriod < skipStart) {
+ text.append((char) (32 + i % 95));
+ } else {
+ skippedChars++;
+ }
+ }
+ return text.toString();
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/MyersDiffPerformanceTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/MyersDiffPerformanceTest.java
new file mode 100644
index 0000000000..fe63e3d183
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/MyersDiffPerformanceTest.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2009, Christian Halstrick <christian.halstrick@sap.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.diff;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.eclipse.jgit.util.CPUTimeStopWatch;
+
+/**
+ * Test cases for the performance of the diff implementation. The tests test
+ * that the performance of the MyersDiff algorithm is really O(N*D). Means the
+ * time for computing the diff between a and b should depend on the product of
+ * a.length+b.length and the number of found differences. The tests compute
+ * diffs between chunks of different length, measure the needed time and check
+ * that time/(N*D) does not differ more than a certain factor (currently 10)
+ */
+public class MyersDiffPerformanceTest extends TestCase {
+ private static final long longTaskBoundary = 5000000000L;
+
+ private static final int minCPUTimerTicks = 10;
+
+ private static final int maxFactor = 15;
+
+ private CPUTimeStopWatch stopwatch=CPUTimeStopWatch.createInstance();
+
+ public class PerfData {
+ private NumberFormat fmt = new DecimalFormat("#.##E0");
+
+ public long runningTime;
+
+ public long D;
+
+ public long N;
+
+ private double p1 = -1;
+
+ private double p2 = -1;
+
+ public double perf1() {
+ if (p1 < 0)
+ p1 = runningTime / ((double) N * D);
+ return p1;
+ }
+
+ public double perf2() {
+ if (p2 < 0)
+ p2 = runningTime / ((double) N * D * D);
+ return p2;
+ }
+
+ public String toString() {
+ return ("diffing " + N / 2 + " bytes took " + runningTime
+ + " ns. N=" + N + ", D=" + D + ", time/(N*D):"
+ + fmt.format(perf1()) + ", time/(N*D^2):" + fmt
+ .format(perf2()));
+ }
+ }
+
+ public static Comparator<PerfData> getComparator(final int whichPerf) {
+ return new Comparator<PerfData>() {
+ public int compare(PerfData o1, PerfData o2) {
+ double p1 = (whichPerf == 1) ? o1.perf1() : o1.perf2();
+ double p2 = (whichPerf == 1) ? o2.perf1() : o2.perf2();
+ return (p1 < p2) ? -1 : (p1 > p2) ? 1 : 0;
+ }
+ };
+ }
+
+ public void test() {
+ if (stopwatch!=null) {
+ List<PerfData> perfData = new LinkedList<PerfData>();
+ perfData.add(test(10000));
+ perfData.add(test(20000));
+ perfData.add(test(50000));
+ perfData.add(test(80000));
+ perfData.add(test(99999));
+ perfData.add(test(999999));
+
+ Comparator<PerfData> c = getComparator(1);
+ double factor = Collections.max(perfData, c).perf1()
+ / Collections.min(perfData, c).perf1();
+ assertTrue(
+ "minimun and maximum of performance-index t/(N*D) differed too much. Measured factor of "
+ + factor
+ + " (maxFactor="
+ + maxFactor
+ + "). Perfdata=<" + perfData.toString() + ">",
+ factor < maxFactor);
+ }
+ }
+
+ /**
+ * Tests the performance of MyersDiff for texts which are similar (not
+ * random data). The CPU time is measured and returned. Because of bad
+ * accuracy of CPU time information the diffs are repeated. During each
+ * repetition the interim CPU time is checked. The diff operation is
+ * repeated until we have seen the CPU time clock changed its value at least
+ * {@link #minCPUTimerTicks} times.
+ *
+ * @param characters
+ * the size of the diffed character sequences.
+ * @return performance data
+ */
+ private PerfData test(int characters) {
+ PerfData ret = new PerfData();
+ String a = DiffTestDataGenerator.generateSequence(characters, 971, 3);
+ String b = DiffTestDataGenerator.generateSequence(characters, 1621, 5);
+ CharArray ac = new CharArray(a);
+ CharArray bc = new CharArray(b);
+ MyersDiff myersDiff = null;
+ int cpuTimeChanges = 0;
+ long lastReadout = 0;
+ long interimTime = 0;
+ int repetitions = 0;
+ stopwatch.start();
+ while (cpuTimeChanges < minCPUTimerTicks && interimTime < longTaskBoundary) {
+ myersDiff = new MyersDiff(ac, bc);
+ repetitions++;
+ interimTime = stopwatch.readout();
+ if (interimTime != lastReadout) {
+ cpuTimeChanges++;
+ lastReadout = interimTime;
+ }
+ }
+ ret.runningTime = stopwatch.stop() / repetitions;
+ ret.N = (ac.size() + bc.size());
+ ret.D = myersDiff.getEdits().size();
+
+ return ret;
+ }
+
+ private static class CharArray implements Sequence {
+ private final char[] array;
+
+ public CharArray(String s) {
+ array = s.toCharArray();
+ }
+
+ public int size() {
+ return array.length;
+ }
+
+ public boolean equals(int i, Sequence other, int j) {
+ CharArray o = (CharArray) other;
+ return array[i] == o.array[j];
+ }
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/MyersDiffTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/MyersDiffTest.java
new file mode 100644
index 0000000000..c91348ffe6
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/MyersDiffTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2009, Johannes E. Schindelin
+ * Copyright (C) 2009, Johannes Schindelin <johannes.schindelin@gmx.de>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.diff;
+
+import junit.framework.TestCase;
+
+public class MyersDiffTest extends TestCase {
+ public void testAtEnd() {
+ assertDiff("HELLO", "HELL", " -4,1 +4,0");
+ }
+
+ public void testAtStart() {
+ assertDiff("Git", "JGit", " -0,0 +0,1");
+ }
+
+ public void testSimple() {
+ assertDiff("HELLO WORLD", "LOW",
+ " -0,3 +0,0 -5,1 +2,0 -7,4 +3,0");
+ // is ambiguous, could be this, too:
+ // " -0,2 +0,0 -3,1 +1,0 -5,1 +2,0 -7,4 +3,0"
+ }
+
+ public void assertDiff(String a, String b, String edits) {
+ MyersDiff diff = new MyersDiff(toCharArray(a), toCharArray(b));
+ assertEquals(edits, toString(diff.getEdits()));
+ }
+
+ private static String toString(EditList list) {
+ StringBuilder builder = new StringBuilder();
+ for (Edit e : list)
+ builder.append(" -" + e.beginA
+ + "," + (e.endA - e.beginA)
+ + " +" + e.beginB + "," + (e.endB - e.beginB));
+ return builder.toString();
+ }
+
+ private static CharArray toCharArray(String s) {
+ return new CharArray(s);
+ }
+
+ protected static String toString(Sequence seq, int begin, int end) {
+ CharArray a = (CharArray)seq;
+ return new String(a.array, begin, end - begin);
+ }
+
+ protected static String toString(CharArray a, CharArray b,
+ int x, int k) {
+ return "(" + x + "," + (k + x)
+ + (x < 0 ? '<' :
+ (x >= a.array.length ?
+ '>' : a.array[x]))
+ + (k + x < 0 ? '<' :
+ (k + x >= b.array.length ?
+ '>' : b.array[k + x]))
+ + ")";
+ }
+
+ private static class CharArray implements Sequence {
+ char[] array;
+ public CharArray(String s) { array = s.toCharArray(); }
+ public int size() { return array.length; }
+ public boolean equals(int i, Sequence other, int j) {
+ CharArray o = (CharArray)other;
+ return array[i] == o.array[j];
+ }
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergeAlgorithmTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergeAlgorithmTest.java
new file mode 100644
index 0000000000..d12fae7c19
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergeAlgorithmTest.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2009, Christian Halstrick <christian.halstrick@sap.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.merge;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+import org.eclipse.jgit.diff.RawText;
+import org.eclipse.jgit.lib.Constants;
+
+public class MergeAlgorithmTest extends TestCase {
+ MergeFormatter fmt=new MergeFormatter();
+
+ // the texts which are used in this merge-tests are constructed by
+ // concatenating fixed chunks of text defined by the String constants
+ // A..Y. The common base text is always the text A+B+C+D+E+F+G+H+I+J.
+ // The two texts being merged are constructed by deleting some chunks
+ // or inserting new chunks. Some of the chunks are one-liners, others
+ // contain more than one line.
+ private static final String A = "aaa\n";
+ private static final String B = "bbbbb\nbb\nbbb\n";
+ private static final String C = "c\n";
+ private static final String D = "dd\n";
+ private static final String E = "ee\n";
+ private static final String F = "fff\nff\n";
+ private static final String G = "gg\n";
+ private static final String H = "h\nhhh\nhh\n";
+ private static final String I = "iiii\n";
+ private static final String J = "jj\n";
+ private static final String Z = "zzz\n";
+ private static final String Y = "y\n";
+
+ // constants which define how conflict-regions are expected to be reported.
+ private static final String XXX_0 = "<<<<<<< O\n";
+ private static final String XXX_1 = "=======\n";
+ private static final String XXX_2 = ">>>>>>> T\n";
+
+ // the common base from which all merges texts derive from
+ String base=A+B+C+D+E+F+G+H+I+J;
+
+ // the following constants define the merged texts. The name of the
+ // constants describe how they are created out of the common base. E.g.
+ // the constant named replace_XYZ_by_MNO stands for the text which is
+ // created from common base by replacing first chunk X by chunk M, then
+ // Y by N and then Z by O.
+ String replace_C_by_Z=A+B+Z+D+E+F+G+H+I+J;
+ String replace_A_by_Y=Y+B+C+D+E+F+G+H+I+J;
+ String replace_A_by_Z=Z+B+C+D+E+F+G+H+I+J;
+ String replace_J_by_Y=A+B+C+D+E+F+G+H+I+Y;
+ String replace_J_by_Z=A+B+C+D+E+F+G+H+I+Z;
+ String replace_BC_by_ZZ=A+Z+Z+D+E+F+G+H+I+J;
+ String replace_BCD_by_ZZZ=A+Z+Z+Z+E+F+G+H+I+J;
+ String replace_BD_by_ZZ=A+Z+C+Z+E+F+G+H+I+J;
+ String replace_BCDEGI_by_ZZZZZZ=A+Z+Z+Z+Z+F+Z+H+Z+J;
+ String replace_CEFGHJ_by_YYYYYY=A+B+Y+D+Y+Y+Y+Y+I+Y;
+ String replace_BDE_by_ZZY=A+Z+C+Z+Y+F+G+H+I+J;
+
+ /**
+ * Check for a conflict where the second text was changed similar to the
+ * first one, but the second texts modification covers one more line.
+ *
+ * @throws IOException
+ */
+ public void testTwoConflictingModifications() throws IOException {
+ assertEquals(A + XXX_0 + B + Z + XXX_1 + Z + Z + XXX_2 + D + E + F + G
+ + H + I + J,
+ merge(base, replace_C_by_Z, replace_BC_by_ZZ));
+ }
+
+ /**
+ * Test a case where we have three consecutive chunks. The first text
+ * modifies all three chunks. The second text modifies the first and the
+ * last chunk. This should be reported as one conflicting region.
+ *
+ * @throws IOException
+ */
+ public void testOneAgainstTwoConflictingModifications() throws IOException {
+ assertEquals(A + XXX_0 + Z + Z + Z + XXX_1 + Z + C + Z + XXX_2 + E + F
+ + G + H + I + J,
+ merge(base, replace_BCD_by_ZZZ, replace_BD_by_ZZ));
+ }
+
+ /**
+ * Test a merge where only the second text contains modifications. Expect as
+ * merge result the second text.
+ *
+ * @throws IOException
+ */
+ public void testNoAgainstOneModification() throws IOException {
+ assertEquals(replace_BD_by_ZZ.toString(),
+ merge(base, base, replace_BD_by_ZZ));
+ }
+
+ /**
+ * Both texts contain modifications but not on the same chunks. Expect a
+ * non-conflict merge result.
+ *
+ * @throws IOException
+ */
+ public void testTwoNonConflictingModifications() throws IOException {
+ assertEquals(Y + B + Z + D + E + F + G + H + I + J,
+ merge(base, replace_C_by_Z, replace_A_by_Y));
+ }
+
+ /**
+ * Merge two complicated modifications. The merge algorithm has to extend
+ * and combine conflicting regions to get to the expected merge result.
+ *
+ * @throws IOException
+ */
+ public void testTwoComplicatedModifications() throws IOException {
+ assertEquals(A + XXX_0 + Z + Z + Z + Z + F + Z + H + XXX_1 + B + Y + D
+ + Y + Y + Y + Y + XXX_2 + Z + Y,
+ merge(base,
+ replace_BCDEGI_by_ZZZZZZ,
+ replace_CEFGHJ_by_YYYYYY));
+ }
+
+ /**
+ * Test a conflicting region at the very start of the text.
+ *
+ * @throws IOException
+ */
+ public void testConflictAtStart() throws IOException {
+ assertEquals(XXX_0 + Z + XXX_1 + Y + XXX_2 + B + C + D + E + F + G + H
+ + I + J, merge(base, replace_A_by_Z, replace_A_by_Y));
+ }
+
+ /**
+ * Test a conflicting region at the very end of the text.
+ *
+ * @throws IOException
+ */
+ public void testConflictAtEnd() throws IOException {
+ assertEquals(A+B+C+D+E+F+G+H+I+XXX_0+Z+XXX_1+Y+XXX_2, merge(base, replace_J_by_Z, replace_J_by_Y));
+ }
+
+ private String merge(String commonBase, String ours, String theirs) throws IOException {
+ MergeResult r=MergeAlgorithm.merge(new RawText(Constants.encode(commonBase)), new RawText(Constants.encode(ours)), new RawText(Constants.encode(theirs)));
+ ByteArrayOutputStream bo=new ByteArrayOutputStream(50);
+ fmt.formatMerge(bo, r, "B", "O", "T", Constants.CHARACTER_ENCODING);
+ return new String(bo.toByteArray(), Constants.CHARACTER_ENCODING);
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/CPUTimeStopWatch.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/CPUTimeStopWatch.java
new file mode 100644
index 0000000000..55e51f710e
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/CPUTimeStopWatch.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2009, Christian Halstrick <christian.halstrick@sap.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.util;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadMXBean;
+
+/**
+ * A simple stopwatch which measures elapsed CPU time of the current thread. CPU
+ * time is the time spent on executing your own code plus the time spent on
+ * executing operating system calls triggered by your application.
+ * <p>
+ * This stopwatch needs a VM which supports getting CPU Time information for the
+ * current thread. The static method createInstance() will take care to return
+ * only a new instance of this class if the VM is capable of returning CPU time.
+ */
+public class CPUTimeStopWatch {
+ private long start;
+
+ private static ThreadMXBean mxBean=ManagementFactory.getThreadMXBean();
+
+ /**
+ * use this method instead of the constructor to be sure that the underlying
+ * VM provides all features needed by this class.
+ *
+ * @return a new instance of {@link #CPUTimeStopWatch()} or
+ * <code>null</code> if the VM does not support getting CPU time
+ * information
+ */
+ public static CPUTimeStopWatch createInstance() {
+ return mxBean.isCurrentThreadCpuTimeSupported() ? new CPUTimeStopWatch()
+ : null;
+ }
+
+ /**
+ * Starts the stopwatch. If the stopwatch is already started this will
+ * restart the stopwatch.
+ */
+ public void start() {
+ start = mxBean.getCurrentThreadCpuTime();
+ }
+
+ /**
+ * Stops the stopwatch and return the elapsed CPU time in nanoseconds.
+ * Should be called only on started stopwatches.
+ *
+ * @return the elapsed CPU time in nanoseconds. When called on non-started
+ * stopwatches (either because {@link #start()} was never called or
+ * {@link #stop()} was called after the last call to
+ * {@link #start()}) this method will return 0.
+ */
+ public long stop() {
+ long cpuTime = readout();
+ start = 0;
+ return cpuTime;
+ }
+
+ /**
+ * Return the elapsed CPU time in nanoseconds. In contrast to
+ * {@link #stop()} the stopwatch will continue to run after this call.
+ *
+ * @return the elapsed CPU time in nanoseconds. When called on non-started
+ * stopwatches (either because {@link #start()} was never called or
+ * {@link #stop()} was called after the last call to
+ * {@link #start()}) this method will return 0.
+ */
+ public long readout() {
+ return (start == 0) ? 0 : mxBean.getCurrentThreadCpuTime() - start;
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/IntListTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/IntListTest.java
index ecabeeea5b..b8d5bd1025 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/IntListTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/IntListTest.java
@@ -150,6 +150,27 @@ public class IntListTest extends TestCase {
}
}
+ public void testSet() {
+ final IntList i = new IntList();
+ i.add(1);
+ assertEquals(1, i.size());
+ assertEquals(1, i.get(0));
+
+ i.set(0, 5);
+ assertEquals(5, i.get(0));
+
+ try {
+ i.set(5, 5);
+ fail("accepted set of 5 beyond end of list");
+ } catch (ArrayIndexOutOfBoundsException e){
+ assertTrue(true);
+ }
+
+ i.set(1, 2);
+ assertEquals(2, i.size());
+ assertEquals(2, i.get(1));
+ }
+
public void testToString() {
final IntList i = new IntList();
i.add(1);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/UnionInputStreamTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/UnionInputStreamTest.java
new file mode 100644
index 0000000000..2bcd134c66
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/UnionInputStreamTest.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2009, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.util.io;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+public class UnionInputStreamTest extends TestCase {
+ public void testEmptyStream() throws IOException {
+ final UnionInputStream u = new UnionInputStream();
+ assertTrue(u.isEmpty());
+ assertEquals(-1, u.read());
+ assertEquals(-1, u.read(new byte[1], 0, 1));
+ assertEquals(0, u.available());
+ assertEquals(0, u.skip(1));
+ u.close();
+ }
+
+ public void testReadSingleBytes() throws IOException {
+ final UnionInputStream u = new UnionInputStream();
+
+ assertTrue(u.isEmpty());
+ u.add(new ByteArrayInputStream(new byte[] { 1, 0, 2 }));
+ u.add(new ByteArrayInputStream(new byte[] { 3 }));
+ u.add(new ByteArrayInputStream(new byte[] { 4, 5 }));
+
+ assertFalse(u.isEmpty());
+ assertEquals(3, u.available());
+ assertEquals(1, u.read());
+ assertEquals(0, u.read());
+ assertEquals(2, u.read());
+ assertEquals(0, u.available());
+
+ assertEquals(3, u.read());
+ assertEquals(0, u.available());
+
+ assertEquals(4, u.read());
+ assertEquals(1, u.available());
+ assertEquals(5, u.read());
+ assertEquals(0, u.available());
+ assertEquals(-1, u.read());
+
+ assertTrue(u.isEmpty());
+ u.add(new ByteArrayInputStream(new byte[] { (byte) 255 }));
+ assertEquals(255, u.read());
+ assertEquals(-1, u.read());
+ assertTrue(u.isEmpty());
+ }
+
+ public void testReadByteBlocks() throws IOException {
+ final UnionInputStream u = new UnionInputStream();
+ u.add(new ByteArrayInputStream(new byte[] { 1, 0, 2 }));
+ u.add(new ByteArrayInputStream(new byte[] { 3 }));
+ u.add(new ByteArrayInputStream(new byte[] { 4, 5 }));
+
+ final byte[] r = new byte[5];
+ assertEquals(5, u.read(r, 0, 5));
+ assertTrue(Arrays.equals(new byte[] { 1, 0, 2, 3, 4 }, r));
+ assertEquals(1, u.read(r, 0, 5));
+ assertEquals(5, r[0]);
+ assertEquals(-1, u.read(r, 0, 5));
+ }
+
+ public void testArrayConstructor() throws IOException {
+ final UnionInputStream u = new UnionInputStream(
+ new ByteArrayInputStream(new byte[] { 1, 0, 2 }),
+ new ByteArrayInputStream(new byte[] { 3 }),
+ new ByteArrayInputStream(new byte[] { 4, 5 }));
+
+ final byte[] r = new byte[5];
+ assertEquals(5, u.read(r, 0, 5));
+ assertTrue(Arrays.equals(new byte[] { 1, 0, 2, 3, 4 }, r));
+ assertEquals(1, u.read(r, 0, 5));
+ assertEquals(5, r[0]);
+ assertEquals(-1, u.read(r, 0, 5));
+ }
+
+ public void testMarkSupported() {
+ final UnionInputStream u = new UnionInputStream();
+ assertFalse(u.markSupported());
+ u.add(new ByteArrayInputStream(new byte[] { 1, 0, 2 }));
+ assertFalse(u.markSupported());
+ }
+
+ public void testSkip() throws IOException {
+ final UnionInputStream u = new UnionInputStream();
+ u.add(new ByteArrayInputStream(new byte[] { 1, 0, 2 }));
+ u.add(new ByteArrayInputStream(new byte[] { 3 }));
+ u.add(new ByteArrayInputStream(new byte[] { 4, 5 }));
+ assertEquals(0, u.skip(0));
+ assertEquals(4, u.skip(4));
+ assertEquals(4, u.read());
+ assertEquals(1, u.skip(5));
+ assertEquals(0, u.skip(5));
+ assertEquals(-1, u.read());
+
+ u.add(new ByteArrayInputStream(new byte[] { 20, 30 }) {
+ public long skip(long n) {
+ return 0;
+ }
+ });
+ assertEquals(2, u.skip(8));
+ assertEquals(-1, u.read());
+ }
+
+ public void testAutoCloseDuringRead() throws IOException {
+ final UnionInputStream u = new UnionInputStream();
+ final boolean closed[] = new boolean[2];
+ u.add(new ByteArrayInputStream(new byte[] { 1 }) {
+ public void close() {
+ closed[0] = true;
+ }
+ });
+ u.add(new ByteArrayInputStream(new byte[] { 2 }) {
+ public void close() {
+ closed[1] = true;
+ }
+ });
+
+ assertFalse(closed[0]);
+ assertFalse(closed[1]);
+
+ assertEquals(1, u.read());
+ assertFalse(closed[0]);
+ assertFalse(closed[1]);
+
+ assertEquals(2, u.read());
+ assertTrue(closed[0]);
+ assertFalse(closed[1]);
+
+ assertEquals(-1, u.read());
+ assertTrue(closed[0]);
+ assertTrue(closed[1]);
+ }
+
+ public void testCloseDuringClose() throws IOException {
+ final UnionInputStream u = new UnionInputStream();
+ final boolean closed[] = new boolean[2];
+ u.add(new ByteArrayInputStream(new byte[] { 1 }) {
+ public void close() {
+ closed[0] = true;
+ }
+ });
+ u.add(new ByteArrayInputStream(new byte[] { 2 }) {
+ public void close() {
+ closed[1] = true;
+ }
+ });
+
+ assertFalse(closed[0]);
+ assertFalse(closed[1]);
+
+ u.close();
+
+ assertTrue(closed[0]);
+ assertTrue(closed[1]);
+ }
+
+ public void testExceptionDuringClose() {
+ final UnionInputStream u = new UnionInputStream();
+ u.add(new ByteArrayInputStream(new byte[] { 1 }) {
+ public void close() throws IOException {
+ throw new IOException("I AM A TEST");
+ }
+ });
+ try {
+ u.close();
+ fail("close ignored inner stream exception");
+ } catch (IOException e) {
+ assertEquals("I AM A TEST", e.getMessage());
+ }
+ }
+}