This is an automated email from the ASF dual-hosted git repository.
zhangliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new bf6c5384f64 Add more test cases on LockClusterExecutorTest (#38033)
bf6c5384f64 is described below
commit bf6c5384f64e396e66ea1e695203b2ec5b3cfb06
Author: Liang Zhang <[email protected]>
AuthorDate: Fri Feb 13 23:53:45 2026 +0800
Add more test cases on LockClusterExecutorTest (#38033)
---
.../core/kernel/KernelDistSQLStatementVisitor.java | 4 +-
.../type/ral/updatable/LockClusterStatement.java | 13 +--
.../ral/updatable/lock/LockClusterExecutor.java | 3 +-
.../updatable/lock/LockClusterExecutorTest.java | 100 +++++++++++++++++----
4 files changed, 88 insertions(+), 32 deletions(-)
diff --git
a/parser/distsql/engine/src/main/java/org/apache/shardingsphere/distsql/parser/core/kernel/KernelDistSQLStatementVisitor.java
b/parser/distsql/engine/src/main/java/org/apache/shardingsphere/distsql/parser/core/kernel/KernelDistSQLStatementVisitor.java
index b9c7239c8e2..20eb588e066 100644
---
a/parser/distsql/engine/src/main/java/org/apache/shardingsphere/distsql/parser/core/kernel/KernelDistSQLStatementVisitor.java
+++
b/parser/distsql/engine/src/main/java/org/apache/shardingsphere/distsql/parser/core/kernel/KernelDistSQLStatementVisitor.java
@@ -329,7 +329,9 @@ public final class KernelDistSQLStatementVisitor extends
KernelDistSQLStatementB
@Override
public ASTNode visitLockCluster(final LockClusterContext ctx) {
- return new LockClusterStatement((AlgorithmSegment)
visitAlgorithmDefinition(ctx.lockStrategy().algorithmDefinition()),
Long.parseLong(IdentifierValueUtils.getValue(ctx.INT_())));
+ String value = IdentifierValueUtils.getValue(ctx.INT_());
+ AlgorithmSegment algorithmSegment = (AlgorithmSegment)
visitAlgorithmDefinition(ctx.lockStrategy().algorithmDefinition());
+ return null == value ? new LockClusterStatement(algorithmSegment) :
new LockClusterStatement(algorithmSegment, Long.parseLong(value));
}
@Override
diff --git
a/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/type/ral/updatable/LockClusterStatement.java
b/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/type/ral/updatable/LockClusterStatement.java
index cb3390c64dd..29f47e67b2f 100644
---
a/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/type/ral/updatable/LockClusterStatement.java
+++
b/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/type/ral/updatable/LockClusterStatement.java
@@ -21,8 +21,6 @@ import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.distsql.segment.AlgorithmSegment;
-import java.util.Optional;
-
/**
* Lock cluster statement.
*/
@@ -32,14 +30,9 @@ public final class LockClusterStatement extends
UpdatableRALStatement {
private final AlgorithmSegment lockStrategy;
- private final Long timeoutMillis;
+ private final long timeoutMillis;
- /**
- * Get lock timeout milliseconds.
- *
- * @return lock timeout milliseconds
- */
- public Optional<Long> getTimeoutMillis() {
- return Optional.of(timeoutMillis);
+ public LockClusterStatement(final AlgorithmSegment lockStrategy) {
+ this(lockStrategy, 3000L);
}
}
diff --git
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/lock/LockClusterExecutor.java
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/lock/LockClusterExecutor.java
index 9537a0161aa..c48d4fa11b0 100644
---
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/lock/LockClusterExecutor.java
+++
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/lock/LockClusterExecutor.java
@@ -41,8 +41,7 @@ public final class LockClusterExecutor implements
DistSQLUpdateExecutor<LockClus
public void executeUpdate(final LockClusterStatement sqlStatement, final
ContextManager contextManager) throws SQLException {
checkState(contextManager);
checkAlgorithm(sqlStatement);
- long timeoutMillis = sqlStatement.getTimeoutMillis().orElse(3000L);
- contextManager.getExclusiveOperatorEngine().operate(new
LockClusterOperation(), timeoutMillis, () -> {
+ contextManager.getExclusiveOperatorEngine().operate(new
LockClusterOperation(), sqlStatement.getTimeoutMillis(), () -> {
checkState(contextManager);
TypedSPILoader.getService(ClusterLockStrategy.class,
sqlStatement.getLockStrategy().getName()).lock();
});
diff --git
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/lock/LockClusterExecutorTest.java
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/lock/LockClusterExecutorTest.java
index 48c0eeadb44..ae47500eef3 100644
---
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/lock/LockClusterExecutorTest.java
+++
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/lock/LockClusterExecutorTest.java
@@ -17,50 +17,112 @@
package
org.apache.shardingsphere.proxy.backend.handler.distsql.ral.updatable.lock;
+import
org.apache.shardingsphere.distsql.handler.engine.update.DistSQLUpdateExecutor;
import org.apache.shardingsphere.distsql.segment.AlgorithmSegment;
import
org.apache.shardingsphere.distsql.statement.type.ral.updatable.LockClusterStatement;
+import
org.apache.shardingsphere.infra.algorithm.core.exception.MissingRequiredAlgorithmException;
import
org.apache.shardingsphere.infra.spi.exception.ServiceProviderNotFoundException;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+import org.apache.shardingsphere.mode.exclusive.ExclusiveOperatorEngine;
+import
org.apache.shardingsphere.mode.exclusive.callback.ExclusiveOperationVoidCallback;
import org.apache.shardingsphere.mode.manager.ContextManager;
import
org.apache.shardingsphere.mode.manager.cluster.lock.exception.LockedClusterException;
import org.apache.shardingsphere.mode.state.ShardingSphereState;
-import org.junit.jupiter.api.Test;
+import org.apache.shardingsphere.mode.state.StatePersistService;
+import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
+import
org.apache.shardingsphere.test.infra.framework.extension.mock.AutoMockExtension;
+import
org.apache.shardingsphere.test.infra.framework.extension.mock.StaticMockSettings;
import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.junit.jupiter.MockitoExtension;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import java.sql.SQLException;
import java.util.Properties;
+import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyLong;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-@ExtendWith(MockitoExtension.class)
+@ExtendWith(AutoMockExtension.class)
+@StaticMockSettings(ProxyContext.class)
class LockClusterExecutorTest {
- private final LockClusterExecutor executor = new LockClusterExecutor();
+ private final LockClusterExecutor executor = (LockClusterExecutor)
TypedSPILoader.getService(DistSQLUpdateExecutor.class,
LockClusterStatement.class);
- @SuppressWarnings("resource")
- @Test
- void assertExecuteUpdateWithLockedCluster() {
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("provideFailureScenarios")
+ void assertExecuteUpdateWithFailureScenarios(final String name, final
LockClusterStatement sqlStatement,
+ final ShardingSphereState
state, final Class<? extends Throwable> expectedException) throws SQLException {
ContextManager contextManager = mock(ContextManager.class,
RETURNS_DEEP_STUBS);
-
when(contextManager.getStateContext().getState()).thenReturn(ShardingSphereState.UNAVAILABLE);
- assertThrows(LockedClusterException.class, () ->
executor.executeUpdate(new LockClusterStatement(new AlgorithmSegment("FOO", new
Properties()), null), contextManager));
+ when(contextManager.getStateContext().getState()).thenReturn(state);
+ assertThrows(expectedException, () ->
executor.executeUpdate(sqlStatement, contextManager));
+ verify(contextManager.getExclusiveOperatorEngine(),
never()).operate(any(), anyLong(), any());
}
- @SuppressWarnings("resource")
- @Test
- void assertExecuteUpdateWithWrongAlgorithm() {
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("provideOperationScenarios")
+ void assertExecuteUpdateWithOperationScenarios(final String name, final
LockClusterStatement sqlStatement,
+ final long
expectedTimeoutMillis, final ShardingSphereState callbackState,
+ final Class<? extends
Throwable> expectedException, final boolean expectStateUpdated) throws
SQLException {
ContextManager contextManager = mock(ContextManager.class,
RETURNS_DEEP_STUBS);
-
when(contextManager.getStateContext().getState()).thenReturn(ShardingSphereState.OK);
- assertThrows(ServiceProviderNotFoundException.class, () ->
executor.executeUpdate(new LockClusterStatement(new AlgorithmSegment("FOO", new
Properties()), null), contextManager));
+ ExclusiveOperatorEngine exclusiveOperatorEngine =
mock(ExclusiveOperatorEngine.class);
+
when(contextManager.getExclusiveOperatorEngine()).thenReturn(exclusiveOperatorEngine);
+
when(contextManager.getStateContext().getState()).thenReturn(ShardingSphereState.OK,
callbackState);
+ StatePersistService stateService = null;
+ if (expectStateUpdated) {
+ stateService = mock(StatePersistService.class);
+ mockStateService(stateService);
+ }
+ doAnswer(invocation -> {
+ ExclusiveOperationVoidCallback callback =
invocation.getArgument(2);
+ callback.execute();
+ return null;
+ }).when(exclusiveOperatorEngine).operate(any(), anyLong(),
any(ExclusiveOperationVoidCallback.class));
+ if (null == expectedException) {
+ assertDoesNotThrow(() -> executor.executeUpdate(sqlStatement,
contextManager));
+ } else {
+ assertThrows(expectedException, () ->
executor.executeUpdate(sqlStatement, contextManager));
+ }
+ verify(exclusiveOperatorEngine).operate(any(),
eq(expectedTimeoutMillis), any(ExclusiveOperationVoidCallback.class));
+ if (expectStateUpdated) {
+ verify(stateService).update(ShardingSphereState.READ_ONLY);
+ }
}
- @SuppressWarnings("resource")
- @Test
- void assertExecuteUpdateWithUsingTimeout() {
+ private void mockStateService(final StatePersistService stateService) {
+ ProxyContext proxyContext = mock(ProxyContext.class);
ContextManager contextManager = mock(ContextManager.class,
RETURNS_DEEP_STUBS);
-
when(contextManager.getStateContext().getState()).thenReturn(ShardingSphereState.OK);
- assertDoesNotThrow(() -> executor.executeUpdate(new
LockClusterStatement(new AlgorithmSegment("WRITE", new Properties()), 2000L),
contextManager));
+ when(proxyContext.getContextManager()).thenReturn(contextManager);
+
when(contextManager.getPersistServiceFacade().getStateService()).thenReturn(stateService);
+ when(ProxyContext.getInstance()).thenReturn(proxyContext);
+ }
+
+ private static Stream<Arguments> provideFailureScenarios() {
+ return Stream.of(
+ Arguments.of("cluster state is unavailable", new
LockClusterStatement(new AlgorithmSegment("WRITE", new Properties()), 2000L),
+ ShardingSphereState.UNAVAILABLE,
LockedClusterException.class),
+ Arguments.of("lock strategy is required", new
LockClusterStatement(null, 2000L), ShardingSphereState.OK,
MissingRequiredAlgorithmException.class),
+ Arguments.of("lock strategy is unsupported", new
LockClusterStatement(new AlgorithmSegment("FOO", new Properties()), 2000L),
+ ShardingSphereState.OK,
ServiceProviderNotFoundException.class));
+ }
+
+ private static Stream<Arguments> provideOperationScenarios() {
+ return Stream.of(
+ Arguments.of("use explicit timeout", new
LockClusterStatement(new AlgorithmSegment("WRITE", new Properties()), 2000L),
+ 2000L, ShardingSphereState.OK, null, true),
+ Arguments.of("use default timeout when absent", new
LockClusterStatement(new AlgorithmSegment("WRITE", new Properties())),
+ 3000L, ShardingSphereState.OK, null, true),
+ Arguments.of("throw exception when callback state changes",
new LockClusterStatement(new AlgorithmSegment("WRITE", new Properties()),
2000L),
+ 2000L, ShardingSphereState.UNAVAILABLE,
LockedClusterException.class, false));
}
}