You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2025/11/27 10:55:39 UTC

(shardingsphere) branch master updated: Add more test cases on TableRefreshUtilsTest (#37199)

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 ab6e7fb4d04 Add more test cases on TableRefreshUtilsTest (#37199)
ab6e7fb4d04 is described below

commit ab6e7fb4d04499e3fb9ffb4f0c69cc22587e2a6c
Author: Liang Zhang <zh...@apache.org>
AuthorDate: Thu Nov 27 18:55:32 2025 +0800

    Add more test cases on TableRefreshUtilsTest (#37199)
---
 AGENTS.md                                          |  2 +
 .../refresher/util/TableRefreshUtilsTest.java      | 76 +++++++++++++++++++++-
 2 files changed, 75 insertions(+), 3 deletions(-)

diff --git a/AGENTS.md b/AGENTS.md
index 0c2a3ba976e..69910ef099a 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -244,6 +244,8 @@ Always state which topology, registry, and engine versions (e.g., MySQL 5.7 vs 8
 - If a test already uses `@ExtendWith(AutoMockExtension.class)`, always declare the needed static collaborators via `@StaticMockSettings` instead of hand-written `mockStatic` blocks; justify any exception explicitly in the plan before coding.
 - When a binder under test instantiates another binder (e.g., `SelectStatementBinder`, `TableSegmentBinder`), prefer `mockConstruction` and capture the injected context rather than reimplementing the constructor logic; only skip this approach if the plan explains why it cannot work.
 - Manage every static binder (`ColumnSegmentBinder`, `ExpressionSegmentBinder`, etc.) via `@StaticMockSettings` to avoid ad-hoc try-with-resources `mockStatic` blocks; if multiple static dependencies are needed, list each one in the plan.
+- For identifier formatting or dialect-dependent logic, default to mocking `DatabaseTypedSPILoader`/`TypedSPILoader` with scoped `MockedStatic` instead of loading real database types, to avoid ClassCast issues and environment-dependent casing.
+- Before adding coverage to a utility with multiple return paths, list every branch (no rule, non-Single config, wildcard blocks, missing data node, positive path, collection overload) and map each to a test; update the plan whenever this checklist changes.
 
 ## Brevity & Signal
 - Prefer tables/bullets over prose walls; cite file paths (`kernel/src/...`) directly.
diff --git a/mode/core/src/test/java/org/apache/shardingsphere/mode/metadata/refresher/util/TableRefreshUtilsTest.java b/mode/core/src/test/java/org/apache/shardingsphere/mode/metadata/refresher/util/TableRefreshUtilsTest.java
index 2733c94095f..742da2fa239 100644
--- a/mode/core/src/test/java/org/apache/shardingsphere/mode/metadata/refresher/util/TableRefreshUtilsTest.java
+++ b/mode/core/src/test/java/org/apache/shardingsphere/mode/metadata/refresher/util/TableRefreshUtilsTest.java
@@ -18,6 +18,9 @@
 package org.apache.shardingsphere.mode.metadata.refresher.util;
 
 import org.apache.shardingsphere.database.connector.core.metadata.database.enums.QuoteCharacter;
+import org.apache.shardingsphere.database.connector.core.metadata.database.metadata.DialectDatabaseMetaData;
+import org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.IdentifierPatternType;
+import org.apache.shardingsphere.database.connector.core.spi.DatabaseTypedSPILoader;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
 import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
 import org.apache.shardingsphere.infra.datanode.DataNode;
@@ -34,6 +37,7 @@ import org.apache.shardingsphere.sql.parser.statement.core.value.identifier.Iden
 import org.apache.shardingsphere.test.infra.framework.extension.mock.AutoMockExtension;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.MockedStatic;
 
 import java.util.Arrays;
 import java.util.Collections;
@@ -49,16 +53,38 @@ import static org.mockito.Mockito.when;
 @ExtendWith(AutoMockExtension.class)
 class TableRefreshUtilsTest {
     
-    private final DatabaseType databaseType = TypedSPILoader.getService(DatabaseType.class, "FIXTURE");
+    private final DatabaseType fixtureDatabaseType = TypedSPILoader.getService(DatabaseType.class, "FIXTURE");
     
     @Test
     void assertGetTableNameFormatsWithIdentifierPattern() {
-        assertThat(TableRefreshUtils.getTableName(new IdentifierValue("Foo_Table"), databaseType), is("Foo_Table"));
+        assertThat(TableRefreshUtils.getTableName(new IdentifierValue("Foo_Table"), fixtureDatabaseType), is("Foo_Table"));
     }
     
     @Test
     void assertGetTableNameWithQuotedIdentifierReturnsOriginal() {
-        assertThat(TableRefreshUtils.getTableName(new IdentifierValue("FooTable", QuoteCharacter.QUOTE), databaseType), is("FooTable"));
+        assertThat(TableRefreshUtils.getTableName(new IdentifierValue("FooTable", QuoteCharacter.QUOTE), fixtureDatabaseType), is("FooTable"));
+    }
+    
+    @Test
+    void assertGetTableNameFormatsUpperCase() {
+        DatabaseType upperCaseDatabaseType = mock(DatabaseType.class);
+        DialectDatabaseMetaData dialectDatabaseMetaData = mock(DialectDatabaseMetaData.class);
+        when(dialectDatabaseMetaData.getIdentifierPatternType()).thenReturn(IdentifierPatternType.UPPER_CASE);
+        try (MockedStatic<DatabaseTypedSPILoader> mockedStatic = org.mockito.Mockito.mockStatic(DatabaseTypedSPILoader.class)) {
+            mockedStatic.when(() -> DatabaseTypedSPILoader.getService(DialectDatabaseMetaData.class, upperCaseDatabaseType)).thenReturn(dialectDatabaseMetaData);
+            assertThat(TableRefreshUtils.getTableName(new IdentifierValue("foo_table"), upperCaseDatabaseType), is("FOO_TABLE"));
+        }
+    }
+    
+    @Test
+    void assertGetTableNameFormatsLowerCase() {
+        DatabaseType lowerCaseDatabaseType = mock(DatabaseType.class);
+        DialectDatabaseMetaData dialectDatabaseMetaData = mock(DialectDatabaseMetaData.class);
+        when(dialectDatabaseMetaData.getIdentifierPatternType()).thenReturn(IdentifierPatternType.LOWER_CASE);
+        try (MockedStatic<DatabaseTypedSPILoader> mockedStatic = org.mockito.Mockito.mockStatic(DatabaseTypedSPILoader.class)) {
+            mockedStatic.when(() -> DatabaseTypedSPILoader.getService(DialectDatabaseMetaData.class, lowerCaseDatabaseType)).thenReturn(dialectDatabaseMetaData);
+            assertThat(TableRefreshUtils.getTableName(new IdentifierValue("Foo_Table"), lowerCaseDatabaseType), is("foo_table"));
+        }
     }
     
     @Test
@@ -108,6 +134,17 @@ class TableRefreshUtilsTest {
         assertFalse(TableRefreshUtils.isNeedRefresh(new RuleMetaData(Collections.singleton(rule)), "foo_schema", "foo_tbl"));
     }
     
+    @Test
+    void assertIsNeedRefreshWhenAllSchemaTablesConfigured() {
+        MutableDataNodeRuleAttribute mutableDataNodeRuleAttribute = mock(MutableDataNodeRuleAttribute.class);
+        SingleRuleConfiguration ruleConfig = new SingleRuleConfiguration();
+        ruleConfig.setTables(Collections.singletonList(SingleTableConstants.ALL_SCHEMA_TABLES));
+        ShardingSphereRule rule = mock(ShardingSphereRule.class);
+        when(rule.getConfiguration()).thenReturn(ruleConfig);
+        when(rule.getAttributes()).thenReturn(new RuleAttributes(mutableDataNodeRuleAttribute));
+        assertFalse(TableRefreshUtils.isNeedRefresh(new RuleMetaData(Collections.singleton(rule)), "foo_schema", "foo_tbl"));
+    }
+    
     @Test
     void assertIsNeedRefreshWhenTableDataNodeMissing() {
         MutableDataNodeRuleAttribute mutableDataNodeRuleAttribute = mock(MutableDataNodeRuleAttribute.class);
@@ -156,4 +193,37 @@ class TableRefreshUtilsTest {
         when(rule.getAttributes()).thenReturn(new RuleAttributes(mutableDataNodeRuleAttribute));
         assertTrue(TableRefreshUtils.isNeedRefresh(new RuleMetaData(Collections.singleton(rule)), "foo_schema", Arrays.asList("bar_tbl", "foo_tbl")));
     }
+    
+    @Test
+    void assertIsNeedRefreshBlockedByDataSourceSchemaWildcard() {
+        MutableDataNodeRuleAttribute mutableDataNodeRuleAttribute = mock(MutableDataNodeRuleAttribute.class);
+        DataNode dataNode = new DataNode("foo_ds", "foo_schema", "foo_tbl");
+        when(mutableDataNodeRuleAttribute.findTableDataNode("foo_schema", "foo_tbl")).thenReturn(Optional.of(dataNode));
+        SingleRuleConfiguration ruleConfig = new SingleRuleConfiguration();
+        ruleConfig.setTables(Collections.singletonList("foo_ds.*.*"));
+        ShardingSphereRule rule = mock(ShardingSphereRule.class);
+        when(rule.getConfiguration()).thenReturn(ruleConfig);
+        when(rule.getAttributes()).thenReturn(new RuleAttributes(mutableDataNodeRuleAttribute));
+        assertFalse(TableRefreshUtils.isNeedRefresh(new RuleMetaData(Collections.singleton(rule)), "foo_schema", "foo_tbl"));
+    }
+    
+    @Test
+    void assertIsNeedRefreshBlockedBySchemaSpecificWildcard() {
+        MutableDataNodeRuleAttribute mutableDataNodeRuleAttribute = mock(MutableDataNodeRuleAttribute.class);
+        DataNode dataNode = new DataNode("foo_ds", "foo_schema", "foo_tbl");
+        when(mutableDataNodeRuleAttribute.findTableDataNode("foo_schema", "foo_tbl")).thenReturn(Optional.of(dataNode));
+        SingleRuleConfiguration ruleConfig = new SingleRuleConfiguration();
+        ruleConfig.setTables(Collections.singletonList("foo_ds.foo_schema.*"));
+        ShardingSphereRule rule = mock(ShardingSphereRule.class);
+        when(rule.getConfiguration()).thenReturn(ruleConfig);
+        when(rule.getAttributes()).thenReturn(new RuleAttributes(mutableDataNodeRuleAttribute));
+        assertFalse(TableRefreshUtils.isNeedRefresh(new RuleMetaData(Collections.singleton(rule)), "foo_schema", "foo_tbl"));
+    }
+    
+    @Test
+    void assertIsNeedRefreshWithTableCollectionWhenNoTableNeedsRefresh() {
+        ShardingSphereRule rule = mock(ShardingSphereRule.class);
+        when(rule.getAttributes()).thenReturn(new RuleAttributes());
+        assertFalse(TableRefreshUtils.isNeedRefresh(new RuleMetaData(Collections.singleton(rule)), "foo_schema", Arrays.asList("bar_tbl", "foo_tbl")));
+    }
 }