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.
2424import java .nio .channels .FileChannel ;
2525import java .nio .channels .ReadableByteChannel ;
2626import java .nio .channels .WritableByteChannel ;
27+ import java .nio .charset .StandardCharsets ;
2728import java .nio .file .Files ;
2829import java .nio .file .Path ;
2930import java .nio .file .Paths ;
3031import java .nio .file .StandardOpenOption ;
3132import java .time .Duration ;
3233import java .util .stream .Collectors ;
3334
35+ import io .netty .buffer .ByteBuf ;
3436import org .junit .Test ;
3537import org .mockito .stubbing .Answer ;
3638import reactor .core .publisher .Flux ;
3739import reactor .test .StepVerifier ;
3840
3941import org .springframework .core .io .ClassPathResource ;
4042import org .springframework .core .io .Resource ;
43+ import org .springframework .core .io .buffer .support .DataBufferTestUtils ;
4144
4245import static org .junit .Assert .*;
4346import static org .mockito .ArgumentMatchers .any ;
@@ -293,27 +296,50 @@ public void releaseConsumer() {
293296
294297 flux .subscribe (DataBufferUtils .releaseConsumer ());
295298
296- // AbstractDataBufferAllocatingTestCase.LeakDetector will assert the release of the buffers
299+ assertReleased (foo );
300+ assertReleased (bar );
301+ assertReleased (baz );
302+ }
303+
304+ private static void assertReleased (DataBuffer dataBuffer ) {
305+ if (dataBuffer instanceof NettyDataBuffer ) {
306+ ByteBuf byteBuf = ((NettyDataBuffer ) dataBuffer ).getNativeBuffer ();
307+ assertEquals (0 , byteBuf .refCnt ());
308+ }
309+ }
310+
311+ @ Test
312+ public void writeAggregator () {
313+ DataBuffer foo = stringBuffer ("foo" );
314+ DataBuffer bar = stringBuffer ("bar" );
315+ DataBuffer baz = stringBuffer ("baz" );
316+ Flux <DataBuffer > flux = Flux .just (foo , bar , baz );
317+
318+ DataBuffer result =
319+ flux .reduce (DataBufferUtils .writeAggregator ()).block (Duration .ofSeconds (1 ));
320+
321+ assertEquals ("foobarbaz" , DataBufferTestUtils .dumpString (result , StandardCharsets .UTF_8 ));
322+
323+ release (result );
297324 }
298325
299326 @ Test
300327 public void SPR16070 () throws Exception {
301328 ReadableByteChannel channel = mock (ReadableByteChannel .class );
302329 when (channel .read (any ()))
303- .thenAnswer (putByte (1 ))
304- .thenAnswer (putByte (2 ))
305- .thenAnswer (putByte (3 ))
330+ .thenAnswer (putByte ('a' ))
331+ .thenAnswer (putByte ('b' ))
332+ .thenAnswer (putByte ('c' ))
306333 .thenReturn (-1 );
307334
308335 Flux <DataBuffer > read = DataBufferUtils .read (channel , this .bufferFactory , 1 );
309336
310- StepVerifier .create (
311- read .reduce (DataBuffer ::write )
312- .map (this ::dataBufferToBytes )
313- .map (this ::encodeHexString )
314- )
315- .expectNext ("010203" )
316- .verifyComplete ();
337+ StepVerifier .create (read )
338+ .consumeNextWith (stringConsumer ("a" ))
339+ .consumeNextWith (stringConsumer ("b" ))
340+ .consumeNextWith (stringConsumer ("c" ))
341+ .expectComplete ()
342+ .verify (Duration .ofSeconds (5 ));
317343
318344 }
319345
@@ -325,27 +351,5 @@ private Answer<Integer> putByte(int b) {
325351 };
326352 }
327353
328- private byte [] dataBufferToBytes (DataBuffer buffer ) {
329- try {
330- int byteCount = buffer .readableByteCount ();
331- byte [] bytes = new byte [byteCount ];
332- buffer .read (bytes );
333- return bytes ;
334- }
335- finally {
336- release (buffer );
337- }
338- }
339-
340- private String encodeHexString (byte [] data ) {
341- StringBuilder builder = new StringBuilder ();
342- for (byte b : data ) {
343- builder .append ((0xF0 & b ) >>> 4 );
344- builder .append (0x0F & b );
345- }
346- return builder .toString ();
347- }
348-
349-
350354
351355}
0 commit comments