Skip to content

Commit 259b2ca

Browse files
committed
Added tests for errors in the source stream
This commit adds decoder/message-reader tests for errors in the source data buffer publisher. Because the tests extend AbstractDataBufferAllocatingTestCase, they also check whether the buffers that precede the error in the stream are properly released. Issue: SPR-17025
1 parent 196c0ad commit 259b2ca

File tree

6 files changed

+126
-18
lines changed

6 files changed

+126
-18
lines changed

spring-core/src/test/java/org/springframework/core/codec/ByteArrayDecoderTests.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@
2929
import org.springframework.core.io.buffer.DataBuffer;
3030
import org.springframework.util.MimeTypeUtils;
3131

32-
import static org.junit.Assert.assertArrayEquals;
33-
import static org.junit.Assert.assertFalse;
34-
import static org.junit.Assert.assertTrue;
32+
import static org.junit.Assert.*;
3533

3634
/**
3735
* @author Arjen Poutsma
@@ -67,6 +65,21 @@ public void decode() {
6765
.verify();
6866
}
6967

68+
@Test
69+
public void decodeError() {
70+
DataBuffer fooBuffer = stringBuffer("foo");
71+
Flux<DataBuffer> source =
72+
Flux.just(fooBuffer).mergeWith(Flux.error(new RuntimeException()));
73+
Flux<byte[]> output = this.decoder.decode(source,
74+
ResolvableType.forClassWithGenerics(Publisher.class, byte[].class),
75+
null, Collections.emptyMap());
76+
77+
StepVerifier.create(output)
78+
.consumeNextWith(bytes -> assertArrayEquals("foo".getBytes(), bytes))
79+
.expectError()
80+
.verify();
81+
}
82+
7083
@Test
7184
public void decodeToMono() {
7285
DataBuffer fooBuffer = stringBuffer("foo");

spring-core/src/test/java/org/springframework/core/codec/ByteBufferDecoderTests.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -30,8 +30,7 @@
3030
import org.springframework.core.io.buffer.DataBuffer;
3131
import org.springframework.util.MimeTypeUtils;
3232

33-
import static org.junit.Assert.assertFalse;
34-
import static org.junit.Assert.assertTrue;
33+
import static org.junit.Assert.*;
3534

3635
/**
3736
* @author Sebastien Deleuze
@@ -65,6 +64,21 @@ public void decode() {
6564
.verify();
6665
}
6766

67+
@Test
68+
public void decodeError() {
69+
DataBuffer fooBuffer = stringBuffer("foo");
70+
Flux<DataBuffer> source =
71+
Flux.just(fooBuffer).mergeWith(Flux.error(new RuntimeException()));
72+
Flux<ByteBuffer> output = this.decoder.decode(source,
73+
ResolvableType.forClassWithGenerics(Publisher.class, ByteBuffer.class),
74+
null, Collections.emptyMap());
75+
76+
StepVerifier.create(output)
77+
.expectNext(ByteBuffer.wrap("foo".getBytes()))
78+
.expectError()
79+
.verify();
80+
}
81+
6882
@Test
6983
public void decodeToMono() {
7084
DataBuffer fooBuffer = stringBuffer("foo");

spring-core/src/test/java/org/springframework/core/codec/ResourceDecoderTests.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
import org.springframework.util.StreamUtils;
3333

3434
import static org.junit.Assert.*;
35-
import static org.springframework.core.ResolvableType.*;
35+
import static org.springframework.core.ResolvableType.forClass;
3636

3737
/**
3838
* @author Arjen Poutsma
@@ -73,4 +73,19 @@ public void decode() {
7373
.verify();
7474
}
7575

76+
@Test
77+
public void decodeError() {
78+
DataBuffer fooBuffer = stringBuffer("foo");
79+
Flux<DataBuffer> source =
80+
Flux.just(fooBuffer).mergeWith(Flux.error(new RuntimeException()));
81+
82+
83+
Flux<Resource> result = this.decoder
84+
.decode(source, forClass(Resource.class), null, Collections.emptyMap());
85+
86+
StepVerifier.create(result)
87+
.expectError()
88+
.verify();
89+
}
90+
7691
}

spring-core/src/test/java/org/springframework/core/codec/StringDecoderTests.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,22 @@ public void decodeEmptyDataBuffer() {
173173

174174
}
175175

176+
@Test
177+
public void decodeError() {
178+
DataBuffer fooBuffer = stringBuffer("foo\n");
179+
Flux<DataBuffer> source =
180+
Flux.just(fooBuffer).mergeWith(Flux.error(new RuntimeException()));
181+
182+
Flux<String> output = this.decoder.decode(source,
183+
ResolvableType.forClass(String.class), null, Collections.emptyMap());
184+
185+
StepVerifier.create(output)
186+
.expectNext("foo")
187+
.expectError()
188+
.verify();
189+
190+
}
191+
176192
@Test
177193
public void decodeToMono() {
178194
Flux<DataBuffer> source = Flux.just(stringBuffer("foo"), stringBuffer("bar"), stringBuffer("baz"));

spring-web/src/test/java/org/springframework/http/codec/FormHttpMessageReaderTests.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,8 +20,14 @@
2020
import java.util.Map;
2121

2222
import org.junit.Test;
23+
import org.reactivestreams.Publisher;
24+
import reactor.core.publisher.Flux;
25+
import reactor.core.publisher.Mono;
26+
import reactor.test.StepVerifier;
2327

2428
import org.springframework.core.ResolvableType;
29+
import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase;
30+
import org.springframework.core.io.buffer.DataBuffer;
2531
import org.springframework.http.HttpHeaders;
2632
import org.springframework.http.HttpMethod;
2733
import org.springframework.http.MediaType;
@@ -34,7 +40,7 @@
3440
/**
3541
* @author Sebastien Deleuze
3642
*/
37-
public class FormHttpMessageReaderTests {
43+
public class FormHttpMessageReaderTests extends AbstractDataBufferAllocatingTestCase {
3844

3945
private final FormHttpMessageReader reader = new FormHttpMessageReader();
4046

@@ -96,8 +102,25 @@ public void readFormAsFlux() {
96102
assertNull("Invalid result", result.getFirst("name 3"));
97103
}
98104

105+
@Test
106+
public void readFormError() {
107+
DataBuffer fooBuffer = stringBuffer("name=value");
108+
Flux<DataBuffer> body =
109+
Flux.just(fooBuffer).mergeWith(Flux.error(new RuntimeException()));
110+
MockServerHttpRequest request = request(body);
111+
112+
Flux<MultiValueMap<String, String>> result = this.reader.read(null, request, null);
113+
StepVerifier.create(result)
114+
.expectError()
115+
.verify();
116+
}
117+
99118

100119
private MockServerHttpRequest request(String body) {
120+
return request(Mono.just(stringBuffer(body)));
121+
}
122+
123+
private MockServerHttpRequest request(Publisher<? extends DataBuffer> body) {
101124
return MockServerHttpRequest
102125
.method(HttpMethod.GET, "/")
103126
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)

spring-web/src/test/java/org/springframework/http/codec/ServerSentEventHttpMessageReaderTests.java

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@
2121

2222
import org.junit.Test;
2323
import reactor.core.publisher.Flux;
24+
import reactor.core.publisher.Mono;
2425
import reactor.test.StepVerifier;
2526

2627
import org.springframework.core.ResolvableType;
2728
import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase;
29+
import org.springframework.core.io.buffer.DataBuffer;
2830
import org.springframework.http.MediaType;
2931
import org.springframework.http.codec.json.Jackson2JsonDecoder;
3032
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
@@ -57,9 +59,10 @@ public void canRead() {
5759

5860
@Test
5961
public void readServerSentEvents() {
60-
MockServerHttpRequest request = MockServerHttpRequest.post("/").body(
61-
"id:c42\nevent:foo\nretry:123\n:bla\n:bla bla\n:bla bla bla\ndata:bar\n\n" +
62-
"id:c43\nevent:bar\nretry:456\ndata:baz\n\n");
62+
MockServerHttpRequest request = MockServerHttpRequest.post("/")
63+
.body(Mono.just(stringBuffer(
64+
"id:c42\nevent:foo\nretry:123\n:bla\n:bla bla\n:bla bla bla\ndata:bar\n\n" +
65+
"id:c43\nevent:bar\nretry:456\ndata:baz\n\n")));
6366

6467
Flux<ServerSentEvent> events = this.messageReader
6568
.read(ResolvableType.forClassWithGenerics(ServerSentEvent.class, String.class),
@@ -117,8 +120,9 @@ public void readServerSentEventsWithMultipleChunks() {
117120

118121
@Test
119122
public void readString() {
120-
String body = "data:foo\ndata:bar\n\ndata:baz\n\n";
121-
MockServerHttpRequest request = MockServerHttpRequest.post("/").body(body);
123+
124+
MockServerHttpRequest request = MockServerHttpRequest.post("/")
125+
.body(Mono.just(stringBuffer("data:foo\ndata:bar\n\ndata:baz\n\n")));
122126

123127
Flux<String> data = messageReader.read(ResolvableType.forClass(String.class),
124128
request, Collections.emptyMap()).cast(String.class);
@@ -132,9 +136,10 @@ public void readString() {
132136

133137
@Test
134138
public void readPojo() {
135-
MockServerHttpRequest request = MockServerHttpRequest.post("/").body(
136-
"data:{\"foo\": \"foofoo\", \"bar\": \"barbar\"}\n\n" +
137-
"data:{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}\n\n");
139+
MockServerHttpRequest request = MockServerHttpRequest.post("/")
140+
.body(Mono.just(stringBuffer(
141+
"data:{\"foo\": \"foofoo\", \"bar\": \"barbar\"}\n\n" +
142+
"data:{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}\n\n")));
138143

139144
Flux<Pojo> data = messageReader.read(ResolvableType.forClass(Pojo.class), request,
140145
Collections.emptyMap()).cast(Pojo.class);
@@ -155,7 +160,8 @@ public void readPojo() {
155160
@Test // SPR-15331
156161
public void decodeFullContentAsString() {
157162
String body = "data:foo\ndata:bar\n\ndata:baz\n\n";
158-
MockServerHttpRequest request = MockServerHttpRequest.post("/").body(body);
163+
MockServerHttpRequest request = MockServerHttpRequest.post("/")
164+
.body(Mono.just(stringBuffer(body)));
159165

160166
String actual = messageReader
161167
.readMono(ResolvableType.forClass(String.class), request, Collections.emptyMap())
@@ -165,4 +171,25 @@ public void decodeFullContentAsString() {
165171
assertEquals(body, actual);
166172
}
167173

174+
@Test
175+
public void readError() {
176+
177+
Flux<DataBuffer> body =
178+
Flux.just(stringBuffer("data:foo\ndata:bar\n\ndata:baz\n\n"))
179+
.mergeWith(Flux.error(new RuntimeException()));
180+
181+
MockServerHttpRequest request = MockServerHttpRequest.post("/")
182+
.body(body);
183+
184+
Flux<String> data = messageReader.read(ResolvableType.forClass(String.class),
185+
request, Collections.emptyMap()).cast(String.class);
186+
187+
StepVerifier.create(data)
188+
.expectNextMatches(elem -> elem.equals("foo\nbar"))
189+
.expectNextMatches(elem -> elem.equals("baz"))
190+
.expectError()
191+
.verify();
192+
}
193+
194+
168195
}

0 commit comments

Comments
 (0)