diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/util/ArrayUtils.java b/core/src/main/java/com/datastax/oss/driver/internal/core/util/ArrayUtils.java index 17b6c01178d..7d7f35e5ffc 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/util/ArrayUtils.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/util/ArrayUtils.java @@ -18,6 +18,7 @@ package com.datastax.oss.driver.internal.core.util; import edu.umd.cs.findbugs.annotations.NonNull; +import java.util.Random; import java.util.concurrent.ThreadLocalRandom; public class ArrayUtils { @@ -70,14 +71,13 @@ public static void shuffleHead(@NonNull ElementT[] elements, int n) { * * @param elements the array to shuffle. * @param n the number of elements to shuffle; must be {@code <= elements.length}. - * @param random the {@link ThreadLocalRandom} instance to use. This is mainly intended to - * facilitate tests. + * @param random the {@link Random} instance to use. This is mainly intended to facilitate tests. * @see Modern * Fisher-Yates shuffle */ public static void shuffleHead( - @NonNull ElementT[] elements, int n, @NonNull ThreadLocalRandom random) { + @NonNull ElementT[] elements, int n, @NonNull Random random) { if (n > elements.length) { throw new ArrayIndexOutOfBoundsException( String.format( diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactoryTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactoryTest.java index a0db82d298e..e9705ffb70b 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactoryTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactoryTest.java @@ -37,8 +37,10 @@ import com.github.tomakehurst.wiremock.jetty9.JettyHttpServer; import com.github.tomakehurst.wiremock.junit.WireMockRule; import com.google.common.base.Joiner; +import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.net.InetSocketAddress; import java.net.URISyntaxException; import java.net.URL; @@ -46,11 +48,16 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; import org.eclipse.jetty.io.NetworkTrafficListener; import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.SslConnectionFactory; import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.junit.After; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -65,21 +72,39 @@ public class CloudConfigFactoryTest { public WireMockRule wireMockRule = new WireMockRule( wireMockConfig() - .httpsPort(30443) .dynamicPort() + .dynamicHttpsPort() .httpServerFactory(new HttpsServerFactory()) .needClientAuth(true) .keystorePath(path("/config/cloud/identity.jks").toString()) .keystorePassword("fakePasswordForTests") + .keyManagerPassword("fakePasswordForTests") + .keystoreType("JKS") .trustStorePath(path("/config/cloud/trustStore.jks").toString()) - .trustStorePassword("fakePasswordForTests2")); + .trustStorePassword("fakePasswordForTests2") + .trustStoreType("JKS")); + + private Path tempBundlePath; + + @Before + public void createBundle() throws Exception { + tempBundlePath = Files.createTempFile("secure-connect", ".zip"); + Files.write(tempBundlePath, secureBundle()); + } + + @After + public void cleanupBundle() throws IOException { + if (tempBundlePath != null) { + Files.deleteIfExists(tempBundlePath); + } + } public CloudConfigFactoryTest() throws URISyntaxException {} @Test public void should_load_config_from_local_filesystem() throws Exception { // given - URL configFile = getClass().getResource(BUNDLE_PATH); + URL configFile = tempBundlePath.toUri().toURL(); mockProxyMetadataService(jsonMetadata()); // when CloudConfigFactory cloudConfigFactory = new CloudConfigFactory(); @@ -91,7 +116,7 @@ public void should_load_config_from_local_filesystem() throws Exception { @Test public void should_load_config_from_external_location() throws Exception { // given - mockHttpSecureBundle(secureBundle()); + mockHttpSecureBundle(Files.readAllBytes(tempBundlePath)); mockProxyMetadataService(jsonMetadata()); // when URL configFile = new URL("http", "localhost", wireMockRule.port(), BUNDLE_PATH); @@ -130,7 +155,7 @@ public void should_throw_when_bundle_not_readable() throws Exception { @Test public void should_throw_when_metadata_not_found() throws Exception { // given - mockHttpSecureBundle(secureBundle()); + mockHttpSecureBundle(Files.readAllBytes(tempBundlePath)); stubFor(any(urlPathEqualTo("/metadata")).willReturn(aResponse().withStatus(404))); // when URL configFile = new URL("http", "localhost", wireMockRule.port(), BUNDLE_PATH); @@ -142,7 +167,7 @@ public void should_throw_when_metadata_not_found() throws Exception { @Test public void should_throw_when_metadata_not_readable() throws Exception { // given - mockHttpSecureBundle(secureBundle()); + mockHttpSecureBundle(Files.readAllBytes(tempBundlePath)); mockProxyMetadataService("not a valid json payload"); // when URL configFile = new URL("http", "localhost", wireMockRule.port(), BUNDLE_PATH); @@ -171,8 +196,37 @@ private void mockProxyMetadataService(String jsonMetadata) { .withBody(jsonMetadata))); } - private byte[] secureBundle() throws IOException, URISyntaxException { - return Files.readAllBytes(path(BUNDLE_PATH)); + private byte[] secureBundle() throws IOException { + try (InputStream in = getClass().getResourceAsStream(BUNDLE_PATH); + ZipInputStream zipIn = new ZipInputStream(in); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ZipOutputStream zipOut = new ZipOutputStream(out)) { + ZipEntry entry; + byte[] buffer = new byte[8192]; + while ((entry = zipIn.getNextEntry()) != null) { + zipOut.putNextEntry(new ZipEntry(entry.getName())); + if ("config.json".equals(entry.getName())) { + ByteArrayOutputStream configBuffer = new ByteArrayOutputStream(); + int len; + while ((len = zipIn.read(buffer)) != -1) { + configBuffer.write(buffer, 0, len); + } + String config = + new String(configBuffer.toByteArray(), StandardCharsets.UTF_8) + .replace("\"port\": 30443", "\"port\": " + wireMockRule.httpsPort()); + zipOut.write(config.getBytes(StandardCharsets.UTF_8)); + } else { + int len; + while ((len = zipIn.read(buffer)) != -1) { + zipOut.write(buffer, 0, len); + } + } + zipOut.closeEntry(); + zipIn.closeEntry(); + } + zipOut.finish(); + return out.toByteArray(); + } } private String jsonMetadata() throws IOException, URISyntaxException { @@ -218,7 +272,8 @@ protected ServerConnector createServerConnector( int port, NetworkTrafficListener listener, ConnectionFactory... connectionFactories) { - if (port == options.httpsSettings().port()) { + if (connectionFactories.length > 0 + && connectionFactories[0] instanceof SslConnectionFactory) { SslConnectionFactory sslConnectionFactory = (SslConnectionFactory) connectionFactories[0]; SslContextFactory sslContextFactory = sslConnectionFactory.getSslContextFactory(); diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/cql/QueryTraceFetcherTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/cql/QueryTraceFetcherTest.java index b355e0fc9f0..d64b37db696 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/cql/QueryTraceFetcherTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/cql/QueryTraceFetcherTest.java @@ -71,6 +71,7 @@ public class QueryTraceFetcherTest { private static final UUID TRACING_ID = UUID.randomUUID(); private static final ByteBuffer PAGING_STATE = Bytes.fromHexString("0xdeadbeef"); private static final int PORT = 7000; + private final InetAddress address = InetAddress.getLoopbackAddress(); @Mock private CqlSession session; @Mock private InternalDriverContext context; @@ -79,8 +80,6 @@ public class QueryTraceFetcherTest { @Mock private NettyOptions nettyOptions; @Mock private EventExecutorGroup adminEventExecutorGroup; @Mock private EventExecutor eventExecutor; - @Mock private InetAddress address; - @Captor private ArgumentCaptor statementCaptor; @Before diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/util/ArrayUtilsTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/util/ArrayUtilsTest.java index c2a7fb70304..f6077c23f34 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/util/ArrayUtilsTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/util/ArrayUtilsTest.java @@ -18,11 +18,8 @@ package com.datastax.oss.driver.internal.core.util; import static com.datastax.oss.driver.Assertions.assertThat; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import java.util.concurrent.ThreadLocalRandom; +import java.util.Random; import org.junit.Test; public class ArrayUtilsTest { @@ -86,15 +83,15 @@ public void should_not_bubble_down_when_target_index_lower() { @Test public void should_shuffle_head() { String[] array = {"a", "b", "c", "d", "e"}; - ThreadLocalRandom random = mock(ThreadLocalRandom.class); - when(random.nextInt(anyInt())) - .thenAnswer( - (invocation) -> { - int i = invocation.getArgument(0); - // shifts elements by 1 to the right - return i - 2; - }); - ArrayUtils.shuffleHead(array, 3, random); + Random deterministicRandom = + new Random() { + @Override + public int nextInt(int bound) { + // shifts elements by 1 to the right + return bound - 2; + } + }; + ArrayUtils.shuffleHead(array, 3, deterministicRandom); assertThat(array[0]).isEqualTo("c"); assertThat(array[1]).isEqualTo("a"); assertThat(array[2]).isEqualTo("b"); diff --git a/pom.xml b/pom.xml index d7f0f9ef8f2..f6a7d947973 100644 --- a/pom.xml +++ b/pom.xml @@ -423,7 +423,7 @@ com.github.tomakehurst wiremock - 2.25.0 + 2.27.2 org.graalvm.sdk @@ -1047,7 +1047,7 @@ height="0" width="0" style="display:none;visibility:hidden"> -XX:+AllowRedefinitionToAddDeleteMethods - --add-opens java.base/jdk.internal.util.random=ALL-UNNAMED + --add-opens java.base/jdk.internal.util.random=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/java.util.concurrent=ALL-UNNAMED