|
10 | 10 | import com.fasterxml.jackson.databind.ObjectMapper;
|
11 | 11 | import com.fasterxml.jackson.databind.type.TypeFactory;
|
12 | 12 | import org.junit.jupiter.api.Assertions;
|
| 13 | +import org.junit.jupiter.api.Named; |
13 | 14 | import org.junit.jupiter.api.Test;
|
14 | 15 | import org.junit.jupiter.params.ParameterizedTest;
|
| 16 | +import org.junit.jupiter.params.provider.Arguments; |
| 17 | +import org.junit.jupiter.params.provider.MethodSource; |
15 | 18 | import org.junit.jupiter.params.provider.ValueSource;
|
16 | 19 | import reactor.core.publisher.Flux;
|
17 | 20 | import reactor.core.publisher.Mono;
|
|
44 | 47 | import java.util.Random;
|
45 | 48 | import java.util.UUID;
|
46 | 49 | import java.util.concurrent.atomic.AtomicInteger;
|
| 50 | +import java.util.function.Supplier; |
47 | 51 | import java.util.stream.Stream;
|
48 | 52 |
|
49 | 53 | import static com.azure.core.implementation.util.BinaryDataContent.STREAM_READ_SIZE;
|
50 | 54 | import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
51 | 55 | import static org.junit.jupiter.api.Assertions.assertEquals;
|
52 | 56 | import static org.junit.jupiter.api.Assertions.assertFalse;
|
53 | 57 | import static org.junit.jupiter.api.Assertions.assertThrows;
|
| 58 | +import static org.junit.jupiter.api.Assertions.assertTrue; |
54 | 59 | import static org.mockito.ArgumentMatchers.any;
|
55 | 60 | import static org.mockito.ArgumentMatchers.anyLong;
|
56 | 61 | import static org.mockito.Mockito.doThrow;
|
@@ -622,6 +627,113 @@ public void testFromFileSegment(int size) throws Exception {
|
622 | 627 |
|
623 | 628 | }
|
624 | 629 |
|
| 630 | + @ParameterizedTest |
| 631 | + @MethodSource("createNonRetryableBinaryData") |
| 632 | + public void testNonReplayableContentTypes(Supplier<BinaryData> binaryDataSupplier) throws IOException { |
| 633 | + |
| 634 | + assertFalse(binaryDataSupplier.get().isReplayable()); |
| 635 | + |
| 636 | + BinaryData data = binaryDataSupplier.get(); |
| 637 | + byte[] firstFluxConsumption = FluxUtil.collectBytesInByteBufferStream(data.toFluxByteBuffer()).block(); |
| 638 | + byte[] secondFluxConsumption = FluxUtil.collectBytesInByteBufferStream(data.toFluxByteBuffer()).block(); |
| 639 | + |
| 640 | + data = binaryDataSupplier.get(); |
| 641 | + byte[] firstStreamConsumption = readInputStream(data.toStream()); |
| 642 | + byte[] secondStreamConsumption = readInputStream(data.toStream()); |
| 643 | + |
| 644 | + // Either flux or stream consumption is not replayable. |
| 645 | + assertFalse( |
| 646 | + Arrays.equals(firstFluxConsumption, secondFluxConsumption) |
| 647 | + && Arrays.equals(firstStreamConsumption, secondStreamConsumption) |
| 648 | + ); |
| 649 | + } |
| 650 | + |
| 651 | + public static Stream<Arguments> createNonRetryableBinaryData() { |
| 652 | + byte[] bytes = new byte[1024]; |
| 653 | + RANDOM.nextBytes(bytes); |
| 654 | + return Stream.of( |
| 655 | + Arguments.of( |
| 656 | + Named.named("stream", |
| 657 | + (Supplier<BinaryData>) () -> BinaryData.fromStream(new ByteArrayInputStream(bytes)))), |
| 658 | + Arguments.of( |
| 659 | + Named.named("unbuffered flux", |
| 660 | + (Supplier<BinaryData>) () -> BinaryData.fromFlux(Flux.just(ByteBuffer.wrap(bytes)), null, false).block())) |
| 661 | + ); |
| 662 | + } |
| 663 | + |
| 664 | + @ParameterizedTest |
| 665 | + @MethodSource("createRetryableBinaryData") |
| 666 | + public void testReplayableContentTypes(Supplier<BinaryData> binaryDataSupplier) throws IOException { |
| 667 | + |
| 668 | + assertTrue(binaryDataSupplier.get().isReplayable()); |
| 669 | + |
| 670 | + // Check toFluxByteBuffer consumption |
| 671 | + BinaryData data = binaryDataSupplier.get(); |
| 672 | + byte[] firstConsumption = FluxUtil.collectBytesInByteBufferStream(data.toFluxByteBuffer()).block(); |
| 673 | + byte[] secondConsumption = FluxUtil.collectBytesInByteBufferStream(data.toFluxByteBuffer()).block(); |
| 674 | + assertArrayEquals(firstConsumption, secondConsumption); |
| 675 | + |
| 676 | + // Check toStream consumption |
| 677 | + data = binaryDataSupplier.get(); |
| 678 | + firstConsumption = readInputStream(data.toStream()); |
| 679 | + secondConsumption = readInputStream(data.toStream()); |
| 680 | + assertArrayEquals(firstConsumption, secondConsumption); |
| 681 | + |
| 682 | + // Check toByteBuffer consumption |
| 683 | + data = binaryDataSupplier.get(); |
| 684 | + firstConsumption = readByteBuffer(data.toByteBuffer()); |
| 685 | + secondConsumption = readByteBuffer(data.toByteBuffer()); |
| 686 | + assertArrayEquals(firstConsumption, secondConsumption); |
| 687 | + |
| 688 | + // Check toBytes consumption |
| 689 | + data = binaryDataSupplier.get(); |
| 690 | + firstConsumption = data.toBytes(); |
| 691 | + secondConsumption = data.toBytes(); |
| 692 | + assertArrayEquals(firstConsumption, secondConsumption); |
| 693 | + } |
| 694 | + |
| 695 | + public static Stream<Arguments> createRetryableBinaryData() throws IOException { |
| 696 | + byte[] bytes = new byte[1024]; |
| 697 | + RANDOM.nextBytes(bytes); |
| 698 | + Path tempFile = Files.createTempFile("retryableData", null); |
| 699 | + tempFile.toFile().deleteOnExit(); |
| 700 | + Files.write(tempFile, bytes); |
| 701 | + return Stream.of( |
| 702 | + Arguments.of( |
| 703 | + Named.named("bytes", |
| 704 | + (Supplier<BinaryData>) () -> BinaryData.fromBytes(bytes))), |
| 705 | + Arguments.of( |
| 706 | + Named.named("string", |
| 707 | + (Supplier<BinaryData>) () -> BinaryData.fromString("test string"))), |
| 708 | + Arguments.of( |
| 709 | + Named.named("object", |
| 710 | + (Supplier<BinaryData>) () -> BinaryData.fromObject("\"test string\""))), |
| 711 | + Arguments.of( |
| 712 | + Named.named("file", |
| 713 | + (Supplier<BinaryData>) () -> BinaryData.fromFile(tempFile))), |
| 714 | + Arguments.of( |
| 715 | + Named.named("buffered flux", |
| 716 | + (Supplier<BinaryData>) () -> BinaryData.fromFlux(Flux.just(ByteBuffer.wrap(bytes))).block())) |
| 717 | + ); |
| 718 | + } |
| 719 | + |
| 720 | + private static byte[] readInputStream(InputStream inputStream) throws IOException { |
| 721 | + byte[] buffer = new byte[1024]; |
| 722 | + ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| 723 | + int read; |
| 724 | + while ((read = inputStream.read(buffer)) >= 0) { |
| 725 | + bos.write(buffer, 0, read); |
| 726 | + } |
| 727 | + return bos.toByteArray(); |
| 728 | + } |
| 729 | + |
| 730 | + private static byte[] readByteBuffer(ByteBuffer buffer) { |
| 731 | + // simplified implementation good enough for testing. |
| 732 | + byte[] result = new byte[buffer.remaining()]; |
| 733 | + buffer.get(result); |
| 734 | + return result; |
| 735 | + } |
| 736 | + |
625 | 737 | public static class MyJsonSerializer implements JsonSerializer {
|
626 | 738 | private final ClientLogger logger = new ClientLogger(MyJsonSerializer.class);
|
627 | 739 | private final ObjectMapper mapper;
|
|
0 commit comments