|
57 | 57 | import java.util.List; |
58 | 58 | import java.util.Objects; |
59 | 59 | import java.util.UUID; |
| 60 | +import java.util.concurrent.ThreadLocalRandom; |
60 | 61 | import java.util.concurrent.atomic.AtomicBoolean; |
61 | 62 | import java.util.concurrent.atomic.AtomicInteger; |
62 | 63 | import java.util.concurrent.atomic.AtomicLong; |
|
68 | 69 | import static com.azure.core.CoreTestUtils.fillArray; |
69 | 70 | import static com.azure.core.CoreTestUtils.readStream; |
70 | 71 | import static com.azure.core.implementation.util.BinaryDataContent.STREAM_READ_SIZE; |
| 72 | +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; |
71 | 73 | import static org.junit.jupiter.api.Assertions.assertEquals; |
72 | 74 | import static org.junit.jupiter.api.Assertions.assertFalse; |
73 | 75 | import static org.junit.jupiter.api.Assertions.assertInstanceOf; |
@@ -1049,6 +1051,68 @@ public void binaryDataAsPropertyDeserialization() throws IOException { |
1049 | 1051 | assertEquals(expected.getProperty().toString(), actual.getProperty().toString()); |
1050 | 1052 | } |
1051 | 1053 |
|
| 1054 | + @Test |
| 1055 | + public void emptyFluxByteBufferToReplayable() { |
| 1056 | + BinaryData binaryData = BinaryData.fromFlux(Flux.empty()).block(); |
| 1057 | + |
| 1058 | + BinaryData replayable = assertDoesNotThrow(() -> binaryData.toReplayableBinaryData()); |
| 1059 | + assertEquals("", replayable.toString()); |
| 1060 | + } |
| 1061 | + |
| 1062 | + @Test |
| 1063 | + public void emptyFluxByteBufferToReplayableAsync() { |
| 1064 | + StepVerifier.create(BinaryData.fromFlux(Flux.empty()) |
| 1065 | + .flatMap(BinaryData::toReplayableBinaryDataAsync)) |
| 1066 | + .assertNext(replayable -> assertEquals("", replayable.toString())) |
| 1067 | + .verifyComplete(); |
| 1068 | + } |
| 1069 | + |
| 1070 | + /** |
| 1071 | + * Tests that {@link FluxByteBufferContent#toReplayableContent()} eagerly makes the {@link FluxByteBufferContent} |
| 1072 | + * replayable. Before, this method wouldn't make the content replayable until the return |
| 1073 | + * {@link FluxByteBufferContent} was consumed, which defeated the purpose of the method as the underlying data could |
| 1074 | + * be reclaimed or consumed before it was made replayable. |
| 1075 | + */ |
| 1076 | + @Test |
| 1077 | + public void fluxByteBufferToReplayableEagerlyConvertsToReplayable() { |
| 1078 | + byte[] data = new byte[1024]; |
| 1079 | + ThreadLocalRandom.current().nextBytes(data); |
| 1080 | + byte[] expectedData = CoreUtils.clone(data); |
| 1081 | + |
| 1082 | + BinaryDataContent binaryDataContent = new FluxByteBufferContent(Flux.just(ByteBuffer.wrap(data))) |
| 1083 | + .toReplayableContent(); |
| 1084 | + |
| 1085 | + Arrays.fill(data, (byte) 0); |
| 1086 | + |
| 1087 | + assertArraysEqual(expectedData, binaryDataContent.toBytes()); |
| 1088 | + } |
| 1089 | + |
| 1090 | + /** |
| 1091 | + * Tests that {@link FluxByteBufferContent} returned by {@link FluxByteBufferContent#toReplayableContentAsync()} |
| 1092 | + * won't attempt to access the original {@link Flux Flux<ByteBuffer>} as the initial duplicated is cached as a |
| 1093 | + * stream of {@link ByteBuffer ByteBuffers} that are shared to all subscribers, and duplicated in each subscription |
| 1094 | + * so that the underlying content cannot be modified. |
| 1095 | + */ |
| 1096 | + @Test |
| 1097 | + public void multipleSubscriptionsToReplayableAsyncFluxByteBufferAreConsistent() { |
| 1098 | + byte[] data = new byte[1024]; |
| 1099 | + ThreadLocalRandom.current().nextBytes(data); |
| 1100 | + byte[] expectedData = CoreUtils.clone(data); |
| 1101 | + |
| 1102 | + Mono<BinaryDataContent> binaryDataContentMono = new FluxByteBufferContent(Flux.just(ByteBuffer.wrap(data))) |
| 1103 | + .toReplayableContentAsync(); |
| 1104 | + |
| 1105 | + StepVerifier.create(binaryDataContentMono) |
| 1106 | + .assertNext(binaryDataContent -> assertArraysEqual(expectedData, binaryDataContent.toBytes())) |
| 1107 | + .verifyComplete(); |
| 1108 | + |
| 1109 | + Arrays.fill(data, (byte) 0); |
| 1110 | + |
| 1111 | + StepVerifier.create(binaryDataContentMono) |
| 1112 | + .assertNext(binaryDataContent -> assertArraysEqual(expectedData, binaryDataContent.toBytes())) |
| 1113 | + .verifyComplete(); |
| 1114 | + } |
| 1115 | + |
1052 | 1116 | public static final class BinaryDataAsProperty { |
1053 | 1117 | @JsonProperty("property") |
1054 | 1118 | private BinaryData property; |
|
0 commit comments