|
16 | 16 | package software.amazon.awssdk.http.nio.netty.internal;
|
17 | 17 |
|
18 | 18 |
|
| 19 | +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; |
19 | 20 | import static org.assertj.core.api.Assertions.assertThat;
|
20 | 21 | import static software.amazon.awssdk.http.SdkHttpConfigurationOption.GLOBAL_HTTP_DEFAULTS;
|
21 | 22 |
|
| 23 | +import com.github.tomakehurst.wiremock.junit.WireMockRule; |
| 24 | +import io.netty.channel.Channel; |
22 | 25 | import io.netty.handler.ssl.SslProvider;
|
| 26 | +import io.netty.util.concurrent.Future; |
23 | 27 | import java.net.URI;
|
24 | 28 | import java.util.ArrayList;
|
| 29 | +import java.util.HashMap; |
25 | 30 | import java.util.List;
|
26 |
| -import java.util.concurrent.ExecutionException; |
| 31 | +import java.util.Map; |
| 32 | +import java.util.stream.Collectors; |
| 33 | +import java.util.stream.Stream; |
27 | 34 | import org.apache.commons.lang3.RandomStringUtils;
|
28 |
| -import org.junit.BeforeClass; |
| 35 | +import org.junit.After; |
| 36 | +import org.junit.Rule; |
29 | 37 | import org.junit.Test;
|
30 | 38 | import software.amazon.awssdk.http.Protocol;
|
| 39 | +import software.amazon.awssdk.http.nio.netty.ProxyConfiguration; |
| 40 | +import software.amazon.awssdk.http.nio.netty.RecordingNetworkTrafficListener; |
31 | 41 | import software.amazon.awssdk.http.nio.netty.SdkEventLoopGroup;
|
32 | 42 |
|
33 | 43 | public class AwaitCloseChannelPoolMapTest {
|
34 | 44 |
|
35 |
| - private static AwaitCloseChannelPoolMap channelPoolMap; |
| 45 | + private final RecordingNetworkTrafficListener recorder = new RecordingNetworkTrafficListener(); |
36 | 46 |
|
| 47 | + private AwaitCloseChannelPoolMap channelPoolMap; |
37 | 48 |
|
38 |
| - @BeforeClass |
39 |
| - public static void setup() { |
40 |
| - channelPoolMap = AwaitCloseChannelPoolMap.builder() |
41 |
| - .sdkChannelOptions(new SdkChannelOptions()) |
42 |
| - .sdkEventLoopGroup(SdkEventLoopGroup.builder().build()) |
43 |
| - .configuration(new NettyConfiguration(GLOBAL_HTTP_DEFAULTS)) |
44 |
| - .protocol(Protocol.HTTP1_1) |
45 |
| - .maxStreams(100) |
46 |
| - .sslProvider(SslProvider.OPENSSL) |
47 |
| - .build(); |
| 49 | + @Rule |
| 50 | + public WireMockRule mockProxy = new WireMockRule(wireMockConfig() |
| 51 | + .dynamicPort() |
| 52 | + .networkTrafficListener(recorder)); |
| 53 | + |
| 54 | + @After |
| 55 | + public void methodTeardown() { |
| 56 | + if (channelPoolMap != null) { |
| 57 | + channelPoolMap.close(); |
| 58 | + } |
| 59 | + channelPoolMap = null; |
| 60 | + |
| 61 | + recorder.reset(); |
48 | 62 | }
|
49 | 63 |
|
50 | 64 | @Test
|
51 |
| - public void close_underlyingPoolsShouldBeClosed() throws ExecutionException, InterruptedException { |
| 65 | + public void close_underlyingPoolsShouldBeClosed() { |
| 66 | + channelPoolMap = AwaitCloseChannelPoolMap.builder() |
| 67 | + .sdkChannelOptions(new SdkChannelOptions()) |
| 68 | + .sdkEventLoopGroup(SdkEventLoopGroup.builder().build()) |
| 69 | + .configuration(new NettyConfiguration(GLOBAL_HTTP_DEFAULTS)) |
| 70 | + .protocol(Protocol.HTTP1_1) |
| 71 | + .maxStreams(100) |
| 72 | + .sslProvider(SslProvider.OPENSSL) |
| 73 | + .build(); |
52 | 74 |
|
53 | 75 | int numberOfChannelPools = 5;
|
54 | 76 | List<SimpleChannelPoolAwareChannelPool> channelPools = new ArrayList<>();
|
55 | 77 |
|
56 | 78 | for (int i = 0; i < numberOfChannelPools; i++) {
|
57 | 79 | channelPools.add(
|
58 |
| - channelPoolMap.get(URI.create("http://" + RandomStringUtils.randomAlphabetic(2) + i + "localhost:" + numberOfChannelPools))); |
| 80 | + channelPoolMap.get(URI.create("http://" + RandomStringUtils.randomAlphabetic(2) + i + "localhost:" + numberOfChannelPools))); |
59 | 81 | }
|
60 | 82 |
|
61 | 83 | assertThat(channelPoolMap.pools().size()).isEqualTo(numberOfChannelPools);
|
62 |
| - |
63 | 84 | channelPoolMap.close();
|
64 | 85 | channelPools.forEach(channelPool -> {
|
65 | 86 | assertThat(channelPool.underlyingSimpleChannelPool().closeFuture()).isDone();
|
66 | 87 | assertThat(channelPool.underlyingSimpleChannelPool().closeFuture().join()).isTrue();
|
67 | 88 | });
|
68 | 89 | }
|
69 | 90 |
|
| 91 | + @Test |
| 92 | + public void usingProxy_usesCachedValueWhenPresent() { |
| 93 | + URI targetUri = URI.create("https://some-awesome-service-1234.amazonaws.com"); |
| 94 | + |
| 95 | + Map<URI, Boolean> shouldProxyCache = new HashMap<>(); |
| 96 | + shouldProxyCache.put(targetUri, true); |
| 97 | + |
| 98 | + ProxyConfiguration proxyConfiguration = ProxyConfiguration.builder() |
| 99 | + .host("localhost") |
| 100 | + .port(mockProxy.port()) |
| 101 | + // Deliberately set the target host as a non-proxy host to see if it will check the cache first |
| 102 | + .nonProxyHosts(Stream.of(targetUri.getHost()).collect(Collectors.toSet())) |
| 103 | + .build(); |
| 104 | + |
| 105 | + AwaitCloseChannelPoolMap.Builder builder = AwaitCloseChannelPoolMap.builder() |
| 106 | + .proxyConfiguration(proxyConfiguration) |
| 107 | + .sdkChannelOptions(new SdkChannelOptions()) |
| 108 | + .sdkEventLoopGroup(SdkEventLoopGroup.builder().build()) |
| 109 | + .configuration(new NettyConfiguration(GLOBAL_HTTP_DEFAULTS)) |
| 110 | + .protocol(Protocol.HTTP1_1) |
| 111 | + .maxStreams(100) |
| 112 | + .sslProvider(SslProvider.OPENSSL); |
| 113 | + |
| 114 | + channelPoolMap = new AwaitCloseChannelPoolMap(builder, shouldProxyCache); |
| 115 | + |
| 116 | + // The target host does not exist so acquiring a channel should fail unless we're configured to connect to |
| 117 | + // the mock proxy host for this URI. |
| 118 | + SimpleChannelPoolAwareChannelPool channelPool = channelPoolMap.newPool(targetUri); |
| 119 | + Future<Channel> channelFuture = channelPool.underlyingSimpleChannelPool().acquire().awaitUninterruptibly(); |
| 120 | + assertThat(channelFuture.isSuccess()).isTrue(); |
| 121 | + channelPool.release(channelFuture.getNow()).awaitUninterruptibly(); |
| 122 | + } |
| 123 | + |
| 124 | + @Test |
| 125 | + public void usingProxy_noSchemeGiven_defaultsToHttp() { |
| 126 | + ProxyConfiguration proxyConfiguration = ProxyConfiguration.builder() |
| 127 | + .host("localhost") |
| 128 | + .port(mockProxy.port()) |
| 129 | + .build(); |
| 130 | + |
| 131 | + channelPoolMap = AwaitCloseChannelPoolMap.builder() |
| 132 | + .proxyConfiguration(proxyConfiguration) |
| 133 | + .sdkChannelOptions(new SdkChannelOptions()) |
| 134 | + .sdkEventLoopGroup(SdkEventLoopGroup.builder().build()) |
| 135 | + .configuration(new NettyConfiguration(GLOBAL_HTTP_DEFAULTS)) |
| 136 | + .protocol(Protocol.HTTP1_1) |
| 137 | + .maxStreams(100) |
| 138 | + .sslProvider(SslProvider.OPENSSL) |
| 139 | + .build(); |
| 140 | + |
| 141 | + SimpleChannelPoolAwareChannelPool simpleChannelPoolAwareChannelPool = channelPoolMap.newPool( |
| 142 | + URI.create("https://some-awesome-service:443")); |
| 143 | + |
| 144 | + simpleChannelPoolAwareChannelPool.acquire().awaitUninterruptibly(); |
| 145 | + |
| 146 | + String requests = recorder.requests().toString(); |
| 147 | + |
| 148 | + assertThat(requests).contains("CONNECT some-awesome-service:443"); |
| 149 | + } |
| 150 | + |
70 | 151 | }
|
0 commit comments