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 67350690681 Add more test cases on ExportStorageNodesExecutorTest
(#38007)
67350690681 is described below
commit 6735069068101f8a2df7a46166f3b2cc1e9c2863
Author: Liang Zhang <[email protected]>
AuthorDate: Wed Feb 11 18:15:41 2026 +0800
Add more test cases on ExportStorageNodesExecutorTest (#38007)
---
AGENTS.md | 4 +-
.../export/ExportStorageNodesExecutorTest.java | 80 +++++++++++++++++-----
2 files changed, 64 insertions(+), 20 deletions(-)
diff --git a/AGENTS.md b/AGENTS.md
index 035278cdb1c..b14093cf1fe 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -90,8 +90,8 @@ Dangerous operation detected! Operation type: [specific
action] Scope of impact:
- **Risk gate:** if any action fits the Dangerous Operation Checklist, pause
and use the confirmation template before proceeding.
- **Planning rules:** use Sequential Thinking with 3-10 actionable steps (no
single-step plans) via the plan tool for non-trivial tasks; convert all hard
requirements (SPI usage, mocking rules, coverage/test naming, forbidden APIs)
into a checklist inside the plan and do not code until each item is addressed
or explicitly waived.
- **Execution discipline:** inspect existing code before edits; keep changes
minimal; default to mocks and SPI loaders; keep variable declarations near
first use and mark retained values `final`; inline single-use locals by default
unless reuse/readability justifies retention; delete dead code and avoid
placeholders/TODOs.
-- **Post-task self-check (before replying):** confirm all instructions were
honored; verify no placeholders/unused code; ensure Checkstyle/Spotless gates
for touched modules are satisfied or explain why not run and what to run; list
commands with exit codes; call out risks and follow-ups.
-- **Final response template:** include intent/why, changed files with paths,
rationale per file/section, commands run (with exit codes), verification
status, and remaining risks/next actions (if tests skipped, state reason and
the exact command to run).
+- **Post-task self-check (before replying):** confirm all instructions were
honored; verify no placeholders/unused code; ensure Checkstyle/Spotless gates
for touched modules are satisfied or explain why not run and what to run; list
commands with exit codes; call out risks and follow-ups; complete all
applicable checks before replying and do not rely on users to find missed rule
violations.
+- **Final response template:** include intent/why, changed files with paths,
rationale per file/section, commands run (with exit codes), verification
status, and remaining risks/next actions (if tests skipped, state reason and
the exact command to run); include a concise self-check result statement
confirming final clean status after fixes.
## Coverage & Branch Checklist
- When coverage targets are declared (including 100%), list every branch/path
with its planned test before coding.
diff --git
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/export/ExportStorageNodesExecutorTest.java
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/export/ExportStorageNodesExecutorTest.java
index 9613e4c5b34..d0f230d1acb 100644
---
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/export/ExportStorageNodesExecutorTest.java
+++
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/export/ExportStorageNodesExecutorTest.java
@@ -21,6 +21,7 @@ import lombok.SneakyThrows;
import org.apache.shardingsphere.authority.rule.AuthorityRule;
import
org.apache.shardingsphere.authority.rule.builder.DefaultAuthorityRuleConfigurationBuilder;
import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import
org.apache.shardingsphere.distsql.handler.engine.query.DistSQLQueryExecutor;
import
org.apache.shardingsphere.distsql.statement.type.ral.queryable.export.ExportStorageNodesStatement;
import
org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
@@ -47,6 +48,7 @@ import
org.apache.shardingsphere.test.infra.fixture.jdbc.MockedDataSource;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.io.TempDir;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@@ -58,7 +60,9 @@ import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
+import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
@@ -78,24 +82,37 @@ import static org.mockito.Mockito.when;
@MockitoSettings(strictness = Strictness.LENIENT)
class ExportStorageNodesExecutorTest {
+ private final ExportStorageNodesExecutor executor =
(ExportStorageNodesExecutor)
TypedSPILoader.getService(DistSQLQueryExecutor.class,
ExportStorageNodesStatement.class);
+
+ @TempDir
+ private Path tempDir;
+
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private ShardingSphereDatabase database;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private ShardingSphereDatabase emptyDatabase;
+
@BeforeEach
void setUp() {
-
when(database.getProtocolType()).thenReturn(TypedSPILoader.getService(DatabaseType.class,
"FIXTURE"));
+ DatabaseType databaseType =
TypedSPILoader.getService(DatabaseType.class, "FIXTURE");
+ when(database.getProtocolType()).thenReturn(databaseType);
+ when(emptyDatabase.getProtocolType()).thenReturn(databaseType);
+ }
+
+ @Test
+ void assertGetColumnNames() {
+ assertThat(executor.getColumnNames(new
ExportStorageNodesStatement(null, null)), is(Arrays.asList("id", "create_time",
"storage_nodes")));
}
@Test
void assertExecuteWithWrongDatabaseName() {
- ExportStorageNodesStatement sqlStatement = new
ExportStorageNodesStatement("foo", null);
- assertThrows(IllegalArgumentException.class, () -> new
ExportStorageNodesExecutor().getRows(sqlStatement, mockEmptyContextManager()));
+ assertThrows(IllegalArgumentException.class, () ->
executor.getRows(new ExportStorageNodesStatement("foo", null),
mockEmptyContextManager()));
}
@Test
void assertExecuteWithEmptyMetaData() {
- ExportStorageNodesStatement sqlStatement = new
ExportStorageNodesStatement(null, null);
- Collection<LocalDataQueryResultRow> actual = new
ExportStorageNodesExecutor().getRows(sqlStatement, mockEmptyContextManager());
+ Collection<LocalDataQueryResultRow> actual = executor.getRows(new
ExportStorageNodesStatement(null, null), mockEmptyContextManager());
assertThat(actual.size(), is(1));
LocalDataQueryResultRow row = actual.iterator().next();
assertThat(row.getCell(3), is("{\"storage_nodes\":{}}"));
@@ -105,19 +122,15 @@ class ExportStorageNodesExecutorTest {
ContextManager result = mock(ContextManager.class, RETURNS_DEEP_STUBS);
ShardingSphereMetaData metaData = new ShardingSphereMetaData(
Collections.emptyList(), new
ResourceMetaData(Collections.emptyMap()), new
RuleMetaData(Collections.emptyList()), new ConfigurationProperties(new
Properties()));
- MetaDataContexts metaDataContexts = new MetaDataContexts(metaData, new
ShardingSphereStatistics());
- when(result.getMetaDataContexts()).thenReturn(metaDataContexts);
+ when(result.getMetaDataContexts()).thenReturn(new
MetaDataContexts(metaData, new ShardingSphereStatistics()));
when(result.getAllDatabaseNames()).thenReturn(Collections.singleton("empty_metadata"));
return result;
}
@Test
void assertExecute() {
- when(database.getName()).thenReturn("normal_db");
- Map<String, StorageUnit> storageUnits = createStorageUnits();
-
when(database.getResourceMetaData().getStorageUnits()).thenReturn(storageUnits);
-
when(database.getRuleMetaData().getConfigurations()).thenReturn(Collections.singleton(createShardingRuleConfiguration()));
- Collection<LocalDataQueryResultRow> actual = new
ExportStorageNodesExecutor().getRows(new ExportStorageNodesStatement(null,
null), mockContextManager());
+ prepareNormalDatabase();
+ Collection<LocalDataQueryResultRow> actual = executor.getRows(new
ExportStorageNodesStatement(null, null), mockContextManager(database));
assertThat(actual.size(), is(1));
LocalDataQueryResultRow row = actual.iterator().next();
assertThat(row.getCell(3), is(loadExpectedRow()));
@@ -125,19 +138,50 @@ class ExportStorageNodesExecutorTest {
@Test
void assertExecuteWithDatabaseName() {
+ prepareNormalDatabase();
+ Collection<LocalDataQueryResultRow> actual = executor.getRows(new
ExportStorageNodesStatement("normal_db", null), mockContextManager(database));
+ assertThat(actual.size(), is(1));
+ LocalDataQueryResultRow row = actual.iterator().next();
+ assertThat(row.getCell(3), is(loadExpectedRow()));
+ }
+
+ @Test
+ void assertExecuteWithFilePath() throws IOException {
+ prepareNormalDatabase();
+ ContextManager contextManager = mockContextManager(database);
+
when(contextManager.getComputeNodeInstanceContext().getInstance().getMetaData().getId()).thenReturn("file_id");
+ Path tempFile = tempDir.resolve("export-storage-nodes.json");
+ Collection<LocalDataQueryResultRow> actual = executor.getRows(new
ExportStorageNodesStatement(null, tempFile.toString()), contextManager);
+ assertThat(actual.size(), is(1));
+ LocalDataQueryResultRow row = actual.iterator().next();
+ assertThat(row.getCell(1), is("file_id"));
+ assertThat(row.getCell(3), is(String.format("Successfully exported
to:'%s'", tempFile)));
+ assertThat(new String(Files.readAllBytes(tempFile)),
is(loadExpectedRow()));
+ }
+
+ @Test
+ void assertExecuteWithEmptyStorageNodeDatabase() {
+ prepareNormalDatabase();
+ when(emptyDatabase.getName()).thenReturn("empty_db");
+
when(emptyDatabase.getResourceMetaData().getAllInstanceDataSourceNames()).thenReturn(Collections.emptySet());
+
when(emptyDatabase.getResourceMetaData().getStorageUnits()).thenReturn(Collections.emptyMap());
+ Collection<LocalDataQueryResultRow> actual = executor.getRows(new
ExportStorageNodesStatement(null, null), mockContextManager(emptyDatabase,
database));
+ assertThat(actual.size(), is(1));
+ LocalDataQueryResultRow row = actual.iterator().next();
+ assertThat(row.getCell(3), is(loadExpectedRow()));
+ }
+
+ private void prepareNormalDatabase() {
when(database.getName()).thenReturn("normal_db");
Map<String, StorageUnit> storageUnits = createStorageUnits();
+
when(database.getResourceMetaData().getAllInstanceDataSourceNames()).thenReturn(storageUnits.keySet());
when(database.getResourceMetaData().getStorageUnits()).thenReturn(storageUnits);
when(database.getRuleMetaData().getConfigurations()).thenReturn(Collections.singleton(createShardingRuleConfiguration()));
- Collection<LocalDataQueryResultRow> actual = new
ExportStorageNodesExecutor().getRows(new
ExportStorageNodesStatement("normal_db", null), mockContextManager());
- assertThat(actual.size(), is(1));
- LocalDataQueryResultRow row = actual.iterator().next();
- assertThat(row.getCell(3), is(loadExpectedRow()));
}
- private ContextManager mockContextManager() {
+ private ContextManager mockContextManager(final ShardingSphereDatabase...
databases) {
ContextManager result = mock(ContextManager.class, RETURNS_DEEP_STUBS);
- ShardingSphereMetaData metaData = new
ShardingSphereMetaData(Collections.singleton(database),
+ ShardingSphereMetaData metaData = new
ShardingSphereMetaData(Arrays.asList(databases),
new ResourceMetaData(Collections.emptyMap()),
new RuleMetaData(Collections.singleton(new AuthorityRule(new
DefaultAuthorityRuleConfigurationBuilder().build()))),
new ConfigurationProperties(PropertiesBuilder.build(new
Property(ConfigurationPropertyKey.SQL_SHOW.getKey(), "true"))));