Skip to content

Commit bf6c538

Browse files
authored
Add more test cases on LockClusterExecutorTest (#38033)
1 parent 3f56bdc commit bf6c538

File tree

4 files changed

+88
-32
lines changed

4 files changed

+88
-32
lines changed

parser/distsql/engine/src/main/java/org/apache/shardingsphere/distsql/parser/core/kernel/KernelDistSQLStatementVisitor.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,9 @@ private Properties buildProperties(final PropertiesDefinitionContext ctx) {
329329

330330
@Override
331331
public ASTNode visitLockCluster(final LockClusterContext ctx) {
332-
return new LockClusterStatement((AlgorithmSegment) visitAlgorithmDefinition(ctx.lockStrategy().algorithmDefinition()), Long.parseLong(IdentifierValueUtils.getValue(ctx.INT_())));
332+
String value = IdentifierValueUtils.getValue(ctx.INT_());
333+
AlgorithmSegment algorithmSegment = (AlgorithmSegment) visitAlgorithmDefinition(ctx.lockStrategy().algorithmDefinition());
334+
return null == value ? new LockClusterStatement(algorithmSegment) : new LockClusterStatement(algorithmSegment, Long.parseLong(value));
333335
}
334336

335337
@Override

parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/type/ral/updatable/LockClusterStatement.java

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
import lombok.RequiredArgsConstructor;
2222
import org.apache.shardingsphere.distsql.segment.AlgorithmSegment;
2323

24-
import java.util.Optional;
25-
2624
/**
2725
* Lock cluster statement.
2826
*/
@@ -32,14 +30,9 @@ public final class LockClusterStatement extends UpdatableRALStatement {
3230

3331
private final AlgorithmSegment lockStrategy;
3432

35-
private final Long timeoutMillis;
33+
private final long timeoutMillis;
3634

37-
/**
38-
* Get lock timeout milliseconds.
39-
*
40-
* @return lock timeout milliseconds
41-
*/
42-
public Optional<Long> getTimeoutMillis() {
43-
return Optional.of(timeoutMillis);
35+
public LockClusterStatement(final AlgorithmSegment lockStrategy) {
36+
this(lockStrategy, 3000L);
4437
}
4538
}

proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/lock/LockClusterExecutor.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ public final class LockClusterExecutor implements DistSQLUpdateExecutor<LockClus
4141
public void executeUpdate(final LockClusterStatement sqlStatement, final ContextManager contextManager) throws SQLException {
4242
checkState(contextManager);
4343
checkAlgorithm(sqlStatement);
44-
long timeoutMillis = sqlStatement.getTimeoutMillis().orElse(3000L);
45-
contextManager.getExclusiveOperatorEngine().operate(new LockClusterOperation(), timeoutMillis, () -> {
44+
contextManager.getExclusiveOperatorEngine().operate(new LockClusterOperation(), sqlStatement.getTimeoutMillis(), () -> {
4645
checkState(contextManager);
4746
TypedSPILoader.getService(ClusterLockStrategy.class, sqlStatement.getLockStrategy().getName()).lock();
4847
});

proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/lock/LockClusterExecutorTest.java

Lines changed: 81 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,50 +17,112 @@
1717

1818
package org.apache.shardingsphere.proxy.backend.handler.distsql.ral.updatable.lock;
1919

20+
import org.apache.shardingsphere.distsql.handler.engine.update.DistSQLUpdateExecutor;
2021
import org.apache.shardingsphere.distsql.segment.AlgorithmSegment;
2122
import org.apache.shardingsphere.distsql.statement.type.ral.updatable.LockClusterStatement;
23+
import org.apache.shardingsphere.infra.algorithm.core.exception.MissingRequiredAlgorithmException;
2224
import org.apache.shardingsphere.infra.spi.exception.ServiceProviderNotFoundException;
25+
import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
26+
import org.apache.shardingsphere.mode.exclusive.ExclusiveOperatorEngine;
27+
import org.apache.shardingsphere.mode.exclusive.callback.ExclusiveOperationVoidCallback;
2328
import org.apache.shardingsphere.mode.manager.ContextManager;
2429
import org.apache.shardingsphere.mode.manager.cluster.lock.exception.LockedClusterException;
2530
import org.apache.shardingsphere.mode.state.ShardingSphereState;
26-
import org.junit.jupiter.api.Test;
31+
import org.apache.shardingsphere.mode.state.StatePersistService;
32+
import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
33+
import org.apache.shardingsphere.test.infra.framework.extension.mock.AutoMockExtension;
34+
import org.apache.shardingsphere.test.infra.framework.extension.mock.StaticMockSettings;
2735
import org.junit.jupiter.api.extension.ExtendWith;
28-
import org.mockito.junit.jupiter.MockitoExtension;
36+
import org.junit.jupiter.params.ParameterizedTest;
37+
import org.junit.jupiter.params.provider.Arguments;
38+
import org.junit.jupiter.params.provider.MethodSource;
2939

40+
import java.sql.SQLException;
3041
import java.util.Properties;
42+
import java.util.stream.Stream;
3143

3244
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
3345
import static org.junit.jupiter.api.Assertions.assertThrows;
3446
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
47+
import static org.mockito.Mockito.any;
48+
import static org.mockito.Mockito.anyLong;
49+
import static org.mockito.Mockito.doAnswer;
50+
import static org.mockito.Mockito.eq;
3551
import static org.mockito.Mockito.mock;
52+
import static org.mockito.Mockito.never;
53+
import static org.mockito.Mockito.verify;
3654
import static org.mockito.Mockito.when;
3755

38-
@ExtendWith(MockitoExtension.class)
56+
@ExtendWith(AutoMockExtension.class)
57+
@StaticMockSettings(ProxyContext.class)
3958
class LockClusterExecutorTest {
4059

41-
private final LockClusterExecutor executor = new LockClusterExecutor();
60+
private final LockClusterExecutor executor = (LockClusterExecutor) TypedSPILoader.getService(DistSQLUpdateExecutor.class, LockClusterStatement.class);
4261

43-
@SuppressWarnings("resource")
44-
@Test
45-
void assertExecuteUpdateWithLockedCluster() {
62+
@ParameterizedTest(name = "{0}")
63+
@MethodSource("provideFailureScenarios")
64+
void assertExecuteUpdateWithFailureScenarios(final String name, final LockClusterStatement sqlStatement,
65+
final ShardingSphereState state, final Class<? extends Throwable> expectedException) throws SQLException {
4666
ContextManager contextManager = mock(ContextManager.class, RETURNS_DEEP_STUBS);
47-
when(contextManager.getStateContext().getState()).thenReturn(ShardingSphereState.UNAVAILABLE);
48-
assertThrows(LockedClusterException.class, () -> executor.executeUpdate(new LockClusterStatement(new AlgorithmSegment("FOO", new Properties()), null), contextManager));
67+
when(contextManager.getStateContext().getState()).thenReturn(state);
68+
assertThrows(expectedException, () -> executor.executeUpdate(sqlStatement, contextManager));
69+
verify(contextManager.getExclusiveOperatorEngine(), never()).operate(any(), anyLong(), any());
4970
}
5071

51-
@SuppressWarnings("resource")
52-
@Test
53-
void assertExecuteUpdateWithWrongAlgorithm() {
72+
@ParameterizedTest(name = "{0}")
73+
@MethodSource("provideOperationScenarios")
74+
void assertExecuteUpdateWithOperationScenarios(final String name, final LockClusterStatement sqlStatement,
75+
final long expectedTimeoutMillis, final ShardingSphereState callbackState,
76+
final Class<? extends Throwable> expectedException, final boolean expectStateUpdated) throws SQLException {
5477
ContextManager contextManager = mock(ContextManager.class, RETURNS_DEEP_STUBS);
55-
when(contextManager.getStateContext().getState()).thenReturn(ShardingSphereState.OK);
56-
assertThrows(ServiceProviderNotFoundException.class, () -> executor.executeUpdate(new LockClusterStatement(new AlgorithmSegment("FOO", new Properties()), null), contextManager));
78+
ExclusiveOperatorEngine exclusiveOperatorEngine = mock(ExclusiveOperatorEngine.class);
79+
when(contextManager.getExclusiveOperatorEngine()).thenReturn(exclusiveOperatorEngine);
80+
when(contextManager.getStateContext().getState()).thenReturn(ShardingSphereState.OK, callbackState);
81+
StatePersistService stateService = null;
82+
if (expectStateUpdated) {
83+
stateService = mock(StatePersistService.class);
84+
mockStateService(stateService);
85+
}
86+
doAnswer(invocation -> {
87+
ExclusiveOperationVoidCallback callback = invocation.getArgument(2);
88+
callback.execute();
89+
return null;
90+
}).when(exclusiveOperatorEngine).operate(any(), anyLong(), any(ExclusiveOperationVoidCallback.class));
91+
if (null == expectedException) {
92+
assertDoesNotThrow(() -> executor.executeUpdate(sqlStatement, contextManager));
93+
} else {
94+
assertThrows(expectedException, () -> executor.executeUpdate(sqlStatement, contextManager));
95+
}
96+
verify(exclusiveOperatorEngine).operate(any(), eq(expectedTimeoutMillis), any(ExclusiveOperationVoidCallback.class));
97+
if (expectStateUpdated) {
98+
verify(stateService).update(ShardingSphereState.READ_ONLY);
99+
}
57100
}
58101

59-
@SuppressWarnings("resource")
60-
@Test
61-
void assertExecuteUpdateWithUsingTimeout() {
102+
private void mockStateService(final StatePersistService stateService) {
103+
ProxyContext proxyContext = mock(ProxyContext.class);
62104
ContextManager contextManager = mock(ContextManager.class, RETURNS_DEEP_STUBS);
63-
when(contextManager.getStateContext().getState()).thenReturn(ShardingSphereState.OK);
64-
assertDoesNotThrow(() -> executor.executeUpdate(new LockClusterStatement(new AlgorithmSegment("WRITE", new Properties()), 2000L), contextManager));
105+
when(proxyContext.getContextManager()).thenReturn(contextManager);
106+
when(contextManager.getPersistServiceFacade().getStateService()).thenReturn(stateService);
107+
when(ProxyContext.getInstance()).thenReturn(proxyContext);
108+
}
109+
110+
private static Stream<Arguments> provideFailureScenarios() {
111+
return Stream.of(
112+
Arguments.of("cluster state is unavailable", new LockClusterStatement(new AlgorithmSegment("WRITE", new Properties()), 2000L),
113+
ShardingSphereState.UNAVAILABLE, LockedClusterException.class),
114+
Arguments.of("lock strategy is required", new LockClusterStatement(null, 2000L), ShardingSphereState.OK, MissingRequiredAlgorithmException.class),
115+
Arguments.of("lock strategy is unsupported", new LockClusterStatement(new AlgorithmSegment("FOO", new Properties()), 2000L),
116+
ShardingSphereState.OK, ServiceProviderNotFoundException.class));
117+
}
118+
119+
private static Stream<Arguments> provideOperationScenarios() {
120+
return Stream.of(
121+
Arguments.of("use explicit timeout", new LockClusterStatement(new AlgorithmSegment("WRITE", new Properties()), 2000L),
122+
2000L, ShardingSphereState.OK, null, true),
123+
Arguments.of("use default timeout when absent", new LockClusterStatement(new AlgorithmSegment("WRITE", new Properties())),
124+
3000L, ShardingSphereState.OK, null, true),
125+
Arguments.of("throw exception when callback state changes", new LockClusterStatement(new AlgorithmSegment("WRITE", new Properties()), 2000L),
126+
2000L, ShardingSphereState.UNAVAILABLE, LockedClusterException.class, false));
65127
}
66128
}

0 commit comments

Comments
 (0)