Skip to content

Commit c543e3d

Browse files
committed
Optimize PreparedStatementIT, BatchStatementIT, and BoundStatementCcmIT to reuse sessions across tests
Convert @rule to @ClassRule for CcmRule and SessionRule so that the CCM cluster and CQL session are created once per test class instead of once per test method. This eliminates repeated cluster startup/teardown overhead across all tests in these classes. For PreparedStatementIT specifically: - Replace DROP+CREATE TABLE with TRUNCATE between tests that don't modify schema, since most tests only need a clean table - Track schema-altering tests (ALTER TABLE, DROP TABLE) with a flag so the table is only recreated when actually needed - Use regular session.execute() for INSERT statements instead of routing them through the slow DDL execution profile - Use try-with-resources in cross-session test to avoid prepare cache interference from the shared session Retain CcmRule as a per-method @rule so that @BackendRequirement, @ScyllaOnly, and @ScyllaSkip annotations are still evaluated per test.
1 parent 18cce15 commit c543e3d

3 files changed

Lines changed: 97 additions & 71 deletions

File tree

integration-tests/src/test/java/com/datastax/oss/driver/core/cql/BatchStatementIT.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@
5656
import com.datastax.oss.driver.internal.core.util.LoggerTest;
5757
import java.util.Iterator;
5858
import java.util.List;
59-
import org.junit.Before;
59+
import org.junit.BeforeClass;
60+
import org.junit.ClassRule;
6061
import org.junit.Ignore;
6162
import org.junit.Rule;
6263
import org.junit.Test;
@@ -68,18 +69,21 @@
6869
@Category(ParallelizableTests.class)
6970
public class BatchStatementIT {
7071

71-
private final CcmRule CCM_RULE = CcmRule.getInstance();
72+
private static final CcmRule CCM_RULE = CcmRule.getInstance();
7273

73-
private final SessionRule<CqlSession> SESSION_RULE = SessionRule.builder(CCM_RULE).build();
74+
private static final SessionRule<CqlSession> SESSION_RULE = SessionRule.builder(CCM_RULE).build();
7475

75-
@Rule public TestRule chain = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE);
76+
@ClassRule public static TestRule classChain = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE);
77+
78+
// CcmRule as @Rule for per-method @BackendRequirement annotation checking
79+
@Rule public TestRule methodChain = CCM_RULE;
7680

7781
@Rule public TestName name = new TestName();
7882

7983
private static final int batchCount = 100;
8084

