Skip to content

Commit 3c046e2

Browse files
authored
Create a test-jar for the core module (apache#957)
This commit also introduces minor enhancements to the following classes: * RequestHandlerTestHarness * CompletionStageAssert * CompletableFutures
1 parent e6bfdd3 commit 3c046e2

5 files changed

Lines changed: 99 additions & 5 deletions

File tree

core/pom.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,17 @@
128128
</resource>
129129
</resources>
130130
<plugins>
131+
<plugin>
132+
<artifactId>maven-jar-plugin</artifactId>
133+
<executions>
134+
<execution>
135+
<id>test-jar</id>
136+
<goals>
137+
<goal>test-jar</goal>
138+
</goals>
139+
</execution>
140+
</executions>
141+
</plugin>
131142
<plugin>
132143
<artifactId>maven-shade-plugin</artifactId>
133144
<executions>
@@ -147,6 +158,7 @@
147158
<shadedPattern>com.datastax.oss.driver.shaded.guava</shadedPattern>
148159
</relocation>
149160
</relocations>
161+
<shadeTestJar>true</shadeTestJar>
150162
</configuration>
151163
</execution>
152164
</executions>

core/src/main/java/com/datastax/oss/driver/internal/core/util/concurrent/CompletableFutures.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ public static <T> void whenAllDone(
7575
}
7676

7777
/** Get the result now, when we know for sure that the future is complete. */
78-
public static <T> T getCompleted(CompletableFuture<T> future) {
78+
public static <T> T getCompleted(CompletionStage<T> stage) {
79+
CompletableFuture<T> future = stage.toCompletableFuture();
7980
Preconditions.checkArgument(future.isDone() && !future.isCompletedExceptionally());
8081
try {
8182
return future.get();
@@ -86,7 +87,8 @@ public static <T> T getCompleted(CompletableFuture<T> future) {
8687
}
8788

8889
/** Get the error now, when we know for sure that the future is failed. */
89-
public static Throwable getFailed(CompletableFuture<?> future) {
90+
public static Throwable getFailed(CompletionStage<?> stage) {
91+
CompletableFuture<?> future = stage.toCompletableFuture();
9092
Preconditions.checkArgument(future.isCompletedExceptionally());
9193
try {
9294
future.get();

core/src/test/java/com/datastax/oss/driver/internal/core/CompletionStageAssert.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static org.assertj.core.api.Assertions.assertThat;
1919
import static org.assertj.core.api.Assertions.fail;
2020

21+
import java.util.concurrent.CancellationException;
2122
import java.util.concurrent.CompletionStage;
2223
import java.util.concurrent.ExecutionException;
2324
import java.util.concurrent.TimeUnit;
@@ -66,8 +67,45 @@ public CompletionStageAssert<V> isFailed() {
6667
return isFailed(f -> {});
6768
}
6869

70+
public CompletionStageAssert<V> isCancelled() {
71+
boolean cancelled = false;
72+
try {
73+
actual.toCompletableFuture().get(2, TimeUnit.SECONDS);
74+
} catch (CancellationException e) {
75+
cancelled = true;
76+
} catch (Exception ignored) {
77+
}
78+
if (!cancelled) {
79+
fail("Expected completion stage to be cancelled");
80+
}
81+
return this;
82+
}
83+
84+
public CompletionStageAssert<V> isNotCancelled() {
85+
boolean cancelled = false;
86+
try {
87+
actual.toCompletableFuture().get(2, TimeUnit.SECONDS);
88+
} catch (CancellationException e) {
89+
cancelled = true;
90+
} catch (Exception ignored) {
91+
}
92+
if (cancelled) {
93+
fail("Expected completion stage not to be cancelled");
94+
}
95+
return this;
96+
}
97+
98+
public CompletionStageAssert<V> isDone() {
99+
assertThat(actual.toCompletableFuture().isDone())
100+
.overridingErrorMessage("Expected completion stage to be done")
101+
.isTrue();
102+
return this;
103+
}
104+
69105
public CompletionStageAssert<V> isNotDone() {
70-
assertThat(actual.toCompletableFuture().isDone()).isFalse();
106+
assertThat(actual.toCompletableFuture().isDone())
107+
.overridingErrorMessage("Expected completion stage not to be done")
108+
.isFalse();
71109
return this;
72110
}
73111
}

core/src/test/java/com/datastax/oss/driver/internal/core/cql/PoolBehavior.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@
2525
import com.datastax.oss.driver.internal.core.channel.ResponseCallback;
2626
import com.datastax.oss.protocol.internal.Frame;
2727
import com.datastax.oss.protocol.internal.Message;
28+
import io.netty.channel.ChannelConfig;
2829
import io.netty.channel.ChannelFuture;
30+
import io.netty.channel.EventLoop;
31+
import io.netty.channel.socket.DefaultSocketChannelConfig;
2932
import io.netty.util.concurrent.GlobalEventExecutor;
3033
import io.netty.util.concurrent.Promise;
3134
import java.util.concurrent.CompletableFuture;
@@ -52,17 +55,25 @@ public PoolBehavior(Node node, boolean createChannel) {
5255
this.writePromise = null;
5356
} else {
5457
this.channel = Mockito.mock(DriverChannel.class);
58+
EventLoop eventLoop = Mockito.mock(EventLoop.class);
59+
ChannelConfig config = Mockito.mock(DefaultSocketChannelConfig.class);
5560
this.writePromise = GlobalEventExecutor.INSTANCE.newPromise();
5661
Mockito.when(
5762
channel.write(
5863
any(Message.class), anyBoolean(), anyMap(), any(ResponseCallback.class)))
5964
.thenAnswer(
6065
invocation -> {
61-
callbackFuture.complete(invocation.getArgument(3));
66+
ResponseCallback callback = invocation.getArgument(3);
67+
if (callback.holdStreamId()) {
68+
callback.onStreamIdAssigned(1);
69+
}
70+
callbackFuture.complete(callback);
6271
return writePromise;
6372
});
6473
ChannelFuture closeFuture = Mockito.mock(ChannelFuture.class);
6574
Mockito.when(channel.closeFuture()).thenReturn(closeFuture);
75+
Mockito.when(channel.eventLoop()).thenReturn(eventLoop);
76+
Mockito.when(channel.config()).thenReturn(config);
6677
}
6778
}
6879

@@ -92,6 +103,14 @@ public void setResponseFailure(Throwable cause) {
92103
callbackFuture.thenAccept(callback -> callback.onFailure(cause));
93104
}
94105

106+
public Node getNode() {
107+
return node;
108+
}
109+
110+
public DriverChannel getChannel() {
111+
return channel;
112+
}
113+
95114
/** Mocks a follow-up request on the same channel. */
96115
public void mockFollowupRequest(Class<? extends Message> expectedMessage, Frame responseFrame) {
97116
Promise<Void> writePromise2 = GlobalEventExecutor.INSTANCE.newPromise();

core/src/test/java/com/datastax/oss/driver/internal/core/cql/RequestHandlerTestHarness.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@
3737
import com.datastax.oss.driver.internal.core.channel.DriverChannel;
3838
import com.datastax.oss.driver.internal.core.context.InternalDriverContext;
3939
import com.datastax.oss.driver.internal.core.context.NettyOptions;
40+
import com.datastax.oss.driver.internal.core.metadata.DefaultMetadata;
4041
import com.datastax.oss.driver.internal.core.metadata.LoadBalancingPolicyWrapper;
42+
import com.datastax.oss.driver.internal.core.metrics.SessionMetricUpdater;
4143
import com.datastax.oss.driver.internal.core.pool.ChannelPool;
4244
import com.datastax.oss.driver.internal.core.servererrors.DefaultWriteTypeRegistry;
4345
import com.datastax.oss.driver.internal.core.session.DefaultSession;
@@ -70,6 +72,7 @@ public static Builder builder() {
7072
}
7173

7274
private final ScheduledTaskCapturingEventLoop schedulingEventLoop;
75+
private final Map<Node, ChannelPool> pools;
7376

7477
@Mock private InternalDriverContext context;
7578
@Mock private DefaultSession session;
@@ -82,6 +85,7 @@ public static Builder builder() {
8285
@Mock private SpeculativeExecutionPolicy speculativeExecutionPolicy;
8386
@Mock private TimestampGenerator timestampGenerator;
8487
@Mock private ProtocolVersionRegistry protocolVersionRegistry;
88+
@Mock private SessionMetricUpdater sessionMetricUpdater;
8589

8690
private RequestHandlerTestHarness(Builder builder) {
8791
MockitoAnnotations.initMocks(this);
@@ -126,7 +130,7 @@ private RequestHandlerTestHarness(Builder builder) {
126130
Mockito.when(timestampGenerator.next()).thenReturn(Long.MIN_VALUE);
127131
Mockito.when(context.timestampGenerator()).thenReturn(timestampGenerator);
128132

129-
Map<Node, ChannelPool> pools = builder.buildMockPools();
133+
pools = builder.buildMockPools();
130134
Mockito.when(session.getChannel(any(Node.class), anyString()))
131135
.thenAnswer(
132136
invocation -> {
@@ -138,12 +142,20 @@ private RequestHandlerTestHarness(Builder builder) {
138142
Mockito.when(session.setKeyspace(any(CqlIdentifier.class)))
139143
.thenReturn(CompletableFuture.completedFuture(null));
140144

145+
Mockito.when(session.getMetricUpdater()).thenReturn(sessionMetricUpdater);
146+
147+
Mockito.when(session.getMetadata()).thenReturn(DefaultMetadata.EMPTY);
148+
141149
Mockito.when(context.protocolVersionRegistry()).thenReturn(protocolVersionRegistry);
142150
Mockito.when(
143151
protocolVersionRegistry.supports(
144152
any(ProtocolVersion.class), any(ProtocolFeature.class)))
145153
.thenReturn(true);
146154

155+
if (builder.protocolVersion != null) {
156+
Mockito.when(context.protocolVersion()).thenReturn(builder.protocolVersion);
157+
}
158+
147159
Mockito.when(context.consistencyLevelRegistry())
148160
.thenReturn(new DefaultConsistencyLevelRegistry());
149161

@@ -158,6 +170,11 @@ public InternalDriverContext getContext() {
158170
return context;
159171
}
160172

173+
public DriverChannel getChannel(Node node) {
174+
ChannelPool pool = pools.get(node);
175+
return pool.next();
176+
}
177+
161178
/**
162179
* Returns the next task that was scheduled on the request handler's admin executor. The test must
163180
* run it manually.
@@ -174,6 +191,7 @@ public void close() {
174191
public static class Builder {
175192
private final List<PoolBehavior> poolBehaviors = new ArrayList<>();
176193
private boolean defaultIdempotence;
194+
private ProtocolVersion protocolVersion;
177195

178196
/**
179197
* Sets the given node as the next one in the query plan; an empty pool will be simulated when
@@ -224,6 +242,11 @@ public Builder withDefaultIdempotence(boolean defaultIdempotence) {
224242
return this;
225243
}
226244

245+
public Builder withProtocolVersion(ProtocolVersion protocolVersion) {
246+
this.protocolVersion = protocolVersion;
247+
return this;
248+
}
249+
227250
/**
228251
* Sets the given node as the next one in the query plan; the test code is responsible of
229252
* calling the methods on the returned object to complete the write and the query.

0 commit comments

Comments
 (0)