You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MergeAlgorithmTest.java 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. * Copyright (C) 2009, Christian Halstrick <christian.halstrick@sap.com>
  3. * and other copyright owners as documented in the project's IP log.
  4. *
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Distribution License v1.0 which
  7. * accompanies this distribution, is reproduced below, and is
  8. * available at http://www.eclipse.org/org/documents/edl-v10.php
  9. *
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or
  13. * without modification, are permitted provided that the following
  14. * conditions are met:
  15. *
  16. * - Redistributions of source code must retain the above copyright
  17. * notice, this list of conditions and the following disclaimer.
  18. *
  19. * - Redistributions in binary form must reproduce the above
  20. * copyright notice, this list of conditions and the following
  21. * disclaimer in the documentation and/or other materials provided
  22. * with the distribution.
  23. *
  24. * - Neither the name of the Eclipse Foundation, Inc. nor the
  25. * names of its contributors may be used to endorse or promote
  26. * products derived from this software without specific prior
  27. * written permission.
  28. *
  29. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  30. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  31. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  32. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  34. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  35. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  37. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  38. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  41. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42. */
  43. package org.eclipse.jgit.merge;
  44. import static org.junit.Assert.assertEquals;
  45. import java.io.ByteArrayOutputStream;
  46. import java.io.IOException;
  47. import org.eclipse.jgit.diff.RawText;
  48. import org.eclipse.jgit.diff.RawTextComparator;
  49. import org.eclipse.jgit.lib.Constants;
  50. import org.junit.Test;
  51. public class MergeAlgorithmTest {
  52. MergeFormatter fmt=new MergeFormatter();
  53. /**
  54. * Check for a conflict where the second text was changed similar to the
  55. * first one, but the second texts modification covers one more line.
  56. *
  57. * @throws IOException
  58. */
  59. @Test
  60. public void testTwoConflictingModifications() throws IOException {
  61. assertEquals(t("a<b=Z>Zdefghij"),
  62. merge("abcdefghij", "abZdefghij", "aZZdefghij"));
  63. }
  64. /**
  65. * Test a case where we have three consecutive chunks. The first text
  66. * modifies all three chunks. The second text modifies the first and the
  67. * last chunk. This should be reported as one conflicting region.
  68. *
  69. * @throws IOException
  70. */
  71. @Test
  72. public void testOneAgainstTwoConflictingModifications() throws IOException {
  73. assertEquals(t("aZ<Z=c>Zefghij"),
  74. merge("abcdefghij", "aZZZefghij", "aZcZefghij"));
  75. }
  76. /**
  77. * Test a merge where only the second text contains modifications. Expect as
  78. * merge result the second text.
  79. *
  80. * @throws IOException
  81. */
  82. @Test
  83. public void testNoAgainstOneModification() throws IOException {
  84. assertEquals(t("aZcZefghij"),
  85. merge("abcdefghij", "abcdefghij", "aZcZefghij"));
  86. }
  87. /**
  88. * Both texts contain modifications but not on the same chunks. Expect a
  89. * non-conflict merge result.
  90. *
  91. * @throws IOException
  92. */
  93. @Test
  94. public void testTwoNonConflictingModifications() throws IOException {
  95. assertEquals(t("YbZdefghij"),
  96. merge("abcdefghij", "abZdefghij", "Ybcdefghij"));
  97. }
  98. /**
  99. * Merge two complicated modifications. The merge algorithm has to extend
  100. * and combine conflicting regions to get to the expected merge result.
  101. *
  102. * @throws IOException
  103. */
  104. @Test
  105. public void testTwoComplicatedModifications() throws IOException {
  106. assertEquals(t("a<ZZZZfZhZj=bYdYYYYiY>"),
  107. merge("abcdefghij", "aZZZZfZhZj", "abYdYYYYiY"));
  108. }
  109. /**
  110. * Test a conflicting region at the very start of the text.
  111. *
  112. * @throws IOException
  113. */
  114. @Test
  115. public void testConflictAtStart() throws IOException {
  116. assertEquals(t("<Z=Y>bcdefghij"),
  117. merge("abcdefghij", "Zbcdefghij", "Ybcdefghij"));
  118. }
  119. /**
  120. * Test a conflicting region at the very end of the text.
  121. *
  122. * @throws IOException
  123. */
  124. @Test
  125. public void testConflictAtEnd() throws IOException {
  126. assertEquals(t("abcdefghi<Z=Y>"),
  127. merge("abcdefghij", "abcdefghiZ", "abcdefghiY"));
  128. }
  129. /**
  130. * Check for a conflict where the second text was changed similar to the
  131. * first one, but the second texts modification covers one more line.
  132. *
  133. * @throws IOException
  134. */
  135. @Test
  136. public void testSameModification() throws IOException {
  137. assertEquals(t("abZdefghij"),
  138. merge("abcdefghij", "abZdefghij", "abZdefghij"));
  139. }
  140. /**
  141. * Check that a deleted vs. a modified line shows up as conflict (see Bug
  142. * 328551)
  143. *
  144. * @throws IOException
  145. */
  146. @Test
  147. public void testDeleteVsModify() throws IOException {
  148. assertEquals(t("ab<=Z>defghij"),
  149. merge("abcdefghij", "abdefghij", "abZdefghij"));
  150. }
  151. @Test
  152. public void testInsertVsModify() throws IOException {
  153. assertEquals(t("a<bZ=XY>"), merge("ab", "abZ", "aXY"));
  154. }
  155. @Test
  156. public void testAdjacentModifications() throws IOException {
  157. assertEquals(t("a<Zc=bY>d"), merge("abcd", "aZcd", "abYd"));
  158. }
  159. @Test
  160. public void testSeperateModifications() throws IOException {
  161. assertEquals(t("aZcYe"), merge("abcde", "aZcde", "abcYe"));
  162. }
  163. /**
  164. * Test merging two contents which do one similar modification and one
  165. * insertion is only done by one side. Between modification and insertion is
  166. * a block which is common between the two contents and the common base
  167. *
  168. * @throws IOException
  169. */
  170. @Test
  171. public void testTwoSimilarModsAndOneInsert() throws IOException {
  172. assertEquals(t("IAAJ"), merge("iA", "IA", "IAAJ"));
  173. assertEquals(t("aBcDde"), merge("abcde", "aBcde", "aBcDde"));
  174. assertEquals(t("IAJ"), merge("iA", "IA", "IAJ"));
  175. assertEquals(t("IAAAJ"), merge("iA", "IA", "IAAAJ"));
  176. assertEquals(t("IAAAJCAB"), merge("iACAB", "IACAB", "IAAAJCAB"));
  177. assertEquals(t("HIAAAJCAB"), merge("HiACAB", "HIACAB", "HIAAAJCAB"));
  178. assertEquals(t("AGADEFHIAAAJCAB"),
  179. merge("AGADEFHiACAB", "AGADEFHIACAB", "AGADEFHIAAAJCAB"));
  180. }
  181. private String merge(String commonBase, String ours, String theirs) throws IOException {
  182. MergeResult r = new MergeAlgorithm().merge(RawTextComparator.DEFAULT,
  183. T(commonBase), T(ours), T(theirs));
  184. ByteArrayOutputStream bo=new ByteArrayOutputStream(50);
  185. fmt.formatMerge(bo, r, "B", "O", "T", Constants.CHARACTER_ENCODING);
  186. return new String(bo.toByteArray(), Constants.CHARACTER_ENCODING);
  187. }
  188. public static String t(String text) {
  189. StringBuilder r = new StringBuilder();
  190. for (int i = 0; i < text.length(); i++) {
  191. char c = text.charAt(i);
  192. switch (c) {
  193. case '<':
  194. r.append("<<<<<<< O\n");
  195. break;
  196. case '=':
  197. r.append("=======\n");
  198. break;
  199. case '>':
  200. r.append(">>>>>>> T\n");
  201. break;
  202. default:
  203. r.append(c);
  204. r.append('\n');
  205. }
  206. }
  207. return r.toString();
  208. }
  209. public static RawText T(String text) {
  210. return new RawText(Constants.encode(t(text)));
  211. }
  212. }