Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -70,14 +71,13 @@ public static <ElementT> 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 <a
* href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm">Modern
* Fisher-Yates shuffle</a>
*/
public static <ElementT> 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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,27 @@
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;
import java.nio.charset.StandardCharsets;
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;
Expand All @@ -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();
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<SimpleStatement> statementCaptor;

@Before
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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");
Expand Down
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<version>2.25.0</version>
<version>2.27.2</version>
</dependency>
<dependency>
<groupId>org.graalvm.sdk</groupId>
Expand Down Expand Up @@ -1047,7 +1047,7 @@ height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- for DriverBlockHoundIntegrationIT when using JDK 13+, see https://github.com/reactor/BlockHound/issues/33 -->
<blockhound.argline>-XX:+AllowRedefinitionToAddDeleteMethods</blockhound.argline>
<!-- allow deep reflection for mockito when using JDK 17+, see https://stackoverflow.com/questions/70993863/mockito-can-not-mock-random-in-java-17 -->
<mockitoopens.argline>--add-opens java.base/jdk.internal.util.random=ALL-UNNAMED</mockitoopens.argline>
<mockitoopens.argline>--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</mockitoopens.argline>
</properties>
</profile>
</profiles>
Expand Down
Loading