// // 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.services; import cloud.commandframework.services.mock.AnnotatedMethodTest; import cloud.commandframework.services.mock.CompletingPartialResultService; import cloud.commandframework.services.mock.DefaultMockService; import cloud.commandframework.services.mock.DefaultPartialRequestService; import cloud.commandframework.services.mock.DefaultSideEffectService; import cloud.commandframework.services.mock.InterruptingMockConsumer; import cloud.commandframework.services.mock.MockChunkedRequest; import cloud.commandframework.services.mock.MockConsumerService; import cloud.commandframework.services.mock.MockOrderedFirst; import cloud.commandframework.services.mock.MockOrderedLast; import cloud.commandframework.services.mock.MockPartialResultService; import cloud.commandframework.services.mock.MockResultConsumer; import cloud.commandframework.services.mock.MockService; import cloud.commandframework.services.mock.MockSideEffectService; import cloud.commandframework.services.mock.SecondaryMockService; import cloud.commandframework.services.mock.SecondaryMockSideEffectService; import cloud.commandframework.services.mock.StateSettingConsumerService; import cloud.commandframework.services.types.Service; import io.leangen.geantyref.GenericTypeReflector; import io.leangen.geantyref.TypeToken; import java.lang.reflect.Type; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.Map; import java.util.UUID; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; public class ServicesTest { @Test public void testPipeline() throws Exception { final ServicePipeline servicePipeline = ServicePipeline.builder().build(); Assertions.assertNotNull(servicePipeline); servicePipeline .registerServiceType(TypeToken.get(MockService.class), new DefaultMockService()); Assertions.assertThrows(IllegalArgumentException.class, () -> servicePipeline .registerServiceType(TypeToken.get(MockService.class), new DefaultMockService())); final SecondaryMockService secondaryMockService = new SecondaryMockService(); servicePipeline .registerServiceImplementation(TypeToken.get(MockService.class), secondaryMockService, Collections.singleton(secondaryMockService) ); servicePipeline.registerServiceImplementation( MockService.class, mockContext -> new MockService.MockResult(-91), Collections.singleton(mockContext -> mockContext.getString().startsWith("-91")) ); Assertions.assertEquals( 32, servicePipeline.pump(new MockService.MockContext("Hello")).through(MockService.class) .getResult().getInteger() ); servicePipeline.pump(new MockService.MockContext("Hello")).through(MockService.class) .getResult( (mockResult, throwable) -> Assertions.assertEquals(32, mockResult.getInteger())); Assertions.assertEquals( 999, servicePipeline.pump(new MockService.MockContext("potato")).through(MockService.class) .getResult().getInteger() ); Assertions.assertEquals( -91, servicePipeline.pump(new MockService.MockContext("-91")).through(MockService.class) .getResult().getInteger() ); Assertions.assertNotNull( servicePipeline.pump(new MockService.MockContext("oi")).through(MockService.class) .getResultAsynchronously().get()); } @Test public void testSideEffectServices() { final ServicePipeline servicePipeline = ServicePipeline.builder().build(); servicePipeline.registerServiceType( TypeToken.get(MockSideEffectService.class), new DefaultSideEffectService() ); final MockSideEffectService.MockPlayer mockPlayer = new MockSideEffectService.MockPlayer(20); Assertions.assertEquals(20, mockPlayer.getHealth()); Assertions.assertEquals( State.ACCEPTED, servicePipeline.pump(mockPlayer).through(MockSideEffectService.class).getResult() ); Assertions.assertEquals(0, mockPlayer.getHealth()); mockPlayer.setHealth(20); servicePipeline.registerServiceImplementation(MockSideEffectService.class, new SecondaryMockSideEffectService(), Collections.emptyList() ); Assertions.assertThrows( IllegalStateException.class, () -> servicePipeline.pump(mockPlayer).through(MockSideEffectService.class) .getResult() ); } @Test public void testForwarding() throws Exception { final ServicePipeline servicePipeline = ServicePipeline.builder().build() .registerServiceType( TypeToken.get(MockService.class), new DefaultMockService() ) .registerServiceType( TypeToken.get(MockResultConsumer.class), new MockResultConsumer() ); Assertions.assertEquals( State.ACCEPTED, servicePipeline.pump(new MockService.MockContext("huh")).through(MockService.class) .forward().through(MockResultConsumer.class).getResult() ); Assertions.assertEquals( State.ACCEPTED, servicePipeline.pump(new MockService.MockContext("Something")) .through(MockService.class).forwardAsynchronously() .thenApply(pump -> pump.through(MockResultConsumer.class)) .thenApply(ServiceSpigot::getResult).get() ); } @Test public void testSorting() { final ServicePipeline servicePipeline = ServicePipeline.builder().build() .registerServiceType( TypeToken.get(MockService.class), new DefaultMockService() ); servicePipeline.registerServiceImplementation(MockService.class, new MockOrderedFirst(), Collections.emptyList() ); servicePipeline.registerServiceImplementation(MockService.class, new MockOrderedLast(), Collections.emptyList() ); // Test that the annotations worked Assertions.assertEquals( 1, servicePipeline.pump(new MockService.MockContext("")).through(MockService.class) .getResult().getInteger() ); } @Test public void testRecognisedTypes() { final ServicePipeline servicePipeline = ServicePipeline.builder().build() .registerServiceType( TypeToken.get(MockService.class), new DefaultMockService() ); Assertions.assertEquals(1, servicePipeline.getRecognizedTypes().size()); } @Test public void testImplementationGetters() { final ServicePipeline servicePipeline = ServicePipeline.builder().build() .registerServiceType( TypeToken.get(MockService.class), new DefaultMockService() ); servicePipeline.registerServiceImplementation(MockService.class, new MockOrderedFirst(), Collections.emptyList() ); servicePipeline.registerServiceImplementation(MockService.class, new MockOrderedLast(), Collections.emptyList() ); final TypeToken> first = TypeToken.get(MockOrderedFirst.class), last = TypeToken.get(MockOrderedLast.class); final TypeToken mockServiceType = TypeToken.get(MockService.class); for (Type typeToken : servicePipeline.getRecognizedTypes()) { Assertions.assertEquals(mockServiceType.getType(), typeToken); } final Collection>> impls = servicePipeline.getImplementations(mockServiceType); Assertions.assertEquals(3, impls.size()); final Iterator>> iterator = impls.iterator(); Assertions.assertEquals(first, iterator.next()); Assertions.assertEquals(last, iterator.next()); Assertions.assertEquals(DefaultMockService.class, GenericTypeReflector.erase(iterator.next().getType())); } @Test public void testAnnotatedMethods() throws Exception { final ServicePipeline servicePipeline = ServicePipeline.builder().build() .registerServiceType( TypeToken.get(MockService.class), new DefaultMockService() ) .registerMethods(new AnnotatedMethodTest()); final String testString = UUID.randomUUID().toString(); Assertions.assertEquals( testString.length(), servicePipeline.pump(new MockService.MockContext(testString)).through(MockService.class) .getResult().getInteger() ); } @Test public void testConsumerServices() { final ServicePipeline servicePipeline = ServicePipeline.builder().build() .registerServiceType( TypeToken.get(MockConsumerService.class), new StateSettingConsumerService() ) .registerServiceImplementation( MockConsumerService.class, new InterruptingMockConsumer(), Collections.emptyList() ); final MockService.MockContext context = new MockService.MockContext(""); servicePipeline.pump(context).through(MockConsumerService.class).getResult(); Assertions.assertEquals("", context.getState()); } @Test public void testPartialResultServices() { final ServicePipeline servicePipeline = ServicePipeline.builder().build() .registerServiceType( TypeToken.get(MockPartialResultService.class), new DefaultPartialRequestService() ) .registerServiceImplementation( MockPartialResultService.class, new CompletingPartialResultService(), Collections.emptyList() ); final MockChunkedRequest.Animal cow = new MockChunkedRequest.Animal("cow"); final MockChunkedRequest.Animal dog = new MockChunkedRequest.Animal("dog"); final MockChunkedRequest.Animal cat = new MockChunkedRequest.Animal("cat"); final Map sounds = servicePipeline.pump(new MockChunkedRequest(Arrays.asList(cow, dog, cat))) .through(MockPartialResultService.class).getResult(); Assertions.assertEquals("moo", sounds.get(cow).getSound()); Assertions.assertEquals("woof", sounds.get(dog).getSound()); Assertions.assertEquals("unknown", sounds.get(cat).getSound()); } @Test public void testExceptions() { final ServicePipeline servicePipeline = ServicePipeline.builder().build(); Assertions.assertNotNull(servicePipeline); servicePipeline .registerServiceType(TypeToken.get(MockService.class), new DefaultMockService()); final PipelineException pipelineException = Assertions.assertThrows( PipelineException.class, () -> servicePipeline.pump(new MockService.MockContext("pls throw exception")) .through(MockService.class).getResult() ); Assertions.assertEquals( DefaultMockService.TotallyIntentionalException.class, pipelineException.getCause().getClass() ); servicePipeline.pump(new MockService.MockContext("pls throw exception")) .through(MockService.class).getResult((result, throwable) -> { Assertions.assertNotNull(throwable); Assertions.assertEquals( DefaultMockService.TotallyIntentionalException.class, throwable.getClass() ); Assertions.assertNull(result); }); } }