diff --git a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/ArgumentListTests.java b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/ArgumentListTests.java index 8287fdc79a..6a699f50c5 100644 --- a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/ArgumentListTests.java +++ b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/ArgumentListTests.java @@ -9,6 +9,7 @@ import dev.jorel.commandapi.arguments.StringArgument; import dev.jorel.commandapi.arguments.parseexceptions.ArgumentParseExceptionContext; import dev.jorel.commandapi.test.arguments.parseexceptions.ArgumentParseExceptionContextVerifier; +import dev.jorel.commandapi.test.arguments.parseexceptions.InitialParseExceptionTextArgumentVerifier; import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.junit.jupiter.api.AfterEach; @@ -445,10 +446,10 @@ public ArgumentParseExceptionListArgumentVerifier(TestBase testBase) { } public void assertCorrectContext( - String exceptionMessage, CommandSender sender, String input, Map previousArgsMap, - ListArgumentCommon.ArgumentParseExceptionInformation.Exceptions type, - List listSoFar, String rawItem, T currentItem, - ArgumentParseExceptionContext, CommandSender> actual + String exceptionMessage, CommandSender sender, String input, Map previousArgsMap, + ListArgumentCommon.ArgumentParseExceptionInformation.Exceptions type, + List listSoFar, String rawItem, T currentItem, + ArgumentParseExceptionContext, CommandSender> actual ) { super.assertCorrectContext(exceptionMessage, sender, input, previousArgsMap, actual); @@ -562,7 +563,97 @@ void argumentParseExceptionTestWithListArgument() { "1 2 3 a 5", Map.of("buffer", "b123456789012345"), List.of(1, 2, 3), "a" ); } - + + @Test + void initialParseExceptionTestWithListTextArgument() { + PlayerMock player = server.addPlayer(); + InitialParseExceptionTextArgumentVerifier verifier = new InitialParseExceptionTextArgumentVerifier(this); + + new CommandAPICommand("test") + .withArguments( + new StringArgument("buffer"), + new ListArgumentBuilder("list") + .withList(1, 2, 3, 4, 5) + .withStringMapper() + .buildText() + .withInitialParseExceptionHandler(verifier.getExceptionHandler()) + ) + .executesPlayer(P_EXEC) + .register(); + + // Test INVALID_ESCAPE cases: Backslash not followed by backslash or the same quote that started argument + verifier.testInvalidEscapeCase( + player, "test b123 \"\\abc\"", + "Invalid escape sequence '\\a' in quoted string at position 12: ...st b123 \"\\<--[HERE]", + 10, 12 + ); + verifier.testInvalidEscapeCase( + player, "test b123 \"ab\\c\"", + "Invalid escape sequence '\\c' in quoted string at position 14: ... b123 \"ab\\<--[HERE]", + 10, 14 + ); + + verifier.testInvalidEscapeCase( + player, "test b123 \"\\'bc\"", + "Invalid escape sequence '\\'' in quoted string at position 12: ...st b123 \"\\<--[HERE]", + 10, 12 + ); + verifier.testInvalidEscapeCase( + player, "test b123 '\\\"bc'", + "Invalid escape sequence '\\\"' in quoted string at position 12: ...st b123 '\\<--[HERE]", + 10, 12 + ); + + + // Test EXPECTED_QUOTE_END cases: Quoted string never ended by same quote that started argument + verifier.testExpectedQuoteEndCase( + player, "test b123 \"abc", + "Unclosed quoted string at position 14: ... b123 \"abc<--[HERE]", + 10 + ); + verifier.testExpectedQuoteEndCase( + player, "test b123 'abcde", + "Unclosed quoted string at position 16: ...123 'abcde<--[HERE]", + 10 + ); + + verifier.testExpectedQuoteEndCase( + player, "test b123 \"abc'", + "Unclosed quoted string at position 15: ...b123 \"abc'<--[HERE]", + 10 + ); + verifier.testExpectedQuoteEndCase( + player, "test b123 'abcde\"", + "Unclosed quoted string at position 17: ...23 'abcde\"<--[HERE]", + 10 + ); + + + // Increasing characters in buffer argument increases cursor start + verifier.testInvalidEscapeCase( + player, "test b12345 '\\\"bc'", + "Invalid escape sequence '\\\"' in quoted string at position 14: ... b12345 '\\<--[HERE]", + 12, 14 + ); + verifier.testInvalidEscapeCase( + player, "test b123456789012345 '\\\"bc'", + "Invalid escape sequence '\\\"' in quoted string at position 24: ...9012345 '\\<--[HERE]", + 22, 24 + ); + + verifier.testExpectedQuoteEndCase( + player, "test b12345 \"abc'", + "Unclosed quoted string at position 17: ...2345 \"abc'<--[HERE]", + 12 + ); + + verifier.testExpectedQuoteEndCase( + player, "test b123456789012345 \"abc'", + "Unclosed quoted string at position 27: ...2345 \"abc'<--[HERE]", + 22 + ); + } + /******************** * Suggestion tests * ********************/ diff --git a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/parseexceptions/ArgumentParseExceptionContextVerifier.java b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/parseexceptions/ArgumentParseExceptionContextVerifier.java index 25064bb99a..ffb461bf9a 100644 --- a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/parseexceptions/ArgumentParseExceptionContextVerifier.java +++ b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/parseexceptions/ArgumentParseExceptionContextVerifier.java @@ -81,7 +81,7 @@ public void verifyGeneratedContext( } /** - * Asserts that the given {@code actual} context has all the given expected attributes + * Asserts that the given {@code actual} context has all the given expected attributes. * * @param exceptionMessage The message of the initial parse exception. * @param sender The {@link CommandSender} who sent the command. diff --git a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/parseexceptions/InitialParseExceptionContextVerifier.java b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/parseexceptions/InitialParseExceptionContextVerifier.java index 3b6c8d5d43..ca0a068fd8 100644 --- a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/parseexceptions/InitialParseExceptionContextVerifier.java +++ b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/parseexceptions/InitialParseExceptionContextVerifier.java @@ -79,7 +79,7 @@ public void verifyGeneratedContext( } /** - * Asserts that the given {@code actual} context has all the given expected attributes + * Asserts that the given {@code actual} context has all the given expected attributes. * * @param exceptionMessage The message of the initial parse exception. * @param readerString The command string being parsed. diff --git a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/parseexceptions/InitialParseExceptionNumberArgumentVerifier.java b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/parseexceptions/InitialParseExceptionNumberArgumentVerifier.java index 69e5df5a65..a5f274be8a 100644 --- a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/parseexceptions/InitialParseExceptionNumberArgumentVerifier.java +++ b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/parseexceptions/InitialParseExceptionNumberArgumentVerifier.java @@ -16,7 +16,7 @@ public class InitialParseExceptionNumberArgumentVerifier extends InitialParseExceptionContextVerifier> { /** - * Creates a new {@link InitialParseExceptionContextVerifier}. + * Creates a new {@link InitialParseExceptionNumberArgumentVerifier}. * * @param testBase The {@link TestBase} object running the test. */ diff --git a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/parseexceptions/InitialParseExceptionTextArgumentVerifier.java b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/parseexceptions/InitialParseExceptionTextArgumentVerifier.java new file mode 100644 index 0000000000..f9748bd82e --- /dev/null +++ b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/arguments/parseexceptions/InitialParseExceptionTextArgumentVerifier.java @@ -0,0 +1,91 @@ +package dev.jorel.commandapi.test.arguments.parseexceptions; + +import dev.jorel.commandapi.arguments.parseexceptions.InitialParseExceptionContext; +import dev.jorel.commandapi.arguments.parseexceptions.InitialParseExceptionTextArgument; +import dev.jorel.commandapi.test.TestBase; +import org.bukkit.command.CommandSender; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * A helper class for verifying {@link InitialParseExceptionContext} objects generated by + * {@link InitialParseExceptionTextArgument}s. + */ +public class InitialParseExceptionTextArgumentVerifier + extends InitialParseExceptionContextVerifier { + /** + * Creates a new {@link InitialParseExceptionTextArgumentVerifier}. + * + * @param testBase The {@link TestBase} object running the test. + */ + public InitialParseExceptionTextArgumentVerifier(TestBase testBase) { + super(testBase); + } + + /** + * Asserts that the given {@code actual} context has all the given expected attributes. + * + * @param exceptionMessage The message of the initial parse exception. + * @param readerString The command string being parsed. + * @param cursorStart The place where the StringReader started parsing the ArgumentType. + * @param readerCursor The place where the StringReader ended when the exception was handled. + * @param exceptionType The type of exception that occurred. + * @param actual The actual {@link InitialParseExceptionContext} generated. + */ + public void assertCorrectContext( + String exceptionMessage, String readerString, int cursorStart, int readerCursor, + InitialParseExceptionTextArgument.ExceptionTypes exceptionType, + InitialParseExceptionContext actual) { + super.assertCorrectContext(exceptionMessage, readerString, cursorStart, readerCursor, actual); + + assertEquals(exceptionType, actual.exceptionInformation()); + } + + /** + * Tests a case where the {@code exceptionType} is {@code INVALID_ESCAPE}, when a quoted String contains the escape + * character {@code \} (backslash) is followed by anything other than another backslash or the same character that + * started the quoted string. + * + * @param sender The sender for the command. + * @param command The command to execute. + * @param exceptionMessage The message of the exception that should be thrown. + * @param cursorStart The index where the StringReader's cursor should start and end. + * @param readerCursor The place where the StringReader ended when the exception was handled. + */ + public void testInvalidEscapeCase( + CommandSender sender, String command, String exceptionMessage, + int cursorStart, int readerCursor + ) { + verifyGeneratedContext( + sender, command, exceptionMessage, + context -> assertCorrectContext( + exceptionMessage, command, cursorStart, readerCursor, + InitialParseExceptionTextArgument.ExceptionTypes.INVALID_ESCAPE, + context + ) + ); + } + + /** + * Tests a case where the {@code exceptionType} is {@code EXPECTED_QUOTE_END}, when a quoted String reaches the end + * of input before the String is closed. {@code readerCursor} should be at the end of the input command. + * + * @param sender The sender for the command. + * @param command The command to execute. + * @param exceptionMessage The message of the exception that should be thrown. + * @param cursorStart The index where the StringReader's cursor should start and end. + */ + public void testExpectedQuoteEndCase( + CommandSender sender, String command, String exceptionMessage, + int cursorStart + ) { + verifyGeneratedContext( + sender, command, exceptionMessage, + context -> assertCorrectContext( + exceptionMessage, command, cursorStart, command.length(), + InitialParseExceptionTextArgument.ExceptionTypes.EXPECTED_QUOTE_END, + context + ) + ); + } +}