mirror of
https://github.com/octoleo/plantuml.git
synced 2024-12-22 10:59:01 +00:00
Remove \r when running PipeTest on Windows
This commit is contained in:
parent
19822a5539
commit
fd920b7d52
@ -1,6 +1,5 @@
|
||||
package net.sourceforge.plantuml;
|
||||
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@ -20,356 +19,393 @@ import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
|
||||
class PipeTest {
|
||||
|
||||
ByteArrayOutputStream baos;
|
||||
ErrorStatus errorStatus;
|
||||
Option option;
|
||||
Pipe pipe;
|
||||
PrintStream ps;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
errorStatus = ErrorStatus.init();
|
||||
|
||||
baos = new ByteArrayOutputStream();
|
||||
option = new Option();
|
||||
ps = new PrintStream(baos);
|
||||
|
||||
pipe = new Pipe(option, ps, new ByteArrayInputStream(new byte[0]), UTF_8.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_managePipe_set_as_no_error_for_empty_input() throws IOException {
|
||||
pipe = new Pipe(option, ps, new ByteArrayInputStream(new byte[0]), UTF_8.name());
|
||||
|
||||
pipe.managePipe(errorStatus);
|
||||
|
||||
try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) {
|
||||
softly.assertThat(errorStatus.hasError()).isFalse();
|
||||
softly.assertThat(errorStatus.isNoData()).isTrue();
|
||||
softly.assertThat(baos.toByteArray()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static List<TestCase> managePipeTestCases() {
|
||||
LinkedList<TestCase> l = new LinkedList<>();
|
||||
|
||||
l.add(TestCase.of("", "", "", Verification.EXACT, false, true));
|
||||
|
||||
// ok render
|
||||
l.add(TestCase.of("", "a->b", "(?s).*PNG.*Generated by http://plantuml.com.*", Verification.REGEX, false, false));
|
||||
l.add(TestCase.of("", "@startuml\na->b\n@enduml", "(?s).*PNG.*Generated by http://plantuml.com.*", Verification.REGEX, false, false));
|
||||
l.add(TestCase.of("", "@startuml\na->b\n@enduml\n@startuml\na->b\nb->c\n@enduml\n", "(?s).*(PNG.*Generated by http://plantuml.com.*){2}", Verification.REGEX, false, false));
|
||||
|
||||
// bad data
|
||||
l.add(TestCase.of("", "a", "(?s).*PNG.*Generated by http://plantuml.com.*", Verification.REGEX, true, false));
|
||||
l.add(TestCase.of("", "@startuml\na\n@enduml\n", "(?s).*PNG.*Generated by http://plantuml.com.*", Verification.REGEX, true, false));
|
||||
l.add(TestCase.of("", "@startuml\na\n@enduml\n@startuml\na\n@enduml\n", "(?s).*PNG.*Generated by http://plantuml.com.*", Verification.REGEX, true, false));
|
||||
|
||||
// ignore garbage before; after; before&between&after diagrams
|
||||
l.add(TestCase.of("", "this-is-garbage\n@startuml\na->b\n@enduml", "(?s).*(PNG.*Generated by http://plantuml.com.*){1}", Verification.REGEX, false, false));
|
||||
l.add(TestCase.of("", "@startuml\na->b\n@enduml\nthis-is-garbage", "(?s).*(PNG.*Generated by http://plantuml.com.*){1}", Verification.REGEX, false, false));
|
||||
l.add(TestCase.of("", "this-is-garbage\n@startuml\na->b\n@enduml\nthis-is-garbage\n@startuml\na->b\n@enduml\nthis-is-garbage", "(?s).*(PNG.*Generated by http://plantuml.com.*){2}", Verification.REGEX, false, false));
|
||||
|
||||
// ignore other diagram start tags when still not closed (but fails to generate)
|
||||
l.add(TestCase.of("", "@startuml\na->b\n@startgantt\n@enduml\n", "(?s).*(PNG.*Generated by http://plantuml.com.*){1}", Verification.REGEX, true, false));
|
||||
|
||||
// manage @@@format svg
|
||||
l.add(TestCase.of("", "@startuml\n@@@format svg\na->b\n@enduml", "(?s).*<\\?xml.*<svg.*</svg>", Verification.REGEX, false, false));
|
||||
l.add(TestCase.of("", "@startuml\n@@@format svg\na->b\n@enduml\n@startuml\n@@@format svg\na->b\n@enduml", "(?s).*(<\\?xml.*<svg.*</svg>.*){2}", Verification.REGEX, false, false));
|
||||
|
||||
// mixed formats
|
||||
l.add(TestCase.of("", "@startuml\n@@@format png\na->b\n@enduml\n@startuml\n@@@format svg\na->b\n@enduml", "(?s).*PNG.*Generated by http://plantuml.com.*<\\?xml.*<svg.*</svg>", Verification.REGEX, false, false));
|
||||
l.add(TestCase.of("", "@startuml\n@@@format svg\na->b\n@enduml\n@startuml\n@@@format png\na->b\n@enduml", "(?s).*<\\?xml.*<svg.*</svg>.*PNG.*Generated by http://plantuml.com.*", Verification.REGEX, false, false));
|
||||
|
||||
// pipe delimitor
|
||||
l.add(TestCase.of("-pipedelimitor PIPE-DELIMITOR", "@startuml\na->b\n@enduml\n@startuml\na->b\nb->c\n@enduml\n", "(?s).*(PNG.*Generated by http://plantuml.com.*PIPE-DELIMITOR.*){2}", Verification.REGEX, false, false));
|
||||
|
||||
// if format is set in first diagram and not in the second, it will be used in both (Possibly incorrect: preseved from old behaviour)
|
||||
l.add(TestCase.of("", "@startuml\n@@@format svg\na->b\n@enduml\n@startuml\na->b\n@enduml", "(?s).*(<\\?xml.*<svg.*</svg>.*){2}", Verification.REGEX, false, false));
|
||||
|
||||
// ok computeurl
|
||||
l.add(TestCase.of("-computeurl", "@startuml\na->b\n@enduml", "IzIrIm80\n", Verification.EXACT, false, true));
|
||||
l.add(TestCase.of("-computeurl", "@startuml\na->b\n@enduml\n@startuml\na->b\nb->c\n@enduml\n", "IzIrIm80\nIzIrI-9AqhLB1W00\n", Verification.EXACT,false, true));
|
||||
|
||||
// ok encodeurl
|
||||
l.add(TestCase.of("-encodeurl", "@startuml\na->b\n@enduml", "IzIrIm80\n", Verification.EXACT,false, true));
|
||||
l.add(TestCase.of("-encodeurl", "@startuml\na->b\n@enduml\n@startuml\na->b\nb->c\n@enduml\n", "IzIrIm80\nIzIrI-9AqhLB1W00\n", Verification.EXACT, false, true));
|
||||
|
||||
// valid syntax
|
||||
l.add(TestCase.of("-syntax", "@startuml\na->b\n@enduml", "SEQUENCE\n(2 participants)\n", Verification.EXACT, false, false));
|
||||
l.add(TestCase.of("-syntax", "@startuml\na->b\n@enduml\n@startuml\na->b\nb->c\n@enduml\n", "SEQUENCE\n(2 participants)\nSEQUENCE\n(3 participants)\n", Verification.EXACT, false, false));
|
||||
l.add(TestCase.of("-syntax", "@startgantt\n[a] lasts 1 day\n@endgantt", "OTHER\n(Project)\n", Verification.EXACT, false, false));
|
||||
|
||||
// invalid syntax
|
||||
l.add(TestCase.of("-syntax", "@startuml\na\n@enduml", "ERROR\n1\nSyntax Error?\n", Verification.EXACT, true, false));
|
||||
l.add(TestCase.of("-syntax", "@startuml\na\n@enduml\n@startuml\na\n@enduml", "ERROR\n1\nSyntax Error?\nERROR\n1\nSyntax Error?\n", Verification.EXACT, true, false));
|
||||
l.add(TestCase.of("-syntax", "@startuml\na->b\n@enduml\n@startuml\na\n@enduml", "SEQUENCE\n(2 participants)\nERROR\n1\nSyntax Error?\n", Verification.EXACT, true, false));
|
||||
l.add(TestCase.of("-syntax", "@startuml\na\n@enduml\n@startuml\na->b\n@enduml", "ERROR\n1\nSyntax Error?\nSEQUENCE\n(2 participants)\n", Verification.EXACT, true, false));
|
||||
|
||||
// pipemap (using regexp to allow any coords so that it doesn't fail on different systems)
|
||||
l.add(TestCase.of("-pipemap", "@startuml\na->b: [[http://a.com]] c\n@enduml",
|
||||
"<map id=\"plantuml_map\" name=\"plantuml_map\">\n" +
|
||||
"<area shape=\"rect\" id=\"id1\" href=\"http://a.com\" title=\"http://a.com\" alt=\"\" coords=\"[0-9]+,[0-9]+,[0-9]+,[0-9]+\"/>\n" +
|
||||
"</map>\n\n",
|
||||
Verification.REGEX, false, false));
|
||||
l.add(TestCase.of("-pipemap", "@startuml\na->b: [[http://a.com]] c\n@enduml\n@startuml\nc->d: [[http://c.com]] e\n@enduml",
|
||||
"<map id=\"plantuml_map\" name=\"plantuml_map\">\n" +
|
||||
"<area shape=\"rect\" id=\"id1\" href=\"http://a.com\" title=\"http://a.com\" alt=\"\" coords=\"[0-9]+,[0-9]+,[0-9]+,[0-9]+\"/>\n" +
|
||||
"</map>\n\n" +
|
||||
"<map id=\"plantuml_map\" name=\"plantuml_map\">\n" +
|
||||
"<area shape=\"rect\" id=\"id1\" href=\"http://c.com\" title=\"http://c.com\" alt=\"\" coords=\"[0-9]+,[0-9]+,[0-9]+,[0-9]+\"/>\n" +
|
||||
"</map>\n\n",
|
||||
Verification.REGEX, false, false));
|
||||
|
||||
// no links/invalid input => no pipemap to output (no error as of https://forum.plantuml.net/10049/2019-pipemap-diagrams-containing-links-give-zero-exit-code )
|
||||
l.add(TestCase.of("-pipemap", "@startuml\na->b\n@enduml", "\n", Verification.EXACT, false, false));
|
||||
l.add(TestCase.of("-pipemap", "@startuml\na\n@enduml", "\n", Verification.EXACT, false, false));
|
||||
|
||||
return l;
|
||||
}
|
||||
@ParameterizedTest
|
||||
@MethodSource("managePipeTestCases")
|
||||
void should_managePipe_manage_success_cases_correctly(TestCase testCase) throws IOException, InterruptedException {
|
||||
option = new Option(testCase.getOptions().split(" "));
|
||||
pipe = new Pipe(option, ps, new ByteArrayInputStream(testCase.getInput().getBytes(UTF_8)), UTF_8.name());
|
||||
|
||||
pipe.managePipe(errorStatus);
|
||||
|
||||
try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) {
|
||||
softly.assertThat(errorStatus.hasError()).isEqualTo(testCase.isExpectedHasErrors());
|
||||
softly.assertThat(errorStatus.isNoData()).isEqualTo(testCase.isExpectedIsNoData());
|
||||
switch(testCase.getExpectedOutVerification()) {
|
||||
case EXACT:
|
||||
softly.assertThat(new String(baos.toByteArray(), UTF_8)).isEqualTo(testCase.getExpectedOut());
|
||||
break;
|
||||
|
||||
case REGEX:
|
||||
softly.assertThat(new String(baos.toByteArray(), UTF_8)).matches(testCase.getExpectedOut());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_readFirstDiagram_return_null_for_empty_input() throws IOException {
|
||||
pipe = new Pipe(option, null, new ByteArrayInputStream(new byte[0]), UTF_8.name());
|
||||
|
||||
String actual = pipe.readFirstDiagram();
|
||||
|
||||
assertThat(actual).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_readFirstDiagram_decode_a_special_unicode_character_when_provided_charset_is_utf8() throws IOException {
|
||||
pipe = new Pipe(option, null, new ByteArrayInputStream("\u2620\n".getBytes(UTF_8)), UTF_8.name());
|
||||
|
||||
String actual = pipe.readFirstDiagram();
|
||||
|
||||
assertThat(actual).isEqualTo("@startuml\n\u2620\n@enduml\n");
|
||||
}
|
||||
|
||||
// The testing is relevant only if the testing VM is configured in non-UTF-8 defaultCharset()
|
||||
@Test
|
||||
void should_readFirstDiagram_uses_current_charset_if_not_provided() throws IOException {
|
||||
String input = "\u00C1"; // A acute accented. (HTML Á). Multibyte in UTF-8.
|
||||
if(Charset.defaultCharset().newEncoder().canEncode(input)) {
|
||||
pipe = new Pipe(option, null, new ByteArrayInputStream(input.getBytes(Charset.defaultCharset())), null);
|
||||
|
||||
String actual = pipe.readFirstDiagram();
|
||||
|
||||
assertThat(actual).isEqualTo("@startuml\n\u00C1\n@enduml\n");
|
||||
|
||||
} else {
|
||||
// default charset can't encode Á. Ignore the test.
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {
|
||||
"ab\nc", // *nix, macOsX
|
||||
"ab\rc", // pre-macOsX macs
|
||||
"ab\r\nc", // Windows
|
||||
// the case \n\r is handled as 2 new lines, thus not added
|
||||
|
||||
"ab\nc\n",
|
||||
"ab\nc\r",
|
||||
"ab\nc\r\n"
|
||||
})
|
||||
void should_readFirstDiagram_decode_correctly_different_line_endings(String input) throws IOException {
|
||||
pipe = new Pipe(option, null, new ByteArrayInputStream(input.getBytes(UTF_8)), UTF_8.name());
|
||||
|
||||
String first = pipe.readFirstDiagram();
|
||||
String second = pipe.readFirstDiagram();
|
||||
|
||||
assertThat(first).isEqualTo("@startuml\nab\nc\n@enduml\n");
|
||||
assertThat(second).isEqualTo(null); // no spurious diagram afterwards
|
||||
}
|
||||
|
||||
static List<InputExpected> firstStartAndEndMarks() {
|
||||
List<InputExpected> l = new LinkedList<>();
|
||||
l.add(InputExpected.of("\nab\r\ncde", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("\nab\r\ncde\n", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("\nab\r\ncde\n@enduml", "@startuml\nab\ncde\n@enduml\n@enduml\n"));
|
||||
l.add(InputExpected.of("\nab\r\ncde\n@endwhatever", "@startuml\nab\ncde\n@endwhatever\n@enduml\n"));
|
||||
l.add(InputExpected.of("\nab\r\ncde\n@enduml\n", "@startuml\nab\ncde\n@enduml\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startuml\nab\r\ncde\n@enduml", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startuml\nab\r\ncde\n@enduml\n", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startuml\nab\r\ncde\n@enduml\n\n", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startuml\nab\r\ncde\n@enduml\r\n\r\n", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("this-is-garbage\n@startuml\nab\rcde\n@enduml\nthis-is-garbage\n", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startwhatever\nab\rcde\n@endwhatever", "@startwhatever\nab\ncde\n@endwhatever\n"));
|
||||
return l;
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("firstStartAndEndMarks")
|
||||
void should_readFirstDiagram_handle_correctly_start_and_end_marks(InputExpected inputExpected) throws IOException {
|
||||
pipe = new Pipe(option, null, new ByteArrayInputStream(inputExpected.getInput().getBytes(UTF_8)), UTF_8.name());
|
||||
|
||||
String actual = pipe.readFirstDiagram();
|
||||
|
||||
assertThat(actual).isEqualTo(inputExpected.getExpected());
|
||||
}
|
||||
|
||||
static List<InputExpected> subsequentStartAndEndMarks() {
|
||||
List<InputExpected> l = new LinkedList<>();
|
||||
l.add(InputExpected.of("\nab\r\ncde", null));
|
||||
l.add(InputExpected.of("\nab\r\ncde\n", null));
|
||||
l.add(InputExpected.of("\nab\r\ncde\n@enduml", null));
|
||||
l.add(InputExpected.of("\nab\r\ncde\n@endwhatever", null));
|
||||
l.add(InputExpected.of("\nab\r\ncde\n@enduml\n", null));
|
||||
l.add(InputExpected.of("@startuml\nab\r\ncde\n@enduml", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startuml\nab\r\ncde\n@enduml\n", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startuml\nab\r\ncde\n@enduml\n\n", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startuml\nab\r\ncde\n@enduml\r\n\r\n", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("this-is-garbage\n@startuml\nab\rcde\n@enduml\nthis-is-garbage\n", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startwhatever\nab\rcde\n@endwhatever", "@startwhatever\nab\ncde\n@endwhatever\n"));
|
||||
return l;
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("subsequentStartAndEndMarks")
|
||||
void should_readSubsequentDiagram_handle_correctly_start_and_end_marks(InputExpected inputExpected) throws IOException {
|
||||
pipe = new Pipe(option, null, new ByteArrayInputStream(inputExpected.getInput().getBytes(UTF_8)), UTF_8.name());
|
||||
|
||||
String actual = pipe.readSubsequentDiagram();
|
||||
|
||||
assertThat(actual).isEqualTo(inputExpected.getExpected());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"@@@format png", "png", "@@@format png <deadbeef>"})
|
||||
void should_manageFormat_handle_png(String valid) {
|
||||
pipe.manageFormat(valid);
|
||||
|
||||
assertThat(option.getFileFormatOption().getFileFormat()).isEqualTo(FileFormat.PNG);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"@@@format svg", "svg", "@@@format svg <deadbeef>"})
|
||||
void should_manageFormat_handle_svg(String valid) {
|
||||
pipe.manageFormat(valid);
|
||||
|
||||
assertThat(option.getFileFormatOption().getFileFormat()).isEqualTo(FileFormat.SVG);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"@@@format invalid", "invalid", "@@@format invalid <deadbeef>"})
|
||||
void should_manageFormat_ignore_any_other_value_and_keep_default_value_as_file_format_option(String valid) {
|
||||
pipe.manageFormat(valid);
|
||||
|
||||
assertThat(option.getFileFormatOption().getFileFormat()).isEqualTo(FileFormat.PNG);
|
||||
}
|
||||
|
||||
static class TestCase {
|
||||
|
||||
private final String options;
|
||||
private final String input;
|
||||
private final String expectedOut;
|
||||
private final Verification expectedOutVerification;
|
||||
private final boolean expectedHasErrors;
|
||||
private final boolean expectedIsNoData;
|
||||
|
||||
|
||||
public TestCase(String options, String input, String expectedOut, Verification expectedOutVerification, boolean expectedHasErrors, boolean expectedIsNoData) {
|
||||
this.options = options;
|
||||
this.input = input;
|
||||
this.expectedOut = expectedOut;
|
||||
this.expectedOutVerification = expectedOutVerification;
|
||||
this.expectedHasErrors = expectedHasErrors;
|
||||
this.expectedIsNoData = expectedIsNoData;
|
||||
}
|
||||
|
||||
public static TestCase of(String option, String input, String expectedOut, Verification expectedOutVerification, boolean expectedHasErrors, boolean expectedIsNoData) {
|
||||
return new TestCase(option, input, expectedOut, expectedOutVerification, expectedHasErrors, expectedIsNoData);
|
||||
}
|
||||
|
||||
public String getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public String getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public String getExpectedOut() {
|
||||
return expectedOut;
|
||||
}
|
||||
|
||||
public Verification getExpectedOutVerification() {
|
||||
return expectedOutVerification;
|
||||
}
|
||||
|
||||
public boolean isExpectedHasErrors() {
|
||||
return expectedHasErrors;
|
||||
}
|
||||
|
||||
public boolean isExpectedIsNoData() {
|
||||
return expectedIsNoData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "o:'" + options + "', i:'" + input + "', e-out='" + expectedOut + "', e-err='" + expectedHasErrors + "', e-nodata='" + expectedIsNoData + "'";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class InputExpected {
|
||||
private final String input;
|
||||
private final String expected;
|
||||
|
||||
|
||||
public InputExpected(String input, String expected) {
|
||||
this.input = input;
|
||||
this.expected = expected;
|
||||
}
|
||||
|
||||
public static InputExpected of(String input, String expected) {
|
||||
return new InputExpected(input, expected);
|
||||
}
|
||||
|
||||
public String getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public String getExpected() {
|
||||
return expected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "i:'" + input + "', e='" + expected + "'";
|
||||
}
|
||||
}
|
||||
|
||||
enum Verification {
|
||||
EXACT,
|
||||
REGEX
|
||||
}
|
||||
ByteArrayOutputStream baos;
|
||||
ErrorStatus errorStatus;
|
||||
Option option;
|
||||
Pipe pipe;
|
||||
PrintStream ps;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
errorStatus = ErrorStatus.init();
|
||||
|
||||
baos = new ByteArrayOutputStream();
|
||||
option = new Option();
|
||||
ps = new PrintStream(baos);
|
||||
|
||||
pipe = new Pipe(option, ps, new ByteArrayInputStream(new byte[0]), UTF_8.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_managePipe_set_as_no_error_for_empty_input() throws IOException {
|
||||
pipe = new Pipe(option, ps, new ByteArrayInputStream(new byte[0]), UTF_8.name());
|
||||
|
||||
pipe.managePipe(errorStatus);
|
||||
|
||||
try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) {
|
||||
softly.assertThat(errorStatus.hasError()).isFalse();
|
||||
softly.assertThat(errorStatus.isNoData()).isTrue();
|
||||
softly.assertThat(baos.toByteArray()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
static List<TestCase> managePipeTestCases() {
|
||||
LinkedList<TestCase> l = new LinkedList<>();
|
||||
|
||||
l.add(TestCase.of("", "", "", Verification.EXACT, false, true));
|
||||
|
||||
// ok render
|
||||
l.add(TestCase.of("", "a->b", "(?s).*PNG.*Generated by http://plantuml.com.*", Verification.REGEX, false,
|
||||
false));
|
||||
l.add(TestCase.of("", "@startuml\na->b\n@enduml", "(?s).*PNG.*Generated by http://plantuml.com.*",
|
||||
Verification.REGEX, false, false));
|
||||
l.add(TestCase.of("", "@startuml\na->b\n@enduml\n@startuml\na->b\nb->c\n@enduml\n",
|
||||
"(?s).*(PNG.*Generated by http://plantuml.com.*){2}", Verification.REGEX, false, false));
|
||||
|
||||
// bad data
|
||||
l.add(TestCase.of("", "a", "(?s).*PNG.*Generated by http://plantuml.com.*", Verification.REGEX, true, false));
|
||||
l.add(TestCase.of("", "@startuml\na\n@enduml\n", "(?s).*PNG.*Generated by http://plantuml.com.*",
|
||||
Verification.REGEX, true, false));
|
||||
l.add(TestCase.of("", "@startuml\na\n@enduml\n@startuml\na\n@enduml\n",
|
||||
"(?s).*PNG.*Generated by http://plantuml.com.*", Verification.REGEX, true, false));
|
||||
|
||||
// ignore garbage before; after; before&between&after diagrams
|
||||
l.add(TestCase.of("", "this-is-garbage\n@startuml\na->b\n@enduml",
|
||||
"(?s).*(PNG.*Generated by http://plantuml.com.*){1}", Verification.REGEX, false, false));
|
||||
l.add(TestCase.of("", "@startuml\na->b\n@enduml\nthis-is-garbage",
|
||||
"(?s).*(PNG.*Generated by http://plantuml.com.*){1}", Verification.REGEX, false, false));
|
||||
l.add(TestCase.of("",
|
||||
"this-is-garbage\n@startuml\na->b\n@enduml\nthis-is-garbage\n@startuml\na->b\n@enduml\nthis-is-garbage",
|
||||
"(?s).*(PNG.*Generated by http://plantuml.com.*){2}", Verification.REGEX, false, false));
|
||||
|
||||
// ignore other diagram start tags when still not closed (but fails to generate)
|
||||
l.add(TestCase.of("", "@startuml\na->b\n@startgantt\n@enduml\n",
|
||||
"(?s).*(PNG.*Generated by http://plantuml.com.*){1}", Verification.REGEX, true, false));
|
||||
|
||||
// manage @@@format svg
|
||||
l.add(TestCase.of("", "@startuml\n@@@format svg\na->b\n@enduml", "(?s).*<\\?xml.*<svg.*</svg>",
|
||||
Verification.REGEX, false, false));
|
||||
l.add(TestCase.of("", "@startuml\n@@@format svg\na->b\n@enduml\n@startuml\n@@@format svg\na->b\n@enduml",
|
||||
"(?s).*(<\\?xml.*<svg.*</svg>.*){2}", Verification.REGEX, false, false));
|
||||
|
||||
// mixed formats
|
||||
l.add(TestCase.of("", "@startuml\n@@@format png\na->b\n@enduml\n@startuml\n@@@format svg\na->b\n@enduml",
|
||||
"(?s).*PNG.*Generated by http://plantuml.com.*<\\?xml.*<svg.*</svg>", Verification.REGEX, false,
|
||||
false));
|
||||
l.add(TestCase.of("", "@startuml\n@@@format svg\na->b\n@enduml\n@startuml\n@@@format png\na->b\n@enduml",
|
||||
"(?s).*<\\?xml.*<svg.*</svg>.*PNG.*Generated by http://plantuml.com.*", Verification.REGEX, false,
|
||||
false));
|
||||
|
||||
// pipe delimitor
|
||||
l.add(TestCase.of("-pipedelimitor PIPE-DELIMITOR", "@startuml\na->b\n@enduml\n@startuml\na->b\nb->c\n@enduml\n",
|
||||
"(?s).*(PNG.*Generated by http://plantuml.com.*PIPE-DELIMITOR.*){2}", Verification.REGEX, false,
|
||||
false));
|
||||
|
||||
// if format is set in first diagram and not in the second, it will be used in
|
||||
// both (Possibly incorrect: preseved from old behaviour)
|
||||
l.add(TestCase.of("", "@startuml\n@@@format svg\na->b\n@enduml\n@startuml\na->b\n@enduml",
|
||||
"(?s).*(<\\?xml.*<svg.*</svg>.*){2}", Verification.REGEX, false, false));
|
||||
|
||||
// ok computeurl
|
||||
l.add(TestCase.of("-computeurl", "@startuml\na->b\n@enduml", "IzIrIm80\n", Verification.EXACT, false, true));
|
||||
l.add(TestCase.of("-computeurl", "@startuml\na->b\n@enduml\n@startuml\na->b\nb->c\n@enduml\n",
|
||||
"IzIrIm80\nIzIrI-9AqhLB1W00\n", Verification.EXACT, false, true));
|
||||
|
||||
// ok encodeurl
|
||||
l.add(TestCase.of("-encodeurl", "@startuml\na->b\n@enduml", "IzIrIm80\n", Verification.EXACT, false, true));
|
||||
l.add(TestCase.of("-encodeurl", "@startuml\na->b\n@enduml\n@startuml\na->b\nb->c\n@enduml\n",
|
||||
"IzIrIm80\nIzIrI-9AqhLB1W00\n", Verification.EXACT, false, true));
|
||||
|
||||
// valid syntax
|
||||
l.add(TestCase.of("-syntax", "@startuml\na->b\n@enduml", "SEQUENCE\n(2 participants)\n", Verification.EXACT,
|
||||
false, false));
|
||||
l.add(TestCase.of("-syntax", "@startuml\na->b\n@enduml\n@startuml\na->b\nb->c\n@enduml\n",
|
||||
"SEQUENCE\n(2 participants)\nSEQUENCE\n(3 participants)\n", Verification.EXACT, false, false));
|
||||
l.add(TestCase.of("-syntax", "@startgantt\n[a] lasts 1 day\n@endgantt", "OTHER\n(Project)\n",
|
||||
Verification.EXACT, false, false));
|
||||
|
||||
// invalid syntax
|
||||
l.add(TestCase.of("-syntax", "@startuml\na\n@enduml", "ERROR\n1\nSyntax Error?\n", Verification.EXACT, true,
|
||||
false));
|
||||
l.add(TestCase.of("-syntax", "@startuml\na\n@enduml\n@startuml\na\n@enduml",
|
||||
"ERROR\n1\nSyntax Error?\nERROR\n1\nSyntax Error?\n", Verification.EXACT, true, false));
|
||||
l.add(TestCase.of("-syntax", "@startuml\na->b\n@enduml\n@startuml\na\n@enduml",
|
||||
"SEQUENCE\n(2 participants)\nERROR\n1\nSyntax Error?\n", Verification.EXACT, true, false));
|
||||
l.add(TestCase.of("-syntax", "@startuml\na\n@enduml\n@startuml\na->b\n@enduml",
|
||||
"ERROR\n1\nSyntax Error?\nSEQUENCE\n(2 participants)\n", Verification.EXACT, true, false));
|
||||
|
||||
// pipemap (using regexp to allow any coords so that it doesn't fail on
|
||||
// different systems)
|
||||
l.add(TestCase.of("-pipemap", "@startuml\na->b: [[http://a.com]] c\n@enduml",
|
||||
"<map id=\"plantuml_map\" name=\"plantuml_map\">\n"
|
||||
+ "<area shape=\"rect\" id=\"id1\" href=\"http://a.com\" title=\"http://a.com\" alt=\"\" coords=\"[0-9]+,[0-9]+,[0-9]+,[0-9]+\"/>\n"
|
||||
+ "</map>\n\n",
|
||||
Verification.REGEX, false, false));
|
||||
l.add(TestCase.of("-pipemap",
|
||||
"@startuml\na->b: [[http://a.com]] c\n@enduml\n@startuml\nc->d: [[http://c.com]] e\n@enduml",
|
||||
"<map id=\"plantuml_map\" name=\"plantuml_map\">\n"
|
||||
+ "<area shape=\"rect\" id=\"id1\" href=\"http://a.com\" title=\"http://a.com\" alt=\"\" coords=\"[0-9]+,[0-9]+,[0-9]+,[0-9]+\"/>\n"
|
||||
+ "</map>\n\n" + "<map id=\"plantuml_map\" name=\"plantuml_map\">\n"
|
||||
+ "<area shape=\"rect\" id=\"id1\" href=\"http://c.com\" title=\"http://c.com\" alt=\"\" coords=\"[0-9]+,[0-9]+,[0-9]+,[0-9]+\"/>\n"
|
||||
+ "</map>\n\n",
|
||||
Verification.REGEX, false, false));
|
||||
|
||||
// no links/invalid input => no pipemap to output (no error as of
|
||||
// https://forum.plantuml.net/10049/2019-pipemap-diagrams-containing-links-give-zero-exit-code
|
||||
// )
|
||||
l.add(TestCase.of("-pipemap", "@startuml\na->b\n@enduml", "\n", Verification.EXACT, false, false));
|
||||
l.add(TestCase.of("-pipemap", "@startuml\na\n@enduml", "\n", Verification.EXACT, false, false));
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("managePipeTestCases")
|
||||
void should_managePipe_manage_success_cases_correctly(TestCase testCase) throws IOException, InterruptedException {
|
||||
option = new Option(testCase.getOptions().split(" "));
|
||||
pipe = new Pipe(option, ps, new ByteArrayInputStream(testCase.getInput().getBytes(UTF_8)), UTF_8.name());
|
||||
|
||||
pipe.managePipe(errorStatus);
|
||||
|
||||
try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) {
|
||||
softly.assertThat(errorStatus.hasError()).isEqualTo(testCase.isExpectedHasErrors());
|
||||
softly.assertThat(errorStatus.isNoData()).isEqualTo(testCase.isExpectedIsNoData());
|
||||
testCase.getExpectedOutVerification().assertOk(softly, baos, testCase.getExpectedOut());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_readFirstDiagram_return_null_for_empty_input() throws IOException {
|
||||
pipe = new Pipe(option, null, new ByteArrayInputStream(new byte[0]), UTF_8.name());
|
||||
|
||||
String actual = pipe.readFirstDiagram();
|
||||
|
||||
assertThat(actual).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_readFirstDiagram_decode_a_special_unicode_character_when_provided_charset_is_utf8() throws IOException {
|
||||
pipe = new Pipe(option, null, new ByteArrayInputStream("\u2620\n".getBytes(UTF_8)), UTF_8.name());
|
||||
|
||||
String actual = pipe.readFirstDiagram();
|
||||
|
||||
assertThat(actual).isEqualTo("@startuml\n\u2620\n@enduml\n");
|
||||
}
|
||||
|
||||
// The testing is relevant only if the testing VM is configured in non-UTF-8
|
||||
// defaultCharset()
|
||||
@Test
|
||||
void should_readFirstDiagram_uses_current_charset_if_not_provided() throws IOException {
|
||||
String input = "\u00C1"; // A acute accented. (HTML Á). Multibyte in UTF-8.
|
||||
if (Charset.defaultCharset().newEncoder().canEncode(input)) {
|
||||
pipe = new Pipe(option, null, new ByteArrayInputStream(input.getBytes(Charset.defaultCharset())), null);
|
||||
|
||||
String actual = pipe.readFirstDiagram();
|
||||
|
||||
assertThat(actual).isEqualTo("@startuml\n\u00C1\n@enduml\n");
|
||||
|
||||
} else {
|
||||
// default charset can't encode Á. Ignore the test.
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = { "ab\nc", // *nix, macOsX
|
||||
"ab\rc", // pre-macOsX macs
|
||||
"ab\r\nc", // Windows
|
||||
// the case \n\r is handled as 2 new lines, thus not added
|
||||
|
||||
"ab\nc\n", "ab\nc\r", "ab\nc\r\n" })
|
||||
void should_readFirstDiagram_decode_correctly_different_line_endings(String input) throws IOException {
|
||||
pipe = new Pipe(option, null, new ByteArrayInputStream(input.getBytes(UTF_8)), UTF_8.name());
|
||||
|
||||
String first = pipe.readFirstDiagram();
|
||||
String second = pipe.readFirstDiagram();
|
||||
|
||||
assertThat(first).isEqualTo("@startuml\nab\nc\n@enduml\n");
|
||||
assertThat(second).isEqualTo(null); // no spurious diagram afterwards
|
||||
}
|
||||
|
||||
static List<InputExpected> firstStartAndEndMarks() {
|
||||
List<InputExpected> l = new LinkedList<>();
|
||||
l.add(InputExpected.of("\nab\r\ncde", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("\nab\r\ncde\n", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("\nab\r\ncde\n@enduml", "@startuml\nab\ncde\n@enduml\n@enduml\n"));
|
||||
l.add(InputExpected.of("\nab\r\ncde\n@endwhatever", "@startuml\nab\ncde\n@endwhatever\n@enduml\n"));
|
||||
l.add(InputExpected.of("\nab\r\ncde\n@enduml\n", "@startuml\nab\ncde\n@enduml\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startuml\nab\r\ncde\n@enduml", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startuml\nab\r\ncde\n@enduml\n", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startuml\nab\r\ncde\n@enduml\n\n", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startuml\nab\r\ncde\n@enduml\r\n\r\n", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("this-is-garbage\n@startuml\nab\rcde\n@enduml\nthis-is-garbage\n",
|
||||
"@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startwhatever\nab\rcde\n@endwhatever", "@startwhatever\nab\ncde\n@endwhatever\n"));
|
||||
return l;
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("firstStartAndEndMarks")
|
||||
void should_readFirstDiagram_handle_correctly_start_and_end_marks(InputExpected inputExpected) throws IOException {
|
||||
pipe = new Pipe(option, null, new ByteArrayInputStream(inputExpected.getInput().getBytes(UTF_8)), UTF_8.name());
|
||||
|
||||
String actual = pipe.readFirstDiagram();
|
||||
|
||||
assertThat(actual).isEqualTo(inputExpected.getExpected());
|
||||
}
|
||||
|
||||
static List<InputExpected> subsequentStartAndEndMarks() {
|
||||
List<InputExpected> l = new LinkedList<>();
|
||||
l.add(InputExpected.of("\nab\r\ncde", null));
|
||||
l.add(InputExpected.of("\nab\r\ncde\n", null));
|
||||
l.add(InputExpected.of("\nab\r\ncde\n@enduml", null));
|
||||
l.add(InputExpected.of("\nab\r\ncde\n@endwhatever", null));
|
||||
l.add(InputExpected.of("\nab\r\ncde\n@enduml\n", null));
|
||||
l.add(InputExpected.of("@startuml\nab\r\ncde\n@enduml", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startuml\nab\r\ncde\n@enduml\n", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startuml\nab\r\ncde\n@enduml\n\n", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startuml\nab\r\ncde\n@enduml\r\n\r\n", "@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("this-is-garbage\n@startuml\nab\rcde\n@enduml\nthis-is-garbage\n",
|
||||
"@startuml\nab\ncde\n@enduml\n"));
|
||||
l.add(InputExpected.of("@startwhatever\nab\rcde\n@endwhatever", "@startwhatever\nab\ncde\n@endwhatever\n"));
|
||||
return l;
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("subsequentStartAndEndMarks")
|
||||
void should_readSubsequentDiagram_handle_correctly_start_and_end_marks(InputExpected inputExpected)
|
||||
throws IOException {
|
||||
pipe = new Pipe(option, null, new ByteArrayInputStream(inputExpected.getInput().getBytes(UTF_8)), UTF_8.name());
|
||||
|
||||
String actual = pipe.readSubsequentDiagram();
|
||||
|
||||
assertThat(actual).isEqualTo(inputExpected.getExpected());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = { "@@@format png", "png", "@@@format png <deadbeef>" })
|
||||
void should_manageFormat_handle_png(String valid) {
|
||||
pipe.manageFormat(valid);
|
||||
|
||||
assertThat(option.getFileFormatOption().getFileFormat()).isEqualTo(FileFormat.PNG);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = { "@@@format svg", "svg", "@@@format svg <deadbeef>" })
|
||||
void should_manageFormat_handle_svg(String valid) {
|
||||
pipe.manageFormat(valid);
|
||||
|
||||
assertThat(option.getFileFormatOption().getFileFormat()).isEqualTo(FileFormat.SVG);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = { "@@@format invalid", "invalid", "@@@format invalid <deadbeef>" })
|
||||
void should_manageFormat_ignore_any_other_value_and_keep_default_value_as_file_format_option(String valid) {
|
||||
pipe.manageFormat(valid);
|
||||
|
||||
assertThat(option.getFileFormatOption().getFileFormat()).isEqualTo(FileFormat.PNG);
|
||||
}
|
||||
|
||||
static class TestCase {
|
||||
|
||||
private final String options;
|
||||
private final String input;
|
||||
private final String expectedOut;
|
||||
private final Verification expectedOutVerification;
|
||||
private final boolean expectedHasErrors;
|
||||
private final boolean expectedIsNoData;
|
||||
|
||||
public TestCase(String options, String input, String expectedOut, Verification expectedOutVerification,
|
||||
boolean expectedHasErrors, boolean expectedIsNoData) {
|
||||
this.options = options;
|
||||
this.input = input;
|
||||
this.expectedOut = expectedOut;
|
||||
this.expectedOutVerification = expectedOutVerification;
|
||||
this.expectedHasErrors = expectedHasErrors;
|
||||
this.expectedIsNoData = expectedIsNoData;
|
||||
}
|
||||
|
||||
public static TestCase of(String option, String input, String expectedOut, Verification expectedOutVerification,
|
||||
boolean expectedHasErrors, boolean expectedIsNoData) {
|
||||
return new TestCase(option, input, expectedOut, expectedOutVerification, expectedHasErrors,
|
||||
expectedIsNoData);
|
||||
}
|
||||
|
||||
public String getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public String getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public String getExpectedOut() {
|
||||
return expectedOut;
|
||||
}
|
||||
|
||||
public Verification getExpectedOutVerification() {
|
||||
return expectedOutVerification;
|
||||
}
|
||||
|
||||
public boolean isExpectedHasErrors() {
|
||||
return expectedHasErrors;
|
||||
}
|
||||
|
||||
public boolean isExpectedIsNoData() {
|
||||
return expectedIsNoData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "o:'" + options + "', i:'" + input + "', e-out='" + expectedOut + "', e-err='" + expectedHasErrors
|
||||
+ "', e-nodata='" + expectedIsNoData + "'";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class InputExpected {
|
||||
private final String input;
|
||||
private final String expected;
|
||||
|
||||
public InputExpected(String input, String expected) {
|
||||
this.input = input;
|
||||
this.expected = expected;
|
||||
}
|
||||
|
||||
public static InputExpected of(String input, String expected) {
|
||||
return new InputExpected(input, expected);
|
||||
}
|
||||
|
||||
public String getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public String getExpected() {
|
||||
return expected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "i:'" + input + "', e='" + expected + "'";
|
||||
}
|
||||
}
|
||||
|
||||
enum Verification {
|
||||
EXACT, REGEX;
|
||||
|
||||
void assertOk(AutoCloseableSoftAssertions softly, ByteArrayOutputStream baos, String expectedOut) {
|
||||
final String result = new String(baos.toByteArray(), UTF_8).replaceAll("\r", "");
|
||||
switch (this) {
|
||||
case EXACT:
|
||||
softly.assertThat(result).isEqualTo(expectedOut);
|
||||
break;
|
||||
|
||||
case REGEX:
|
||||
softly.assertThat(result).matches(expectedOut);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user