From fa390cf9ee8f07b6524ec8ae719c71a95a4b38ab Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Fri, 3 Feb 2017 13:45:45 +0300 Subject: [PATCH] diff: tests for computation with ignored ranges follow-up: 74921ef --- .../comparison/IgnoreComparisonUtilTest.kt | 396 ++++++++++++++++++ 1 file changed, 396 insertions(+) create mode 100644 platform/diff-impl/tests/com/intellij/diff/comparison/IgnoreComparisonUtilTest.kt diff --git a/platform/diff-impl/tests/com/intellij/diff/comparison/IgnoreComparisonUtilTest.kt b/platform/diff-impl/tests/com/intellij/diff/comparison/IgnoreComparisonUtilTest.kt new file mode 100644 index 000000000000..f88100eba356 --- /dev/null +++ b/platform/diff-impl/tests/com/intellij/diff/comparison/IgnoreComparisonUtilTest.kt @@ -0,0 +1,396 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.diff.comparison + +import com.intellij.diff.DiffTestCase +import com.intellij.diff.fragments.LineFragment +import com.intellij.diff.util.IntPair +import com.intellij.openapi.util.Couple +import com.intellij.openapi.util.TextRange +import java.util.* + +class IgnoreComparisonUtilTest : DiffTestCase() { + fun testSimple() { + Test("", "", + "", "", + "", "") + .run() + + Test("X", "Y", + " ", " ", + "-", "-") + .run() + + Test("X", "Y", + "+", " ", + " ", "-") + .run() + + Test("X", "Y", + " ", "+", + "-", " ") + .run() + + Test("X", "Y", + "+", "+", + " ", " ") + .run() + + Test("X", "", + " ", "", + "-", "") + .run() + + Test("X", "", + "+", "", + " ", "") + .run() + + Test("", "Y", + "", "+", + "", " ") + .run() + } + + fun testSpaces() { + Test("X Y Z", "A B Z", + "++ ", "++ ", + " - ", " - ") + .run() + + Test("X Y Z", "A B Z", + " ++", " ++", + "--- ", "--- ") + .run() + + Test("X Y Z", "A Y C", + "++ ", "++ ", + " -", " -") + .run() + + Test("X Y Z", "A Y C", + "+++++", "+++++", + " ", " ") + .run() + + Test("X Y Z", "A B C", + "+ +", "+ +", + "-----", "-----") + .run() + + Test("A Y C", "A B C", + "+ +", "+ +", + " - ", " - ") + .run() + + Test("A B", "A B", + " ++ ", " + ", + " ", " ") + .run() + + Test("A B", "A X", + " ++ ", " + ", + " -", " -") + .run() + + Test(" A B", "X B ", + "+ ++ ", " + +", + " - ", "- ") + .run() + + Test("A B", "A B", + " + ", " ", + " - ", " ") + .run() + + Test("A B", "A B", + " + ", " ", + " -- ", " ") + .run() + } + + fun testLines() { + Test("X_", "X_Y_", + " ", " ", + " ", " --") + .changedLinesNumber(0, 1) + .run() + + Test("X_", "X_Y_", + " ", " ++", + " ", " ") + .run() + + Test("X_", "X_Y_", + " ", "++ ", + " ", " --") + .run() + + Test("X_Y_", "X_", + " ", " ", + " --", " ") + .run() + + Test("X_Y_", "X_", + " ++", " ", + " ", " ") + .run() + + Test("X_Y_Z", "X_B_Z", + " ", " ", + " - ", " - ") + .changedLinesNumber(1, 1) + .run() + + Test("X_Y_Z", "X_Y_Z", + " ", " ", + " ", " ") + .run() + + Test("X_Y_Z", "X_Y_Z", + " + + ", " + + ", + " ", " ") + .run() + + Test("X_Y_Z", "A_Y_Z", + " ", " ", + "- ", "- ") + .run() + + Test("X_Y_Z", "A_Y_Z", + "++ ", " ", + " ", "- ") + .run() + + Test("X_Y_Z", "A_Y_Z", + "++ ", "++ ", + " ", " ") + .run() + + Test("X_Y_Z", "A_Y_Z", + " ", " ++ ", + "- ", "- ") + .run() + + Test("X_Y_Z", "X_Y_C", + " ", " ", + " -", " -") + .run() + + Test("X_Y_Z", "X_Y_C", + " ", " +", + " -", " ") + .run() + + Test("X_Y_Z", "X_Y_C", + " +", " ", + " ", " -") + .run() + + Test("X_Y_Z", "X_B_Z", + " ", " ", + " - ", " - ") + .run() + + Test("X_Y_Z", "X_B_Z", + " + ", " + ", + " ", " ") + .run() + + Test("X_Y_Z", "X_B_Z", + " + ", " ", + " ", " - ") + .run() + } + + fun testTrimLines() { + Test("X_W_Y_W_Z", "X_B_Z", + " +++ +++ ", " + + ", + " - ", " - ") + .changedLinesNumber(1, 1) + .run() + + Test("X_W_W_Z", "X_Z", + " +++++ ", " + ", + " ", " ") + .changedLinesNumber(0, 0) + .run() + + Test("X_W 1 W_Y_W 2 W_Z", "X_W 3 W_B_W 4 W_Z", + " + + ", " + + ", + " - ", " - ") + .changedLinesNumber(1, 1) + .run() + + Test("X_W W W_Z", "X_W W_ W_Z", + " + + + + ", " + + ++ + ", + " ", " ") + .changedLinesNumber(0, 0) + .run() + + Test("X_W M W_Z", "X_W W_ W_Z", + " + + + + ", " + + ++ + ", + " - ", " - ") + .changedLinesNumber(1, 2) + .run() + } + + fun testNoInnerChanges() { + Test("X_W_Y_W_Z", "X_B_Z", + " +++ +++ ", " + + ", + " -- ", " -- ") + .changedLinesNumber(1, 1) + .noInnerChanges() + .run() + + Test("X_W_W_Z", "X_Z", + " +++++ ", " + ", + " ", " ") + .changedLinesNumber(0, 0) + .noInnerChanges() + .run() + + Test("X_W 1 W_Y_W 2 W_Z", "X_W 3 W_B_W 4 W_Z", + " + + ", " + + ", + " -- ", " -- ") + .changedLinesNumber(1, 1) + .noInnerChanges() + .run() + + Test("X_W W W_Z", "X_W W_ W_Z", + " + + + + ", " + + ++ + ", + " ------ ", " ------- ") + .changedLinesNumber(1, 2) + .noInnerChanges() + .run() + + Test("X_W M W_Z", "X_W W_ W_Z", + " + + + + ", " + + ++ + ", + " ------ ", " ------- ") + .changedLinesNumber(1, 2) + .noInnerChanges() + .run() + } + + + fun testBadCases() { + // TODO + + Test("X M Y Z", "A B Y C", + "+ +", "+ +", + " -- ", " -- ") + .run() + + Test("X M Y Z", "A B Y C", + " + ", " + ", + "-- -", "-- -") + .run() + } + + private inner class Test(val input1: String, val input2: String, + val ignored1: String, val ignored2: String, + val result1: String, val result2: String) { + private var inner = true + private var changedLines: IntPair? = null + + fun noInnerChanges(): Test { + inner = false + return this + } + + fun changedLinesNumber(lines1: Int, lines2: Int): Test { + changedLines = IntPair(lines1, lines2) + return this + } + + fun run() { + assertEquals(input1.length, ignored1.length) + assertEquals(input1.length, result1.length) + assertEquals(input2.length, ignored2.length) + assertEquals(input2.length, result2.length) + + val text1 = parseText(input1) + val text2 = parseText(input2) + + val ignoredRanges1 = parseIgnored(ignored1) + val ignoredRanges2 = parseIgnored(ignored2) + + val result = MANAGER.compareLinesWithIgnoredRanges(text1, text2, ignoredRanges1, ignoredRanges2, inner, INDICATOR) + + val expected = Couple(parseExpected(result1), parseExpected(result2)) + val actual = parseActual(result) + assertEquals(expected, actual) + + if (changedLines != null) { + val actualLines = countChangedLines(result) + assertEquals(changedLines, actualLines) + } + } + } + + private fun parseText(input: String): String { + return input.replace('_', '\n') + } + + private fun parseIgnored(ignored: String): List { + assertTrue(ignored.find { it != ' ' && it != '+' } == null) + + val result = ArrayList() + ignored.forEachIndexed { index, c -> + if (c == '+') result += TextRange(index, index + 1) + } + return result + } + + private fun parseExpected(result: String): BitSet { + assertTrue(result.find { it != ' ' && it != '-' } == null) + + val set = BitSet() + result.forEachIndexed { index, c -> + if (c == '-') set.set(index) + } + return set + } + + private fun parseActual(result: List): Couple { + val set1 = BitSet() + val set2 = BitSet() + result.forEach { fragment -> + val inner = fragment.innerFragments + if (inner == null) { + set1.set(fragment.startOffset1, fragment.endOffset1) + set2.set(fragment.startOffset2, fragment.endOffset2) + } + else { + inner.forEach { inner -> + set1.set(fragment.startOffset1 + inner.startOffset1, fragment.startOffset1 + inner.endOffset1) + set2.set(fragment.startOffset2 + inner.startOffset2, fragment.startOffset2 + inner.endOffset2) + } + } + } + return Couple(set1, set2) + } + + private fun countChangedLines(result: List): IntPair { + var count1 = 0 + var count2 = 0 + result.forEach { + count1 += it.endLine1 - it.startLine1 + count2 += it.endLine2 - it.startLine2 + } + return IntPair(count1, count2) + } +} \ No newline at end of file