81-
@Before
82-
public void createTable() {
85+
@BeforeClass
86+
public static void createTable() {
8387
String[] schemaStatements =
8488
new String[] {
8589
"CREATE TABLE test (k0 text, k1 int, v int, PRIMARY KEY (k0, k1))",

integration-tests/src/test/java/com/datastax/oss/driver/core/cql/BoundStatementCcmIT.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@
7777
import java.util.Map;
7878
import java.util.concurrent.CompletionStage;
7979
import java.util.function.Function;
80-
import org.junit.Before;
80+
import org.junit.BeforeClass;
81+
import org.junit.ClassRule;
8182
import org.junit.Ignore;
8283
import org.junit.Rule;
8384
import org.junit.Test;
@@ -91,28 +92,31 @@
9192
@RunWith(DataProviderRunner.class)
9293
public class BoundStatementCcmIT {
9394

94-
private CcmRule ccmRule = CcmRule.getInstance();
95+
private static final CcmRule ccmRule = CcmRule.getInstance();
9596

96-
private final boolean atLeastV4 = ccmRule.getHighestProtocolVersion().getCode() >= 4;
97+
private static final boolean atLeastV4 = ccmRule.getHighestProtocolVersion().getCode() >= 4;
9798

98-
private SessionRule<CqlSession> sessionRule =
99+
private static final SessionRule<CqlSession> sessionRule =
99100
SessionRule.builder(ccmRule)
100101
.withConfigLoader(
101102
SessionUtils.configLoaderBuilder()
102103
.withInt(DefaultDriverOption.REQUEST_PAGE_SIZE, 20)
103104
.build())
104105
.build();
105106

106-
@Rule public TestRule chain = RuleChain.outerRule(ccmRule).around(sessionRule);
107+
@ClassRule public static TestRule classChain = RuleChain.outerRule(ccmRule).around(sessionRule);
108+
109+
// CcmRule as @Rule for per-method @ScyllaSkip / @BackendRequirement annotation checking
110+
@Rule public TestRule methodChain = ccmRule;
107111

108112
@Rule public TestName name = new TestName();
109113

110114
private static final String KEY = "test";
111115

112116
private static final int VALUE = 7;
113117

114-
@Before
115-
public void setupSchema() {
118+
@BeforeClass
119+
public static void setupSchema() {
116120
// table where every column forms the primary key.
117121
SchemaChangeSynchronizer.withLock(
118122
() -> {

integration-tests/src/test/java/com/datastax/oss/driver/core/cql/PreparedStatementIT.java

Lines changed: 76 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
import junit.framework.TestCase;
6565
import org.assertj.core.api.AbstractThrowableAssert;
6666
import org.junit.Before;
67+
import org.junit.ClassRule;
6768
import org.junit.Rule;
6869
import org.junit.Test;
6970
import org.junit.experimental.categories.Category;
@@ -84,9 +85,9 @@ public class PreparedStatementIT {
8485
private static final Version SCYLLA_METADATA_ID_SUPPORT_VERSION =
8586
Objects.requireNonNull(Version.parse("2025.3"));
8687

87-
private final CcmRule ccmRule = CcmRule.getInstance();
88+
private static final CcmRule ccmRule = CcmRule.getInstance();
8889

89-
private final SessionRule<CqlSession> sessionRule =
90+
private static final SessionRule<CqlSession> sessionRule =
9091
SessionRule.builder(ccmRule)
9192
.withConfigLoader(
9293
SessionUtils.configLoaderBuilder()
@@ -95,19 +96,31 @@ public class PreparedStatementIT {
9596
.build())
9697
.build();
9798

98-
@Rule public TestRule chain = RuleChain.outerRule(ccmRule).around(sessionRule);
99+
@ClassRule public static TestRule classChain = RuleChain.outerRule(ccmRule).around(sessionRule);
100+
101+
// CcmRule as @Rule for per-method @ScyllaOnly / @BackendRequirement annotation checking
102+
@Rule public TestRule methodChain = ccmRule;
103+
104+
// When true, @Before will DROP+CREATE the table (needed after tests that ALTER TABLE).
105+
// Starts as true so the table is created on first run.
106+
private static boolean needsTableRecreate = true;
99107

100108
@Before
101109
public void setupSchema() {
110+
if (needsTableRecreate) {
111+
executeDdl("DROP TABLE IF EXISTS prepared_statement_test");
112+
executeDdl("CREATE TABLE prepared_statement_test (a int PRIMARY KEY, b int, c int)");
113+
needsTableRecreate = false;
114+
} else {
115+
executeDdl("TRUNCATE prepared_statement_test");
116+
}
102117
for (String query :
103118
ImmutableList.of(
104-
"DROP TABLE IF EXISTS prepared_statement_test",
105-
"CREATE TABLE prepared_statement_test (a int PRIMARY KEY, b int, c int)",
106119
"INSERT INTO prepared_statement_test (a, b, c) VALUES (1, 1, 1)",
107120
"INSERT INTO prepared_statement_test (a, b, c) VALUES (2, 2, 2)",
108121
"INSERT INTO prepared_statement_test (a, b, c) VALUES (3, 3, 3)",
109122
"INSERT INTO prepared_statement_test (a, b, c) VALUES (4, 4, 4)")) {
110-
executeDdl(query);
123+
sessionRule.session().execute(query);
111124
}
112125
}
113126

@@ -176,6 +189,7 @@ public void should_update_metadata_when_schema_changed_across_executions() {
176189
}
177190

178191
// When
192+
needsTableRecreate = true;
179193
session.execute(
180194
SimpleStatement.builder("ALTER TABLE prepared_statement_test ADD d int")
181195
.setExecutionProfile(sessionRule.slowProfile())
@@ -239,6 +253,7 @@ public void should_update_metadata_when_schema_changed_across_pages() {
239253
}
240254

241255
// When
256+
needsTableRecreate = true;
242257
session.execute(
243258
SimpleStatement.builder("ALTER TABLE prepared_statement_test ADD d int")
244259
.setExecutionProfile(sessionRule.slowProfile())
@@ -271,71 +286,71 @@ public void should_update_metadata_when_schema_changed_across_pages() {
271286
@BackendRequirement(type = BackendType.CASSANDRA, minInclusive = "4.0")
272287
@BackendRequirement(type = BackendType.SCYLLA)
273288
public void should_update_metadata_when_schema_changed_across_sessions() {
274-
// Given
275-
CqlSession session1 = sessionRule.session();
276-
CqlSession session2 = SessionUtils.newSession(ccmRule, sessionRule.keyspace());
277-
278-
PreparedStatement ps1 = session1.prepare("SELECT * FROM prepared_statement_test WHERE a = ?");
279-
PreparedStatement ps2 = session2.prepare("SELECT * FROM prepared_statement_test WHERE a = ?");
280-
281-
ByteBuffer id1a = ps1.getResultMetadataId();
282-
ByteBuffer id2a = ps2.getResultMetadataId();
283-
if (hasNoScyllaMetadataIdSupport()) {
284-
// Scylla does not support CQL5 extensions and metadata id
285-
assertThat(id1a).isNull();
286-
assertThat(id2a).isNull();
287-
}
289+
// Use fresh sessions to avoid prepare cache interference from other tests that use the
290+
// same query string on the shared session.
291+
try (CqlSession session1 = SessionUtils.newSession(ccmRule, sessionRule.keyspace());
292+
CqlSession session2 = SessionUtils.newSession(ccmRule, sessionRule.keyspace())) {
293+
// Given
294+
PreparedStatement ps1 = session1.prepare("SELECT * FROM prepared_statement_test WHERE a = ?");
295+
PreparedStatement ps2 = session2.prepare("SELECT * FROM prepared_statement_test WHERE a = ?");
296+
297+
ByteBuffer id1a = ps1.getResultMetadataId();
298+
ByteBuffer id2a = ps2.getResultMetadataId();
299+
if (hasNoScyllaMetadataIdSupport()) {
300+
// Scylla does not support CQL5 extensions and metadata id
301+
assertThat(id1a).isNull();
302+
assertThat(id2a).isNull();
303+
}
288304

289-
ResultSet rows1 = session1.execute(ps1.bind(1));
290-
ResultSet rows2 = session2.execute(ps2.bind(1));
305+
ResultSet rows1 = session1.execute(ps1.bind(1));
306+
ResultSet rows2 = session2.execute(ps2.bind(1));
291307

292-
assertThat(rows1.getColumnDefinitions()).hasSize(3);
293-
assertThat(rows1.getColumnDefinitions().contains("d")).isFalse();
294-
assertThat(rows2.getColumnDefinitions()).hasSize(3);
295-
assertThat(rows2.getColumnDefinitions().contains("d")).isFalse();
308+
assertThat(rows1.getColumnDefinitions()).hasSize(3);
309+
assertThat(rows1.getColumnDefinitions().contains("d")).isFalse();
310+
assertThat(rows2.getColumnDefinitions()).hasSize(3);
311+
assertThat(rows2.getColumnDefinitions().contains("d")).isFalse();
296312

297-
// When
298-
session1.execute("ALTER TABLE prepared_statement_test ADD d int");
313+
// When
314+
needsTableRecreate = true;
315+
session1.execute("ALTER TABLE prepared_statement_test ADD d int");
299316

300-
rows1 = session1.execute(ps1.bind(1));
301-
rows2 = session2.execute(ps2.bind(1));
317+
rows1 = session1.execute(ps1.bind(1));
318+
rows2 = session2.execute(ps2.bind(1));
302319

303-
ByteBuffer id1b = ps1.getResultMetadataId();
304-
ByteBuffer id2b = ps2.getResultMetadataId();
320+
ByteBuffer id1b = ps1.getResultMetadataId();
321+
ByteBuffer id2b = ps2.getResultMetadataId();
305322

306-
// Then
307-
if (hasNoScyllaMetadataIdSupport()) {
308-
// Scylla does not support CQL5 extensions and metadata id
309-
assertThat(id1b).isNull();
310-
assertThat(id2b).isNull();
323+
// Then
324+
if (hasNoScyllaMetadataIdSupport()) {
325+
// Scylla does not support CQL5 extensions and metadata id
326+
assertThat(id1b).isNull();
327+
assertThat(id2b).isNull();
328+
329+
assertThat(ps1.getResultSetDefinitions()).hasSize(3);
330+
assertThat(ps1.getResultSetDefinitions().contains("d")).isFalse();
331+
assertThat(ps2.getResultSetDefinitions()).hasSize(3);
332+
assertThat(ps2.getResultSetDefinitions().contains("d")).isFalse();
333+
334+
assertThat(rows1.getColumnDefinitions()).hasSize(4);
335+
assertThat(rows1.getColumnDefinitions().contains("d")).isTrue();
336+
assertThat(rows2.getColumnDefinitions()).hasSize(4);
337+
assertThat(rows2.getColumnDefinitions().contains("d")).isTrue();
338+
339+
return;
340+
}
341+
assertThat(Bytes.toHexString(id1b)).isNotEqualTo(Bytes.toHexString(id1a));
342+
assertThat(Bytes.toHexString(id2b)).isNotEqualTo(Bytes.toHexString(id2a));
311343

312-
assertThat(ps1.getResultSetDefinitions()).hasSize(3);
313-
assertThat(ps1.getResultSetDefinitions().contains("d")).isFalse();
314-
assertThat(ps2.getResultSetDefinitions()).hasSize(3);
315-
assertThat(ps2.getResultSetDefinitions().contains("d")).isFalse();
344+
assertThat(ps1.getResultSetDefinitions()).hasSize(4);
345+
assertThat(ps1.getResultSetDefinitions().contains("d")).isTrue();
346+
assertThat(ps2.getResultSetDefinitions()).hasSize(4);
347+
assertThat(ps2.getResultSetDefinitions().contains("d")).isTrue();
316348

317349
assertThat(rows1.getColumnDefinitions()).hasSize(4);
318350
assertThat(rows1.getColumnDefinitions().contains("d")).isTrue();
319351
assertThat(rows2.getColumnDefinitions()).hasSize(4);
320352
assertThat(rows2.getColumnDefinitions().contains("d")).isTrue();
321-
322-
session2.close();
323-
return;
324353
}
325-
assertThat(Bytes.toHexString(id1b)).isNotEqualTo(Bytes.toHexString(id1a));
326-
assertThat(Bytes.toHexString(id2b)).isNotEqualTo(Bytes.toHexString(id2a));
327-
328-
assertThat(ps1.getResultSetDefinitions()).hasSize(4);
329-
assertThat(ps1.getResultSetDefinitions().contains("d")).isTrue();
330-
assertThat(ps2.getResultSetDefinitions()).hasSize(4);
331-
assertThat(ps2.getResultSetDefinitions().contains("d")).isTrue();
332-
333-
assertThat(rows1.getColumnDefinitions()).hasSize(4);
334-
assertThat(rows1.getColumnDefinitions().contains("d")).isTrue();
335-
assertThat(rows2.getColumnDefinitions()).hasSize(4);
336-
assertThat(rows2.getColumnDefinitions().contains("d")).isTrue();
337-
338-
session2.close();
339354
}
340355

341356
@Test
@@ -344,6 +359,7 @@ public void should_update_metadata_when_schema_changed_across_sessions() {
344359
public void should_fail_to_reprepare_if_query_becomes_invalid() {
345360
// Given
346361
CqlSession session = sessionRule.session();
362+
needsTableRecreate = true;
347363
session.execute("ALTER TABLE prepared_statement_test ADD d int");
348364
PreparedStatement ps =
349365
session.prepare("SELECT a, b, c, d FROM prepared_statement_test WHERE a = ?");
@@ -439,6 +455,7 @@ private void should_not_store_metadata_for_conditional_updates(CqlSession sessio
439455
assertThat(Bytes.toHexString(ps.getResultMetadataId())).isEqualTo(Bytes.toHexString(idBefore));
440456

441457
// When
458+
needsTableRecreate = true;
442459
session.execute("ALTER TABLE prepared_statement_test ADD d int");
443460
rs = session.execute(ps.bind(5, 5, 5));
444461

@@ -565,6 +582,7 @@ public void should_create_separate_instances_for_different_statement_parameters(
565582
session.execute("USE " + sessionRule.keyspace().asCql(false));
566583

567584
// Drop and recreate the table to invalidate the prepared statement server-side
585+
needsTableRecreate = true;
568586
executeDdl("DROP TABLE prepared_statement_test");
569587
executeDdl("CREATE TABLE prepared_statement_test (a int PRIMARY KEY, b int, c int)");
570588

0 commit comments

Comments
 (0)