Skip to content

Commit

Permalink
Add Javadoc and more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sormuras committed Mar 17, 2017
1 parent 6159955 commit b57e0b9
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 16 deletions.
Expand Up @@ -16,11 +16,9 @@
import static org.junit.platform.commons.util.Preconditions.condition; import static org.junit.platform.commons.util.Preconditions.condition;
import static org.junit.platform.commons.util.Preconditions.notNull; import static org.junit.platform.commons.util.Preconditions.notNull;


import java.util.ArrayDeque;
import java.util.Deque; import java.util.Deque;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException; import java.util.regex.PatternSyntaxException;


/** /**
Expand All @@ -43,7 +41,7 @@ static void assertLinesMatch(List<String> expectedLines, List<String> actualLine
int expectedSize = expectedLines.size(); int expectedSize = expectedLines.size();
int actualSize = actualLines.size(); int actualSize = actualLines.size();


// trivial case: when expecting more then actual lines available, something is wrong // trivial case: when expecting more than actual lines available, something is wrong
if (expectedSize > actualSize) { if (expectedSize > actualSize) {
// use standard assertEquals(Object, Object, message) to let IDEs present the textual difference // use standard assertEquals(Object, Object, message) to let IDEs present the textual difference
String expected = String.join(System.lineSeparator(), expectedLines); String expected = String.join(System.lineSeparator(), expectedLines);
Expand Down Expand Up @@ -71,8 +69,8 @@ static void assertLinesMatch(List<String> expectedLines, List<String> actualLine
} }


private static void assertLinesMatchWithFastForward(List<String> expectedLines, List<String> actualLines) { private static void assertLinesMatchWithFastForward(List<String> expectedLines, List<String> actualLines) {
Deque<String> expectedDeque = new LinkedList<>(expectedLines); Deque<String> expectedDeque = new ArrayDeque<>(expectedLines);
Deque<String> actualDeque = new LinkedList<>(actualLines); Deque<String> actualDeque = new ArrayDeque<>(actualLines);


while (!expectedDeque.isEmpty()) { while (!expectedDeque.isEmpty()) {
String expectedLine = expectedDeque.pop(); String expectedLine = expectedDeque.pop();
Expand Down Expand Up @@ -132,31 +130,29 @@ private static void assertLinesMatchWithFastForward(List<String> expectedLines,
} }
} }


private static boolean isFastForwardLine(String line) { static boolean isFastForwardLine(String line) {
line = line.trim(); line = line.trim();
return line.startsWith(">>") && line.endsWith(">>"); return line.length() >= 4 && line.startsWith(">>") && line.endsWith(">>");
} }


private static int parseFastForwardLimit(String fastForwardLine) { static int parseFastForwardLimit(String fastForwardLine) {
String text = fastForwardLine.trim().substring(2, fastForwardLine.length() - 2).trim(); String text = fastForwardLine.trim().substring(2, fastForwardLine.length() - 2).trim();
try { try {
int limit = Integer.parseInt(text); int limit = Integer.parseInt(text);
condition(limit > 0, "fast-forward must greater than zero, it is: " + limit); condition(limit > 0, "fast-forward limit must be greater than zero, it is: " + limit);
return limit; return limit;
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
return Integer.MAX_VALUE; return Integer.MAX_VALUE;
} }
} }


private static boolean matches(String expectedLine, String actualLine) { static boolean matches(String expectedLine, String actualLine) {
if (expectedLine.equals(actualLine)) { if (expectedLine.equals(actualLine)) {
return true; return true;
} }
try { try {
Pattern pattern = Pattern.compile(expectedLine); return actualLine.matches(expectedLine);
Matcher matcher = pattern.matcher(actualLine);
return matcher.matches();
} }
catch (PatternSyntaxException ignore) { catch (PatternSyntaxException ignore) {
return false; return false;
Expand Down
Expand Up @@ -873,8 +873,47 @@ public static void assertIterableEquals(Iterable<?> expected, Iterable<?> actual


// --- assertLinesMatch ---------------------------------------------------- // --- assertLinesMatch ----------------------------------------------------


public static void assertLinesMatch(List<String> expected, List<String> actual) { /**
AssertLinesMatch.assertLinesMatch(expected, actual); * <em>Asserts</em> that {@code expected} list of {@linkplain String}s matches {@code actual}
* list.
*
* <p>This method differs from other assertions that effectively only check {@link String#equals(Object)},
* in that it uses the following staged match-making algorithm:
*
* <p>For each pair of expected and actual lines do
* <ol>
* <li>check if {@code expected.equals(actual)} - if yes, continue with next pair</li>
* <li>otherwise treat {@code expected} as a regular expression and check via
* {@link String#matches(String)} - if yes, continue with next pair</li>
* <li>otherwise check if {@code expected} line is a fast-forward marker, if yes apply
* fast-forward actual lines accordingly (see below) and goto 1.</li>
* </ol>
*
* <p>A valid fast-forward marker is an expected line that starts and ends with the literal
* {@code >>} and contains at least 4 characters. Examples:
* <ul>
* <li>{@code >>>>}<br>{@code >> stacktrace >>}<br>{@code >> single line, non Integer.parse()-able comment >>}
* <br>Skip arbitrary number of actual lines, until first matching subsequent expected line is found. Any
* character between the fast-forward literals are discarded.</li>
* <li>{@code ">> 21 >>"}
* <br>Skip strictly 21 lines. If they can't be skipped for any reason, an assertion error is raised.</li>
* </ul>
*
* <p>Example showing all three kinds of expected line formats:
* <pre>{@code
* │ │ │ caught: AssertionFailedError: single line fail message
* >> S T A C K T R A C E >>
* │ │ │ duration: [\d]+ ms
* │ │ │ status: ✘ FAILED
* │ └─ test() finished after [\d]+ ms\.
* └─ JUnit Jupiter finished after [\d]+ ms\.
* Test plan execution finished. Number of all tests: 1
*
* Test run finished after [\d]+ ms
* }</pre>
*/
public static void assertLinesMatch(List<String> expectedLines, List<String> actualLines) {
AssertLinesMatch.assertLinesMatch(expectedLines, actualLines);
} }


