Skip to content

Commit 375c5e7

Browse files
committed
Adds reproducer for protobuf msg conversion issue (#1094)
Conversion of protobuf messages fails if the encoded message looks like a JSON string. Added a test that reproduces the issue.
1 parent 062db0b commit 375c5e7

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

spring-cloud-function-context/pom.xml

+8
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@
109109
<optional>true</optional>
110110
</dependency>
111111

112+
<!-- Protobuf -->
113+
<dependency>
114+
<groupId>com.google.protobuf</groupId>
115+
<artifactId>protobuf-java</artifactId>
116+
<version>3.25.1</version>
117+
<scope>test</scope>
118+
</dependency>
119+
112120
<!-- Actuator -->
113121
<dependency>
114122
<groupId>org.springframework.boot</groupId>

spring-cloud-function-context/src/test/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistryTests.java

+38
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.cloud.function.context.catalog;
1818

19+
import java.io.ByteArrayOutputStream;
20+
import java.io.IOException;
1921
import java.lang.reflect.Field;
2022
import java.lang.reflect.Type;
2123
import java.util.ArrayList;
@@ -28,6 +30,7 @@
2830
import java.util.concurrent.ExecutorService;
2931
import java.util.concurrent.Executors;
3032
import java.util.concurrent.atomic.AtomicInteger;
33+
import java.util.concurrent.atomic.AtomicReference;
3134
import java.util.function.BiConsumer;
3235
import java.util.function.Consumer;
3336
import java.util.function.Function;
@@ -37,6 +40,7 @@
3740

3841
import com.fasterxml.jackson.databind.ObjectMapper;
3942
import com.google.gson.Gson;
43+
import com.google.protobuf.StringValue;
4044
import org.junit.jupiter.api.Assertions;
4145
import org.junit.jupiter.api.BeforeEach;
4246
import org.junit.jupiter.api.Disabled;
@@ -72,12 +76,14 @@
7276
import org.springframework.messaging.converter.ByteArrayMessageConverter;
7377
import org.springframework.messaging.converter.CompositeMessageConverter;
7478
import org.springframework.messaging.converter.MessageConverter;
79+
import org.springframework.messaging.converter.ProtobufMessageConverter;
7580
import org.springframework.messaging.converter.StringMessageConverter;
7681
import org.springframework.messaging.support.MessageBuilder;
7782
import org.springframework.util.MimeType;
7883
import org.springframework.util.ReflectionUtils;
7984

8085
import static org.assertj.core.api.Assertions.assertThat;
86+
import static org.assertj.core.api.Assertions.assertThatNoException;
8187

8288
/**
8389
* @author Oleg Zhurakousky
@@ -97,6 +103,7 @@ public void before() {
97103
messageConverters.add(new JsonMessageConverter(jsonMapper));
98104
messageConverters.add(new ByteArrayMessageConverter());
99105
messageConverters.add(new StringMessageConverter());
106+
messageConverters.add(new ProtobufMessageConverter());
100107
this.messageConverter = new SmartCompositeMessageConverter(messageConverters);
101108

102109
this.conversionService = new DefaultConversionService();
@@ -207,6 +214,37 @@ void textContentTypeWithValueWrappedBracketsIsOk(String inputMessagePayloadValue
207214
assertThat(functionResult).isEqualTo(inputMessagePayloadValue);
208215
}
209216

217+
@ParameterizedTest
218+
@ValueSource(strings = {
219+
"aaaaaaaaaa", // no problem
220+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]" // protobuf encoder prepends '[' for length (91 bytes)
221+
})
222+
public void testSCF1094(String stringValue) throws IOException {
223+
224+
Function<StringValue, String> getValue = msg -> msg != null ? msg.getValue() : null;
225+
Type functionType = ResolvableType.forClassWithGenerics(Function.class, ResolvableType.forClass(StringValue.class), ResolvableType.forClass(String.class)).getType();
226+
227+
var catalog = new SimpleFunctionRegistry(this.conversionService, this.messageConverter, new JacksonMapper(new ObjectMapper()));
228+
catalog.register(new FunctionRegistration<>(getValue, "getValue").type(functionType));
229+
FunctionInvocationWrapper lookedUpFunction = catalog.lookup("getValue");
230+
231+
ByteArrayOutputStream payload = new ByteArrayOutputStream();
232+
StringValue.newBuilder()
233+
.setValue(stringValue)
234+
.build()
235+
.writeTo(payload);
236+
237+
var inputMessage = MessageBuilder.withPayload(payload.toByteArray())
238+
.setHeader("contentType", "application/x-protobuf")
239+
.build();
240+
241+
final AtomicReference<Object> result = new AtomicReference<>();
242+
assertThatNoException().isThrownBy(() -> {
243+
result.set(lookedUpFunction.apply(inputMessage));
244+
});
245+
assertThat(result.get()).isEqualTo(stringValue);
246+
}
247+
210248
@SuppressWarnings("unchecked")
211249
@Test
212250
public void testSCF762() {

0 commit comments

Comments
 (0)