From 943c42ae98d17dc905baf694a4394dbf79ff80c7 Mon Sep 17 00:00:00 2001 From: "alexander.soderberg" Date: Sat, 27 Nov 2021 16:30:37 +0100 Subject: [PATCH] Chore: Improve the test setup for cloud-core and clean up some test cases. --- build-logic/src/main/kotlin/Versions.kt | 3 + .../kotlin/cloud.base-conventions.gradle.kts | 4 + .../AnnotationAccessorTest.java | 19 ++- .../CommandHelpHandlerTest.java | 14 +- .../CommandPerformanceTest.java | 4 +- .../CommandPermissionTest.java | 27 ++-- .../CommandPostProcessorTest.java | 9 +- .../CommandPreProcessorTest.java | 7 +- .../CommandRegistrationStateTest.java | 23 ++- .../CommandSuggestionsTest.java | 24 +-- .../cloud/commandframework/CommandTest.java | 17 ++- .../commandframework/CommandTreeTest.java | 8 +- .../commandframework/ExecutionBenchmark.java | 4 +- .../ParameterInjectorRegistryTest.java | 43 ++++-- .../commandframework/ParserRegistryTest.java | 141 +++++++++++------- .../commandframework/TestCommandManager.java | 52 ------- .../commandframework/TestCommandSender.java | 1 - .../standard/StringArgumentTest.java | 59 +++++--- .../commandframework/util/TestUtils.java | 90 +++++++++++ 19 files changed, 356 insertions(+), 193 deletions(-) delete mode 100644 cloud-core/src/test/java/cloud/commandframework/TestCommandManager.java create mode 100644 cloud-core/src/test/java/cloud/commandframework/util/TestUtils.java diff --git a/build-logic/src/main/kotlin/Versions.kt b/build-logic/src/main/kotlin/Versions.kt index 4f40bb641..320e2fe8f 100644 --- a/build-logic/src/main/kotlin/Versions.kt +++ b/build-logic/src/main/kotlin/Versions.kt @@ -33,4 +33,7 @@ object Versions { // TEST DEPENDENCIES const val jupiterEngine = "5.8.1" const val jmh = "1.27" + const val mockitoCore = "4.1.0" + const val mockitoKotlin = "4.0.0" + const val truth = "1.1.3" } diff --git a/build-logic/src/main/kotlin/cloud.base-conventions.gradle.kts b/build-logic/src/main/kotlin/cloud.base-conventions.gradle.kts index fc0baf2ee..315d433df 100644 --- a/build-logic/src/main/kotlin/cloud.base-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/cloud.base-conventions.gradle.kts @@ -89,6 +89,10 @@ repositories { dependencies { compileOnlyApi("org.checkerframework", "checker-qual", Versions.checkerQual) testImplementation("org.junit.jupiter", "junit-jupiter-engine", Versions.jupiterEngine) + testImplementation("org.mockito", "mockito-core", Versions.mockitoCore) + testImplementation("org.mockito.kotlin", "mockito-kotlin", Versions.mockitoKotlin) + testImplementation("com.google.truth", "truth", Versions.truth) + testImplementation("com.google.truth.extensions", "truth-java8-extension", Versions.truth) errorprone("com.google.errorprone", "error_prone_core", Versions.errorprone) // Silences compiler warnings from guava using errorprone compileOnly("com.google.errorprone", "error_prone_annotations", Versions.errorprone) diff --git a/cloud-core/src/test/java/cloud/commandframework/AnnotationAccessorTest.java b/cloud-core/src/test/java/cloud/commandframework/AnnotationAccessorTest.java index 5d6ca056b..9aeddbeaa 100644 --- a/cloud-core/src/test/java/cloud/commandframework/AnnotationAccessorTest.java +++ b/cloud-core/src/test/java/cloud/commandframework/AnnotationAccessorTest.java @@ -23,8 +23,9 @@ // package cloud.commandframework; +import static com.google.common.truth.Truth.assertThat; + import cloud.commandframework.annotations.AnnotationAccessor; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.lang.annotation.ElementType; @@ -36,21 +37,29 @@ public class AnnotationAccessorTest { - @Qualifier("method") - public static void annotatedMethod(@Qualifier("parameter") final String parameter) { + private static final String QUALIFIER_TEST_STRING_PARAMETER = "parameter"; + private static final String QUALIFIER_TEST_STRING_METHOD = "method"; + + @Qualifier(QUALIFIER_TEST_STRING_METHOD) + public static void annotatedMethod(@Qualifier(QUALIFIER_TEST_STRING_PARAMETER) final String parameter) { } @Test void testQualifierResolutionOrder() throws Exception { + // Given final Method method = AnnotationAccessorTest.class.getMethod("annotatedMethod", String.class); final Parameter parameter = method.getParameters()[0]; final AnnotationAccessor accessor = AnnotationAccessor.of( AnnotationAccessor.of(parameter), AnnotationAccessor.of(method) ); + + // When final Qualifier qualifier = accessor.annotation(Qualifier.class); - Assertions.assertNotNull(qualifier); - Assertions.assertEquals("parameter", qualifier.value()); + + // Then + assertThat(qualifier).isNotNull(); + assertThat(qualifier.value()).isEqualTo(QUALIFIER_TEST_STRING_PARAMETER); } @Target({ElementType.PARAMETER, ElementType.METHOD}) diff --git a/cloud-core/src/test/java/cloud/commandframework/CommandHelpHandlerTest.java b/cloud-core/src/test/java/cloud/commandframework/CommandHelpHandlerTest.java index 7f05c38ee..42f3aca37 100644 --- a/cloud-core/src/test/java/cloud/commandframework/CommandHelpHandlerTest.java +++ b/cloud-core/src/test/java/cloud/commandframework/CommandHelpHandlerTest.java @@ -23,6 +23,8 @@ // package cloud.commandframework; +import static cloud.commandframework.util.TestUtils.createManager; + import cloud.commandframework.arguments.CommandArgument; import cloud.commandframework.arguments.StaticArgument; import cloud.commandframework.arguments.standard.IntegerArgument; @@ -47,7 +49,7 @@ class CommandHelpHandlerTest { @BeforeAll static void setup() { - manager = new TestCommandManager(); + manager = createManager(); final SimpleCommandMeta meta1 = SimpleCommandMeta.builder().with(CommandMeta.DESCRIPTION, "Command with only literals").build(); manager.command(manager.commandBuilder("test", meta1).literal("this").literal("thing").build()); final SimpleCommandMeta meta2 = SimpleCommandMeta.builder().with(CommandMeta.DESCRIPTION, "Command with variables").build(); @@ -103,10 +105,8 @@ void testPredicateFilter() { * This predicate only displays the commands starting with /test * The one command ending in 'thing' is excluded as well, for complexity */ - final Predicate> predicate = (command) -> { - return command.toString().startsWith("test ") - && !command.toString().endsWith(" thing"); - }; + final Predicate> predicate = (command) -> command.toString().startsWith("test ") + && !command.toString().endsWith(" thing"); /* * List all commands from root, which should show only: @@ -132,7 +132,7 @@ void testPredicateFilter() { */ final CommandHelpHandler.HelpTopic query3 = manager.getCommandHelpHandler(predicate).queryHelp("test int"); Assertions.assertTrue(query3 instanceof CommandHelpHandler.VerboseHelpTopic); - Assertions.assertEquals(Arrays.asList("test int "), getSortedSyntaxStrings(query3)); + Assertions.assertEquals(Collections.singletonList("test int "), getSortedSyntaxStrings(query3)); /* * List all commands from /vec, which should show none @@ -228,7 +228,7 @@ private void printMultiHelpTopic(final CommandHelpHandler.MultiHelpTopic manager.executeCommand(new TestCommandSender(), "first 10").join() ); @@ -77,10 +82,12 @@ void testComplexPermissions() { void testAndPermissions() { final CommandPermission test = Permission.of("one").and(Permission.of("two")); final TestCommandSender sender = new TestCommandSender("one"); - assertFalse(manager.hasPermission(sender, test)); - assertFalse(manager.hasPermission(new TestCommandSender("two"), test)); + + assertThat(manager.hasPermission(sender, test)).isFalse(); + assertThat(manager.hasPermission(new TestCommandSender("two"), test)).isFalse(); + sender.addPermission("two"); - assertTrue(manager.hasPermission(sender, test)); + assertThat(manager.hasPermission(sender, test)).isTrue(); } @Test @@ -126,7 +133,7 @@ void testPredicatePermissions() { manager.executeCommand(new TestCommandSender(), "predicate").join(); // Now we force it to fail condition.set(false); - Assertions.assertThrows( + assertThrows( CompletionException.class, () -> manager.executeCommand(new TestCommandSender(), "predicate").join() ); @@ -141,7 +148,7 @@ private PermissionOutputtingCommandManager() { @Override public boolean hasPermission( - final TestCommandSender sender, + final @NonNull TestCommandSender sender, final String permission ) { if (permission.equalsIgnoreCase("first")) { @@ -154,7 +161,7 @@ public boolean hasPermission( } @Override - public CommandMeta createDefaultCommandMeta() { + public @NonNull CommandMeta createDefaultCommandMeta() { return SimpleCommandMeta.empty(); } diff --git a/cloud-core/src/test/java/cloud/commandframework/CommandPostProcessorTest.java b/cloud-core/src/test/java/cloud/commandframework/CommandPostProcessorTest.java index cfc1c1b49..df4870d66 100644 --- a/cloud-core/src/test/java/cloud/commandframework/CommandPostProcessorTest.java +++ b/cloud-core/src/test/java/cloud/commandframework/CommandPostProcessorTest.java @@ -23,10 +23,13 @@ // package cloud.commandframework; +import static cloud.commandframework.util.TestUtils.createManager; + import cloud.commandframework.execution.postprocessor.CommandPostprocessingContext; import cloud.commandframework.execution.postprocessor.CommandPostprocessor; import cloud.commandframework.meta.SimpleCommandMeta; import cloud.commandframework.services.types.ConsumerService; +import org.checkerframework.checker.nullness.qual.NonNull; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -38,7 +41,7 @@ public class CommandPostProcessorTest { @BeforeAll static void newTree() { - manager = new TestCommandManager(); + manager = createManager(); manager.command(manager.commandBuilder("test", SimpleCommandMeta.empty()) .handler(c -> state[0] = true) .build()); @@ -48,13 +51,13 @@ static void newTree() { @Test void testPreprocessing() { manager.executeCommand(new TestCommandSender(), "test").join(); - Assertions.assertEquals(false, state[0]); + Assertions.assertFalse(state[0]); } static final class SamplePostprocessor implements CommandPostprocessor { @Override - public void accept(final CommandPostprocessingContext context) { + public void accept(final @NonNull CommandPostprocessingContext context) { ConsumerService.interrupt(); } diff --git a/cloud-core/src/test/java/cloud/commandframework/CommandPreProcessorTest.java b/cloud-core/src/test/java/cloud/commandframework/CommandPreProcessorTest.java index 96ad0e685..bda9e24f1 100644 --- a/cloud-core/src/test/java/cloud/commandframework/CommandPreProcessorTest.java +++ b/cloud-core/src/test/java/cloud/commandframework/CommandPreProcessorTest.java @@ -23,11 +23,14 @@ // package cloud.commandframework; +import static cloud.commandframework.util.TestUtils.createManager; + import cloud.commandframework.arguments.standard.EnumArgument; import cloud.commandframework.execution.preprocessor.CommandPreprocessingContext; import cloud.commandframework.execution.preprocessor.CommandPreprocessor; import cloud.commandframework.meta.SimpleCommandMeta; import cloud.commandframework.services.types.ConsumerService; +import org.checkerframework.checker.nullness.qual.NonNull; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -38,7 +41,7 @@ public class CommandPreProcessorTest { @BeforeAll static void newTree() { - manager = new TestCommandManager(); + manager = createManager(); manager.command(manager.commandBuilder("test", SimpleCommandMeta.empty()) .argument(EnumArgument.of(SampleEnum.class, "enum")) .handler( @@ -72,7 +75,7 @@ enum SampleEnum { static final class SamplePreprocessor implements CommandPreprocessor { @Override - public void accept(final CommandPreprocessingContext context) { + public void accept(final @NonNull CommandPreprocessingContext context) { try { final int num = Integer.parseInt(context.getInputQueue().removeFirst()); context.getCommandContext().store("int", num); diff --git a/cloud-core/src/test/java/cloud/commandframework/CommandRegistrationStateTest.java b/cloud-core/src/test/java/cloud/commandframework/CommandRegistrationStateTest.java index 6107f4bfb..8f35f9ba6 100644 --- a/cloud-core/src/test/java/cloud/commandframework/CommandRegistrationStateTest.java +++ b/cloud-core/src/test/java/cloud/commandframework/CommandRegistrationStateTest.java @@ -26,6 +26,7 @@ import cloud.commandframework.internal.CommandRegistrationHandler; import org.junit.jupiter.api.Test; +import static cloud.commandframework.util.TestUtils.createManager; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -33,25 +34,35 @@ public class CommandRegistrationStateTest { @Test void testInitialState() { - final TestCommandManager manager = new TestCommandManager(); + final CommandManager manager = createManager(); assertEquals(CommandManager.RegistrationState.BEFORE_REGISTRATION, manager.getRegistrationState()); } @Test void testRegistrationChangesState() { - final TestCommandManager manager = new TestCommandManager(); + final CommandManager manager = createManager(); + manager.command(manager.commandBuilder("test").handler(ctx -> { })); + assertEquals(CommandManager.RegistrationState.REGISTERING, manager.getRegistrationState()); - // And a second registration maintains it + } + + @Test + void testDoubleRegistrationPersistsState() { + final CommandManager manager = createManager(); + + manager.command(manager.commandBuilder("test").handler(ctx -> { + })); manager.command(manager.commandBuilder("test2").handler(ctx -> { })); + assertEquals(CommandManager.RegistrationState.REGISTERING, manager.getRegistrationState()); } @Test void testChangingRegistrationHandlerFails() { - final TestCommandManager manager = new TestCommandManager(); + final CommandManager manager = createManager(); manager.command(manager.commandBuilder("test").handler(ctx -> { })); assertThrows( @@ -62,7 +73,7 @@ void testChangingRegistrationHandlerFails() { @Test void testRegistrationFailsInAfterRegistrationState() { - final TestCommandManager manager = new TestCommandManager(); + final CommandManager manager = createManager(); manager.command(manager.commandBuilder("test").handler(ctx -> { })); @@ -76,7 +87,7 @@ void testRegistrationFailsInAfterRegistrationState() { @Test void testAllowUnsafeRegistration() { - final TestCommandManager manager = new TestCommandManager(); + final CommandManager manager = createManager(); manager.setSetting(CommandManager.ManagerSettings.ALLOW_UNSAFE_REGISTRATION, true); manager.command(manager.commandBuilder("test").handler(ctx -> { })); diff --git a/cloud-core/src/test/java/cloud/commandframework/CommandSuggestionsTest.java b/cloud-core/src/test/java/cloud/commandframework/CommandSuggestionsTest.java index c8bb80778..60834bdc0 100644 --- a/cloud-core/src/test/java/cloud/commandframework/CommandSuggestionsTest.java +++ b/cloud-core/src/test/java/cloud/commandframework/CommandSuggestionsTest.java @@ -23,6 +23,8 @@ // package cloud.commandframework; +import static cloud.commandframework.util.TestUtils.createManager; + import cloud.commandframework.arguments.compound.ArgumentTriplet; import cloud.commandframework.arguments.standard.BooleanArgument; import cloud.commandframework.arguments.standard.EnumArgument; @@ -45,7 +47,7 @@ public class CommandSuggestionsTest { @BeforeAll static void setupManager() { - manager = new TestCommandManager(); + manager = createManager(); manager.command(manager.commandBuilder("test", "testalias").literal("one").build()); manager.command(manager.commandBuilder("test").literal("two").build()); manager.command(manager.commandBuilder("test") @@ -107,16 +109,18 @@ static void setupManager() { .argument(IntegerArgument.newBuilder("num").withMin(5).withMax(100))); manager.command(manager.commandBuilder("partial") - .argument(StringArgument.newBuilder("arg").withSuggestionsProvider((contect, input) -> { - return Arrays.asList("hi", "hey", "heya", "hai", "hello"); - })) + .argument( + StringArgument.newBuilder("arg") + .withSuggestionsProvider((contect, input) -> Arrays.asList("hi", "hey", "heya", "hai", "hello")) + ) .literal("literal") .build()); manager.command(manager.commandBuilder("literal_with_variable") - .argument(StringArgument.newBuilder("arg").withSuggestionsProvider((context, input) -> { - return Arrays.asList("veni", "vidi"); - }).build()) + .argument( + StringArgument.newBuilder("arg") + .withSuggestionsProvider((context, input) -> Arrays.asList("veni", "vidi")).build() + ) .literal("now")); manager.command(manager.commandBuilder("literal_with_variable") .literal("vici") @@ -239,7 +243,7 @@ void testCompoundFlags() { final String input2 = "flags3 --c"; final List suggestions2 = manager.suggest(new TestCommandSender(), input2); - Assertions.assertEquals(Arrays.asList("--compound"), suggestions2); + Assertions.assertEquals(Collections.singletonList("--compound"), suggestions2); final String input3 = "flags3 --compound "; final List suggestions3 = manager.suggest(new TestCommandSender(), input3); @@ -264,11 +268,11 @@ void testCompoundFlags() { final String input8 = "flags3 --compound 22 33 44 --pres"; final List suggestions8 = manager.suggest(new TestCommandSender(), input8); - Assertions.assertEquals(Arrays.asList("--presence"), suggestions8); + Assertions.assertEquals(Collections.singletonList("--presence"), suggestions8); final String input9 = "flags3 --compound 22 33 44 --presence "; final List suggestions9 = manager.suggest(new TestCommandSender(), input9); - Assertions.assertEquals(Arrays.asList("--single"), suggestions9); + Assertions.assertEquals(Collections.singletonList("--single"), suggestions9); final String input10 = "flags3 --compound 22 33 44 --single "; final List suggestions10 = manager.suggest(new TestCommandSender(), input10); diff --git a/cloud-core/src/test/java/cloud/commandframework/CommandTest.java b/cloud-core/src/test/java/cloud/commandframework/CommandTest.java index fa0620934..260b48a10 100644 --- a/cloud-core/src/test/java/cloud/commandframework/CommandTest.java +++ b/cloud-core/src/test/java/cloud/commandframework/CommandTest.java @@ -23,6 +23,8 @@ // package cloud.commandframework; +import static com.google.common.truth.Truth.assertThat; + import cloud.commandframework.arguments.StaticArgument; import cloud.commandframework.arguments.standard.StringArgument; import cloud.commandframework.meta.SimpleCommandMeta; @@ -33,14 +35,23 @@ class CommandTest { @Test() void noArguments() { - Assertions.assertEquals(1, Command.newBuilder("test", SimpleCommandMeta.empty()).build().getArguments().size()); + assertThat( + Command + .newBuilder("test", SimpleCommandMeta.empty()) + .build() + .getArguments() + .size() + ).isEqualTo(1); } @Test void ensureOrdering() { Assertions.assertThrows(IllegalArgumentException.class, () -> - Command.newBuilder("test", SimpleCommandMeta.empty()).argument(StringArgument.optional("something")) - .argument(StaticArgument.of("somethingelse")).build()); + Command.newBuilder("test", SimpleCommandMeta.empty()) + .argument(StringArgument.optional("something")) + .argument(StaticArgument.of("somethingelse")) + .build() + ); } } diff --git a/cloud-core/src/test/java/cloud/commandframework/CommandTreeTest.java b/cloud-core/src/test/java/cloud/commandframework/CommandTreeTest.java index 7fe2e8405..0815fc86d 100644 --- a/cloud-core/src/test/java/cloud/commandframework/CommandTreeTest.java +++ b/cloud-core/src/test/java/cloud/commandframework/CommandTreeTest.java @@ -23,6 +23,8 @@ // package cloud.commandframework; +import static cloud.commandframework.util.TestUtils.createManager; + import cloud.commandframework.arguments.CommandArgument; import cloud.commandframework.arguments.compound.ArgumentPair; import cloud.commandframework.arguments.flags.CommandFlag; @@ -55,7 +57,7 @@ class CommandTreeTest { @BeforeAll static void newTree() { - manager = new TestCommandManager(); + manager = createManager(); /* Build general test commands */ manager.command(manager.commandBuilder("test", SimpleCommandMeta.empty()) @@ -146,9 +148,7 @@ static void newTree() { /* Build command for testing float */ manager.command(manager.commandBuilder("float") .argument(FloatArgument.of("num")) - .handler(c -> { - System.out.printf("%f\n", c.get("num")); - })); + .handler(c -> System.out.printf("%f\n", c.get("num")))); /* Build command for testing preprocessing */ manager.command(manager.commandBuilder("preprocess") diff --git a/cloud-core/src/test/java/cloud/commandframework/ExecutionBenchmark.java b/cloud-core/src/test/java/cloud/commandframework/ExecutionBenchmark.java index d42c509c5..a3465b367 100644 --- a/cloud-core/src/test/java/cloud/commandframework/ExecutionBenchmark.java +++ b/cloud-core/src/test/java/cloud/commandframework/ExecutionBenchmark.java @@ -23,6 +23,8 @@ // package cloud.commandframework; +import static cloud.commandframework.util.TestUtils.createManager; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -46,7 +48,7 @@ public class ExecutionBenchmark { @Setup(Level.Trial) public void setup() { - manager = new TestCommandManager(); + manager = createManager(); final StringBuilder literalBuilder = new StringBuilder("literals"); diff --git a/cloud-core/src/test/java/cloud/commandframework/ParameterInjectorRegistryTest.java b/cloud-core/src/test/java/cloud/commandframework/ParameterInjectorRegistryTest.java index 54b4d6ec9..e0ca15612 100644 --- a/cloud-core/src/test/java/cloud/commandframework/ParameterInjectorRegistryTest.java +++ b/cloud-core/src/test/java/cloud/commandframework/ParameterInjectorRegistryTest.java @@ -23,6 +23,10 @@ // package cloud.commandframework; +import static com.google.common.truth.Truth8.assertThat; + +import static cloud.commandframework.util.TestUtils.createManager; + import cloud.commandframework.annotations.AnnotationAccessor; import cloud.commandframework.annotations.injection.GuiceInjectionService; import cloud.commandframework.annotations.injection.ParameterInjectorRegistry; @@ -50,7 +54,7 @@ public class ParameterInjectorRegistryTest { @BeforeEach void setup() { this.commandSender = new TestCommandSender(); - this.commandManager = new TestCommandManager(); + this.commandManager = createManager(); this.commandContextFactory = new StandardCommandContextFactory<>(); this.parameterInjectorRegistry = new ParameterInjectorRegistry<>(); this.parameterInjectorRegistry.registerInjector(Integer.class, (context, annotationAccessor) -> INJECTED_INTEGER); @@ -64,30 +68,37 @@ void setup() { @Test void testSimpleInjection() { - Assertions.assertEquals(INJECTED_INTEGER, parameterInjectorRegistry.getInjectable( - Integer.class, - this.createContext(), - AnnotationAccessor.empty() - ).orElse(-1)); + assertThat( + parameterInjectorRegistry.getInjectable( + Integer.class, + this.createContext(), + AnnotationAccessor.empty() + ) + ).hasValue(INJECTED_INTEGER); } @Test void testGuiceInjection() { this.parameterInjectorRegistry.registerInjectionService(GuiceInjectionService.create(this.injector)); - Assertions.assertEquals(TestModule.INJECTED_INTEGER, parameterInjectorRegistry.getInjectable( - Integer.class, - this.createContext(), - AnnotationAccessor.empty() - ).orElse(-1)); + + assertThat( + parameterInjectorRegistry.getInjectable( + Integer.class, + this.createContext(), + AnnotationAccessor.empty() + ) + ).hasValue(TestModule.INJECTED_INTEGER); } @Test void testNonExistentInjection() { - Assertions.assertNull(parameterInjectorRegistry.getInjectable( - String.class, - this.createContext(), - AnnotationAccessor.empty() - ).orElse(null)); + assertThat( + parameterInjectorRegistry.getInjectable( + String.class, + this.createContext(), + AnnotationAccessor.empty() + ) + ).isEmpty(); } private static final class TestModule extends AbstractModule { diff --git a/cloud-core/src/test/java/cloud/commandframework/ParserRegistryTest.java b/cloud-core/src/test/java/cloud/commandframework/ParserRegistryTest.java index 058d62284..af16909dc 100644 --- a/cloud-core/src/test/java/cloud/commandframework/ParserRegistryTest.java +++ b/cloud-core/src/test/java/cloud/commandframework/ParserRegistryTest.java @@ -23,6 +23,9 @@ // package cloud.commandframework; +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth8.assertThat; + import cloud.commandframework.annotations.specifier.Range; import cloud.commandframework.arguments.parser.ArgumentParser; import cloud.commandframework.arguments.parser.ParserParameters; @@ -31,7 +34,10 @@ import cloud.commandframework.arguments.parser.StandardParserRegistry; import cloud.commandframework.arguments.standard.IntegerArgument; import io.leangen.geantyref.TypeToken; -import org.junit.jupiter.api.Assertions; + +import java.util.Optional; + +import org.checkerframework.checker.nullness.qual.NonNull; import org.junit.jupiter.api.Test; import java.lang.annotation.Annotation; @@ -40,70 +46,105 @@ public class ParserRegistryTest { - public static final int RANGE_MIN = 10; - public static final int RANGE_MAX = 100; + private static final int RANGE_MIN = 10; + private static final int RANGE_MAX = 100; + private static final Range RANGE = new Range() { - @SuppressWarnings("ReturnValueIgnored") - @Test - void testParserRegistry() { - final ParserRegistry parserRegistry = new StandardParserRegistry<>(); - final Range range = new Range() { + @Override + public Class annotationType() { + return Range.class; + } - @Override - public Class annotationType() { - return Range.class; - } + @Override + public @NonNull String min() { + return Integer.toString(RANGE_MIN); + } - @Override - public String min() { - return Integer.toString(RANGE_MIN); - } + @Override + public @NonNull String max() { + return Integer.toString(RANGE_MAX); + } - @Override - public String max() { - return Integer.toString(RANGE_MAX); + @Override + public boolean equals(final Object obj) { + if (!(obj instanceof Range)) { + return false; } + final Range range = (Range) obj; + return this.min().equals(range.min()) && this.max().equals(range.max()); + } - @Override - public boolean equals(final Object obj) { - if (!(obj instanceof Range)) { - return false; - } - final Range range = (Range) obj; - return this.min().equals(range.min()) && this.max().equals(range.max()); - } + @Override + public int hashCode() { + return Objects.hash(this.min(), this.max()); + } + }; - @Override - public int hashCode() { - return Objects.hash(this.min(), this.max()); - } - }; + @Test + void parsing_range_annotation_results_in_correct_parser_parameters() { + // Given + final ParserRegistry parserRegistry = new StandardParserRegistry<>(); + final TypeToken parsedType = TypeToken.get(int.class); + // When + final ParserParameters parserParameters = parserRegistry.parseAnnotations(parsedType, Collections.singleton(RANGE)); + // Then + assertThat(parserParameters.has(StandardParameters.RANGE_MIN)).isTrue(); + assertThat(parserParameters.has(StandardParameters.RANGE_MAX)).isTrue(); + } + + @Test + void creating_integer_parser_from_parameters_results_in_correct_parser() { + final ParserRegistry parserRegistry = new StandardParserRegistry<>(); final TypeToken parsedType = TypeToken.get(int.class); - final ParserParameters parserParameters = parserRegistry.parseAnnotations(parsedType, Collections.singleton(range)); - Assertions.assertTrue(parserParameters.has(StandardParameters.RANGE_MIN)); - Assertions.assertTrue(parserParameters.has(StandardParameters.RANGE_MAX)); + + final ParserParameters parserParameters = ParserParameters.empty(); + parserParameters.store(StandardParameters.RANGE_MIN, RANGE_MIN); + parserParameters.store(StandardParameters.RANGE_MAX, RANGE_MAX); + final ArgumentParser parser = parserRegistry.createParser( - parsedType, - parserParameters - ) - .orElseThrow( - () -> new NullPointerException( - "No parser found")); - Assertions.assertTrue(parser instanceof IntegerArgument.IntegerParser); + parsedType, + parserParameters + ).orElseThrow(() -> new NullPointerException("No parser found")); + + assertThat(parser).isInstanceOf(IntegerArgument.IntegerParser.class); + @SuppressWarnings("unchecked") final IntegerArgument.IntegerParser integerParser = (IntegerArgument.IntegerParser) parser; - Assertions.assertEquals(RANGE_MIN, integerParser.getMin()); - Assertions.assertEquals(RANGE_MAX, integerParser.getMax()); - /* Test integer */ - parserRegistry.createParser(TypeToken.get(int.class), ParserParameters.empty()) - .orElseThrow(() -> new IllegalArgumentException("No parser found for int.class")); + assertThat(integerParser.getMin()).isEqualTo(RANGE_MIN); + assertThat(integerParser.getMax()).isEqualTo(RANGE_MAX); + } + + @Test + void retrieving_integer_parser_from_parser_registry() { + // Given + final ParserRegistry parserRegistry = new StandardParserRegistry<>(); + + // When + final Optional parserOptional = parserRegistry.createParser( + TypeToken.get(int.class), + ParserParameters.empty() + ); + + // Then + assertThat(parserOptional).isPresent(); + } + + @Test + void retrieving_enum_parser_from_registry() { + // Given + final ParserRegistry parserRegistry = new StandardParserRegistry<>(); + + // When + final Optional parserOptional = parserRegistry.createParser( + TypeToken.get(CommandManager.ManagerSettings.class), + ParserParameters.empty() + ); - /* Test Enum */ - parserRegistry.createParser(TypeToken.get(CommandManager.ManagerSettings.class), ParserParameters.empty()) - .orElseThrow(() -> new IllegalArgumentException("No parser found for enum")); + // Then + assertThat(parserOptional).isPresent(); } } diff --git a/cloud-core/src/test/java/cloud/commandframework/TestCommandManager.java b/cloud-core/src/test/java/cloud/commandframework/TestCommandManager.java deleted file mode 100644 index 47de43535..000000000 --- a/cloud-core/src/test/java/cloud/commandframework/TestCommandManager.java +++ /dev/null @@ -1,52 +0,0 @@ -// -// MIT License -// -// Copyright (c) 2021 Alexander Söderberg & Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -package cloud.commandframework; - -import cloud.commandframework.execution.CommandExecutionCoordinator; -import cloud.commandframework.internal.CommandRegistrationHandler; -import cloud.commandframework.meta.SimpleCommandMeta; - -public class TestCommandManager extends CommandManager { - - /** - * Construct a new test command manager - */ - public TestCommandManager() { - super(CommandExecutionCoordinator.simpleCoordinator(), CommandRegistrationHandler.nullCommandRegistrationHandler()); - } - - - @Override - public final SimpleCommandMeta createDefaultCommandMeta() { - return SimpleCommandMeta.empty(); - } - - @Override - public final boolean hasPermission(final TestCommandSender sender, final String permission) { - System.out.printf("Testing permission: %s\n", permission); - return !permission.equalsIgnoreCase("no"); - } - -} - diff --git a/cloud-core/src/test/java/cloud/commandframework/TestCommandSender.java b/cloud-core/src/test/java/cloud/commandframework/TestCommandSender.java index 43fe3fd17..07368e91c 100644 --- a/cloud-core/src/test/java/cloud/commandframework/TestCommandSender.java +++ b/cloud-core/src/test/java/cloud/commandframework/TestCommandSender.java @@ -41,7 +41,6 @@ public boolean hasPermisison(final String permission) { return this.permissions.contains(permission); } - public void addPermission(final String permission) { this.permissions.add(permission); } diff --git a/cloud-core/src/test/java/cloud/commandframework/arguments/standard/StringArgumentTest.java b/cloud-core/src/test/java/cloud/commandframework/arguments/standard/StringArgumentTest.java index 4178cd3a2..e7fcbbe02 100644 --- a/cloud-core/src/test/java/cloud/commandframework/arguments/standard/StringArgumentTest.java +++ b/cloud-core/src/test/java/cloud/commandframework/arguments/standard/StringArgumentTest.java @@ -23,9 +23,12 @@ // package cloud.commandframework.arguments.standard; +import static com.google.common.truth.Truth.assertThat; +import static cloud.commandframework.util.TestUtils.createManager; + import cloud.commandframework.CommandManager; -import cloud.commandframework.TestCommandManager; import cloud.commandframework.TestCommandSender; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -39,7 +42,7 @@ class StringArgumentTest { @BeforeAll static void setup() { - manager = new TestCommandManager(); + manager = createManager(); manager.command(manager.commandBuilder("quoted") .argument(StringArgument.of("message1", StringArgument.StringMode.QUOTED)) .argument(StringArgument.of("message2")) @@ -66,32 +69,44 @@ static void setup() { .build()); } - private static void clear() { + @AfterEach + void reset() { storage[0] = storage[1] = null; } @Test - void testSingle() { - clear(); - manager.executeCommand(new TestCommandSender(), "single string"); - Assertions.assertEquals("string", storage[0]); + void single_single() { + manager.executeCommand(new TestCommandSender(), "single string").join(); + + assertThat(storage[0]).isEqualTo("string"); } @Test - void testQuotes() { - clear(); + void quoted_single_quoted_string_containing_double_quote_followed_by_unquoted() { manager.executeCommand(new TestCommandSender(), "quoted 'quoted \" string' unquoted").join(); - Assertions.assertEquals("quoted \" string", storage[0]); - Assertions.assertEquals("unquoted", storage[1]); - clear(); - manager.executeCommand(new TestCommandSender(), "quoted quoted unquoted"); - Assertions.assertEquals("quoted", storage[0]); - Assertions.assertEquals("unquoted", storage[1]); - clear(); + + assertThat(storage[0]).isEqualTo("quoted \" string"); + assertThat(storage[1]).isEqualTo("unquoted"); + } + + @Test + void quoted_unquoted_strings() { + manager.executeCommand(new TestCommandSender(), "quoted quoted unquoted").join(); + + assertThat(storage[0]).isEqualTo("quoted"); + assertThat(storage[1]).isEqualTo("unquoted"); + } + + @Test + void quoted_quoted_string_containing_escaped_quote_followed_by_unquoted() { manager.executeCommand(new TestCommandSender(), "quoted \"quoted \\\" string\" unquoted").join(); - Assertions.assertEquals("quoted \" string", storage[0]); - Assertions.assertEquals("unquoted", storage[1]); - clear(); + + assertThat(storage[0]).isEqualTo("quoted \" string"); + assertThat(storage[1]).isEqualTo("unquoted"); + } + + @Test + void quoted_unmatched_quotes_failing() { Assertions.assertThrows(CompletionException.class, () -> manager.executeCommand( new TestCommandSender(), "'quoted quoted unquoted" @@ -99,10 +114,10 @@ void testQuotes() { } @Test - void testGreedy() { - clear(); + void greedy_consumes_all() { manager.executeCommand(new TestCommandSender(), "greedy greedy string content").join(); - Assertions.assertEquals("greedy string content", storage[0]); + + assertThat(storage[0]).isEqualTo("greedy string content"); } } diff --git a/cloud-core/src/test/java/cloud/commandframework/util/TestUtils.java b/cloud-core/src/test/java/cloud/commandframework/util/TestUtils.java new file mode 100644 index 000000000..e59f6e280 --- /dev/null +++ b/cloud-core/src/test/java/cloud/commandframework/util/TestUtils.java @@ -0,0 +1,90 @@ +// +// MIT License +// +// Copyright (c) 2021 Alexander Söderberg & Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +package cloud.commandframework.util; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.withSettings; + +import cloud.commandframework.CommandManager; +import cloud.commandframework.CommandTree; +import cloud.commandframework.TestCommandSender; +import cloud.commandframework.execution.CommandExecutionCoordinator; +import cloud.commandframework.internal.CommandRegistrationHandler; +import cloud.commandframework.meta.SimpleCommandMeta; + +import java.util.function.Function; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.mockito.Mockito; + +public final class TestUtils { + + /** + * A permission value which always returns {@code false}. + */ + public static final String FAILING_PERMISSION = "no"; + + private TestUtils() { + } + + private abstract static class TestCommandSenderCommandManager extends CommandManager { + + protected TestCommandSenderCommandManager( + final @NonNull Function<@NonNull CommandTree, @NonNull CommandExecutionCoordinator> commandExecutionCoordinator, + final @NonNull CommandRegistrationHandler commandRegistrationHandler + ) { + super(commandExecutionCoordinator, commandRegistrationHandler); + } + + } + + /** + * Creates a {@link CommandManager} that can be used for testing. + * + * @return Mocked command manager. + */ + public static @NonNull CommandManager createManager() { + final CommandManager manager = mock( + TestCommandSenderCommandManager.class, + withSettings().useConstructor( + CommandExecutionCoordinator.simpleCoordinator(), + CommandRegistrationHandler.nullCommandRegistrationHandler() + ).defaultAnswer(Mockito.CALLS_REAL_METHODS) + ); + + // We don't care about the actual command meta. + when(manager.createDefaultCommandMeta()).thenReturn(SimpleCommandMeta.empty()); + + // The permission check should always return true, unless "no" is the parameter. + when(manager.hasPermission(any(), anyString())).thenReturn(true); + when(manager.hasPermission(any(), eq(FAILING_PERMISSION))).thenReturn(false); + + return manager; + } + +}