// --- assertNotEquals ----------------------------------------------------- // --- assertNotEquals -----------------------------------------------------
Expand Down
Expand Up @@ -10,9 +10,13 @@


package org.junit.jupiter.api; package org.junit.jupiter.api;


import static org.junit.jupiter.api.AssertLinesMatch.isFastForwardLine;
import static org.junit.jupiter.api.AssertLinesMatch.parseFastForwardLimit;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static org.junit.jupiter.api.Assertions.assertLinesMatch;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;


import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
Expand Down Expand Up @@ -98,4 +102,33 @@ void assertLinesMatchUsingFastForwardMarkerWithTooHighLimitFails() {
Error error = assertThrows(AssertionFailedError.class, () -> assertLinesMatch(expected, actual)); Error error = assertThrows(AssertionFailedError.class, () -> assertLinesMatch(expected, actual));
assertEquals("terminal fast-forward(100) error: fast-forward(2) expected", error.getMessage()); assertEquals("terminal fast-forward(100) error: fast-forward(2) expected", error.getMessage());
} }

@Test
void assertLinesMatchIsFastForwardLine() {
assertAll("valid fast-forward lines", //
() -> assertTrue(isFastForwardLine(">>>>")), () -> assertTrue(isFastForwardLine(">> >>")),
() -> assertTrue(isFastForwardLine(">> stacktrace >>")),
() -> assertTrue(isFastForwardLine(">> single line, non Integer.parse()-able comment >>")),
() -> assertTrue(isFastForwardLine(">>9>>")), () -> assertTrue(isFastForwardLine(">> 9 >>")),
() -> assertTrue(isFastForwardLine(">> -9 >>")));
}

@Test
void assertLinesMatchParseFastForwardLimit() {
assertAll("valid fast-forward limits", //
() -> assertEquals(Integer.MAX_VALUE, parseFastForwardLimit(">>>>")),
() -> assertEquals(Integer.MAX_VALUE, parseFastForwardLimit(">> >>")),
() -> assertEquals(Integer.MAX_VALUE, parseFastForwardLimit(">> stacktrace >>")),
() -> assertEquals(Integer.MAX_VALUE, parseFastForwardLimit(">> non Integer.parse()-able comment >>")),
() -> assertEquals(9, parseFastForwardLimit(">>9>>")),
() -> assertEquals(9, parseFastForwardLimit(">> 9 >>")));
}

@Test
void assertLinesMatchMatches() {
assertAll("valid fast-forward lines", //
() -> assertTrue(AssertLinesMatch.matches("123", "123")),
() -> assertTrue(AssertLinesMatch.matches(".*", "123")),
() -> assertTrue(AssertLinesMatch.matches("\\d+", "123")));
}
} }

0 comments on commit b57e0b9

Please sign in to comment.