-
Notifications
You must be signed in to change notification settings - Fork 886
JAVA-3076: NullSavingStrategyIT sometimes fails with ProtocolError: M… #1669
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,9 +36,11 @@ | |
| import com.datastax.oss.driver.api.mapper.entity.saving.NullSavingStrategy; | ||
| import com.datastax.oss.driver.api.testinfra.ccm.CcmRule; | ||
| import com.datastax.oss.driver.api.testinfra.session.SessionRule; | ||
| import com.datastax.oss.driver.api.testinfra.session.SessionUtils; | ||
| import com.datastax.oss.driver.categories.ParallelizableTests; | ||
| import java.util.Objects; | ||
| import java.util.UUID; | ||
| import org.junit.AfterClass; | ||
| import org.junit.BeforeClass; | ||
| import org.junit.ClassRule; | ||
| import org.junit.Test; | ||
|
|
@@ -51,13 +53,24 @@ public class NullSavingStrategyIT { | |
|
|
||
| private static final CcmRule CCM_RULE = CcmRule.getInstance(); | ||
|
|
||
| private static final SessionRule<CqlSession> SESSION_RULE = | ||
| SessionRule.builder(CCM_RULE) | ||
| .withConfigLoader( | ||
| DriverConfigLoader.programmaticBuilder() | ||
| .withString(DefaultDriverOption.PROTOCOL_VERSION, "V3") | ||
| .build()) | ||
| .build(); | ||
| private static final SessionRule<CqlSession> SESSION_RULE = SessionRule.builder(CCM_RULE).build(); | ||
|
|
||
| // JAVA-3076: V3 protocol calls that could trigger cassandra to issue client warnings appear to be | ||
| // inherently unstable when used at the same time as V4+ protocol clients (common since this is | ||
| // part of the parallelizable test suite). | ||
| // | ||
| // For this test we'll use latest protocol version for SessionRule set-up, which creates the | ||
| // keyspace and could potentially result in warning about too many keyspaces, and then create a | ||
| // new client for the tests to use, which they access via the static InventoryMapper instance | ||
| // `mapper`. | ||
| // | ||
| // This additional client is created in the @BeforeClass method #setup() and guaranteed to be | ||
| // closed in @AfterClass method #teardown(). | ||
| // | ||
| // Note: The standard junit runner executes rules before class/test setup so the order of | ||
| // execution will be CcmRule#before > SessionRule#before > NullSavingStrategyIT#setup, meaning | ||
| // CCM_RULE/SESSION_RULE should be fully initialized by the time #setup() is invoked. | ||
| private static CqlSession v3Session; | ||
|
|
||
| @ClassRule | ||
| public static final TestRule CHAIN = RuleChain.outerRule(CCM_RULE).around(SESSION_RULE); | ||
|
|
@@ -66,14 +79,34 @@ public class NullSavingStrategyIT { | |
|
|
||
| @BeforeClass | ||
| public static void setup() { | ||
| CqlSession session = SESSION_RULE.session(); | ||
| session.execute( | ||
| SimpleStatement.builder( | ||
| "CREATE TABLE product_simple(id uuid PRIMARY KEY, description text)") | ||
| .setExecutionProfile(SESSION_RULE.slowProfile()) | ||
| .build()); | ||
|
|
||
| mapper = new NullSavingStrategyIT_InventoryMapperBuilder(session).build(); | ||
| // setup table for use in tests, this can use the default session | ||
| SESSION_RULE | ||
| .session() | ||
| .execute( | ||
| SimpleStatement.builder( | ||
| "CREATE TABLE product_simple(id uuid PRIMARY KEY, description text)") | ||
| .setExecutionProfile(SESSION_RULE.slowProfile()) | ||
| .build()); | ||
|
|
||
| // Create V3 protocol session for use in tests, will be closed in #teardown() | ||
| v3Session = | ||
| SessionUtils.newSession( | ||
| CCM_RULE, | ||
| SESSION_RULE.keyspace(), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An interesting question (that I genuinely don't know the answer to)... is this always safe? We're accessing a static field from a static method which presumes that the field will always be initialized before the method is called... even though both are static. This isn't a change in behaviour (the old code did it too)... just something I wondered about.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It depends on the junit runner. In this case we're using the default which ends up being
So the order will be |
||
| DriverConfigLoader.programmaticBuilder() | ||
| .withString(DefaultDriverOption.PROTOCOL_VERSION, "V3") | ||
| .build()); | ||
|
|
||
| // Hand V3 session to InventoryMapper which the tests will use to perform db calls | ||
| mapper = new NullSavingStrategyIT_InventoryMapperBuilder(v3Session).build(); | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per my comment above... doesn't this accomplish exactly the same thing without requiring a new field (or a teardown method)? @BeforeClass
public static void setup() {
// JAVA-3076: Perform setup using a one-off v5 session to avoid any errors when using v3
DriverConfigLoader setupSessionLoader = DriverConfigLoader.programmaticBuilder()
.withString(DefaultDriverOption.PROTOCOL_VERSION, "V5")
.build());
try (CqlSession setupSession = SessionUtils.newSession(CCM_RULE, SESSION_RULE.keyspace(), setupSessionLoader)) {
setupSession.execute(
SimpleStatement.builder(
"CREATE TABLE product_simple(id uuid PRIMARY KEY, description text)")
.setExecutionProfile(SESSION_RULE.slowProfile())
.build());
}
// JAVA-3076: Actual test should continue to use v3 just like it always has
mapper = new NullSavingStrategyIT_InventoryMapperBuilder(SESSION_RULE.session()).build();
}The code snippet above assumes that SESSION_RULE remains identical to what it current is in 4.x.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The error isn't coming from the table create in the |
||
|
|
||
| @AfterClass | ||
| public static void teardown() { | ||
| // Close V3 session (SESSION_RULE will be closed separately by @ClassRule handling) | ||
| if (v3Session != null) { | ||
| v3Session.close(); | ||
| } | ||
| } | ||
|
|
||
| @Test | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit confused as to why we're keeping this session around as a static reference when we really only need it for a one-off operation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to close this session at the end of the test class, for
SESSION_RULEthis is handled automatically by junit which callsSessionRule#after()(and subsequentlysession.close()) because it's a@ClassRuleThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the comments could be clearer here - this session instance is being used in all the tests via the
mapperobject so we need to keep it around until after they've all finished