Skip to content

Commit cc186ba

Browse files
authored
Add version information to yaml test exceptions (#3189)
This does the following: 1. It introduces a `YamlConnection` interface that wraps the underlying connection. 2. This makes it easier to have the connection expose what versions it is testing against The issue we found is that when running in mixed-mode it runs the same query multiple times in parallel (as intended, I just didn't realize). This makes it incredibly hard to tell if a failing test is failing because it fails when going from the old version to the new version, or vice-versa.
1 parent b5d6d27 commit cc186ba

21 files changed

+471
-309
lines changed

yaml-tests/src/main/java/com/apple/foundationdb/relational/yamltests/MultiServerConnectionFactory.java

Lines changed: 66 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,19 @@
2020

2121
package com.apple.foundationdb.relational.yamltests;
2222

23-
import com.apple.foundationdb.relational.api.Options;
24-
import com.apple.foundationdb.relational.api.RelationalConnection;
2523
import com.apple.foundationdb.relational.api.RelationalPreparedStatement;
2624
import com.apple.foundationdb.relational.api.RelationalStatement;
25+
import com.apple.foundationdb.relational.api.metrics.MetricCollector;
26+
import com.apple.foundationdb.relational.recordlayer.EmbeddedRelationalConnection;
27+
import com.apple.foundationdb.relational.util.Assert;
2728
import org.apache.logging.log4j.LogManager;
2829
import org.apache.logging.log4j.Logger;
2930
import org.junit.jupiter.api.Assertions;
3031

3132
import javax.annotation.Nonnull;
33+
import javax.annotation.Nullable;
3234
import java.net.URI;
33-
import java.sql.Array;
34-
import java.sql.Connection;
35-
import java.sql.DatabaseMetaData;
3635
import java.sql.SQLException;
37-
import java.sql.Struct;
3836
import java.util.ArrayList;
3937
import java.util.List;
4038
import java.util.Set;
@@ -48,7 +46,7 @@
4846
* running concurrently, and verify that the results (e.g. Continuations) are correctly handled through the entire
4947
* setup.
5048
*/
51-
public class MultiServerConnectionFactory implements YamlRunner.YamlConnectionFactory {
49+
public class MultiServerConnectionFactory implements YamlConnectionFactory {
5250
// The fixed index of the default connection
5351
public static final int DEFAULT_CONNECTION = 0;
5452
private final Set<String> versionsUnderTest;
@@ -63,22 +61,17 @@ public enum ConnectionSelectionPolicy { DEFAULT, ALTERNATE }
6361
@Nonnull
6462
private final ConnectionSelectionPolicy connectionSelectionPolicy;
6563
@Nonnull
66-
private final YamlRunner.YamlConnectionFactory defaultFactory;
64+
private final YamlConnectionFactory defaultFactory;
6765
@Nonnull
68-
private final List<YamlRunner.YamlConnectionFactory> alternateFactories;
66+
private final List<YamlConnectionFactory> alternateFactories;
6967
private final int totalFactories;
7068
@Nonnull
7169
private final AtomicInteger currentConnectionSelector;
7270

73-
public MultiServerConnectionFactory(@Nonnull final YamlRunner.YamlConnectionFactory defaultFactory,
74-
@Nonnull final List<YamlRunner.YamlConnectionFactory> alternateFactories) {
75-
this(ConnectionSelectionPolicy.DEFAULT, 0, defaultFactory, alternateFactories);
76-
}
77-
7871
public MultiServerConnectionFactory(@Nonnull final ConnectionSelectionPolicy connectionSelectionPolicy,
7972
final int initialConnection,
80-
@Nonnull final YamlRunner.YamlConnectionFactory defaultFactory,
81-
@Nonnull final List<YamlRunner.YamlConnectionFactory> alternateFactories) {
73+
@Nonnull final YamlConnectionFactory defaultFactory,
74+
@Nonnull final List<YamlConnectionFactory> alternateFactories) {
8275
this.connectionSelectionPolicy = connectionSelectionPolicy;
8376
this.defaultFactory = defaultFactory;
8477
this.alternateFactories = alternateFactories;
@@ -93,8 +86,13 @@ public MultiServerConnectionFactory(@Nonnull final ConnectionSelectionPolicy con
9386
}
9487

9588
@Override
96-
public Connection getNewConnection(@Nonnull URI connectPath) throws SQLException {
97-
return new MultiServerRelationalConnection(connectionSelectionPolicy, getNextConnectionNumber(), defaultFactory.getNewConnection(connectPath), alternateConnections(connectPath));
89+
public YamlConnection getNewConnection(@Nonnull URI connectPath) throws SQLException {
90+
if (connectionSelectionPolicy == ConnectionSelectionPolicy.DEFAULT) {
91+
return defaultFactory.getNewConnection(connectPath);
92+
} else {
93+
return new MultiServerConnection(connectionSelectionPolicy, getNextConnectionNumber(),
94+
defaultFactory.getNewConnection(connectPath), alternateConnections(connectPath));
95+
}
9896
}
9997

10098
@Override
@@ -107,12 +105,8 @@ public boolean isMultiServer() {
107105
return true;
108106
}
109107

110-
public int getCurrentConnectionSelector() {
111-
return currentConnectionSelector.get();
112-
}
113-
114108
@Nonnull
115-
private List<Connection> alternateConnections(URI connectPath) {
109+
private List<YamlConnection> alternateConnections(URI connectPath) {
116110
return alternateFactories.stream().map(factory -> {
117111
try {
118112
return factory.getNewConnection(connectPath);
@@ -144,32 +138,30 @@ private int getNextConnectionNumber() {
144138
* A connection that wraps around multiple connections.
145139
*/
146140
@SuppressWarnings("PMD.CloseResource") // false-positive as constituent connections are closed when object is closed
147-
public static class MultiServerRelationalConnection implements RelationalConnection {
148-
private static final Logger logger = LogManager.getLogger(MultiServerRelationalConnection.class);
141+
public static class MultiServerConnection implements YamlConnection {
142+
private static final Logger logger = LogManager.getLogger(MultiServerConnection.class);
149143

150144
private int currentConnectionSelector;
151145

152146
@Nonnull
153147
private final ConnectionSelectionPolicy connectionSelectionPolicy;
154148
@Nonnull
155-
private final List<RelationalConnection> relationalConnections;
149+
private final List<YamlConnection> underlyingConnections;
150+
@Nonnull
151+
private final List<String> versions;
156152

157-
public MultiServerRelationalConnection(@Nonnull ConnectionSelectionPolicy connectionSelectionPolicy,
158-
final int initialConnecion,
159-
@Nonnull final Connection defaultConnection,
160-
@Nonnull List<Connection> alternateConnections) throws SQLException {
153+
public MultiServerConnection(@Nonnull ConnectionSelectionPolicy connectionSelectionPolicy,
154+
final int initialConnecion,
155+
@Nonnull final YamlConnection defaultConnection,
156+
@Nonnull List<YamlConnection> alternateConnections) throws SQLException {
161157
this.connectionSelectionPolicy = connectionSelectionPolicy;
162158
this.currentConnectionSelector = initialConnecion;
163-
relationalConnections = new ArrayList<>();
159+
underlyingConnections = new ArrayList<>();
164160
// The default connection is always the one at location 0
165-
relationalConnections.add(defaultConnection.unwrap(RelationalConnection.class));
166-
for (final Connection alternateConnection : alternateConnections) {
167-
relationalConnections.add(alternateConnection.unwrap(RelationalConnection.class));
168-
}
169-
}
161+
underlyingConnections.add(defaultConnection);
162+
underlyingConnections.addAll(alternateConnections);
170163

171-
public int getCurrentConnectionSelector() {
172-
return currentConnectionSelector;
164+
versions = createVersionsList(initialConnecion, underlyingConnections);
173165
}
174166

175167
@Override
@@ -182,103 +174,35 @@ public RelationalPreparedStatement prepareStatement(String sql) throws SQLExcept
182174
return getCurrentConnection(true, "prepareStatement").prepareStatement(sql);
183175
}
184176

177+
@Nullable
185178
@Override
186-
public void setAutoCommit(boolean autoCommit) throws SQLException {
187-
if (!autoCommit) {
188-
throw new UnsupportedOperationException("setAutoCommit(false) is not supported in YAML tests");
189-
}
190-
logger.info("Sending operation {} to all connections", "setAutoCommit");
191-
for (RelationalConnection connection: relationalConnections) {
192-
connection.setAutoCommit(autoCommit);
193-
}
194-
}
195-
196-
@Override
197-
public boolean getAutoCommit() throws SQLException {
198-
return getCurrentConnection(false, "getAutoCommit").getAutoCommit();
179+
public MetricCollector getMetricCollector() {
180+
throw new UnsupportedOperationException("MultiServer does not support getting the metric collector");
199181
}
200182

183+
@Nullable
201184
@Override
202-
public void commit() throws SQLException {
203-
throw new UnsupportedOperationException("commit is not supported in YAML tests");
185+
public EmbeddedRelationalConnection tryGetEmbedded() {
186+
return null;
204187
}
205188

189+
@Nonnull
206190
@Override
207-
public void rollback() throws SQLException {
208-
throw new UnsupportedOperationException("rollback is not supported in YAML tests");
191+
public List<String> getVersions() {
192+
return this.versions;
209193
}
210194

211195
@Override
212196
public void close() throws SQLException {
213197
logger.info("Sending operation {} to all connections", "close");
214-
for (RelationalConnection connection : relationalConnections) {
198+
for (var connection : underlyingConnections) {
215199
connection.close();
216200
}
217201
}
218202

219203
@Override
220-
public boolean isClosed() throws SQLException {
221-
return getCurrentConnection(false, "isClosed").isClosed();
222-
}
223-
224-
@Override
225-
public DatabaseMetaData getMetaData() throws SQLException {
226-
return getCurrentConnection(false, "getMetaData").getMetaData();
227-
}
228-
229-
@Override
230-
public void setTransactionIsolation(int level) throws SQLException {
231-
logger.info("Sending operation {} to all connections", "setTransactionIsolation");
232-
for (RelationalConnection connection : relationalConnections) {
233-
connection.setTransactionIsolation(level);
234-
}
235-
}
236-
237-
@Override
238-
public int getTransactionIsolation() throws SQLException {
239-
return getCurrentConnection(false, "getTransactionIsolation").getTransactionIsolation();
240-
}
241-
242-
@Override
243-
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
244-
return getCurrentConnection(true, "createArrayOf").createArrayOf(typeName, elements);
245-
}
246-
247-
@Override
248-
public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
249-
return getCurrentConnection(true, "createStruct").createStruct(typeName, attributes);
250-
}
251-
252-
@Override
253-
public void setSchema(String schema) throws SQLException {
254-
logger.info("Sending operation {} to all connections", "setSchema");
255-
for (RelationalConnection connection: relationalConnections) {
256-
connection.setSchema(schema);
257-
}
258-
}
259-
260-
@Override
261-
public String getSchema() throws SQLException {
262-
return getCurrentConnection(false, "getSchema").getSchema();
263-
}
264-
265-
@Nonnull
266-
@Override
267-
public Options getOptions() {
268-
return getCurrentConnection(false, "getOptions").getOptions();
269-
}
270-
271-
@Override
272-
public void setOption(Options.Name name, Object value) throws SQLException {
273-
logger.info("Sending operation {} to all connections", "setOption");
274-
for (RelationalConnection connection: relationalConnections) {
275-
connection.setOption(name, value);
276-
}
277-
}
278-
279-
@Override
280-
public URI getPath() {
281-
return getCurrentConnection(false, "getPath").getPath();
204+
public boolean supportsMetricCollector() {
205+
return false;
282206
}
283207

284208
/**
@@ -290,34 +214,34 @@ public URI getPath() {
290214
* @param op the name of the operation (for logging)
291215
* @return the underlying connection to use
292216
*/
293-
private RelationalConnection getCurrentConnection(boolean advance, String op) {
294-
switch (connectionSelectionPolicy) {
295-
case DEFAULT:
296-
if (logger.isInfoEnabled()) {
297-
logger.info("Sending operation {} to connection {}", op, "DEFAULT");
298-
}
299-
return relationalConnections.get(DEFAULT_CONNECTION);
300-
case ALTERNATE:
301-
RelationalConnection result = relationalConnections.get(currentConnectionSelector);
302-
if (logger.isInfoEnabled()) {
303-
logger.info("Sending operation {} to connection {}", op, currentConnectionSelector);
304-
}
305-
if (advance) {
306-
currentConnectionSelector = (currentConnectionSelector + 1) % relationalConnections.size();
307-
}
308-
return result;
309-
default:
310-
throw new IllegalStateException("Unsupported selection policy " + connectionSelectionPolicy);
217+
private YamlConnection getCurrentConnection(boolean advance, String op) {
218+
if (connectionSelectionPolicy == ConnectionSelectionPolicy.ALTERNATE) {
219+
YamlConnection result = underlyingConnections.get(currentConnectionSelector);
220+
if (logger.isInfoEnabled()) {
221+
logger.info("Sending operation {} to connection {}", op, currentConnectionSelector);
222+
}
223+
if (advance) {
224+
currentConnectionSelector = (currentConnectionSelector + 1) % underlyingConnections.size();
225+
}
226+
return result;
311227
}
228+
throw new IllegalStateException("Unsupported selection policy " + connectionSelectionPolicy);
312229
}
313230

314-
@Override
315-
public <T> T unwrap(final Class<T> iface) throws SQLException {
316-
if (iface.equals(RelationalConnection.class)) {
317-
return iface.cast(this);
318-
} else {
319-
return RelationalConnection.super.unwrap(iface);
231+
private static List<String> createVersionsList(final int initialConnecion,
232+
final List<YamlConnection> relationalConnections) {
233+
List<String> versions = new ArrayList<>();
234+
for (int i = initialConnecion; i < relationalConnections.size(); i++) {
235+
final List<String> underlying = relationalConnections.get(i).getVersions();
236+
Assert.thatUnchecked(underlying.size() == 1, "Part of multi server config has more than one version");
237+
versions.add(underlying.get(0));
238+
}
239+
for (int i = 0; i < initialConnecion; i++) {
240+
final List<String> underlying = relationalConnections.get(i).getVersions();
241+
Assert.thatUnchecked(underlying.size() == 1, "Part of multi server config has more than one version");
242+
versions.add(underlying.get(0));
320243
}
244+
return List.copyOf(versions);
321245
}
322246
}
323247
}

0 commit comments

Comments
 (0)