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")));
+ }
}