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 08e11717b82 Add more test cases on Shadow DistSQL (#38247)
08e11717b82 is described below
commit 08e11717b824b233da5b354f39e0184f9974df20
Author: Liang Zhang <[email protected]>
AuthorDate: Fri Feb 27 19:08:06 2026 +0800
Add more test cases on Shadow DistSQL (#38247)
* Add more test cases on Shadow DistSQL
* Add more test cases on Shadow DistSQL
* Add more test cases on Shadow DistSQL
* Add more test cases on Shadow DistSQL
* Add more test cases on Shadow DistSQL
* Add more test cases on Shadow DistSQL
* Add more test cases on Shadow DistSQL
---
.../ShadowRuleStatementSupporterTest.java | 129 +++++++++++++++
.../AlterDefaultShadowAlgorithmExecutorTest.java | 35 +++-
.../update/AlterShadowRuleExecutorTest.java | 161 ++++++++++---------
.../CreateDefaultShadowAlgorithmExecutorTest.java | 91 ++++++++---
.../update/CreateShadowRuleExecutorTest.java | 176 +++++++++++----------
.../DropDefaultShadowAlgorithmExecutorTest.java | 13 +-
.../update/DropShadowAlgorithmExecutorTest.java | 126 ++++++++++++---
.../handler/update/DropShadowRuleExecutorTest.java | 160 ++++++++++++-------
.../handler/update/UnusedAlgorithmFinderTest.java | 65 ++++++++
9 files changed, 690 insertions(+), 266 deletions(-)
diff --git
a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/supporter/ShadowRuleStatementSupporterTest.java
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/supporter/ShadowRuleStatementSupporterTest.java
new file mode 100644
index 00000000000..cc8ecf3eaff
--- /dev/null
+++
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/supporter/ShadowRuleStatementSupporterTest.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.shadow.distsql.handler.supporter;
+
+import org.apache.shardingsphere.distsql.segment.AlgorithmSegment;
+import
org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
+import org.apache.shardingsphere.shadow.config.ShadowRuleConfiguration;
+import
org.apache.shardingsphere.shadow.config.datasource.ShadowDataSourceConfiguration;
+import org.apache.shardingsphere.shadow.config.table.ShadowTableConfiguration;
+import org.apache.shardingsphere.shadow.distsql.segment.ShadowAlgorithmSegment;
+import org.apache.shardingsphere.shadow.distsql.segment.ShadowRuleSegment;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import java.util.stream.Stream;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+class ShadowRuleStatementSupporterTest {
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("getRuleNamesByConfigurationArguments")
+ void assertGetRuleNamesByConfiguration(final String name, final
ShadowRuleConfiguration ruleConfig, final List<String> expected) {
+ assertThat(ShadowRuleStatementSupporter.getRuleNames(ruleConfig),
is(expected));
+ }
+
+ @Test
+ void assertGetRuleNamesBySegmentsWhenEmpty() {
+
assertThat(ShadowRuleStatementSupporter.getRuleNames(Collections.emptyList()),
is(Collections.emptyList()));
+ }
+
+ @Test
+ void assertGetRuleNamesBySegmentsWhenPresent() {
+ Collection<ShadowRuleSegment> segments = Arrays.asList(
+ new ShadowRuleSegment("ds_0", "source_0", "shadow_0",
Collections.emptyMap()), new ShadowRuleSegment("ds_1", "source_1", "shadow_1",
Collections.emptyMap()));
+ assertThat(ShadowRuleStatementSupporter.getRuleNames(segments),
is(Arrays.asList("ds_0", "ds_1")));
+ }
+
+ @Test
+ void assertGetStorageUnitNamesWhenEmpty() {
+
assertThat(ShadowRuleStatementSupporter.getStorageUnitNames(Collections.emptyList()),
is(Collections.emptyList()));
+ }
+
+ @Test
+ void assertGetStorageUnitNamesWhenPresent() {
+ Collection<ShadowRuleSegment> segments = Arrays.asList(
+ new ShadowRuleSegment("ds_0", "source_0", "shadow_0",
Collections.emptyMap()), new ShadowRuleSegment("ds_1", null, "shadow_1",
Collections.emptyMap()));
+ assertThat(ShadowRuleStatementSupporter.getStorageUnitNames(segments),
is(Arrays.asList("source_0", "shadow_0", "shadow_1")));
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("getAlgorithmNamesByConfigurationArguments")
+ void assertGetAlgorithmNamesByConfiguration(final String name, final
ShadowRuleConfiguration ruleConfig, final List<String> expected) {
+ assertThat(ShadowRuleStatementSupporter.getAlgorithmNames(ruleConfig),
is(expected));
+ }
+
+ @Test
+ void assertGetAlgorithmNamesBySegmentsWhenEmpty() {
+
assertThat(ShadowRuleStatementSupporter.getAlgorithmNames(Collections.emptyList()),
is(Collections.emptyList()));
+ }
+
+ @Test
+ void assertGetAlgorithmNamesBySegmentsWhenPresent() {
+ Collection<ShadowAlgorithmSegment> segments = Arrays.asList(
+ new ShadowAlgorithmSegment("algorithm_0", new
AlgorithmSegment("SQL_HINT", new Properties())),
+ new ShadowAlgorithmSegment("algorithm_1", new
AlgorithmSegment("SQL_HINT", new Properties())));
+ assertThat(ShadowRuleStatementSupporter.getAlgorithmNames(
+ Collections.singleton(new ShadowRuleSegment("ds_0",
"source_0", "shadow_0", Collections.singletonMap("t_order", segments)))),
is(Arrays.asList("algorithm_0", "algorithm_1")));
+ }
+
+ @Test
+ void assertMergeConfiguration() {
+ ShadowTableConfiguration existingConfig = new
ShadowTableConfiguration(new ArrayList<>(Collections.singleton("ds_0")), new
ArrayList<>(Collections.singleton("algorithm_0")));
+ ShadowTableConfiguration newConfig = new ShadowTableConfiguration(new
LinkedList<>(Collections.singleton("ds_1")), new
LinkedList<>(Collections.singleton("algorithm_1")));
+ ShadowTableConfiguration actual =
ShadowRuleStatementSupporter.mergeConfiguration(existingConfig, newConfig);
+ assertThat(actual.getDataSourceNames(), is(Arrays.asList("ds_0",
"ds_1")));
+ assertThat(actual.getShadowAlgorithmNames(),
is(Arrays.asList("algorithm_0", "algorithm_1")));
+ }
+
+ private static Stream<Arguments> getRuleNamesByConfigurationArguments() {
+ return Stream.of(
+ Arguments.of("null configuration", null,
Collections.emptyList()),
+ Arguments.of("single datasource",
createRuleConfiguration(Collections.singleton("ds_0"),
Collections.emptyList()), Collections.singletonList("ds_0")),
+ Arguments.of("multiple datasources",
createRuleConfiguration(Arrays.asList("ds_0", "ds_1"),
Collections.emptyList()), Arrays.asList("ds_0", "ds_1")));
+ }
+
+ private static Stream<Arguments>
getAlgorithmNamesByConfigurationArguments() {
+ return Stream.of(
+ Arguments.of("null configuration", null,
Collections.emptyList()),
+ Arguments.of("single algorithm",
createRuleConfiguration(Collections.emptyList(),
Collections.singleton("algorithm_0")),
Collections.singletonList("algorithm_0")),
+ Arguments.of("multiple algorithms",
createRuleConfiguration(Collections.emptyList(), Arrays.asList("algorithm_0",
"algorithm_1")), Arrays.asList("algorithm_0", "algorithm_1")));
+ }
+
+ private static ShadowRuleConfiguration createRuleConfiguration(final
Collection<String> dataSourceNames, final Collection<String> algorithmNames) {
+ ShadowRuleConfiguration result = new ShadowRuleConfiguration();
+ for (String each : dataSourceNames) {
+ result.getDataSources().add(new
ShadowDataSourceConfiguration(each, each + "_source", each + "_shadow"));
+ }
+ for (String each : algorithmNames) {
+ result.getShadowAlgorithms().put(each, new
AlgorithmConfiguration("SQL_HINT", new Properties()));
+ }
+ return result;
+ }
+}
diff --git
a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/AlterDefaultShadowAlgorithmExecutorTest.java
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/AlterDefaultShadowAlgorithmExecutorTest.java
index c0f998672ae..f7602cd1870 100644
---
a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/AlterDefaultShadowAlgorithmExecutorTest.java
+++
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/AlterDefaultShadowAlgorithmExecutorTest.java
@@ -17,12 +17,14 @@
package org.apache.shardingsphere.shadow.distsql.handler.update;
+import
org.apache.shardingsphere.distsql.handler.engine.update.rdl.rule.spi.database.DatabaseRuleDefinitionExecutor;
import org.apache.shardingsphere.distsql.segment.AlgorithmSegment;
import
org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
import
org.apache.shardingsphere.infra.algorithm.core.exception.MissingRequiredAlgorithmException;
import
org.apache.shardingsphere.infra.algorithm.core.exception.UnregisteredAlgorithmException;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import
org.apache.shardingsphere.infra.spi.exception.ServiceProviderNotFoundException;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
import org.apache.shardingsphere.infra.util.props.PropertiesBuilder;
import org.apache.shardingsphere.infra.util.props.PropertiesBuilder.Property;
import org.apache.shardingsphere.shadow.config.ShadowRuleConfiguration;
@@ -38,6 +40,10 @@ import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Collections;
import java.util.Properties;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
@@ -46,7 +52,8 @@ import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class AlterDefaultShadowAlgorithmExecutorTest {
- private final AlterDefaultShadowAlgorithmExecutor executor = new
AlterDefaultShadowAlgorithmExecutor();
+ private final AlterDefaultShadowAlgorithmExecutor executor =
(AlterDefaultShadowAlgorithmExecutor) TypedSPILoader.getService(
+ DatabaseRuleDefinitionExecutor.class,
AlterDefaultShadowAlgorithmStatement.class);
@Mock
private ShadowRuleConfiguration currentConfig;
@@ -60,8 +67,7 @@ class AlterDefaultShadowAlgorithmExecutorTest {
void assertExecuteAlgorithmNotInMetaData() {
Properties props = PropertiesBuilder.build(new Property("type",
"value"));
when(currentConfig.getShadowAlgorithms()).thenReturn(Collections.singletonMap("sqlHintAlgorithm",
new AlgorithmConfiguration("type", props)));
- AlterDefaultShadowAlgorithmStatement sqlStatement = new
AlterDefaultShadowAlgorithmStatement(
- new ShadowAlgorithmSegment("default_shadow_algorithm", new
AlgorithmSegment("SQL_HINT", props)));
+ AlterDefaultShadowAlgorithmStatement sqlStatement = new
AlterDefaultShadowAlgorithmStatement(new
ShadowAlgorithmSegment("default_shadow_algorithm", new
AlgorithmSegment("SQL_HINT", props)));
ShadowRule rule = mock(ShadowRule.class);
when(rule.getConfiguration()).thenReturn(currentConfig);
executor.setRule(rule);
@@ -89,7 +95,28 @@ class AlterDefaultShadowAlgorithmExecutorTest {
ShadowRule rule = mock(ShadowRule.class);
when(rule.getConfiguration()).thenReturn(currentConfig);
executor.setRule(rule);
+ assertDoesNotThrow(() -> executor.checkBeforeUpdate(
+ new AlterDefaultShadowAlgorithmStatement(new
ShadowAlgorithmSegment("default_shadow_algorithm", new
AlgorithmSegment("SQL_HINT", props)))));
+ }
+
+ @Test
+ void assertBuildToBeAlteredRuleConfiguration() {
+ Properties props = PropertiesBuilder.build(new Property("foo", "bar"));
AlterDefaultShadowAlgorithmStatement sqlStatement = new
AlterDefaultShadowAlgorithmStatement(new
ShadowAlgorithmSegment("default_shadow_algorithm", new
AlgorithmSegment("SQL_HINT", props)));
- executor.checkBeforeUpdate(sqlStatement);
+ ShadowRuleConfiguration actual =
executor.buildToBeAlteredRuleConfiguration(sqlStatement);
+ assertThat(actual.getDefaultShadowAlgorithmName(),
is("default_shadow_algorithm"));
+ assertThat(actual.getShadowAlgorithms().size(), is(1));
+
assertThat(actual.getShadowAlgorithms().get("default_shadow_algorithm").getType(),
is("SQL_HINT"));
+
assertThat(actual.getShadowAlgorithms().get("default_shadow_algorithm").getProps(),
is(props));
+ }
+
+ @Test
+ void assertBuildToBeDroppedRuleConfiguration() {
+ assertNull(executor.buildToBeDroppedRuleConfiguration(new
ShadowRuleConfiguration()));
+ }
+
+ @Test
+ void assertGetRuleClass() {
+ assertThat(executor.getRuleClass(), is(ShadowRule.class));
}
}
diff --git
a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/AlterShadowRuleExecutorTest.java
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/AlterShadowRuleExecutorTest.java
index c8f081f164b..ca06f074d80 100644
---
a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/AlterShadowRuleExecutorTest.java
+++
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/AlterShadowRuleExecutorTest.java
@@ -17,17 +17,22 @@
package org.apache.shardingsphere.shadow.distsql.handler.update;
+import
org.apache.shardingsphere.distsql.handler.engine.update.rdl.rule.spi.database.DatabaseRuleDefinitionExecutor;
import org.apache.shardingsphere.distsql.segment.AlgorithmSegment;
+import
org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
import
org.apache.shardingsphere.infra.algorithm.core.exception.InUsedAlgorithmException;
import
org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.MissingRequiredStorageUnitsException;
import
org.apache.shardingsphere.infra.exception.kernel.metadata.rule.DuplicateRuleException;
import
org.apache.shardingsphere.infra.exception.kernel.metadata.rule.MissingRequiredRuleException;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import
org.apache.shardingsphere.infra.metadata.database.resource.ResourceMetaData;
+import
org.apache.shardingsphere.infra.spi.exception.ServiceProviderNotFoundException;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
import org.apache.shardingsphere.infra.util.props.PropertiesBuilder;
import org.apache.shardingsphere.infra.util.props.PropertiesBuilder.Property;
import org.apache.shardingsphere.shadow.config.ShadowRuleConfiguration;
import
org.apache.shardingsphere.shadow.config.datasource.ShadowDataSourceConfiguration;
+import org.apache.shardingsphere.shadow.config.table.ShadowTableConfiguration;
import org.apache.shardingsphere.shadow.distsql.segment.ShadowAlgorithmSegment;
import org.apache.shardingsphere.shadow.distsql.segment.ShadowRuleSegment;
import
org.apache.shardingsphere.shadow.distsql.statement.AlterShadowRuleStatement;
@@ -35,21 +40,30 @@ import org.apache.shardingsphere.shadow.rule.ShadowRule;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
+import java.util.stream.Stream;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -57,7 +71,10 @@ import static org.mockito.Mockito.when;
@MockitoSettings(strictness = Strictness.LENIENT)
class AlterShadowRuleExecutorTest {
- private final AlterShadowRuleExecutor executor = new
AlterShadowRuleExecutor();
+ private final AlterShadowRuleExecutor executor = (AlterShadowRuleExecutor)
TypedSPILoader.getService(DatabaseRuleDefinitionExecutor.class,
AlterShadowRuleStatement.class);
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private ShardingSphereDatabase database;
@Mock
private ResourceMetaData resourceMetaData;
@@ -70,98 +87,94 @@ class AlterShadowRuleExecutorTest {
Collection<ShadowDataSourceConfiguration> shadowDataSource = new
LinkedList<>();
shadowDataSource.add(new
ShadowDataSourceConfiguration("initRuleName1", "ds1", "ds_shadow1"));
shadowDataSource.add(new
ShadowDataSourceConfiguration("initRuleName2", "ds2", "ds_shadow2"));
- ShardingSphereDatabase database = mock(ShardingSphereDatabase.class,
RETURNS_DEEP_STUBS);
when(database.getResourceMetaData()).thenReturn(resourceMetaData);
+ when(database.getName()).thenReturn("shadow_db");
+
when(resourceMetaData.getNotExistedDataSources(any())).thenReturn(Collections.emptyList());
when(currentConfig.getDataSources()).thenReturn(shadowDataSource);
executor.setDatabase(database);
+ executor.setRule(createRule(currentConfig));
}
- @Test
- void assertExecuteWithDuplicateRuleName() {
- ShadowRuleSegment ruleSegment = new ShadowRuleSegment("ruleName",
null, null, null);
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(currentConfig);
- executor.setRule(rule);
- AlterShadowRuleStatement sqlStatement = new
AlterShadowRuleStatement(Arrays.asList(ruleSegment, ruleSegment));
- sqlStatement.buildAttributes();
- assertThrows(DuplicateRuleException.class, () ->
executor.checkBeforeUpdate(sqlStatement));
+ private ShadowRule createRule(final ShadowRuleConfiguration ruleConfig) {
+ ShadowRule result = mock(ShadowRule.class);
+ when(result.getConfiguration()).thenReturn(ruleConfig);
+ return result;
}
- @Test
- void assertExecuteWithRuleNameNotInMetaData() {
- ShadowRuleSegment ruleSegment = new ShadowRuleSegment("ruleName",
null, null, null);
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(currentConfig);
- executor.setRule(rule);
- AlterShadowRuleStatement sqlStatement = new
AlterShadowRuleStatement(Collections.singleton(ruleSegment));
- sqlStatement.buildAttributes();
- assertThrows(MissingRequiredRuleException.class, () ->
executor.checkBeforeUpdate(sqlStatement));
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("checkBeforeUpdateFailureArguments")
+ void assertCheckBeforeUpdateWithInvalidInput(final String name, final
AlterShadowRuleStatement sqlStatement,
+ final List<String>
notExistedStorageUnits, final Class<? extends Exception> expectedException) {
+
when(resourceMetaData.getNotExistedDataSources(any())).thenReturn(notExistedStorageUnits);
+ assertThrows(expectedException, () ->
executor.checkBeforeUpdate(sqlStatement));
}
@Test
- void assertExecuteWithNotExistResource() {
- List<String> dataSources = Arrays.asList("ds", "ds0");
-
when(resourceMetaData.getNotExistedDataSources(any())).thenReturn(dataSources);
- AlterShadowRuleStatement sqlStatement = new
AlterShadowRuleStatement(Collections.singleton(new
ShadowRuleSegment("initRuleName1", "ds3", null, null)));
- sqlStatement.buildAttributes();
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(currentConfig);
- executor.setRule(rule);
- assertThrows(MissingRequiredStorageUnitsException.class, () ->
executor.checkBeforeUpdate(sqlStatement));
+ void assertCheckBeforeUpdate() {
+ Properties props = PropertiesBuilder.build(new Property("type",
"value"));
+ ShadowAlgorithmSegment segment1 = new
ShadowAlgorithmSegment("algorithmName1", new AlgorithmSegment("SQL_HINT",
props));
+ ShadowAlgorithmSegment segment2 = new
ShadowAlgorithmSegment("algorithmName2", new AlgorithmSegment("SQL_HINT",
props));
+ AlterShadowRuleStatement sqlStatement =
createAlterStatement(Arrays.asList(
+ new ShadowRuleSegment("initRuleName1", "ds_0", null,
Collections.singletonMap("t_order", Collections.singleton(segment1))),
+ new ShadowRuleSegment("initRuleName2", "ds_1", null,
Collections.singletonMap("t_order_1", Collections.singleton(segment2)))));
+ assertDoesNotThrow(() -> executor.checkBeforeUpdate(sqlStatement));
}
@Test
- void assertExecuteDuplicateAlgorithm() {
- ShadowAlgorithmSegment segment = new
ShadowAlgorithmSegment("algorithmName", new AlgorithmSegment("name",
PropertiesBuilder.build(new Property("type", "value"))));
- AlterShadowRuleStatement sqlStatement = new
AlterShadowRuleStatement(Arrays.asList(
- new ShadowRuleSegment("initRuleName1", "ds", null,
Collections.singletonMap("t_order", Collections.singleton(segment))),
- new ShadowRuleSegment("initRuleName2", "ds1", null,
Collections.singletonMap("t_order_1", Collections.singleton(segment)))));
- sqlStatement.buildAttributes();
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(currentConfig);
- executor.setRule(rule);
- assertThrows(InUsedAlgorithmException.class, () ->
executor.checkBeforeUpdate(sqlStatement));
+ void assertBuildToBeAlteredRuleConfiguration() {
+ ShadowAlgorithmSegment algorithmSegment = new
ShadowAlgorithmSegment("algorithm_name", new AlgorithmSegment("SQL_HINT",
PropertiesBuilder.build(new Property("type", "value"))));
+ AlterShadowRuleStatement sqlStatement = createAlterStatement(
+ Collections.singleton(new ShadowRuleSegment("initRuleName1",
"ds_0", "ds_0_shadow", Collections.singletonMap("t_order",
Collections.singleton(algorithmSegment)))));
+ ShadowRuleConfiguration actual =
executor.buildToBeAlteredRuleConfiguration(sqlStatement);
+ assertThat(actual.getDataSources().size(), is(1));
+ assertThat(actual.getShadowAlgorithms().size(), is(1));
+ assertThat(actual.getTables().size(), is(1));
}
@Test
- void assertExecuteDuplicateAlgorithmWithoutConfiguration() {
- ShadowAlgorithmSegment segment = new
ShadowAlgorithmSegment("algorithmName", new AlgorithmSegment("name",
PropertiesBuilder.build(new Property("type", "value"))));
- AlterShadowRuleStatement sqlStatement = new
AlterShadowRuleStatement(Arrays.asList(
- new ShadowRuleSegment("initRuleName1", "ds", null,
Collections.singletonMap("t_order", Collections.singleton(segment))),
- new ShadowRuleSegment("initRuleName2", "ds1", null,
Collections.singletonMap("t_order_1", Collections.singleton(segment)))));
- sqlStatement.buildAttributes();
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(currentConfig);
- executor.setRule(rule);
- assertThrows(InUsedAlgorithmException.class, () ->
executor.checkBeforeUpdate(sqlStatement));
+ void assertBuildToBeDroppedRuleConfiguration() {
+ ShadowRuleConfiguration ruleConfig = new ShadowRuleConfiguration();
+ ruleConfig.getShadowAlgorithms().put("used_algorithm", new
AlgorithmConfiguration("SQL_HINT", new Properties()));
+ ruleConfig.getShadowAlgorithms().put("unused_algorithm", new
AlgorithmConfiguration("SQL_HINT", new Properties()));
+ ruleConfig.getTables().put("t_order", new ShadowTableConfiguration(new
ArrayList<>(Collections.singleton("initRuleName1")), new
ArrayList<>(Collections.singleton("used_algorithm"))));
+ ruleConfig.setDefaultShadowAlgorithmName("used_algorithm");
+ executor.setRule(createRule(ruleConfig));
+ ShadowRuleConfiguration actual =
executor.buildToBeDroppedRuleConfiguration(new ShadowRuleConfiguration());
+ assertThat(actual.getShadowAlgorithms().size(), is(1));
+
assertTrue(actual.getShadowAlgorithms().containsKey("unused_algorithm"));
}
@Test
- void assertExecuteSuccess() {
- Properties props = PropertiesBuilder.build(new Property("type",
"value"));
- ShadowAlgorithmSegment segment1 = new
ShadowAlgorithmSegment("algorithmName1", new AlgorithmSegment("SQL_HINT",
props));
- ShadowAlgorithmSegment segment2 = new
ShadowAlgorithmSegment("algorithmName2", new AlgorithmSegment("SQL_HINT",
props));
- AlterShadowRuleStatement sqlStatement = new
AlterShadowRuleStatement(Arrays.asList(
- new ShadowRuleSegment("initRuleName1", "ds", null,
Collections.singletonMap("t_order", Collections.singleton(segment1))),
- new ShadowRuleSegment("initRuleName2", "ds1", null,
Collections.singletonMap("t_order_1", Collections.singleton(segment2)))));
- sqlStatement.buildAttributes();
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(currentConfig);
- executor.setRule(rule);
- executor.checkBeforeUpdate(sqlStatement);
+ void assertGetRuleClass() {
+ assertThat(executor.getRuleClass(), is(ShadowRule.class));
}
- @Test
- void assertExecuteSuccessWithoutProps() {
- ShadowAlgorithmSegment segment1 = new
ShadowAlgorithmSegment("algorithmName1", new AlgorithmSegment("SQL_HINT",
null));
- ShadowAlgorithmSegment segment2 = new
ShadowAlgorithmSegment("algorithmName2", new AlgorithmSegment("SQL_HINT",
null));
- AlterShadowRuleStatement sqlStatement = new
AlterShadowRuleStatement(Arrays.asList(
- new ShadowRuleSegment("initRuleName1", "ds", null,
Collections.singletonMap("t_order", Collections.singleton(segment1))),
- new ShadowRuleSegment("initRuleName2", "ds1", null,
Collections.singletonMap("t_order_1", Collections.singleton(segment2)))));
- sqlStatement.buildAttributes();
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(currentConfig);
- executor.setRule(rule);
- executor.checkBeforeUpdate(sqlStatement);
+ private static Stream<Arguments> checkBeforeUpdateFailureArguments() {
+ ShadowAlgorithmSegment duplicatedAlgorithmSegment = new
ShadowAlgorithmSegment("duplicated_algorithm",
+ new AlgorithmSegment("SQL_HINT", PropertiesBuilder.build(new
Property("type", "value"))));
+ ShadowAlgorithmSegment invalidTypeSegment = new
ShadowAlgorithmSegment("invalid_type_algorithm",
+ new AlgorithmSegment("INVALID_TYPE",
PropertiesBuilder.build(new Property("type", "value"))));
+ return Stream.of(
+ Arguments.of("duplicate rule name",
createAlterStatement(Arrays.asList(
+ new ShadowRuleSegment("rule_name", null, null, null),
+ new ShadowRuleSegment("rule_name", null, null,
null))), Collections.emptyList(), DuplicateRuleException.class),
+ Arguments.of("rule not found",
createAlterStatement(Collections.singleton(
+ new ShadowRuleSegment("missing_rule", null, null,
null))), Collections.emptyList(), MissingRequiredRuleException.class),
+ Arguments.of("storage unit not found",
createAlterStatement(Collections.singleton(
+ new ShadowRuleSegment("initRuleName1",
"missing_storage_unit", null, null))),
Collections.singletonList("missing_storage_unit"),
+ MissingRequiredStorageUnitsException.class),
+ Arguments.of("duplicate algorithm name",
createAlterStatement(Arrays.asList(
+ new ShadowRuleSegment("initRuleName1", "ds_0", null,
Collections.singletonMap("t_order",
Collections.singleton(duplicatedAlgorithmSegment))),
+ new ShadowRuleSegment("initRuleName2", "ds_1", null,
Collections.singletonMap("t_order_1",
Collections.singleton(duplicatedAlgorithmSegment))))),
+ Collections.emptyList(),
InUsedAlgorithmException.class),
+ Arguments.of("invalid algorithm type",
createAlterStatement(Collections.singleton(
+ new ShadowRuleSegment("initRuleName1", "ds_0", null,
Collections.singletonMap("t_order",
Collections.singleton(invalidTypeSegment))))),
+ Collections.emptyList(),
ServiceProviderNotFoundException.class));
+ }
+
+ private static AlterShadowRuleStatement createAlterStatement(final
Collection<ShadowRuleSegment> rules) {
+ AlterShadowRuleStatement result = new AlterShadowRuleStatement(rules);
+ result.buildAttributes();
+ return result;
}
}
diff --git
a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/CreateDefaultShadowAlgorithmExecutorTest.java
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/CreateDefaultShadowAlgorithmExecutorTest.java
index 3b70e9bf25f..396b0c400d5 100644
---
a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/CreateDefaultShadowAlgorithmExecutorTest.java
+++
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/CreateDefaultShadowAlgorithmExecutorTest.java
@@ -17,57 +17,112 @@
package org.apache.shardingsphere.shadow.distsql.handler.update;
+import
org.apache.shardingsphere.distsql.handler.engine.update.rdl.rule.spi.database.DatabaseRuleDefinitionExecutor;
import org.apache.shardingsphere.distsql.segment.AlgorithmSegment;
+import
org.apache.shardingsphere.infra.algorithm.core.exception.InUsedAlgorithmException;
+import
org.apache.shardingsphere.infra.algorithm.core.exception.MissingRequiredAlgorithmException;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import
org.apache.shardingsphere.infra.spi.exception.ServiceProviderNotFoundException;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
import org.apache.shardingsphere.infra.util.props.PropertiesBuilder;
import org.apache.shardingsphere.infra.util.props.PropertiesBuilder.Property;
+import org.apache.shardingsphere.shadow.config.ShadowRuleConfiguration;
import org.apache.shardingsphere.shadow.distsql.segment.ShadowAlgorithmSegment;
import
org.apache.shardingsphere.shadow.distsql.statement.CreateDefaultShadowAlgorithmStatement;
import org.apache.shardingsphere.shadow.rule.ShadowRule;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.Answers;
+import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+import org.mockito.quality.Strictness;
+import java.util.stream.Stream;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+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.mock;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
class CreateDefaultShadowAlgorithmExecutorTest {
- private final CreateDefaultShadowAlgorithmExecutor executor = new
CreateDefaultShadowAlgorithmExecutor();
+ private final CreateDefaultShadowAlgorithmExecutor executor =
(CreateDefaultShadowAlgorithmExecutor) TypedSPILoader.getService(
+ DatabaseRuleDefinitionExecutor.class,
CreateDefaultShadowAlgorithmStatement.class);
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private ShardingSphereDatabase database;
@BeforeEach
void setUp() {
- executor.setDatabase(mock(ShardingSphereDatabase.class,
RETURNS_DEEP_STUBS));
+ when(database.getName()).thenReturn("shadow_db");
+ executor.setDatabase(database);
}
- @Test
- void assertExecuteWithInvalidAlgorithm() {
- CreateDefaultShadowAlgorithmStatement statement =
mock(CreateDefaultShadowAlgorithmStatement.class);
- when(statement.getShadowAlgorithmSegment()).thenReturn(new
ShadowAlgorithmSegment("algorithmName", new AlgorithmSegment("name",
PropertiesBuilder.build(new Property("type", "value")))));
- ShadowRule rule = mock(ShadowRule.class);
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("checkBeforeUpdateFailureArguments")
+ void assertCheckBeforeUpdateWithInvalidInput(final String name, final
CreateDefaultShadowAlgorithmStatement sqlStatement,
+ final ShadowRule rule, final
Class<? extends Exception> expectedException) {
executor.setRule(rule);
- assertThrows(ServiceProviderNotFoundException.class, () ->
executor.checkBeforeUpdate(statement));
+ assertThrows(expectedException, () ->
executor.checkBeforeUpdate(sqlStatement));
}
@Test
- void assertExecuteSuccess() {
- CreateDefaultShadowAlgorithmStatement sqlStatement =
mock(CreateDefaultShadowAlgorithmStatement.class);
- when(sqlStatement.getShadowAlgorithmSegment()).thenReturn(
- new ShadowAlgorithmSegment("algorithmName", new
AlgorithmSegment("SQL_HINT", PropertiesBuilder.build(new Property("type",
"value")))));
+ void assertCheckBeforeUpdate() {
+ executor.setRule(null);
+ assertDoesNotThrow(() ->
executor.checkBeforeUpdate(createStatement(false, "SQL_HINT")));
+ }
+
+ @Test
+ void assertCheckBeforeUpdateWithIfNotExists() {
ShadowRule rule = mock(ShadowRule.class);
executor.setRule(rule);
- executor.checkBeforeUpdate(sqlStatement);
+ assertDoesNotThrow(() ->
executor.checkBeforeUpdate(createStatement(true, "SQL_HINT")));
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("buildToBeCreatedRuleConfigurationArguments")
+ void assertBuildToBeCreatedRuleConfiguration(final String name, final
ShadowRule rule, final int expectedAlgorithmSize, final String
expectedDefaultAlgorithmName) {
+ executor.setRule(rule);
+ ShadowRuleConfiguration actual =
executor.buildToBeCreatedRuleConfiguration(createStatement(false, "SQL_HINT"));
+ assertThat(actual.getShadowAlgorithms().size(),
is(expectedAlgorithmSize));
+
assertThat(actual.getShadowAlgorithms().containsKey("default_shadow_algorithm"),
is(expectedAlgorithmSize > 0));
+ assertThat(actual.getDefaultShadowAlgorithmName(),
is(expectedDefaultAlgorithmName));
}
@Test
- void assertExecuteWithIfNotExists() {
- ShadowAlgorithmSegment shadowAlgorithmSegment = new
ShadowAlgorithmSegment("algorithmName", new AlgorithmSegment("SQL_HINT",
PropertiesBuilder.build(new Property("type", "value"))));
- CreateDefaultShadowAlgorithmStatement sqlStatement = new
CreateDefaultShadowAlgorithmStatement(true, shadowAlgorithmSegment);
- executor.checkBeforeUpdate(sqlStatement);
+ void assertGetRuleClass() {
+ assertThat(executor.getRuleClass(), is(ShadowRule.class));
+ }
+
+ private static Stream<Arguments> checkBeforeUpdateFailureArguments() {
+ ShadowRule duplicatedRule = mock(ShadowRule.class);
+
when(duplicatedRule.containsShadowAlgorithm("default_shadow_algorithm")).thenReturn(true);
+ return Stream.of(
+ Arguments.of("missing algorithm type", createStatement(false,
""), null, MissingRequiredAlgorithmException.class),
+ Arguments.of("invalid algorithm type", createStatement(false,
"INVALID_TYPE"), null, ServiceProviderNotFoundException.class),
+ Arguments.of("duplicate default algorithm",
createStatement(false, "SQL_HINT"), duplicatedRule,
InUsedAlgorithmException.class));
+ }
+
+ private static CreateDefaultShadowAlgorithmStatement createStatement(final
boolean ifNotExists, final String algorithmType) {
+ ShadowAlgorithmSegment shadowAlgorithmSegment = new
ShadowAlgorithmSegment("algorithm_name", new AlgorithmSegment(algorithmType,
PropertiesBuilder.build(new Property("type", "value"))));
+ return new CreateDefaultShadowAlgorithmStatement(ifNotExists,
shadowAlgorithmSegment);
+ }
+
+ private static Stream<Arguments>
buildToBeCreatedRuleConfigurationArguments() {
+ ShadowRule duplicatedRule = mock(ShadowRule.class);
+
when(duplicatedRule.containsShadowAlgorithm("default_shadow_algorithm")).thenReturn(true);
+ return Stream.of(
+ Arguments.of("rule is null", null, 1,
"default_shadow_algorithm"),
+ Arguments.of("rule without default algorithm",
mock(ShadowRule.class), 1, "default_shadow_algorithm"),
+ Arguments.of("rule already has default algorithm",
duplicatedRule, 0, null));
}
}
diff --git
a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/CreateShadowRuleExecutorTest.java
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/CreateShadowRuleExecutorTest.java
index 073d36f03db..e6c28c347b3 100644
---
a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/CreateShadowRuleExecutorTest.java
+++
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/CreateShadowRuleExecutorTest.java
@@ -17,6 +17,7 @@
package org.apache.shardingsphere.shadow.distsql.handler.update;
+import
org.apache.shardingsphere.distsql.handler.engine.update.rdl.rule.spi.database.DatabaseRuleDefinitionExecutor;
import org.apache.shardingsphere.distsql.segment.AlgorithmSegment;
import
org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.MissingRequiredStorageUnitsException;
import
org.apache.shardingsphere.infra.exception.kernel.metadata.rule.DuplicateRuleException;
@@ -25,6 +26,7 @@ import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import
org.apache.shardingsphere.infra.metadata.database.resource.ResourceMetaData;
import
org.apache.shardingsphere.infra.rule.attribute.datasource.DataSourceMapperRuleAttribute;
import
org.apache.shardingsphere.infra.spi.exception.ServiceProviderNotFoundException;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
import org.apache.shardingsphere.infra.util.props.PropertiesBuilder;
import org.apache.shardingsphere.infra.util.props.PropertiesBuilder.Property;
import org.apache.shardingsphere.shadow.config.ShadowRuleConfiguration;
@@ -36,6 +38,9 @@ import org.apache.shardingsphere.shadow.rule.ShadowRule;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@@ -43,11 +48,17 @@ import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
+import java.util.LinkedList;
+import java.util.stream.Stream;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -55,7 +66,7 @@ import static org.mockito.Mockito.when;
@MockitoSettings(strictness = Strictness.LENIENT)
class CreateShadowRuleExecutorTest {
- private final CreateShadowRuleExecutor executor = new
CreateShadowRuleExecutor();
+ private final CreateShadowRuleExecutor executor =
(CreateShadowRuleExecutor)
TypedSPILoader.getService(DatabaseRuleDefinitionExecutor.class,
CreateShadowRuleStatement.class);
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private ShardingSphereDatabase database;
@@ -63,116 +74,109 @@ class CreateShadowRuleExecutorTest {
@Mock
private ResourceMetaData resourceMetaData;
- @Mock
- private ShadowRuleConfiguration currentConfig;
-
@BeforeEach
void setUp() {
+
when(resourceMetaData.getNotExistedDataSources(any())).thenReturn(Collections.emptyList());
when(database.getResourceMetaData()).thenReturn(resourceMetaData);
+
when(database.getRuleMetaData().getAttributes(DataSourceMapperRuleAttribute.class)).thenReturn(Collections.emptyList());
when(database.getName()).thenReturn("shadow_db");
-
when(currentConfig.getDataSources()).thenReturn(Collections.singleton(new
ShadowDataSourceConfiguration("initRuleName", "initDs0", "initDs0Shadow")));
executor.setDatabase(database);
+ executor.setRule(createRule(createCurrentRuleConfiguration()));
}
- @Test
- void assertExecuteWithDuplicateRuleName() {
- ShadowRuleSegment ruleSegment = new ShadowRuleSegment("ruleName",
null, null, null);
- CreateShadowRuleStatement sqlStatement = new
CreateShadowRuleStatement(false, Arrays.asList(ruleSegment, ruleSegment));
- sqlStatement.buildAttributes();
- assertThrows(DuplicateRuleException.class, () ->
executor.checkBeforeUpdate(sqlStatement));
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("checkBeforeUpdateFailureArguments")
+ void assertCheckBeforeUpdateWithInvalidInput(final String name, final
CreateShadowRuleStatement sqlStatement, final ShadowRule rule,
+ final Collection<String>
notExistedStorageUnits, final Collection<DataSourceMapperRuleAttribute>
ruleAttributes,
+ final Class<? extends
Exception> expectedException) {
+
when(resourceMetaData.getNotExistedDataSources(any())).thenReturn(notExistedStorageUnits);
+
when(database.getRuleMetaData().getAttributes(DataSourceMapperRuleAttribute.class)).thenReturn(ruleAttributes);
+ executor.setRule(rule);
+ assertThrows(expectedException, () ->
executor.checkBeforeUpdate(sqlStatement));
}
@Test
- void assertExecuteWithDuplicateRuleNameInMetaData() {
-
when(currentConfig.getDataSources()).thenReturn(Collections.singleton(new
ShadowDataSourceConfiguration("ruleName", "ds", "ds_shadow")));
- ShadowRuleSegment ruleSegment = new ShadowRuleSegment("ruleName",
null, null, null);
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(currentConfig);
- executor.setRule(rule);
- CreateShadowRuleStatement sqlStatement = new
CreateShadowRuleStatement(false, Collections.singleton(ruleSegment));
- sqlStatement.buildAttributes();
- assertThrows(DuplicateRuleException.class, () ->
executor.checkBeforeUpdate(sqlStatement));
+ void assertCheckBeforeUpdate() {
+ assertDoesNotThrow(() ->
executor.checkBeforeUpdate(createStatement(false,
Collections.singleton(createShadowRuleSegment("rule_name", "ds_0",
"algorithm_name", "SQL_HINT", "t_order")))));
}
@Test
- void assertExecuteWithDuplicateLogicResource() {
- DataSourceMapperRuleAttribute ruleAttribute =
mock(DataSourceMapperRuleAttribute.class, RETURNS_DEEP_STUBS);
-
when(ruleAttribute.getDataSourceMapper()).thenReturn(Collections.singletonMap("duplicate_ds",
Collections.singleton("ds_0")));
-
when(database.getRuleMetaData().getAttributes(DataSourceMapperRuleAttribute.class)).thenReturn(Collections.singleton(ruleAttribute));
- executor.setDatabase(database);
- ShadowRuleSegment ruleSegment = new ShadowRuleSegment("duplicate_ds",
null, null, null);
- CreateShadowRuleStatement sqlStatement = new
CreateShadowRuleStatement(false, Collections.singleton(ruleSegment));
- sqlStatement.buildAttributes();
- assertThrows(InvalidRuleConfigurationException.class, () ->
executor.checkBeforeUpdate(sqlStatement));
+ void assertBuildToBeCreatedRuleConfiguration() {
+ ShadowRuleConfiguration actual =
executor.buildToBeCreatedRuleConfiguration(
+ createStatement(false,
Collections.singleton(createShadowRuleSegment("rule_name", "ds_0",
"algorithm_name", "SQL_HINT", "t_order"))));
+ assertThat(actual.getDataSources().size(), is(1));
+ assertThat(actual.getTables().size(), is(1));
+ assertThat(actual.getShadowAlgorithms().size(), is(1));
}
@Test
- void assertExecuteWithNotExistResource() {
-
when(resourceMetaData.getNotExistedDataSources(any())).thenReturn(Arrays.asList("ds0",
"ds1"));
- CreateShadowRuleStatement sqlStatement = new
CreateShadowRuleStatement(false, Collections.singleton(new
ShadowRuleSegment("ruleName", "ds1", null, null)));
- sqlStatement.buildAttributes();
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(currentConfig);
- executor.setRule(rule);
- assertThrows(MissingRequiredStorageUnitsException.class, () ->
executor.checkBeforeUpdate(sqlStatement));
+ void assertBuildToBeCreatedRuleConfigurationWithIfNotExists() {
+ CreateShadowRuleStatement sqlStatement = createStatement(true,
Arrays.asList(
+ createShadowRuleSegment("initRuleName", "ds_0",
"algorithm_name_0", "SQL_HINT", "t_order"),
+ createShadowRuleSegment("new_rule_name", "ds_1",
"algorithm_name_1", "SQL_HINT", "t_order_1")));
+ executor.setRule(createRule(createCurrentRuleConfiguration()));
+ ShadowRuleConfiguration actual =
executor.buildToBeCreatedRuleConfiguration(sqlStatement);
+ assertThat(actual.getDataSources().size(), is(1));
+ assertThat(actual.getDataSources().iterator().next().getName(),
is("new_rule_name"));
+ assertTrue(actual.getTables().containsKey("t_order_1"));
+
assertTrue(actual.getShadowAlgorithms().containsKey("algorithm_name_1"));
}
@Test
- void assertExecuteDuplicateAlgorithm() {
- ShadowAlgorithmSegment segment = new
ShadowAlgorithmSegment("algorithmName", new AlgorithmSegment("name",
PropertiesBuilder.build(new Property("type", "value"))));
- CreateShadowRuleStatement sqlStatement = new
CreateShadowRuleStatement(false, Arrays.asList(
- new ShadowRuleSegment("ruleName", "ds", null,
Collections.singletonMap("t_order", Collections.singleton(segment))),
- new ShadowRuleSegment("ruleName", "ds1", null,
Collections.singletonMap("t_order_1", Collections.singleton(segment)))));
- sqlStatement.buildAttributes();
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(currentConfig);
- executor.setRule(rule);
- assertThrows(DuplicateRuleException.class, () ->
executor.checkBeforeUpdate(sqlStatement));
+ void assertGetRuleClass() {
+ assertThat(executor.getRuleClass(), is(ShadowRule.class));
}
- @Test
- void assertExecuteDuplicateAlgorithmWithoutConfiguration() {
- ShadowAlgorithmSegment segment = new
ShadowAlgorithmSegment("algorithmName", new AlgorithmSegment("name",
PropertiesBuilder.build(new Property("type", "value"))));
- CreateShadowRuleStatement sqlStatement = new
CreateShadowRuleStatement(false, Arrays.asList(
- new ShadowRuleSegment("ruleName", "ds", null,
Collections.singletonMap("t_order", Collections.singleton(segment))),
- new ShadowRuleSegment("ruleName1", "ds1", null,
Collections.singletonMap("t_order_1", Collections.singleton(segment)))));
- sqlStatement.buildAttributes();
- assertThrows(DuplicateRuleException.class, () ->
executor.checkBeforeUpdate(sqlStatement));
+ private static Stream<Arguments> checkBeforeUpdateFailureArguments() {
+ DataSourceMapperRuleAttribute duplicatedLogicDataSourceAttribute =
mock(DataSourceMapperRuleAttribute.class);
+
when(duplicatedLogicDataSourceAttribute.getDataSourceMapper()).thenReturn(Collections.singletonMap("duplicate_ds",
Collections.singleton("ds_0")));
+ ShadowAlgorithmSegment duplicatedAlgorithmSegment =
createShadowAlgorithmSegment("duplicated_algorithm", "SQL_HINT");
+ return Stream.of(
+ Arguments.of("duplicate rule name", createStatement(false,
Arrays.asList(
+ new ShadowRuleSegment("rule_name", null, null, null),
+ new ShadowRuleSegment("rule_name", null, null,
null))), createRule(createCurrentRuleConfiguration()),
+ Collections.emptyList(), Collections.emptyList(),
DuplicateRuleException.class),
+ Arguments.of("duplicate current rule", createStatement(false,
Collections.singleton(
+ createShadowRuleSegment("initRuleName", "ds_0",
"algorithm_name", "SQL_HINT", "t_order"))),
createRule(createCurrentRuleConfiguration()),
+ Collections.emptyList(), Collections.emptyList(),
DuplicateRuleException.class),
+ Arguments.of("duplicate logic datasource",
createStatement(false, Collections.singleton(
+ createShadowRuleSegment("duplicate_ds", "ds_0",
"algorithm_name", "SQL_HINT", "t_order"))),
createRule(createCurrentRuleConfiguration()),
+ Collections.emptyList(),
Collections.singleton(duplicatedLogicDataSourceAttribute),
InvalidRuleConfigurationException.class),
+ Arguments.of("missing storage unit", createStatement(false,
Collections.singleton(
+ createShadowRuleSegment("rule_name", "missing_ds",
"algorithm_name", "SQL_HINT", "t_order"))),
createRule(createCurrentRuleConfiguration()),
+ Collections.singleton("missing_ds"),
Collections.emptyList(), MissingRequiredStorageUnitsException.class),
+ Arguments.of("duplicate algorithm", createStatement(false,
Arrays.asList(
+ new ShadowRuleSegment("rule_name_0", "ds_0", null,
Collections.singletonMap("t_order",
Collections.singleton(duplicatedAlgorithmSegment))),
+ new ShadowRuleSegment("rule_name_1", "ds_1", null,
Collections.singletonMap("t_order_1",
Collections.singleton(duplicatedAlgorithmSegment))))),
+ createRule(createCurrentRuleConfiguration()),
Collections.emptyList(), Collections.emptyList(), DuplicateRuleException.class),
+ Arguments.of("invalid algorithm type", createStatement(false,
Collections.singleton(
+ createShadowRuleSegment("rule_name", "ds_0",
"algorithm_name", "INVALID_TYPE", "t_order"))),
createRule(createCurrentRuleConfiguration()),
+ Collections.emptyList(), Collections.emptyList(),
ServiceProviderNotFoundException.class));
}
- @Test
- void assertInvalidAlgorithmConfiguration() {
- ShadowAlgorithmSegment segment = new
ShadowAlgorithmSegment("algorithmName", new AlgorithmSegment("type",
PropertiesBuilder.build(new Property("type", "value"))));
- CreateShadowRuleStatement sqlStatement = new
CreateShadowRuleStatement(false,
- Collections.singleton(new ShadowRuleSegment("ruleName", "ds",
null, Collections.singletonMap("t_order", Collections.singleton(segment)))));
- sqlStatement.buildAttributes();
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(currentConfig);
- executor.setRule(rule);
- assertThrows(ServiceProviderNotFoundException.class, () ->
executor.checkBeforeUpdate(sqlStatement));
+ private static CreateShadowRuleStatement createStatement(final boolean
ifNotExists, final Collection<ShadowRuleSegment> rules) {
+ CreateShadowRuleStatement result = new
CreateShadowRuleStatement(ifNotExists, new LinkedList<>(rules));
+ result.buildAttributes();
+ return result;
}
- @Test
- void assertExecuteWithoutProps() {
- ShadowAlgorithmSegment segment = new
ShadowAlgorithmSegment("algorithmName", new AlgorithmSegment("SQL_HINT", null));
- CreateShadowRuleStatement sqlStatement = new
CreateShadowRuleStatement(false,
- Collections.singleton(new
ShadowRuleSegment("initRuleNameWithoutProps", "ds", null,
Collections.singletonMap("t_order", Collections.singleton(segment)))));
- sqlStatement.buildAttributes();
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(currentConfig);
- executor.setRule(rule);
- executor.checkBeforeUpdate(sqlStatement);
+ private static ShadowRuleSegment createShadowRuleSegment(final String
ruleName, final String source, final String algorithmName, final String
algorithmType, final String tableName) {
+ return new ShadowRuleSegment(ruleName, source, null,
Collections.singletonMap(tableName,
Collections.singleton(createShadowAlgorithmSegment(algorithmName,
algorithmType))));
}
- @Test
- void assertExecuteWithIfNotExists() {
- ShadowAlgorithmSegment segment = new
ShadowAlgorithmSegment("algorithmName", new AlgorithmSegment("SQL_HINT",
PropertiesBuilder.build(new Property("type", "value"))));
- CreateShadowRuleStatement sqlStatement = new
CreateShadowRuleStatement(true,
- Collections.singleton(new ShadowRuleSegment("initRuleName",
"ds", null, Collections.singletonMap("t_order",
Collections.singleton(segment)))));
- sqlStatement.buildAttributes();
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(currentConfig);
- executor.setRule(rule);
- executor.checkBeforeUpdate(sqlStatement);
+ private static ShadowAlgorithmSegment createShadowAlgorithmSegment(final
String algorithmName, final String algorithmType) {
+ return new ShadowAlgorithmSegment(algorithmName, new
AlgorithmSegment(algorithmType, PropertiesBuilder.build(new Property("type",
"value"))));
+ }
+
+ private static ShadowRuleConfiguration createCurrentRuleConfiguration() {
+ ShadowRuleConfiguration result = new ShadowRuleConfiguration();
+ result.getDataSources().add(new
ShadowDataSourceConfiguration("initRuleName", "init_ds_0", "init_ds_0_shadow"));
+ return result;
+ }
+
+ private static ShadowRule createRule(final ShadowRuleConfiguration
ruleConfig) {
+ ShadowRule result = mock(ShadowRule.class);
+ when(result.getConfiguration()).thenReturn(ruleConfig);
+ return result;
}
}
diff --git
a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/DropDefaultShadowAlgorithmExecutorTest.java
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/DropDefaultShadowAlgorithmExecutorTest.java
index 6d7d9176c0f..d37c73507ca 100644
---
a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/DropDefaultShadowAlgorithmExecutorTest.java
+++
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/DropDefaultShadowAlgorithmExecutorTest.java
@@ -19,7 +19,9 @@ package
org.apache.shardingsphere.shadow.distsql.handler.update;
import
org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
import
org.apache.shardingsphere.infra.algorithm.core.exception.UnregisteredAlgorithmException;
+import
org.apache.shardingsphere.distsql.handler.engine.update.rdl.rule.spi.database.DatabaseRuleDefinitionExecutor;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
import org.apache.shardingsphere.shadow.config.ShadowRuleConfiguration;
import
org.apache.shardingsphere.shadow.distsql.statement.DropDefaultShadowAlgorithmStatement;
import org.apache.shardingsphere.shadow.rule.ShadowRule;
@@ -31,6 +33,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
@@ -40,7 +43,8 @@ import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class DropDefaultShadowAlgorithmExecutorTest {
- private final DropDefaultShadowAlgorithmExecutor executor = new
DropDefaultShadowAlgorithmExecutor();
+ private final DropDefaultShadowAlgorithmExecutor executor =
(DropDefaultShadowAlgorithmExecutor) TypedSPILoader.getService(
+ DatabaseRuleDefinitionExecutor.class,
DropDefaultShadowAlgorithmStatement.class);
@Mock
private ShadowRuleConfiguration currentConfig;
@@ -60,7 +64,7 @@ class DropDefaultShadowAlgorithmExecutorTest {
@Test
void assertCheckWithIfExists() {
- executor.checkBeforeUpdate(new
DropDefaultShadowAlgorithmStatement(true));
+ assertDoesNotThrow(() -> executor.checkBeforeUpdate(new
DropDefaultShadowAlgorithmStatement(true)));
}
@Test
@@ -78,4 +82,9 @@ class DropDefaultShadowAlgorithmExecutorTest {
assertThat(toBeDroppedRuleConfig.getDefaultShadowAlgorithmName(),
is("default"));
assertThat(toBeDroppedRuleConfig.getShadowAlgorithms().size(), is(1));
}
+
+ @Test
+ void assertGetRuleClass() {
+ assertThat(executor.getRuleClass(), is(ShadowRule.class));
+ }
}
diff --git
a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/DropShadowAlgorithmExecutorTest.java
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/DropShadowAlgorithmExecutorTest.java
index 196cb706bff..c130bfddb21 100644
---
a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/DropShadowAlgorithmExecutorTest.java
+++
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/DropShadowAlgorithmExecutorTest.java
@@ -17,58 +17,138 @@
package org.apache.shardingsphere.shadow.distsql.handler.update;
+import
org.apache.shardingsphere.distsql.handler.engine.update.rdl.rule.spi.database.DatabaseRuleDefinitionExecutor;
import
org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
+import
org.apache.shardingsphere.infra.algorithm.core.exception.InUsedAlgorithmException;
+import
org.apache.shardingsphere.infra.algorithm.core.exception.UnregisteredAlgorithmException;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
import org.apache.shardingsphere.shadow.config.ShadowRuleConfiguration;
+import org.apache.shardingsphere.shadow.config.table.ShadowTableConfiguration;
import
org.apache.shardingsphere.shadow.distsql.statement.DropShadowAlgorithmStatement;
import org.apache.shardingsphere.shadow.rule.ShadowRule;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+import org.mockito.quality.Strictness;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.Properties;
+import java.util.stream.Stream;
-import static org.hamcrest.Matchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
class DropShadowAlgorithmExecutorTest {
- private final DropShadowAlgorithmExecutor executor = new
DropShadowAlgorithmExecutor();
+ private final DropShadowAlgorithmExecutor executor =
(DropShadowAlgorithmExecutor)
TypedSPILoader.getService(DatabaseRuleDefinitionExecutor.class,
DropShadowAlgorithmStatement.class);
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private ShardingSphereDatabase database;
@BeforeEach
void setUp() {
- executor.setDatabase(mock(ShardingSphereDatabase.class,
RETURNS_DEEP_STUBS));
+ when(database.getName()).thenReturn("shadow_db");
+ executor.setDatabase(database);
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("checkBeforeUpdateFailureArguments")
+ void assertCheckBeforeUpdateWithInvalidInput(final String name, final
ShadowRuleConfiguration ruleConfig,
+ final
DropShadowAlgorithmStatement sqlStatement, final Class<? extends Exception>
expectedException) {
+ executor.setRule(createRule(ruleConfig));
+ assertThrows(expectedException, () ->
executor.checkBeforeUpdate(sqlStatement));
}
@Test
- void assertExecuteWithIfExists() {
- DropShadowAlgorithmStatement sqlStatement = createSQLStatement(true,
"ruleSegment");
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(new
ShadowRuleConfiguration());
- executor.setRule(rule);
- executor.checkBeforeUpdate(sqlStatement);
+ void assertCheckBeforeUpdate() {
+ ShadowRuleConfiguration ruleConfig = new ShadowRuleConfiguration();
+ ruleConfig.getShadowAlgorithms().put("droppable_algorithm", new
AlgorithmConfiguration("SQL_HINT", new Properties()));
+ ruleConfig.getTables().put("t_order_empty", new
ShadowTableConfiguration(new LinkedList<>(), new
LinkedList<>(Collections.singleton("droppable_algorithm"))));
+ executor.setRule(createRule(ruleConfig));
+ assertDoesNotThrow(() -> executor.checkBeforeUpdate(new
DropShadowAlgorithmStatement(false,
Collections.singleton("droppable_algorithm"))));
}
@Test
- void assertUpdate() {
+ void assertCheckBeforeUpdateWithIfExists() {
+ executor.setRule(createRule(new ShadowRuleConfiguration()));
+ assertDoesNotThrow(() -> executor.checkBeforeUpdate(new
DropShadowAlgorithmStatement(true,
Collections.singleton("missing_algorithm"))));
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("hasAnyOneToBeDroppedArguments")
+ void assertHasAnyOneToBeDropped(final String name, final
DropShadowAlgorithmStatement sqlStatement, final boolean expected) {
ShadowRuleConfiguration ruleConfig = new ShadowRuleConfiguration();
- ruleConfig.getShadowAlgorithms().put("shadow_algorithm", new
AlgorithmConfiguration("type", null));
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(ruleConfig);
- executor.setRule(rule);
- DropShadowAlgorithmStatement sqlStatement =
createSQLStatement("shadow_algorithm");
- executor.checkBeforeUpdate(sqlStatement);
- ShadowRuleConfiguration toBeDroppedRuleConfig =
executor.buildToBeDroppedRuleConfiguration(sqlStatement);
- assertThat(toBeDroppedRuleConfig.getShadowAlgorithms().size(), is(1));
+ ruleConfig.getShadowAlgorithms().put("algorithm_0", new
AlgorithmConfiguration("SQL_HINT", new Properties()));
+ ruleConfig.getShadowAlgorithms().put("algorithm_1", new
AlgorithmConfiguration("SQL_HINT", new Properties()));
+ executor.setRule(createRule(ruleConfig));
+ assertThat(executor.hasAnyOneToBeDropped(sqlStatement), is(expected));
+ }
+
+ @Test
+ void assertBuildToBeDroppedRuleConfiguration() {
+ ShadowRuleConfiguration ruleConfig = new ShadowRuleConfiguration();
+ ruleConfig.getShadowAlgorithms().put("algorithm_0", new
AlgorithmConfiguration("SQL_HINT", new Properties()));
+ ruleConfig.getShadowAlgorithms().put("algorithm_1", new
AlgorithmConfiguration("SQL_HINT", new Properties()));
+ executor.setRule(createRule(ruleConfig));
+ DropShadowAlgorithmStatement sqlStatement = new
DropShadowAlgorithmStatement(false, Arrays.asList("algorithm_0",
"algorithm_1"));
+ ShadowRuleConfiguration actual =
executor.buildToBeDroppedRuleConfiguration(sqlStatement);
+ assertThat(actual.getShadowAlgorithms().size(), is(2));
+
assertTrue(actual.getShadowAlgorithms().keySet().containsAll(sqlStatement.getNames()));
+ }
+
+ private ShadowRule createRule(final ShadowRuleConfiguration ruleConfig) {
+ ShadowRule result = mock(ShadowRule.class);
+ when(result.getConfiguration()).thenReturn(ruleConfig);
+ return result;
+ }
+
+ @Test
+ void assertGetRuleClass() {
+ assertThat(executor.getRuleClass(), is(ShadowRule.class));
}
- private DropShadowAlgorithmStatement createSQLStatement(final String...
ruleName) {
- return new DropShadowAlgorithmStatement(false,
Arrays.asList(ruleName));
+ private static Stream<Arguments> checkBeforeUpdateFailureArguments() {
+ ShadowRuleConfiguration notRegisteredConfig = new
ShadowRuleConfiguration();
+ notRegisteredConfig.getShadowAlgorithms().put("registered_algorithm",
new AlgorithmConfiguration("SQL_HINT", new Properties()));
+ ShadowRuleConfiguration inUsedAlgorithmConfig = new
ShadowRuleConfiguration();
+ inUsedAlgorithmConfig.getShadowAlgorithms().put("in_used_algorithm",
new AlgorithmConfiguration("SQL_HINT", new Properties()));
+
inUsedAlgorithmConfig.getShadowAlgorithms().put("algorithm_from_empty_table",
new AlgorithmConfiguration("SQL_HINT", new Properties()));
+ inUsedAlgorithmConfig.getTables().put("t_order",
+ new ShadowTableConfiguration(new
LinkedList<>(Collections.singleton("shadow_group")), new
LinkedList<>(Collections.singleton("in_used_algorithm"))));
+ inUsedAlgorithmConfig.getTables().put("t_order_empty", new
ShadowTableConfiguration(new LinkedList<>(), new
LinkedList<>(Collections.singleton("algorithm_from_empty_table"))));
+ ShadowRuleConfiguration defaultAlgorithmConfig = new
ShadowRuleConfiguration();
+
defaultAlgorithmConfig.getShadowAlgorithms().put("default_shadow_algorithm",
new AlgorithmConfiguration("SQL_HINT", new Properties()));
+
defaultAlgorithmConfig.setDefaultShadowAlgorithmName("default_shadow_algorithm");
+ return Stream.of(
+ Arguments.of("algorithm not registered", notRegisteredConfig,
+ new DropShadowAlgorithmStatement(false,
Collections.singleton("missing_algorithm")),
UnregisteredAlgorithmException.class),
+ Arguments.of("algorithm in use", inUsedAlgorithmConfig,
+ new DropShadowAlgorithmStatement(false,
Collections.singleton("in_used_algorithm")), InUsedAlgorithmException.class),
+ Arguments.of("default algorithm", defaultAlgorithmConfig,
+ new DropShadowAlgorithmStatement(false,
Collections.singleton("default_shadow_algorithm")),
InUsedAlgorithmException.class));
}
- private DropShadowAlgorithmStatement createSQLStatement(final boolean
ifExists, final String... ruleName) {
- return new DropShadowAlgorithmStatement(ifExists,
Arrays.asList(ruleName));
+ private static Stream<Arguments> hasAnyOneToBeDroppedArguments() {
+ return Stream.of(
+ Arguments.of("contains dropped algorithm", new
DropShadowAlgorithmStatement(false, Collections.singleton("algorithm_0")),
true),
+ Arguments.of("contains no dropped algorithm", new
DropShadowAlgorithmStatement(false, Collections.singleton("algorithm_9")),
false),
+ Arguments.of("contains one of dropped algorithms", new
DropShadowAlgorithmStatement(false, Arrays.asList("algorithm_9",
"algorithm_1")), true));
}
}
diff --git
a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/DropShadowRuleExecutorTest.java
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/DropShadowRuleExecutorTest.java
index f3181e1a84e..ab449e2aca4 100644
---
a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/DropShadowRuleExecutorTest.java
+++
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/DropShadowRuleExecutorTest.java
@@ -17,9 +17,11 @@
package org.apache.shardingsphere.shadow.distsql.handler.update;
-import
org.apache.shardingsphere.infra.exception.kernel.metadata.rule.MissingRequiredRuleException;
+import
org.apache.shardingsphere.distsql.handler.engine.update.rdl.rule.spi.database.DatabaseRuleDefinitionExecutor;
import
org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
+import
org.apache.shardingsphere.infra.exception.kernel.metadata.rule.MissingRequiredRuleException;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
import org.apache.shardingsphere.shadow.config.ShadowRuleConfiguration;
import
org.apache.shardingsphere.shadow.config.datasource.ShadowDataSourceConfiguration;
import org.apache.shardingsphere.shadow.config.table.ShadowTableConfiguration;
@@ -27,104 +29,144 @@ import
org.apache.shardingsphere.shadow.distsql.statement.DropShadowRuleStatemen
import org.apache.shardingsphere.shadow.rule.ShadowRule;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+import org.mockito.quality.Strictness;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Properties;
+import java.util.stream.Stream;
-import static org.hamcrest.Matchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
class DropShadowRuleExecutorTest {
- private final DropShadowRuleExecutor executor = new
DropShadowRuleExecutor();
+ private final DropShadowRuleExecutor executor = (DropShadowRuleExecutor)
TypedSPILoader.getService(DatabaseRuleDefinitionExecutor.class,
DropShadowRuleStatement.class);
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private ShardingSphereDatabase database;
@BeforeEach
void setUp() {
- executor.setDatabase(mock(ShardingSphereDatabase.class,
RETURNS_DEEP_STUBS));
+ when(database.getName()).thenReturn("shadow_db");
+ executor.setDatabase(database);
}
- @Test
- void assertCheckWithRuleNotExisted() {
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(new
ShadowRuleConfiguration());
- executor.setRule(rule);
- assertThrows(MissingRequiredRuleException.class,
- () ->
executor.checkBeforeUpdate(createSQLStatement("notExistedRuleName")));
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("checkBeforeUpdateWithMissingRuleArguments")
+ void assertCheckBeforeUpdateWithMissingRule(final String name, final
DropShadowRuleStatement sqlStatement) {
+ executor.setRule(createRule(new ShadowRuleConfiguration()));
+ assertThrows(MissingRequiredRuleException.class, () ->
executor.checkBeforeUpdate(sqlStatement));
}
@Test
- void assertCheckWithIfExists() {
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(new
ShadowRuleConfiguration());
+ void assertCheckBeforeUpdateWithIfExists() {
+ executor.setRule(createRule(new ShadowRuleConfiguration()));
+ assertDoesNotThrow(() ->
executor.checkBeforeUpdate(createStatement(true, "missing_rule")));
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("hasAnyOneToBeDroppedArguments")
+ void assertHasAnyOneToBeDropped(final String name, final ShadowRule rule,
final DropShadowRuleStatement sqlStatement, final boolean expected) {
executor.setRule(rule);
- executor.checkBeforeUpdate(createSQLStatement(true,
"notExistedRuleName"));
+ assertThat(executor.hasAnyOneToBeDropped(sqlStatement), is(expected));
}
@Test
- void assertUpdateCurrentRuleConfigurationWithUnusedAlgorithms() {
- DropShadowRuleStatement sqlStatement =
createSQLStatement("shadow_group");
- ShadowRuleConfiguration ruleConfig = createCurrentRuleConfiguration();
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(ruleConfig);
- executor.setRule(rule);
+ void assertBuildToBeDroppedRuleConfiguration() {
+ ShadowRuleConfiguration ruleConfig = createRuleConfigurationForDrop();
+ executor.setRule(createRule(ruleConfig));
+ DropShadowRuleStatement sqlStatement = createStatement(false,
"shadow_group");
executor.checkBeforeUpdate(sqlStatement);
- ShadowRuleConfiguration toBeDroppedRuleConfig =
executor.buildToBeDroppedRuleConfiguration(sqlStatement);
- assertThat(toBeDroppedRuleConfig.getDataSources().size(), is(1));
- assertThat(toBeDroppedRuleConfig.getTables().size(), is(1));
- assertThat(toBeDroppedRuleConfig.getShadowAlgorithms().size(), is(1));
+ ShadowRuleConfiguration actual =
executor.buildToBeDroppedRuleConfiguration(sqlStatement);
+ assertThat(actual.getDataSources().size(), is(1));
+ assertThat(actual.getDataSources().iterator().next().getName(),
is("shadow_group"));
+ assertThat(actual.getTables().size(), is(1));
+ assertTrue(actual.getTables().containsKey("t_order"));
+ assertThat(actual.getShadowAlgorithms().size(), is(2));
+
assertTrue(actual.getShadowAlgorithms().containsKey("only_drop_algorithm"));
+
assertTrue(actual.getShadowAlgorithms().containsKey("unused_algorithm"));
+ assertThat(ruleConfig.getDataSources().size(), is(1));
+ assertFalse(ruleConfig.getTables().containsKey("t_order"));
+
assertThat(ruleConfig.getTables().get("t_order_item").getDataSourceNames().size(),
is(1));
+
assertThat(ruleConfig.getTables().get("t_order_item").getDataSourceNames().iterator().next(),
is("shadow_group_1"));
}
@Test
- void assertUpdateMultipleCurrentRuleConfigurationWithInUsedAlgorithms() {
- DropShadowRuleStatement sqlStatement =
createSQLStatement("shadow_group");
- ShadowRuleConfiguration ruleConfig =
createMultipleCurrentRuleConfiguration();
- ShadowRule rule = mock(ShadowRule.class);
- when(rule.getConfiguration()).thenReturn(ruleConfig);
- executor.setRule(rule);
- executor.checkBeforeUpdate(sqlStatement);
- ShadowRuleConfiguration toBeDroppedRuleConfig =
executor.buildToBeDroppedRuleConfiguration(sqlStatement);
- assertThat(toBeDroppedRuleConfig.getDataSources().size(), is(1));
- assertThat(toBeDroppedRuleConfig.getTables().size(), is(1));
- assertThat(toBeDroppedRuleConfig.getShadowAlgorithms().size(), is(1));
+ void assertBuildToBeAlteredRuleConfiguration() {
+ ShadowRuleConfiguration ruleConfig = createRuleConfigurationForDrop();
+ executor.setRule(createRule(ruleConfig));
+ ShadowRuleConfiguration actual =
executor.buildToBeAlteredRuleConfiguration(createStatement(false,
"shadow_group"));
+ assertThat(actual.getTables().size(), is(1));
+ assertFalse(actual.getTables().containsKey("t_order"));
+ assertTrue(actual.getTables().containsKey("t_order_item"));
+
assertThat(actual.getTables().get("t_order_item").getDataSourceNames().size(),
is(1));
+
assertThat(actual.getTables().get("t_order_item").getDataSourceNames().iterator().next(),
is("shadow_group_1"));
}
- private DropShadowRuleStatement createSQLStatement(final String...
ruleName) {
- DropShadowRuleStatement result = new DropShadowRuleStatement(false,
Arrays.asList(ruleName));
- result.buildAttributes();
+ private ShadowRuleConfiguration createRuleConfigurationForDrop() {
+ ShadowRuleConfiguration result = new ShadowRuleConfiguration();
+ result.getDataSources().add(new
ShadowDataSourceConfiguration("shadow_group", "production_0", "shadow_0"));
+ result.getDataSources().add(new
ShadowDataSourceConfiguration("shadow_group_1", "production_1", "shadow_1"));
+ result.getTables().put("t_order",
+ new ShadowTableConfiguration(new
ArrayList<>(Collections.singleton("shadow_group")), new
ArrayList<>(Collections.singleton("only_drop_algorithm"))));
+ result.getTables().put("t_order_item",
+ new ShadowTableConfiguration(new
ArrayList<>(Arrays.asList("shadow_group", "shadow_group_1")), new
ArrayList<>(Collections.singleton("shared_algorithm"))));
+ result.getShadowAlgorithms().put("only_drop_algorithm", new
AlgorithmConfiguration("SQL_HINT", new Properties()));
+ result.getShadowAlgorithms().put("shared_algorithm", new
AlgorithmConfiguration("SQL_HINT", new Properties()));
+ result.getShadowAlgorithms().put("unused_algorithm", new
AlgorithmConfiguration("SQL_HINT", new Properties()));
+ result.setDefaultShadowAlgorithmName("shared_algorithm");
return result;
}
- private DropShadowRuleStatement createSQLStatement(final boolean ifExists,
final String... ruleName) {
- DropShadowRuleStatement result = new DropShadowRuleStatement(ifExists,
Arrays.asList(ruleName));
- result.buildAttributes();
- return result;
+ @Test
+ void assertGetRuleClass() {
+ assertThat(executor.getRuleClass(), is(ShadowRule.class));
}
- private ShadowRuleConfiguration createCurrentRuleConfiguration() {
- ShadowRuleConfiguration result = new ShadowRuleConfiguration();
-
result.getDataSources().add(createShadowDataSourceConfiguration("shadow_group"));
- result.getTables().put("t_order", new ShadowTableConfiguration(new
ArrayList<>(Collections.singleton("shadow_group")), Collections.emptyList()));
- result.getShadowAlgorithms().put("t_order_algorithm", new
AlgorithmConfiguration("SHADOW", new Properties()));
- return result;
+ private static Stream<Arguments>
checkBeforeUpdateWithMissingRuleArguments() {
+ return Stream.of(
+ Arguments.of("single missing rule", createStatement(false,
"missing_rule_0")),
+ Arguments.of("multiple missing rules", createStatement(false,
"missing_rule_0", "missing_rule_1")),
+ Arguments.of("another missing rule", createStatement(false,
"missing_rule_2")));
}
- private ShadowRuleConfiguration createMultipleCurrentRuleConfiguration() {
- ShadowRuleConfiguration result = new ShadowRuleConfiguration();
-
result.getDataSources().add(createShadowDataSourceConfiguration("shadow_group"));
- result.getTables().put("t_order", new ShadowTableConfiguration(new
ArrayList<>(Collections.singleton("shadow_group")), Collections.emptyList()));
- result.getShadowAlgorithms().put("t_order_algorithm_inUsed", new
AlgorithmConfiguration("SHADOW", new Properties()));
- result.getShadowAlgorithms().put("t_order_algorithm_unused", new
AlgorithmConfiguration("SHADOW", new Properties()));
- result.setDefaultShadowAlgorithmName("t_order_algorithm_inUsed");
+ private static Stream<Arguments> hasAnyOneToBeDroppedArguments() {
+ ShadowRuleConfiguration ruleConfig = new ShadowRuleConfiguration();
+ ruleConfig.getDataSources().add(new
ShadowDataSourceConfiguration("shadow_group", "production_0", "shadow_0"));
+ ruleConfig.getDataSources().add(new
ShadowDataSourceConfiguration("shadow_group_1", "production_1", "shadow_1"));
+ return Stream.of(
+ Arguments.of("contains dropped rule", createRule(ruleConfig),
createStatement(false, "shadow_group"), true),
+ Arguments.of("contains no dropped rules",
createRule(ruleConfig), createStatement(false, "missing_rule"), false),
+ Arguments.of("contains one dropped rule",
createRule(ruleConfig), createStatement(false, "missing_rule",
"shadow_group_1"), true));
+ }
+
+ private static DropShadowRuleStatement createStatement(final boolean
ifExists, final String... ruleNames) {
+ DropShadowRuleStatement result = new DropShadowRuleStatement(ifExists,
Arrays.asList(ruleNames));
+ result.buildAttributes();
return result;
}
- private ShadowDataSourceConfiguration
createShadowDataSourceConfiguration(final String ruleName) {
- return new ShadowDataSourceConfiguration(ruleName, "production",
"shadow");
+ private static ShadowRule createRule(final ShadowRuleConfiguration
ruleConfig) {
+ ShadowRule result = mock(ShadowRule.class);
+ when(result.getConfiguration()).thenReturn(ruleConfig);
+ return result;
}
}
diff --git
a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/UnusedAlgorithmFinderTest.java
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/UnusedAlgorithmFinderTest.java
new file mode 100644
index 00000000000..9999d616e0b
--- /dev/null
+++
b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/handler/update/UnusedAlgorithmFinderTest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.shadow.distsql.handler.update;
+
+import
org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
+import org.apache.shardingsphere.shadow.config.ShadowRuleConfiguration;
+import org.apache.shardingsphere.shadow.config.table.ShadowTableConfiguration;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Properties;
+import java.util.stream.Stream;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+class UnusedAlgorithmFinderTest {
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("findUnusedShadowAlgorithmArguments")
+ void assertFindUnusedShadowAlgorithm(final String name, final
ShadowRuleConfiguration ruleConfig, final Collection<String> expected) {
+ assertThat(new
LinkedHashSet<>(UnusedAlgorithmFinder.findUnusedShadowAlgorithm(ruleConfig)),
is(new LinkedHashSet<>(expected)));
+ }
+
+ private static Stream<Arguments> findUnusedShadowAlgorithmArguments() {
+ return Stream.of(
+ Arguments.of("table references one algorithm",
createRuleConfiguration(Collections.singleton("algorithm_used"), null,
Arrays.asList("algorithm_used", "algorithm_unused")),
+ Collections.singleton("algorithm_unused")),
+ Arguments.of("table and default algorithm are both in use",
+
createRuleConfiguration(Collections.singleton("algorithm_used"),
"algorithm_default", Arrays.asList("algorithm_used", "algorithm_default",
"algorithm_unused")),
+ Collections.singleton("algorithm_unused")),
+ Arguments.of("default algorithm only",
createRuleConfiguration(Collections.emptyList(), "algorithm_default",
Arrays.asList("algorithm_default", "algorithm_unused")),
+ Collections.singleton("algorithm_unused")));
+ }
+
+ private static ShadowRuleConfiguration createRuleConfiguration(final
Collection<String> tableAlgorithmNames, final String defaultAlgorithmName,
final Collection<String> algorithmNames) {
+ ShadowRuleConfiguration result = new ShadowRuleConfiguration();
+ result.getTables().put("t_order", new
ShadowTableConfiguration(Collections.singletonList("ds_0"),
tableAlgorithmNames));
+ result.setDefaultShadowAlgorithmName(defaultAlgorithmName);
+ for (String each : algorithmNames) {
+ result.getShadowAlgorithms().put(each, new
AlgorithmConfiguration("SQL_HINT", new Properties()));
+ }
+ return result;
+ }
+}