Skip to content

Commit 37530a6

Browse files
committed
chore(spanner): update test cases
1 parent ba76d77 commit 37530a6

File tree

1 file changed

+91
-10
lines changed

1 file changed

+91
-10
lines changed

google-cloud-spanner/src/test/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClientMockServerTest.java

Lines changed: 91 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,12 +1253,6 @@ public void testMutationOnlyUsingAsyncTransactionManager() {
12531253
}
12541254

12551255
private Spanner setupSpannerForAbortedBeginTransactionTests() {
1256-
// Force the BeginTransaction RPC to return Aborted the first time it is called. The exception
1257-
// is cleared after the first call, so the retry should succeed.
1258-
mockSpanner.setBeginTransactionExecutionTime(
1259-
SimulatedExecutionTime.ofException(
1260-
mockSpanner.createAbortedException(ByteString.copyFromUtf8("test"))));
1261-
12621256
return SpannerOptions.newBuilder()
12631257
.setProjectId("test-project")
12641258
.setChannelProvider(channelProvider)
@@ -1304,6 +1298,13 @@ public void testMutationOnlyCaseAbortedDuringBeginTransaction() {
13041298
// 1. The mutation key is correctly included in the BeginTransaction request.
13051299
// 2. The precommit token is properly set in the Commit request.
13061300
Spanner spanner = setupSpannerForAbortedBeginTransactionTests();
1301+
1302+
// Force the BeginTransaction RPC to return Aborted the first time it is called. The exception
1303+
// is cleared after the first call, so the retry should succeed.
1304+
mockSpanner.setBeginTransactionExecutionTime(
1305+
SimulatedExecutionTime.ofException(
1306+
mockSpanner.createAbortedException(ByteString.copyFromUtf8("test"))));
1307+
13071308
DatabaseClientImpl client =
13081309
(DatabaseClientImpl) spanner.getDatabaseClient(DatabaseId.of("p", "i", "d"));
13091310

@@ -1336,6 +1337,13 @@ public void testMutationOnlyUsingTransactionManagerAbortedDuringBeginTransaction
13361337
// 1. The mutation key is correctly included in the BeginTransaction request.
13371338
// 2. The precommit token is properly set in the Commit request.
13381339
Spanner spanner = setupSpannerForAbortedBeginTransactionTests();
1340+
1341+
// Force the BeginTransaction RPC to return Aborted the first time it is called. The exception
1342+
// is cleared after the first call, so the retry should succeed.
1343+
mockSpanner.setBeginTransactionExecutionTime(
1344+
SimulatedExecutionTime.ofException(
1345+
mockSpanner.createAbortedException(ByteString.copyFromUtf8("test"))));
1346+
13391347
DatabaseClientImpl client =
13401348
(DatabaseClientImpl) spanner.getDatabaseClient(DatabaseId.of("p", "i", "d"));
13411349

@@ -1375,6 +1383,13 @@ public void testMutationOnlyUsingAsyncRunnerAbortedDuringBeginTransaction() {
13751383
// 2. The precommit token is properly set in the Commit request.
13761384

13771385
Spanner spanner = setupSpannerForAbortedBeginTransactionTests();
1386+
1387+
// Force the BeginTransaction RPC to return Aborted the first time it is called. The exception
1388+
// is cleared after the first call, so the retry should succeed.
1389+
mockSpanner.setBeginTransactionExecutionTime(
1390+
SimulatedExecutionTime.ofException(
1391+
mockSpanner.createAbortedException(ByteString.copyFromUtf8("test"))));
1392+
13781393
DatabaseClientImpl client =
13791394
(DatabaseClientImpl) spanner.getDatabaseClient(DatabaseId.of("p", "i", "d"));
13801395

@@ -1408,6 +1423,13 @@ public void testMutationOnlyUsingTransactionManagerAsyncAbortedDuringBeginTransa
14081423
// request
14091424
// and precommit token is set in Commit request.
14101425
Spanner spanner = setupSpannerForAbortedBeginTransactionTests();
1426+
1427+
// Force the BeginTransaction RPC to return Aborted the first time it is called. The exception
1428+
// is cleared after the first call, so the retry should succeed.
1429+
mockSpanner.setBeginTransactionExecutionTime(
1430+
SimulatedExecutionTime.ofException(
1431+
mockSpanner.createAbortedException(ByteString.copyFromUtf8("test"))));
1432+
14111433
DatabaseClientImpl client =
14121434
(DatabaseClientImpl) spanner.getDatabaseClient(DatabaseId.of("p", "i", "d"));
14131435

@@ -1589,7 +1611,7 @@ public void testPartitionedQuery_receivesUnimplemented_fallsBackToRegularSession
15891611

15901612
@Test
15911613
public void
1592-
testReadWriteUnimplementedErrorDuringInitialBeginTransactionRPC_firstReceivesError_secondFallsBackToRegularSessions() {
1614+
testReadWriteUnimplementedErrorDuringInitialBeginTransactionRPC_firstRetriedWithRegularSession_secondFallsBackToRegularSessions() {
15931615
// This test simulates the following scenario,
15941616
// 1. The server-side flag for RW multiplexed sessions is disabled.
15951617
// 2. Application starts. The initial BeginTransaction RPC during client initialization will
@@ -1638,6 +1660,8 @@ public void testPartitionedQuery_receivesUnimplemented_fallsBackToRegularSession
16381660
}
16391661
return null;
16401662
});
1663+
assertNotNull(runner.getCommitTimestamp());
1664+
assertNotNull(runner.getCommitResponse());
16411665

16421666
// Wait until the client sees that MultiplexedSessions are not supported for read-write.
16431667
assertNotNull(client.multiplexedSessionDatabaseClient);
@@ -1689,7 +1713,8 @@ public void testPartitionedQuery_receivesUnimplemented_fallsBackToRegularSession
16891713
}
16901714

16911715
@Test
1692-
public void testReadWriteUnimplemented_firstReceivesError_secondFallsBackToRegularSessions() {
1716+
public void
1717+
testReadWriteUnimplemented_firstRetriedWithRegularSession_secondFallsBackToRegularSessions() {
16931718
// This test simulates the following scenario,
16941719
// 1. The server side flag for read-write multiplexed session is not disabled. When an
16951720
// application starts, the initial BeginTransaction RPC with read-write will succeed.
@@ -1716,6 +1741,10 @@ public void testReadWriteUnimplemented_firstReceivesError_secondFallsBackToRegul
17161741
assertNotNull(txn.getId());
17171742
assertFalse(client.multiplexedSessionDatabaseClient.unimplementedForRW.get());
17181743

1744+
// Initially, the first attempt executes an ExecuteSqlRequest using multiplexed sessions, but it
1745+
// fails with UNIMPLEMENTED.
1746+
// On retry, the request should automatically switch to regular sessions, ensuring the
1747+
// transaction completes successfully.
17191748
client
17201749
.readWriteTransaction()
17211750
.run(
@@ -1728,11 +1757,12 @@ public void testReadWriteUnimplemented_firstReceivesError_secondFallsBackToRegul
17281757
return null;
17291758
});
17301759

1731-
// Verify that the previous failed transaction has marked multiplexed session client to be
1760+
// Verify that the previous failed transaction during first attempt has marked multiplexed
1761+
// session client to be
17321762
// unimplemented for read-write.
17331763
assertTrue(client.multiplexedSessionDatabaseClient.unimplementedForRW.get());
17341764

1735-
// The next read-write transaction will fall back to regular sessions and succeed.
1765+
// The next read-write transaction will automatically fall back to regular sessions and succeed.
17361766
client
17371767
.readWriteTransaction()
17381768
.run(
@@ -1929,6 +1959,57 @@ public void testBatchWriteAtLeastOnce() {
19291959
assertEquals(1L, client.multiplexedSessionDatabaseClient.getNumSessionsReleased().get());
19301960
}
19311961

1962+
@Test
1963+
public void
1964+
testReadWriteUnimplementedError_DuringExplicitBegin_RetriedWithRegularSessionForInFlightTransaction() {
1965+
// Test scenario:
1966+
// 1. The first attempt does an inline begin using a multiplexed session with an invalid
1967+
// statement, resulting in failure due to invalid syntax.
1968+
// 2. A retry occurs with an explicit begin using a multiplexed session, but we assume the
1969+
// backend flag is turned OFF, leading to UNIMPLEMENTED errors.
1970+
// 3. Upon encountering the UNIMPLEMENTED error, the entire transaction callable is retried
1971+
// using regular sessions, but the inline begin fails again.
1972+
// 4. A final retry executes the explicit BeginTransaction on a regular session.
1973+
Spanner spanner = setupSpannerForAbortedBeginTransactionTests();
1974+
mockSpanner.setBeginTransactionExecutionTime(
1975+
SimulatedExecutionTime.ofException(
1976+
Status.UNIMPLEMENTED
1977+
.withDescription(
1978+
"Transaction type read_write not supported with multiplexed sessions")
1979+
.asRuntimeException()));
1980+
1981+
DatabaseClientImpl client =
1982+
(DatabaseClientImpl) spanner.getDatabaseClient(DatabaseId.of("p", "i", "d"));
1983+
TransactionRunner runner = client.readWriteTransaction();
1984+
Long updateCount =
1985+
runner.run(
1986+
transaction -> {
1987+
// This update statement carries the BeginTransaction, but fails. This will
1988+
// cause the entire transaction to be retried with an explicit
1989+
// BeginTransaction RPC to ensure all statements in the transaction are
1990+
// actually executed against the same transaction.
1991+
SpannerException e =
1992+
assertThrows(
1993+
SpannerException.class,
1994+
() -> transaction.executeUpdate(INVALID_UPDATE_STATEMENT));
1995+
assertEquals(ErrorCode.INVALID_ARGUMENT, e.getErrorCode());
1996+
return transaction.executeUpdate(UPDATE_STATEMENT);
1997+
});
1998+
1999+
assertThat(updateCount).isEqualTo(1L);
2000+
List<BeginTransactionRequest> beginTransactionRequests =
2001+
mockSpanner.getRequestsOfType(BeginTransactionRequest.class);
2002+
assertEquals(2, beginTransactionRequests.size());
2003+
2004+
// Verify the first BeginTransaction request is executed using multiplexed sessions.
2005+
assertTrue(
2006+
mockSpanner.getSession(beginTransactionRequests.get(0).getSession()).getMultiplexed());
2007+
2008+
// Verify the second BeginTransaction request is executed using regular sessions.
2009+
assertFalse(
2010+
mockSpanner.getSession(beginTransactionRequests.get(1).getSession()).getMultiplexed());
2011+
}
2012+
19322013
private void waitForSessionToBeReplaced(DatabaseClientImpl client) {
19332014
assertNotNull(client.multiplexedSessionDatabaseClient);
19342015
SessionReference sessionReference =

0 commit comments

Comments
 (0)