|
|
|
|
@@ -16,17 +16,31 @@
|
|
|
|
|
|
|
|
|
|
package org.springframework.cloud.function.context.catalog;
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.function.Function;
|
|
|
|
|
import java.util.function.Supplier;
|
|
|
|
|
|
|
|
|
|
import com.google.gson.Gson;
|
|
|
|
|
import org.junit.Before;
|
|
|
|
|
import org.junit.Ignore;
|
|
|
|
|
import org.junit.Test;
|
|
|
|
|
import reactor.core.publisher.Flux;
|
|
|
|
|
|
|
|
|
|
import org.springframework.cloud.function.context.FunctionRegistration;
|
|
|
|
|
import org.springframework.cloud.function.context.FunctionType;
|
|
|
|
|
import org.springframework.cloud.function.core.FluxFunction;
|
|
|
|
|
import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper;
|
|
|
|
|
import org.springframework.cloud.function.context.config.JsonMessageConverter;
|
|
|
|
|
import org.springframework.cloud.function.context.config.NegotiatingMessageConverterWrapper;
|
|
|
|
|
import org.springframework.cloud.function.json.GsonMapper;
|
|
|
|
|
import org.springframework.cloud.function.json.JsonMapper;
|
|
|
|
|
import org.springframework.core.convert.ConversionService;
|
|
|
|
|
import org.springframework.core.convert.support.DefaultConversionService;
|
|
|
|
|
import org.springframework.messaging.Message;
|
|
|
|
|
import org.springframework.messaging.converter.ByteArrayMessageConverter;
|
|
|
|
|
import org.springframework.messaging.converter.CompositeMessageConverter;
|
|
|
|
|
import org.springframework.messaging.converter.MessageConverter;
|
|
|
|
|
import org.springframework.messaging.converter.StringMessageConverter;
|
|
|
|
|
import org.springframework.messaging.support.MessageBuilder;
|
|
|
|
|
|
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
|
|
@@ -35,37 +49,40 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|
|
|
|
* @author Oleg Zhurakousky
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public class InMemoryFunctionCatalogTests {
|
|
|
|
|
public class SimpleFunctionRegistryTests {
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
@Ignore // we no longer have a need to register the actual target function as it is contained within wrapper
|
|
|
|
|
public void testFunctionRegistration() {
|
|
|
|
|
TestFunction function = new TestFunction();
|
|
|
|
|
FunctionRegistration<TestFunction> registration = new FunctionRegistration<>(
|
|
|
|
|
function, "foo").type(FunctionType.of(TestFunction.class));
|
|
|
|
|
InMemoryFunctionCatalog catalog = new InMemoryFunctionCatalog();
|
|
|
|
|
catalog.register(registration);
|
|
|
|
|
FunctionRegistration<?> registration2 = catalog.getRegistration(function);
|
|
|
|
|
assertThat(registration2.getType()).isEqualTo(registration.getType());
|
|
|
|
|
private CompositeMessageConverter messageConverter;
|
|
|
|
|
|
|
|
|
|
private ConversionService conversionService;
|
|
|
|
|
|
|
|
|
|
@Before
|
|
|
|
|
public void before() {
|
|
|
|
|
List<MessageConverter> messageConverters = new ArrayList<>();
|
|
|
|
|
JsonMapper jsonMapper = new GsonMapper(new Gson());
|
|
|
|
|
messageConverters.add(NegotiatingMessageConverterWrapper.wrap(new JsonMessageConverter(jsonMapper)));
|
|
|
|
|
messageConverters.add(NegotiatingMessageConverterWrapper.wrap(new ByteArrayMessageConverter()));
|
|
|
|
|
messageConverters.add(NegotiatingMessageConverterWrapper.wrap(new StringMessageConverter()));
|
|
|
|
|
this.messageConverter = new CompositeMessageConverter(messageConverters);
|
|
|
|
|
|
|
|
|
|
this.conversionService = new DefaultConversionService();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testFunctionLookup() {
|
|
|
|
|
|
|
|
|
|
TestFunction function = new TestFunction();
|
|
|
|
|
FunctionRegistration<TestFunction> registration = new FunctionRegistration<>(
|
|
|
|
|
function, "foo").type(FunctionType.of(TestFunction.class));
|
|
|
|
|
InMemoryFunctionCatalog catalog = new InMemoryFunctionCatalog();
|
|
|
|
|
SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter);
|
|
|
|
|
catalog.register(registration);
|
|
|
|
|
|
|
|
|
|
Object lookedUpFunction = catalog.lookup("hello");
|
|
|
|
|
FunctionInvocationWrapper lookedUpFunction = catalog.lookup("hello");
|
|
|
|
|
assertThat(lookedUpFunction).isNotNull(); // becouse we only have one and can look it up with any name
|
|
|
|
|
FunctionRegistration<TestFunction> registration2 = new FunctionRegistration<>(
|
|
|
|
|
function, "foo2").type(FunctionType.of(TestFunction.class));
|
|
|
|
|
catalog.register(registration2);
|
|
|
|
|
lookedUpFunction = catalog.lookup("hello");
|
|
|
|
|
assertThat(lookedUpFunction).isNull();
|
|
|
|
|
|
|
|
|
|
lookedUpFunction = catalog.lookup("foo");
|
|
|
|
|
assertThat(lookedUpFunction).isNotNull();
|
|
|
|
|
assertThat(catalog.lookupFunctionName(lookedUpFunction)).isEqualTo("foo");
|
|
|
|
|
assertThat(catalog.getFunctionType("foo").getOutputType())
|
|
|
|
|
.isEqualTo(String.class);
|
|
|
|
|
assertThat(lookedUpFunction instanceof FluxFunction).isTrue();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
@@ -74,50 +91,48 @@ public class InMemoryFunctionCatalogTests {
|
|
|
|
|
new UpperCase(), "uppercase").type(FunctionType.of(UpperCase.class));
|
|
|
|
|
FunctionRegistration<Reverse> reverseRegistration = new FunctionRegistration<>(
|
|
|
|
|
new Reverse(), "reverse").type(FunctionType.of(Reverse.class));
|
|
|
|
|
InMemoryFunctionCatalog catalog = new InMemoryFunctionCatalog();
|
|
|
|
|
SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter);
|
|
|
|
|
catalog.register(upperCaseRegistration);
|
|
|
|
|
catalog.register(reverseRegistration);
|
|
|
|
|
|
|
|
|
|
Function<Flux<String>, Flux<String>> lookedUpFunction = catalog
|
|
|
|
|
.lookup("uppercase|reverse");
|
|
|
|
|
assertThat(catalog.getFunctionType("uppercase|reverse").isMessage()).isFalse();
|
|
|
|
|
|
|
|
|
|
assertThat(lookedUpFunction).isNotNull();
|
|
|
|
|
assertThat(lookedUpFunction.apply(Flux.just("star")).blockFirst())
|
|
|
|
|
.isEqualTo("RATS");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
@Ignore
|
|
|
|
|
public void testFunctionCompositionImplicit() {
|
|
|
|
|
FunctionRegistration<Words> wordsRegistration = new FunctionRegistration<>(
|
|
|
|
|
new Words(), "words").type(FunctionType.of(Words.class));
|
|
|
|
|
FunctionRegistration<Reverse> reverseRegistration = new FunctionRegistration<>(
|
|
|
|
|
new Reverse(), "reverse").type(FunctionType.of(Reverse.class));
|
|
|
|
|
InMemoryFunctionCatalog catalog = new InMemoryFunctionCatalog();
|
|
|
|
|
SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter);
|
|
|
|
|
catalog.register(wordsRegistration);
|
|
|
|
|
catalog.register(reverseRegistration);
|
|
|
|
|
|
|
|
|
|
// There's only one function, we should be able to leave that blank
|
|
|
|
|
Supplier<Flux<String>> lookedUpFunction = catalog.lookup("words|");
|
|
|
|
|
assertThat(catalog.getFunctionType("words|").isMessage()).isFalse();
|
|
|
|
|
|
|
|
|
|
assertThat(lookedUpFunction).isNotNull();
|
|
|
|
|
assertThat(lookedUpFunction.get().blockFirst()).isEqualTo("olleh");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
@Ignore
|
|
|
|
|
public void testFunctionCompletelyImplicitComposition() {
|
|
|
|
|
FunctionRegistration<Words> wordsRegistration = new FunctionRegistration<>(
|
|
|
|
|
new Words(), "words").type(FunctionType.of(Words.class));
|
|
|
|
|
FunctionRegistration<Reverse> reverseRegistration = new FunctionRegistration<>(
|
|
|
|
|
new Reverse(), "reverse").type(FunctionType.of(Reverse.class));
|
|
|
|
|
InMemoryFunctionCatalog catalog = new InMemoryFunctionCatalog();
|
|
|
|
|
SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter);
|
|
|
|
|
catalog.register(wordsRegistration);
|
|
|
|
|
catalog.register(reverseRegistration);
|
|
|
|
|
|
|
|
|
|
// There's only one function, we should be able to leave that blank
|
|
|
|
|
Supplier<Flux<String>> lookedUpFunction = catalog.lookup("|");
|
|
|
|
|
assertThat(catalog.getFunctionType("|").isMessage()).isFalse();
|
|
|
|
|
|
|
|
|
|
assertThat(lookedUpFunction).isNotNull();
|
|
|
|
|
assertThat(lookedUpFunction.get().blockFirst()).isEqualTo("olleh");
|
|
|
|
|
@@ -129,15 +144,14 @@ public class InMemoryFunctionCatalogTests {
|
|
|
|
|
new Words(), "words").type(FunctionType.of(Words.class));
|
|
|
|
|
FunctionRegistration<Reverse> reverseRegistration = new FunctionRegistration<>(
|
|
|
|
|
new Reverse(), "reverse").type(FunctionType.of(Reverse.class));
|
|
|
|
|
InMemoryFunctionCatalog catalog = new InMemoryFunctionCatalog();
|
|
|
|
|
SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter);
|
|
|
|
|
catalog.register(wordsRegistration);
|
|
|
|
|
catalog.register(reverseRegistration);
|
|
|
|
|
|
|
|
|
|
Supplier<Flux<String>> lookedUpFunction = catalog.lookup("words|reverse");
|
|
|
|
|
assertThat(catalog.getFunctionType("words|reverse").isMessage()).isFalse();
|
|
|
|
|
Supplier<String> lookedUpFunction = catalog.lookup("words|reverse");
|
|
|
|
|
|
|
|
|
|
assertThat(lookedUpFunction).isNotNull();
|
|
|
|
|
assertThat(lookedUpFunction.get().blockFirst()).isEqualTo("olleh");
|
|
|
|
|
assertThat(lookedUpFunction.get()).isEqualTo("olleh");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
@@ -148,15 +162,12 @@ public class InMemoryFunctionCatalogTests {
|
|
|
|
|
FunctionRegistration<ReverseMessage> reverseRegistration = new FunctionRegistration<>(
|
|
|
|
|
new ReverseMessage(), "reverse")
|
|
|
|
|
.type(FunctionType.of(ReverseMessage.class));
|
|
|
|
|
InMemoryFunctionCatalog catalog = new InMemoryFunctionCatalog();
|
|
|
|
|
SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter);
|
|
|
|
|
catalog.register(upperCaseRegistration);
|
|
|
|
|
catalog.register(reverseRegistration);
|
|
|
|
|
|
|
|
|
|
Function<Flux<Message<String>>, Flux<Message<String>>> lookedUpFunction = catalog
|
|
|
|
|
.lookup("uppercase|reverse");
|
|
|
|
|
assertThat(catalog.getFunctionType("uppercase|reverse").isMessage()).isTrue();
|
|
|
|
|
assertThat(catalog.lookupFunctionName(lookedUpFunction))
|
|
|
|
|
.isEqualTo("uppercase|reverse");
|
|
|
|
|
|
|
|
|
|
assertThat(lookedUpFunction).isNotNull();
|
|
|
|
|
assertThat(lookedUpFunction
|
|
|
|
|
@@ -171,20 +182,16 @@ public class InMemoryFunctionCatalogTests {
|
|
|
|
|
.type(FunctionType.of(UpperCaseMessage.class));
|
|
|
|
|
FunctionRegistration<Reverse> reverseRegistration = new FunctionRegistration<>(
|
|
|
|
|
new Reverse(), "reverse").type(FunctionType.of(Reverse.class));
|
|
|
|
|
InMemoryFunctionCatalog catalog = new InMemoryFunctionCatalog();
|
|
|
|
|
SimpleFunctionRegistry catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter);
|
|
|
|
|
catalog.register(upperCaseRegistration);
|
|
|
|
|
catalog.register(reverseRegistration);
|
|
|
|
|
|
|
|
|
|
Function<Flux<Message<String>>, Flux<Message<String>>> lookedUpFunction = catalog
|
|
|
|
|
Function<Message<String>, String> lookedUpFunction = catalog
|
|
|
|
|
.lookup("uppercase|reverse");
|
|
|
|
|
assertThat(catalog.getFunctionType("uppercase|reverse").isMessage()).isTrue();
|
|
|
|
|
|
|
|
|
|
assertThat(lookedUpFunction).isNotNull();
|
|
|
|
|
Message<String> message = lookedUpFunction.apply(Flux
|
|
|
|
|
.just(MessageBuilder.withPayload("star").setHeader("foo", "bar").build()))
|
|
|
|
|
.blockFirst();
|
|
|
|
|
assertThat(message.getPayload()).isEqualTo("RATS");
|
|
|
|
|
assertThat(message.getHeaders().get("foo")).isEqualTo("bar");
|
|
|
|
|
String result = lookedUpFunction.apply(MessageBuilder.withPayload("star").setHeader("foo", "bar").build());
|
|
|
|
|
assertThat(result).isEqualTo("RATS");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static class Words implements Supplier<String> {
|