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 4f0649a2e7d Add more test cases on UnloadSingleTableExecutorTest 
(#38100)
4f0649a2e7d is described below

commit 4f0649a2e7dec361f0dd9c00115273e29b9a9d05
Author: Liang Zhang <[email protected]>
AuthorDate: Thu Feb 19 18:33:51 2026 +0800

    Add more test cases on UnloadSingleTableExecutorTest (#38100)
    
    * Add more test cases on UnloadSingleTableExecutorTest
    
    * Add more test cases on UnloadSingleTableExecutorTest
---
 .../update/UnloadSingleTableExecutorTest.java      | 202 +++++++++++++++++++++
 1 file changed, 202 insertions(+)

diff --git 
a/kernel/single/distsql/handler/src/test/java/org/apache/shardingsphere/single/distsql/handler/update/UnloadSingleTableExecutorTest.java
 
b/kernel/single/distsql/handler/src/test/java/org/apache/shardingsphere/single/distsql/handler/update/UnloadSingleTableExecutorTest.java
new file mode 100644
index 00000000000..4c08226be4f
--- /dev/null
+++ 
b/kernel/single/distsql/handler/src/test/java/org/apache/shardingsphere/single/distsql/handler/update/UnloadSingleTableExecutorTest.java
@@ -0,0 +1,202 @@
+/*
+ * 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.single.distsql.handler.update;
+
+import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import 
org.apache.shardingsphere.database.exception.core.exception.syntax.table.NoSuchTableException;
+import 
org.apache.shardingsphere.distsql.handler.engine.update.rdl.rule.spi.database.DatabaseRuleDefinitionExecutor;
+import org.apache.shardingsphere.infra.datanode.DataNode;
+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.rule.RuleMetaData;
+import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
+import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereTable;
+import org.apache.shardingsphere.infra.rule.attribute.RuleAttributes;
+import 
org.apache.shardingsphere.infra.rule.attribute.datanode.DataNodeRuleAttribute;
+import 
org.apache.shardingsphere.infra.rule.attribute.table.TableMapperRuleAttribute;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+import org.apache.shardingsphere.single.config.SingleRuleConfiguration;
+import 
org.apache.shardingsphere.single.distsql.statement.rdl.UnloadSingleTableStatement;
+import org.apache.shardingsphere.single.exception.SingleTableNotFoundException;
+import org.apache.shardingsphere.single.rule.SingleRule;
+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.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.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.stream.Collectors;
+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.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
+class UnloadSingleTableExecutorTest {
+    
+    private final DatabaseType databaseType = 
TypedSPILoader.getService(DatabaseType.class, "FIXTURE");
+    
+    private final UnloadSingleTableExecutor executor = 
(UnloadSingleTableExecutor) 
TypedSPILoader.getService(DatabaseRuleDefinitionExecutor.class, 
UnloadSingleTableStatement.class);
+    
+    @Mock
+    private ShardingSphereDatabase database;
+    
+    @Mock
+    private SingleRule rule;
+    
+    @Mock
+    private TableMapperRuleAttribute tableMapperRuleAttribute;
+    
+    @Mock
+    private DataNodeRuleAttribute dataNodeRuleAttribute;
+    
+    @BeforeEach
+    void setUp() {
+        executor.setDatabase(database);
+        executor.setRule(rule);
+        when(database.getName()).thenReturn("foo_db");
+        when(database.getProtocolType()).thenReturn(databaseType);
+        when(database.getRuleMetaData()).thenReturn(new 
RuleMetaData(Collections.singleton(rule)));
+        when(rule.getAttributes()).thenReturn(new 
RuleAttributes(tableMapperRuleAttribute, dataNodeRuleAttribute));
+    }
+    
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("assertCheckBeforeUpdateWithFailureArguments")
+    void assertCheckBeforeUpdateWithFailure(final String name, final 
Collection<String> allTables, final Collection<String> singleTables, final 
Collection<DataNode> dataNodes,
+                                            final Collection<String> 
configuredTables, final Class<? extends RuntimeException> expectedException) {
+        Map<String, Collection<DataNode>> tableDataNodes = new HashMap<>(1, 
1F);
+        tableDataNodes.put("foo_tbl", dataNodes);
+        prepareCheckBeforeUpdateContext(allTables, singleTables, 
tableDataNodes, configuredTables);
+        assertThrows(expectedException, () -> executor.checkBeforeUpdate(new 
UnloadSingleTableStatement(false, Collections.singletonList("foo_tbl"))));
+    }
+    
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("assertCheckBeforeUpdateWithSuccessArguments")
+    void assertCheckBeforeUpdate(final String name, final 
UnloadSingleTableStatement sqlStatement, final Collection<String> allTables,
+                                 final Collection<String> singleTables, final 
Map<String, Collection<DataNode>> tableDataNodes, final Collection<String> 
configuredTables) {
+        prepareCheckBeforeUpdateContext(allTables, singleTables, 
tableDataNodes, configuredTables);
+        assertDoesNotThrow(() -> executor.checkBeforeUpdate(sqlStatement));
+    }
+    
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("assertBuildToBeAlteredRuleConfigurationArguments")
+    void assertBuildToBeAlteredRuleConfiguration(final String name, final 
Collection<String> currentTables,
+                                                 final 
UnloadSingleTableStatement sqlStatement, final Collection<String> 
expectedTables) {
+        when(rule.getConfiguration()).thenReturn(new 
SingleRuleConfiguration(new LinkedList<>(currentTables), null));
+        SingleRuleConfiguration actual = 
executor.buildToBeAlteredRuleConfiguration(sqlStatement);
+        assertThat(new HashSet<>(actual.getTables()), is(new 
HashSet<>(expectedTables)));
+    }
+    
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("assertBuildToBeDroppedRuleConfigurationArguments")
+    void assertBuildToBeDroppedRuleConfiguration(final String name, final 
Collection<String> currentTables, final Collection<String> toBeAlteredTables,
+                                                 final boolean expectedNull, 
final Collection<String> expectedTables) {
+        when(rule.getConfiguration()).thenReturn(new 
SingleRuleConfiguration(new LinkedList<>(currentTables), null));
+        SingleRuleConfiguration toBeAltered = new SingleRuleConfiguration(new 
LinkedList<>(toBeAlteredTables), null);
+        SingleRuleConfiguration actual = 
executor.buildToBeDroppedRuleConfiguration(toBeAltered);
+        if (expectedNull) {
+            assertNull(actual);
+        } else {
+            assertNotNull(actual);
+            assertThat(new HashSet<>(actual.getTables()), is(new 
HashSet<>(expectedTables)));
+        }
+    }
+    
+    @Test
+    void assertGetRuleClass() {
+        assertThat(executor.getRuleClass(), is(SingleRule.class));
+    }
+    
+    private void prepareCheckBeforeUpdateContext(final Collection<String> 
allTables, final Collection<String> singleTables,
+                                                 final Map<String, 
Collection<DataNode>> tableDataNodes, final Collection<String> 
configuredTables) {
+        ShardingSphereSchema schema = mock(ShardingSphereSchema.class);
+        when(schema.getAllTables()).thenReturn(
+                allTables.stream().map(each -> new ShardingSphereTable(each, 
Collections.emptyList(), Collections.emptyList(), 
Collections.emptyList())).collect(Collectors.toList()));
+        when(database.getSchema("foo_db")).thenReturn(schema);
+        
when(tableMapperRuleAttribute.getLogicTableNames()).thenReturn(singleTables);
+        
when(dataNodeRuleAttribute.getDataNodesByTableName(anyString())).thenAnswer(invocation
 -> tableDataNodes.getOrDefault(invocation.getArgument(0), 
Collections.emptyList()));
+        when(rule.getConfiguration()).thenReturn(new 
SingleRuleConfiguration(new LinkedList<>(configuredTables), null));
+    }
+    
+    private static Stream<Arguments> 
assertCheckBeforeUpdateWithFailureArguments() {
+        return Stream.of(
+                Arguments.of("missing table throws NoSuchTableException", 
Collections.emptyList(), Collections.singleton("foo_tbl"), 
Collections.singleton(new DataNode("foo_ds.foo_tbl")),
+                        Collections.singleton("foo_ds.foo_tbl"), 
NoSuchTableException.class),
+                Arguments.of("non single table throws 
SingleTableNotFoundException", Collections.singleton("foo_tbl"), 
Collections.emptyList(), Collections.singleton(new DataNode("foo_ds.foo_tbl")),
+                        Collections.singleton("foo_ds.foo_tbl"), 
SingleTableNotFoundException.class),
+                Arguments.of("missing data node throws 
MissingRequiredRuleException", Collections.singleton("foo_tbl"), 
Collections.singleton("foo_tbl"), Collections.emptyList(),
+                        Collections.singleton("foo_ds.foo_tbl"), 
MissingRequiredRuleException.class),
+                Arguments.of("missing rule config throws 
MissingRequiredRuleException", Collections.singleton("foo_tbl"), 
Collections.singleton("foo_tbl"),
+                        Collections.singleton(new DataNode("foo_ds.foo_tbl")),
+                        Collections.emptyList(), 
MissingRequiredRuleException.class));
+    }
+    
+    private static Stream<Arguments> 
assertCheckBeforeUpdateWithSuccessArguments() {
+        Map<String, Collection<DataNode>> singleTableNodes = new HashMap<>(1, 
1F);
+        singleTableNodes.put("foo_tbl", Collections.singleton(new 
DataNode("foo_ds.foo_tbl")));
+        Map<String, Collection<DataNode>> multipleTableNodes = new 
HashMap<>(2, 1F);
+        multipleTableNodes.put("foo_tbl", Collections.singleton(new 
DataNode("foo_ds.foo_tbl")));
+        multipleTableNodes.put("bar_tbl", Collections.singleton(new 
DataNode("foo_ds.foo_schema.bar_tbl")));
+        return Stream.of(
+                Arguments.of("unload all tables bypasses table checks", new 
UnloadSingleTableStatement(true, Collections.emptyList()),
+                        Collections.emptyList(), Collections.emptyList(), 
Collections.emptyMap(), Collections.emptyList()),
+                Arguments.of("valid single table passes checks", new 
UnloadSingleTableStatement(false, Collections.singletonList("foo_tbl")),
+                        Collections.singleton("foo_tbl"), 
Collections.singleton("foo_tbl"), singleTableNodes, 
Collections.singleton("foo_ds.foo_tbl")),
+                Arguments.of("valid multiple tables pass checks", new 
UnloadSingleTableStatement(false, Arrays.asList("foo_tbl", "bar_tbl")),
+                        Arrays.asList("foo_tbl", "bar_tbl"), 
Arrays.asList("foo_tbl", "bar_tbl"), multipleTableNodes, 
Arrays.asList("foo_ds.foo_tbl", "foo_ds.bar_tbl")));
+    }
+    
+    private static Stream<Arguments> 
assertBuildToBeAlteredRuleConfigurationArguments() {
+        return Stream.of(
+                Arguments.of("unload all tables keeps altered config empty", 
Arrays.asList("foo_ds.foo_tbl", "foo_ds.bar_tbl"), new 
UnloadSingleTableStatement(true, Collections.emptyList()),
+                        Collections.emptyList()),
+                Arguments.of("unload one table removes matching two-segment 
node", Arrays.asList("foo_ds.foo_tbl", "foo_ds.bar_tbl"),
+                        new UnloadSingleTableStatement(false, 
Collections.singletonList("foo_tbl")), Collections.singleton("foo_ds.bar_tbl")),
+                Arguments.of("unload one table removes matching three-segment 
node", Arrays.asList("foo_ds.foo_schema.bar_tbl", "foo_ds.foo_tbl"),
+                        new UnloadSingleTableStatement(false, 
Collections.singletonList("bar_tbl")), 
Collections.singleton("foo_ds.foo_tbl")));
+    }
+    
+    private static Stream<Arguments> 
assertBuildToBeDroppedRuleConfigurationArguments() {
+        return Stream.of(
+                Arguments.of("empty altered config drops current rule config", 
Arrays.asList("foo_ds.foo_tbl", "foo_ds.bar_tbl"), Collections.emptyList(), 
false,
+                        Arrays.asList("foo_ds.foo_tbl", "foo_ds.bar_tbl")),
+                Arguments.of("non-empty altered config does not drop rule", 
Collections.singleton("foo_ds.foo_tbl"), 
Collections.singleton("foo_ds.foo_tbl"), true, Collections.emptyList()),
+                Arguments.of("multi-table altered config does not drop rule", 
Arrays.asList("foo_ds.foo_tbl", "foo_ds.bar_tbl"), 
Arrays.asList("foo_ds.foo_tbl", "foo_ds.bar_tbl"), true,
+                        Collections.emptyList()));
+    }
+}

Reply via email to