|
41 | 41 | import com.azure.core.test.implementation.entities.HttpBinFormDataJSON.PizzaSize; |
42 | 42 | import com.azure.core.test.implementation.entities.HttpBinHeaders; |
43 | 43 | import com.azure.core.test.implementation.entities.HttpBinJSON; |
| 44 | +import com.azure.core.test.utils.MessageDigestUtils; |
44 | 45 | import com.azure.core.util.BinaryData; |
| 46 | +import com.azure.core.util.Context; |
45 | 47 | import com.azure.core.util.FluxUtil; |
| 48 | +import com.azure.core.util.IOUtils; |
46 | 49 | import org.junit.jupiter.api.Assertions; |
| 50 | +import org.junit.jupiter.api.Named; |
47 | 51 | import org.junit.jupiter.api.Test; |
| 52 | +import org.junit.jupiter.params.ParameterizedTest; |
| 53 | +import org.junit.jupiter.params.provider.Arguments; |
| 54 | +import org.junit.jupiter.params.provider.MethodSource; |
| 55 | +import reactor.core.Exceptions; |
48 | 56 | import reactor.core.publisher.Flux; |
49 | 57 | import reactor.core.publisher.Mono; |
| 58 | +import reactor.core.scheduler.Schedulers; |
50 | 59 | import reactor.test.StepVerifier; |
| 60 | +import reactor.util.function.Tuples; |
51 | 61 |
|
52 | 62 | import java.io.ByteArrayInputStream; |
| 63 | +import java.io.ByteArrayOutputStream; |
| 64 | +import java.io.IOException; |
53 | 65 | import java.nio.ByteBuffer; |
54 | 66 | import java.nio.channels.AsynchronousFileChannel; |
| 67 | +import java.nio.channels.Channels; |
55 | 68 | import java.nio.charset.StandardCharsets; |
56 | 69 | import java.nio.file.Files; |
57 | 70 | import java.nio.file.Path; |
|
62 | 75 | import java.util.LinkedHashMap; |
63 | 76 | import java.util.List; |
64 | 77 | import java.util.Map; |
| 78 | +import java.util.stream.Stream; |
65 | 79 |
|
66 | 80 | import static org.junit.jupiter.api.Assertions.assertArrayEquals; |
67 | 81 | import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; |
|
74 | 88 | import static org.junit.jupiter.api.Assertions.fail; |
75 | 89 |
|
76 | 90 | public abstract class RestProxyTests { |
| 91 | + private static final String HTTP_REST_PROXY_SYNC_PROXY_ENABLE = "com.azure.core.http.restproxy.syncproxy.enable"; |
77 | 92 |
|
78 | 93 | /** |
79 | 94 | * Get the HTTP client that will be used for each test. This will be called once per test. |
@@ -1619,20 +1634,125 @@ public void service21GetBytes100() { |
1619 | 1634 | @Host("http://localhost") |
1620 | 1635 | @ServiceInterface(name = "DownloadService") |
1621 | 1636 | interface DownloadService { |
| 1637 | + |
1622 | 1638 | @Get("/bytes/30720") |
1623 | | - StreamResponse getBytes(); |
| 1639 | + StreamResponse getBytes(Context context); |
| 1640 | + |
| 1641 | + @Get("/bytes/30720") |
| 1642 | + Mono<StreamResponse> getBytesAsync(Context context); |
1624 | 1643 |
|
1625 | 1644 | @Get("/bytes/30720") |
1626 | 1645 | Flux<ByteBuffer> getBytesFlux(); |
1627 | 1646 | } |
1628 | 1647 |
|
1629 | | - @Test |
1630 | | - public void simpleDownloadTest() { |
1631 | | - StepVerifier.create(Flux.using(() -> createService(DownloadService.class).getBytes(), |
| 1648 | + @ParameterizedTest |
| 1649 | + @MethodSource("downloadTestArgumentProvider") |
| 1650 | + public void simpleDownloadTest(Context context) { |
| 1651 | + StepVerifier.create(Flux.using(() -> createService(DownloadService.class).getBytes(context), |
1632 | 1652 | response -> response.getValue().map(ByteBuffer::remaining).reduce(0, Integer::sum), |
1633 | 1653 | StreamResponse::close)) |
1634 | 1654 | .assertNext(count -> assertEquals(30720, count)) |
1635 | 1655 | .verifyComplete(); |
| 1656 | + |
| 1657 | + StepVerifier.create(Flux.using(() -> createService(DownloadService.class).getBytes(context), |
| 1658 | + response -> Mono.zip(MessageDigestUtils.md5(response.getValue()), Mono.just(response.getHeaders().getValue("ETag"))), |
| 1659 | + StreamResponse::close)) |
| 1660 | + .assertNext(hashTuple -> assertEquals(hashTuple.getT2(), hashTuple.getT1())) |
| 1661 | + .verifyComplete(); |
| 1662 | + } |
| 1663 | + |
| 1664 | + @ParameterizedTest |
| 1665 | + @MethodSource("downloadTestArgumentProvider") |
| 1666 | + public void simpleDownloadTestAsync(Context context) { |
| 1667 | + StepVerifier.create(createService(DownloadService.class).getBytesAsync(context) |
| 1668 | + .flatMap(response -> response.getValue().map(ByteBuffer::remaining) |
| 1669 | + .reduce(0, Integer::sum) |
| 1670 | + .doFinally(ignore -> response.close()))) |
| 1671 | + .assertNext(count -> assertEquals(30720, count)) |
| 1672 | + .verifyComplete(); |
| 1673 | + |
| 1674 | + StepVerifier.create(createService(DownloadService.class).getBytesAsync(context) |
| 1675 | + .flatMap(response -> Mono.zip(MessageDigestUtils.md5(response.getValue()), Mono.just(response.getHeaders().getValue("ETag"))) |
| 1676 | + .doFinally(ignore -> response.close()))) |
| 1677 | + .assertNext(hashTuple -> assertEquals(hashTuple.getT2(), hashTuple.getT1())) |
| 1678 | + .verifyComplete(); |
| 1679 | + } |
| 1680 | + |
| 1681 | + @ParameterizedTest |
| 1682 | + @MethodSource("downloadTestArgumentProvider") |
| 1683 | + public void streamResponseCanTransferBody(Context context) throws IOException { |
| 1684 | + try (StreamResponse streamResponse = createService(DownloadService.class).getBytes(context)) { |
| 1685 | + ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| 1686 | + streamResponse.transferValueTo(Channels.newChannel(bos)); |
| 1687 | + assertEquals(streamResponse.getHeaders().getValue("ETag"), MessageDigestUtils.md5(bos.toByteArray())); |
| 1688 | + } |
| 1689 | + |
| 1690 | + Path tempFile = Files.createTempFile("streamResponseCanTransferBody", null); |
| 1691 | + tempFile.toFile().deleteOnExit(); |
| 1692 | + try (StreamResponse streamResponse = createService(DownloadService.class).getBytes(context)) { |
| 1693 | + StepVerifier.create(Mono.using( |
| 1694 | + () -> IOUtils.toAsynchronousByteChannel(AsynchronousFileChannel.open(tempFile, StandardOpenOption.WRITE), 0), |
| 1695 | + streamResponse::transferValueToAsync, |
| 1696 | + channel -> { |
| 1697 | + try { |
| 1698 | + channel.close(); |
| 1699 | + } catch (IOException e) { |
| 1700 | + throw Exceptions.propagate(e); |
| 1701 | + } |
| 1702 | + }).then(Mono.fromCallable(() -> MessageDigestUtils.md5(Files.readAllBytes(tempFile))))) |
| 1703 | + .assertNext(hash -> assertEquals(streamResponse.getHeaders().getValue("ETag"), hash)) |
| 1704 | + .verifyComplete(); |
| 1705 | + } |
| 1706 | + } |
| 1707 | + |
| 1708 | + @ParameterizedTest |
| 1709 | + @MethodSource("downloadTestArgumentProvider") |
| 1710 | + public void streamResponseCanTransferBodyAsync(Context context) throws IOException { |
| 1711 | + StepVerifier.create(createService(DownloadService.class).getBytesAsync(context) |
| 1712 | + .publishOn(Schedulers.boundedElastic()) |
| 1713 | + .map(streamResponse -> { |
| 1714 | + ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| 1715 | + try { |
| 1716 | + streamResponse.transferValueTo(Channels.newChannel(bos)); |
| 1717 | + } catch (IOException e) { |
| 1718 | + throw Exceptions.propagate(e); |
| 1719 | + } finally { |
| 1720 | + streamResponse.close(); |
| 1721 | + } |
| 1722 | + return Tuples.of(streamResponse.getHeaders().getValue("Etag"), MessageDigestUtils.md5(bos.toByteArray())); |
| 1723 | + })) |
| 1724 | + .assertNext(hashTuple -> assertEquals(hashTuple.getT1(), hashTuple.getT2())) |
| 1725 | + .verifyComplete(); |
| 1726 | + |
| 1727 | + Path tempFile = Files.createTempFile("streamResponseCanTransferBody", null); |
| 1728 | + tempFile.toFile().deleteOnExit(); |
| 1729 | + StepVerifier.create(createService(DownloadService.class).getBytesAsync(context) |
| 1730 | + .flatMap(streamResponse -> Mono.using( |
| 1731 | + () -> IOUtils.toAsynchronousByteChannel(AsynchronousFileChannel.open(tempFile, StandardOpenOption.WRITE), 0), |
| 1732 | + streamResponse::transferValueToAsync, |
| 1733 | + channel -> { |
| 1734 | + try { |
| 1735 | + channel.close(); |
| 1736 | + } catch (IOException e) { |
| 1737 | + throw Exceptions.propagate(e); |
| 1738 | + } |
| 1739 | + }).doFinally(ignored -> streamResponse.close()) |
| 1740 | + .then(Mono.just(streamResponse.getHeaders().getValue("ETag"))))) |
| 1741 | + .assertNext(hash -> { |
| 1742 | + try { |
| 1743 | + assertEquals(hash, MessageDigestUtils.md5(Files.readAllBytes(tempFile))); |
| 1744 | + } catch (IOException e) { |
| 1745 | + Exceptions.propagate(e); |
| 1746 | + } |
| 1747 | + }) |
| 1748 | + .verifyComplete(); |
| 1749 | + } |
| 1750 | + |
| 1751 | + public static Stream<Arguments> downloadTestArgumentProvider() { |
| 1752 | + return Stream.of( |
| 1753 | + Arguments.of(Named.named("default", Context.NONE)), |
| 1754 | + Arguments.of(Named.named("sync proxy enabled", Context.NONE |
| 1755 | + .addData(HTTP_REST_PROXY_SYNC_PROXY_ENABLE, true)))); |
1636 | 1756 | } |
1637 | 1757 |
|
1638 | 1758 | @Test |
|
0 commit comments