Skip to content

Commit f17e20d

Browse files
committed
Adds reproducer for protobuf msg conversion issue (spring-cloud#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 f17e20d

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

spring-cloud-function-context/pom.xml

Lines changed: 8 additions & 0 deletions
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

Lines changed: 34 additions & 0 deletions
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;
@@ -37,13 +39,15 @@
3739

3840
import com.fasterxml.jackson.databind.ObjectMapper;
3941
import com.google.gson.Gson;
42+
import com.google.protobuf.StringValue;
4043
import org.junit.jupiter.api.Assertions;
4144
import org.junit.jupiter.api.BeforeEach;
4245
import org.junit.jupiter.api.Disabled;
4346
import org.junit.jupiter.api.Test;
4447
import org.junit.jupiter.params.ParameterizedTest;
4548
import org.junit.jupiter.params.provider.ValueSource;
4649
import org.reactivestreams.Publisher;
50+
import org.springframework.messaging.converter.ProtobufMessageConverter;
4751
import reactor.core.publisher.Flux;
4852
import reactor.core.publisher.Mono;
4953

@@ -78,6 +82,7 @@
7882
import org.springframework.util.ReflectionUtils;
7983

8084
import static org.assertj.core.api.Assertions.assertThat;
85+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
8186

8287
/**
8388
* @author Oleg Zhurakousky
@@ -97,6 +102,7 @@ public void before() {
97102
messageConverters.add(new JsonMessageConverter(jsonMapper));
98103
messageConverters.add(new ByteArrayMessageConverter());
99104
messageConverters.add(new StringMessageConverter());
105+
messageConverters.add(new ProtobufMessageConverter());
100106
this.messageConverter = new SmartCompositeMessageConverter(messageConverters);
101107

102108
this.conversionService = new DefaultConversionService();
@@ -207,6 +213,34 @@ void textContentTypeWithValueWrappedBracketsIsOk(String inputMessagePayloadValue
207213
assertThat(functionResult).isEqualTo(inputMessagePayloadValue);
208214
}
209215

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

0 commit comments

Comments
 (0)