Copilot commented on code in PR #8111:
URL: https://github.com/apache/incubator-seata/pull/8111#discussion_r3556746785
##########
server/src/test/java/org/apache/seata/server/storage/db/lock/DataBaseDistributedLockerTest.java:
##########
@@ -830,6 +830,125 @@ void testReleaseLock_NullConnection_HandlesGracefully()
throws Exception {
verify(mockConnection, never()).close();
}
+ @Test
+ void testIgnoreSQLException_WithMySqlNoWaitErrorCode_ReturnsTrue()
throws Exception {
+ // MySQL 8.0+ ER_LOCK_NOWAIT
+ SQLException exception = new SQLException(
+ "Statement aborted because lock(s) could not be acquired "
+ "immediately and NOWAIT is set",
+ "HY000",
+ 3572);
+
+ Method method =
DataBaseDistributedLocker.class.getDeclaredMethod("ignoreSQLException",
SQLException.class);
+ method.setAccessible(true);
+ boolean result = (boolean) method.invoke(locker, exception);
+
+ assertTrue(result, "ignoreSQLException should treat MySQL error
code 3572 as fast-fail");
+ }
+
+ @Test
+ void testIgnoreSQLException_WithOracleNoWaitErrorCode_ReturnsTrue()
throws Exception {
+ // ORA-00054 resource busy
+ SQLException exception = new SQLException(
+ "ORA-00054: resource busy and acquire with NOWAIT
specified or timeout expired", "61000", 54);
+
+ Method method =
DataBaseDistributedLocker.class.getDeclaredMethod("ignoreSQLException",
SQLException.class);
+ method.setAccessible(true);
+ boolean result = (boolean) method.invoke(locker, exception);
+
+ assertTrue(result, "ignoreSQLException should treat Oracle error
code 54 as fast-fail");
+ }
+
+ @Test
+ void testIgnoreSQLException_WithPostgresqlNoWaitSqlState_ReturnsTrue()
throws Exception {
+ // PostgreSQL 55P03 lock_not_available - vendor-specific error
code is not 0
+ // in real life, but we match on SQLState rather than vendor code.
+ SQLException exception = new SQLException("could not obtain lock
on row in relation", "55P03", 0);
+
+ Method method =
DataBaseDistributedLocker.class.getDeclaredMethod("ignoreSQLException",
SQLException.class);
+ method.setAccessible(true);
+ boolean result = (boolean) method.invoke(locker, exception);
+
+ assertTrue(result, "ignoreSQLException should treat PostgreSQL
SQLState 55P03 as fast-fail");
+ }
+
+ @Test
+ void testStaticInitializer_PopulatesNoWaitIgnoreSets() throws
Exception {
+ Field codeField =
DataBaseDistributedLocker.class.getDeclaredField("IGNORE_NOWAIT_CODE");
+ codeField.setAccessible(true);
+ @SuppressWarnings("unchecked")
+ Set<Integer> ignoreNoWaitCode = (Set<Integer>) codeField.get(null);
+
+ Field stateField =
DataBaseDistributedLocker.class.getDeclaredField("IGNORE_NOWAIT_SQLSTATE");
+ stateField.setAccessible(true);
+ @SuppressWarnings("unchecked")
+ Set<String> ignoreNoWaitSqlState = (Set<String>)
stateField.get(null);
+
+ assertTrue(ignoreNoWaitCode.contains(3572), "IGNORE_NOWAIT_CODE
should contain 3572 (MySQL)");
+ assertTrue(ignoreNoWaitCode.contains(54), "IGNORE_NOWAIT_CODE
should contain 54 (Oracle)");
+ assertTrue(
+ ignoreNoWaitSqlState.contains("55P03"),
"IGNORE_NOWAIT_SQLSTATE should contain 55P03 (PostgreSQL)");
+ }
+
+ @Test
+ void testAcquireLock_NoWaitEnabled_UsesNoWaitSelectSql() throws
Exception {
+ when(mockDataSource.getConnection()).thenReturn(mockConnection);
+ when(mockConnection.getAutoCommit()).thenReturn(true);
+
when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement);
+
when(mockPreparedStatement.executeQuery()).thenReturn(mockResultSet);
+ when(mockResultSet.next()).thenReturn(false);
+ when(mockPreparedStatement.executeUpdate()).thenReturn(1);
+
+ // Force the locker into nowait mode and switch its dbType so that
+ // the SPI returns a dialect with a real NOWAIT implementation.
+ setNowaitEnabled(locker, true);
+ setDbType(locker, "mysql");
+ setDistributedLockTable(locker, "distributed_lock");
+
+ DistributedLockDO lockDO = new DistributedLockDO();
+ lockDO.setLockKey("test-key");
+ lockDO.setLockValue("test-value");
+ lockDO.setExpireTime(5000L);
+
+ ArgumentCaptor<String> sqlCaptor =
ArgumentCaptor.forClass(String.class);
+
+ boolean result = locker.acquireLock(lockDO);
+
+ assertTrue(result);
+ verify(mockConnection,
atLeastOnce()).prepareStatement(sqlCaptor.capture());
+ boolean noWaitSqlSeen = sqlCaptor.getAllValues().stream()
+ .anyMatch(sql -> sql.toUpperCase().contains("FOR UPDATE
NOWAIT"));
+ assertTrue(noWaitSqlSeen, "NOWAIT mode should issue a SELECT ...
FOR UPDATE NOWAIT statement");
+ }
+
+ @Test
+ void testAcquireLock_NoWaitDisabled_UsesBlockingSelectSql() throws
Exception {
+ when(mockDataSource.getConnection()).thenReturn(mockConnection);
+ when(mockConnection.getAutoCommit()).thenReturn(true);
+
when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement);
+
when(mockPreparedStatement.executeQuery()).thenReturn(mockResultSet);
+ when(mockResultSet.next()).thenReturn(false);
+ when(mockPreparedStatement.executeUpdate()).thenReturn(1);
+
+ setNowaitEnabled(locker, false);
+ setDbType(locker, "mysql");
+ setDistributedLockTable(locker, "distributed_lock");
+
Review Comment:
Same as the NOWAIT-enabled test: avoid mutating the `final` `dbType` field
via reflection; it can be unreliable and makes the test dependent on JVM
reflection behavior rather than the feature under test.
##########
server/src/test/java/org/apache/seata/server/storage/db/lock/DataBaseDistributedLockerTest.java:
##########
@@ -830,6 +830,125 @@ void testReleaseLock_NullConnection_HandlesGracefully()
throws Exception {
verify(mockConnection, never()).close();
}
+ @Test
+ void testIgnoreSQLException_WithMySqlNoWaitErrorCode_ReturnsTrue()
throws Exception {
+ // MySQL 8.0+ ER_LOCK_NOWAIT
+ SQLException exception = new SQLException(
+ "Statement aborted because lock(s) could not be acquired "
+ "immediately and NOWAIT is set",
+ "HY000",
+ 3572);
+
+ Method method =
DataBaseDistributedLocker.class.getDeclaredMethod("ignoreSQLException",
SQLException.class);
+ method.setAccessible(true);
+ boolean result = (boolean) method.invoke(locker, exception);
+
+ assertTrue(result, "ignoreSQLException should treat MySQL error
code 3572 as fast-fail");
+ }
+
+ @Test
+ void testIgnoreSQLException_WithOracleNoWaitErrorCode_ReturnsTrue()
throws Exception {
+ // ORA-00054 resource busy
+ SQLException exception = new SQLException(
+ "ORA-00054: resource busy and acquire with NOWAIT
specified or timeout expired", "61000", 54);
+
+ Method method =
DataBaseDistributedLocker.class.getDeclaredMethod("ignoreSQLException",
SQLException.class);
+ method.setAccessible(true);
+ boolean result = (boolean) method.invoke(locker, exception);
+
+ assertTrue(result, "ignoreSQLException should treat Oracle error
code 54 as fast-fail");
+ }
+
+ @Test
+ void testIgnoreSQLException_WithPostgresqlNoWaitSqlState_ReturnsTrue()
throws Exception {
+ // PostgreSQL 55P03 lock_not_available - vendor-specific error
code is not 0
+ // in real life, but we match on SQLState rather than vendor code.
+ SQLException exception = new SQLException("could not obtain lock
on row in relation", "55P03", 0);
+
+ Method method =
DataBaseDistributedLocker.class.getDeclaredMethod("ignoreSQLException",
SQLException.class);
+ method.setAccessible(true);
+ boolean result = (boolean) method.invoke(locker, exception);
+
+ assertTrue(result, "ignoreSQLException should treat PostgreSQL
SQLState 55P03 as fast-fail");
+ }
+
+ @Test
+ void testStaticInitializer_PopulatesNoWaitIgnoreSets() throws
Exception {
+ Field codeField =
DataBaseDistributedLocker.class.getDeclaredField("IGNORE_NOWAIT_CODE");
+ codeField.setAccessible(true);
+ @SuppressWarnings("unchecked")
+ Set<Integer> ignoreNoWaitCode = (Set<Integer>) codeField.get(null);
+
+ Field stateField =
DataBaseDistributedLocker.class.getDeclaredField("IGNORE_NOWAIT_SQLSTATE");
+ stateField.setAccessible(true);
+ @SuppressWarnings("unchecked")
+ Set<String> ignoreNoWaitSqlState = (Set<String>)
stateField.get(null);
+
+ assertTrue(ignoreNoWaitCode.contains(3572), "IGNORE_NOWAIT_CODE
should contain 3572 (MySQL)");
+ assertTrue(ignoreNoWaitCode.contains(54), "IGNORE_NOWAIT_CODE
should contain 54 (Oracle)");
+ assertTrue(
+ ignoreNoWaitSqlState.contains("55P03"),
"IGNORE_NOWAIT_SQLSTATE should contain 55P03 (PostgreSQL)");
+ }
+
+ @Test
+ void testAcquireLock_NoWaitEnabled_UsesNoWaitSelectSql() throws
Exception {
+ when(mockDataSource.getConnection()).thenReturn(mockConnection);
+ when(mockConnection.getAutoCommit()).thenReturn(true);
+
when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement);
+
when(mockPreparedStatement.executeQuery()).thenReturn(mockResultSet);
+ when(mockResultSet.next()).thenReturn(false);
+ when(mockPreparedStatement.executeUpdate()).thenReturn(1);
+
+ // Force the locker into nowait mode and switch its dbType so that
+ // the SPI returns a dialect with a real NOWAIT implementation.
+ setNowaitEnabled(locker, true);
+ setDbType(locker, "mysql");
+ setDistributedLockTable(locker, "distributed_lock");
Review Comment:
`dbType` in `DataBaseDistributedLocker` is a `final` field, so mutating it
via reflection (`setDbType`) is brittle and may not reliably take effect across
JVMs (and can even be blocked under stricter reflection settings). This test
already has MySQL configured via test config, so it should avoid attempting to
overwrite `dbType` and just toggle `nowaitEnabled` / table name.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]