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 c5aa35131eb Add SPI-based executor test cases (#37560)
c5aa35131eb is described below

commit c5aa35131eb0df27d61d5f075964c66004c70d4e
Author: Liang Zhang <[email protected]>
AuthorDate: Sun Dec 28 18:26:20 2025 +0800

    Add SPI-based executor test cases (#37560)
    
    * Add SPI-based executor test cases
    
    * Add SPI-based executor test cases
---
 .../DatabaseProxyConnectorFactoryTest.java         | 31 ++++++++
 .../ShowComputeNodeInfoExecutorTest.java           | 34 ++++++++-
 .../ShowComputeNodeModeExecutorTest.java           | 24 +++++-
 .../computenode/ShowComputeNodesExecutorTest.java  | 38 +++++++++-
 .../ExportDatabaseConfigurationExecutorTest.java   | 85 +++++++++++++++-------
 .../export/ExportMetaDataExecutorTest.java         | 33 ++++++++-
 .../tcl/TCLProxyBackendHandlerFactoryTest.java     | 38 ++++++----
 7 files changed, 233 insertions(+), 50 deletions(-)

diff --git 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseProxyConnectorFactoryTest.java
 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseProxyConnectorFactoryTest.java
index c653ec0bd54..d891fe6d49d 100644
--- 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseProxyConnectorFactoryTest.java
+++ 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseProxyConnectorFactoryTest.java
@@ -20,6 +20,7 @@ package org.apache.shardingsphere.proxy.backend.connector;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
 import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
+import 
org.apache.shardingsphere.infra.executor.sql.prepare.driver.jdbc.JDBCDriverType;
 import org.apache.shardingsphere.infra.hint.HintValueContext;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
@@ -37,11 +38,18 @@ import 
org.apache.shardingsphere.test.infra.framework.extension.mock.AutoMockExt
 import 
org.apache.shardingsphere.test.infra.framework.extension.mock.StaticMockSettings;
 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.internal.configuration.plugins.Plugins;
 
 import java.util.Collections;
+import java.util.List;
 import java.util.Optional;
 import java.util.Properties;
+import java.util.stream.Stream;
 
+import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.isA;
 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
@@ -96,6 +104,23 @@ class DatabaseProxyConnectorFactoryTest {
                 isA(DatabaseProxyConnector.class));
     }
     
+    @ParameterizedTest
+    @MethodSource("driverTypeProvider")
+    void assertDriverTypeSelection(final boolean preferPreparedStatement, 
final List<Object> parameters, final JDBCDriverType expected) throws 
ReflectiveOperationException {
+        ProxyDatabaseConnectionManager databaseConnectionManager = 
mock(ProxyDatabaseConnectionManager.class, RETURNS_DEEP_STUBS);
+        
when(databaseConnectionManager.getConnectionSession().getUsedDatabaseName()).thenReturn("foo_db");
+        SQLStatementContext sqlStatementContext = 
mock(SQLStatementContext.class, RETURNS_DEEP_STUBS);
+        
when(sqlStatementContext.getTablesContext().getDatabaseNames()).thenReturn(Collections.emptyList());
+        
when(sqlStatementContext.getSqlStatement().getDatabaseType()).thenReturn(databaseType);
+        ShardingSphereDatabase database = mockDatabase();
+        ShardingSphereMetaData metaData = new 
ShardingSphereMetaData(Collections.singleton(database), mock(), mock(), new 
ConfigurationProperties(new Properties()));
+        QueryContext queryContext = new QueryContext(sqlStatementContext, 
"schemaName", parameters, new HintValueContext(), mockConnectionContext(), 
metaData);
+        ContextManager contextManager = mockContextManager(database);
+        
when(ProxyContext.getInstance().getContextManager()).thenReturn(contextManager);
+        DatabaseProxyConnector connector = 
DatabaseProxyConnectorFactory.newInstance(queryContext, 
databaseConnectionManager, preferPreparedStatement);
+        assertThat((JDBCDriverType) 
Plugins.getMemberAccessor().get(connector.getClass().getDeclaredField("driverType"),
 connector), is(expected));
+    }
+    
     private ContextManager mockContextManager(final ShardingSphereDatabase 
database) {
         ShardingSphereMetaData metaData = new ShardingSphereMetaData(
                 Collections.singleton(database), mock(ResourceMetaData.class), 
mock(RuleMetaData.class), new ConfigurationProperties(new Properties()));
@@ -114,4 +139,10 @@ class DatabaseProxyConnectorFactoryTest {
         when(result.getProtocolType()).thenReturn(databaseType);
         return result;
     }
+    
+    private static Stream<Arguments> driverTypeProvider() {
+        return Stream.of(
+                Arguments.of(true, Collections.emptyList(), 
JDBCDriverType.PREPARED_STATEMENT),
+                Arguments.of(false, Collections.singletonList(1), 
JDBCDriverType.PREPARED_STATEMENT));
+    }
 }
diff --git 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/computenode/ShowComputeNodeInfoExecutorTest.java
 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/computenode/ShowComputeNodeInfoExecutorTest.java
index 3cf3732991a..dc0a6e14fff 100644
--- 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/computenode/ShowComputeNodeInfoExecutorTest.java
+++ 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/computenode/ShowComputeNodeInfoExecutorTest.java
@@ -17,16 +17,22 @@
 
 package 
org.apache.shardingsphere.proxy.backend.handler.distsql.ral.queryable.computenode;
 
+import 
org.apache.shardingsphere.distsql.handler.engine.query.DistSQLQueryExecutor;
 import 
org.apache.shardingsphere.distsql.statement.type.ral.queryable.show.ShowComputeNodeInfoStatement;
 import org.apache.shardingsphere.infra.config.mode.ModeConfiguration;
+import org.apache.shardingsphere.infra.instance.ComputeNodeInstance;
 import org.apache.shardingsphere.infra.instance.ComputeNodeInstanceContext;
+import 
org.apache.shardingsphere.infra.instance.metadata.jdbc.JDBCInstanceMetaData;
 import 
org.apache.shardingsphere.infra.instance.metadata.proxy.ProxyInstanceMetaData;
 import 
org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.apache.shardingsphere.infra.state.instance.InstanceStateContext;
+import org.apache.shardingsphere.infra.util.eventbus.EventBusContext;
 import org.apache.shardingsphere.mode.manager.ContextManager;
 import 
org.apache.shardingsphere.mode.repository.standalone.StandalonePersistRepositoryConfiguration;
 import org.junit.jupiter.api.Test;
 
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Properties;
 
@@ -38,9 +44,16 @@ import static org.mockito.Mockito.when;
 
 class ShowComputeNodeInfoExecutorTest {
     
+    private final ShowComputeNodeInfoExecutor executor = 
(ShowComputeNodeInfoExecutor) 
TypedSPILoader.getService(DistSQLQueryExecutor.class, 
ShowComputeNodeInfoStatement.class);
+    
+    @Test
+    void assertGetColumnNames() {
+        ShowComputeNodeInfoStatement sqlStatement = 
mock(ShowComputeNodeInfoStatement.class);
+        assertThat(executor.getColumnNames(sqlStatement), 
is(Arrays.asList("instance_id", "host", "port", "status", "mode_type", 
"worker_id", "labels", "version")));
+    }
+    
     @Test
     void assertExecute() {
-        ShowComputeNodeInfoExecutor executor = new 
ShowComputeNodeInfoExecutor();
         ContextManager contextManager = mock(ContextManager.class);
         ComputeNodeInstanceContext computeNodeInstanceContext = 
createInstanceContext();
         
when(contextManager.getComputeNodeInstanceContext()).thenReturn(computeNodeInstanceContext);
@@ -57,6 +70,25 @@ class ShowComputeNodeInfoExecutorTest {
         assertThat(row.getCell(8), is("foo_version"));
     }
     
+    @Test
+    void assertExecuteWithJdbcInstance() {
+        ComputeNodeInstance computeNodeInstance = new ComputeNodeInstance(new 
JDBCInstanceMetaData("jdbc_instance", "10.0.0.1", "jdbc_version", "logic_db"));
+        computeNodeInstance.setWorkerId(5);
+        computeNodeInstance.getLabels().add("blue");
+        ContextManager contextManager = mock(ContextManager.class);
+        when(contextManager.getComputeNodeInstanceContext()).thenReturn(new 
ComputeNodeInstanceContext(computeNodeInstance, new 
ModeConfiguration("Cluster", null), new EventBusContext()));
+        Collection<LocalDataQueryResultRow> actual = 
executor.getRows(mock(ShowComputeNodeInfoStatement.class), contextManager);
+        LocalDataQueryResultRow row = actual.iterator().next();
+        assertThat(row.getCell(1), is("jdbc_instance"));
+        assertThat(row.getCell(2), is("10.0.0.1"));
+        assertThat(row.getCell(3), is("-1"));
+        assertThat(row.getCell(4), is("OK"));
+        assertThat(row.getCell(5), is("Cluster"));
+        assertThat(row.getCell(6), is("5"));
+        assertThat(row.getCell(7), is("blue"));
+        assertThat(row.getCell(8), is("jdbc_version"));
+    }
+    
     private ComputeNodeInstanceContext createInstanceContext() {
         ComputeNodeInstanceContext result = 
mock(ComputeNodeInstanceContext.class, RETURNS_DEEP_STUBS);
         when(result.getInstance().getMetaData()).thenReturn(new 
ProxyInstanceMetaData("foo", "127.0.0.1@3309", "foo_version"));
diff --git 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/computenode/ShowComputeNodeModeExecutorTest.java
 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/computenode/ShowComputeNodeModeExecutorTest.java
index 27112c54926..3e957ed457e 100644
--- 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/computenode/ShowComputeNodeModeExecutorTest.java
+++ 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/computenode/ShowComputeNodeModeExecutorTest.java
@@ -17,16 +17,19 @@
 
 package 
org.apache.shardingsphere.proxy.backend.handler.distsql.ral.queryable.computenode;
 
+import 
org.apache.shardingsphere.distsql.handler.engine.query.DistSQLQueryExecutor;
 import 
org.apache.shardingsphere.distsql.statement.type.ral.queryable.show.ShowComputeNodeModeStatement;
 import org.apache.shardingsphere.infra.config.mode.ModeConfiguration;
 import org.apache.shardingsphere.infra.instance.ComputeNodeInstanceContext;
 import 
org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
+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.mode.manager.ContextManager;
 import 
org.apache.shardingsphere.mode.repository.cluster.ClusterPersistRepositoryConfiguration;
 import org.junit.jupiter.api.Test;
 
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Iterator;
 
@@ -38,9 +41,15 @@ import static org.mockito.Mockito.when;
 
 class ShowComputeNodeModeExecutorTest {
     
+    private final ShowComputeNodeModeExecutor executor = 
(ShowComputeNodeModeExecutor) 
TypedSPILoader.getService(DistSQLQueryExecutor.class, 
ShowComputeNodeModeStatement.class);
+    
+    @Test
+    void assertGetColumnNames() {
+        assertThat(executor.getColumnNames(new 
ShowComputeNodeModeStatement()), is(Arrays.asList("type", "repository", 
"props")));
+    }
+    
     @Test
     void assertExecute() {
-        ShowComputeNodeModeExecutor executor = new 
ShowComputeNodeModeExecutor();
         ContextManager contextManager = mock(ContextManager.class);
         ComputeNodeInstanceContext computeNodeInstanceContext = 
createInstanceContext();
         
when(contextManager.getComputeNodeInstanceContext()).thenReturn(computeNodeInstanceContext);
@@ -53,6 +62,19 @@ class ShowComputeNodeModeExecutorTest {
         assertThat(row.getCell(3), is("{\"key\":\"value1,value2\"}"));
     }
     
+    @Test
+    void assertExecuteWithNullRepository() {
+        ContextManager contextManager = mock(ContextManager.class, 
RETURNS_DEEP_STUBS);
+        ComputeNodeInstanceContext computeNodeInstanceContext = 
mock(ComputeNodeInstanceContext.class, RETURNS_DEEP_STUBS);
+        when(computeNodeInstanceContext.getModeConfiguration()).thenReturn(new 
ModeConfiguration("Standalone", null));
+        
when(contextManager.getComputeNodeInstanceContext()).thenReturn(computeNodeInstanceContext);
+        Collection<LocalDataQueryResultRow> actual = executor.getRows(new 
ShowComputeNodeModeStatement(), contextManager);
+        LocalDataQueryResultRow row = actual.iterator().next();
+        assertThat(row.getCell(1), is("Standalone"));
+        assertThat(row.getCell(2), is(""));
+        assertThat(row.getCell(3), is(""));
+    }
+    
     private ComputeNodeInstanceContext createInstanceContext() {
         ComputeNodeInstanceContext result = 
mock(ComputeNodeInstanceContext.class, RETURNS_DEEP_STUBS);
         
when(result.getInstance().getMetaData().getId()).thenReturn("127.0.0.1@3309");
diff --git 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/computenode/ShowComputeNodesExecutorTest.java
 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/computenode/ShowComputeNodesExecutorTest.java
index f0a13100283..91f6b9b2938 100644
--- 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/computenode/ShowComputeNodesExecutorTest.java
+++ 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/computenode/ShowComputeNodesExecutorTest.java
@@ -17,14 +17,17 @@
 
 package 
org.apache.shardingsphere.proxy.backend.handler.distsql.ral.queryable.computenode;
 
+import 
org.apache.shardingsphere.distsql.handler.engine.query.DistSQLQueryExecutor;
 import 
org.apache.shardingsphere.distsql.statement.type.ral.queryable.show.ShowComputeNodesStatement;
 import org.apache.shardingsphere.infra.config.mode.ModeConfiguration;
 import 
org.apache.shardingsphere.infra.config.mode.PersistRepositoryConfiguration;
 import org.apache.shardingsphere.infra.instance.ComputeNodeInstance;
 import org.apache.shardingsphere.infra.instance.ComputeNodeInstanceContext;
+import 
org.apache.shardingsphere.infra.instance.metadata.jdbc.JDBCInstanceMetaData;
 import 
org.apache.shardingsphere.infra.instance.metadata.proxy.ProxyInstanceMetaData;
 import 
org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
 import org.apache.shardingsphere.infra.state.instance.InstanceStateContext;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.apache.shardingsphere.mode.manager.ContextManager;
 import 
org.apache.shardingsphere.mode.manager.cluster.persist.facade.ClusterPersistServiceFacade;
 import 
org.apache.shardingsphere.mode.manager.standalone.persist.facade.StandalonePersistServiceFacade;
@@ -32,6 +35,7 @@ import 
org.apache.shardingsphere.mode.metadata.manager.MetaDataContextManager;
 import 
org.apache.shardingsphere.mode.repository.standalone.StandalonePersistRepositoryConfiguration;
 import org.junit.jupiter.api.Test;
 
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Properties;
@@ -44,9 +48,16 @@ import static org.mockito.Mockito.when;
 
 class ShowComputeNodesExecutorTest {
     
+    private final ShowComputeNodesExecutor executor = 
(ShowComputeNodesExecutor) 
TypedSPILoader.getService(DistSQLQueryExecutor.class, 
ShowComputeNodesStatement.class);
+    
+    @Test
+    void assertGetColumnNames() {
+        
assertThat(executor.getColumnNames(mock(ShowComputeNodesStatement.class)),
+                is(Arrays.asList("instance_id", "instance_type", "host", 
"port", "status", "mode_type", "worker_id", "labels", "version", 
"database_name")));
+    }
+    
     @Test
     void assertExecuteWithStandaloneMode() {
-        ShowComputeNodesExecutor executor = new ShowComputeNodesExecutor();
         ContextManager contextManager = mock(ContextManager.class, 
RETURNS_DEEP_STUBS);
         ComputeNodeInstanceContext computeNodeInstanceContext = 
createStandaloneInstanceContext();
         
when(contextManager.getComputeNodeInstanceContext()).thenReturn(computeNodeInstanceContext);
@@ -80,7 +91,6 @@ class ShowComputeNodesExecutorTest {
     
     @Test
     void assertExecuteWithClusterMode() {
-        ShowComputeNodesExecutor executor = new ShowComputeNodesExecutor();
         ContextManager contextManager = mock(ContextManager.class, 
RETURNS_DEEP_STUBS);
         ComputeNodeInstanceContext computeNodeInstanceContext = 
createClusterInstanceContext(contextManager);
         
when(contextManager.getComputeNodeInstanceContext()).thenReturn(computeNodeInstanceContext);
@@ -112,4 +122,28 @@ class ShowComputeNodesExecutorTest {
         
when(contextManager.getPersistServiceFacade().getModeFacade()).thenReturn(clusterPersistServiceFacade);
         return result;
     }
+    
+    @Test
+    void assertExecuteWithJdbcInstance() {
+        ContextManager contextManager = mock(ContextManager.class, 
RETURNS_DEEP_STUBS);
+        ComputeNodeInstanceContext computeNodeInstanceContext = 
mock(ComputeNodeInstanceContext.class, RETURNS_DEEP_STUBS);
+        when(computeNodeInstanceContext.getModeConfiguration()).thenReturn(new 
ModeConfiguration("Cluster", mock(PersistRepositoryConfiguration.class)));
+        
when(contextManager.getComputeNodeInstanceContext()).thenReturn(computeNodeInstanceContext);
+        ComputeNodeInstance computeNodeInstance = new ComputeNodeInstance(new 
JDBCInstanceMetaData("jdbc_instance", "192.168.0.1", "jdbc_version", 
"logic_db"));
+        computeNodeInstance.setWorkerId(2);
+        computeNodeInstance.getLabels().add("prod");
+        
when(contextManager.getPersistServiceFacade().getModeFacade().getComputeNodeService().loadAllInstances()).thenReturn(Collections.singleton(computeNodeInstance));
+        Collection<LocalDataQueryResultRow> actual = 
executor.getRows(mock(ShowComputeNodesStatement.class), contextManager);
+        LocalDataQueryResultRow row = actual.iterator().next();
+        assertThat(row.getCell(1), is("jdbc_instance"));
+        assertThat(row.getCell(2), is("JDBC"));
+        assertThat(row.getCell(3), is("192.168.0.1"));
+        assertThat(row.getCell(4), is("-1"));
+        assertThat(row.getCell(5), is("OK"));
+        assertThat(row.getCell(6), is("Cluster"));
+        assertThat(row.getCell(7), is("2"));
+        assertThat(row.getCell(8), is("prod"));
+        assertThat(row.getCell(9), is("jdbc_version"));
+        assertThat(row.getCell(10), is("logic_db"));
+    }
 }
diff --git 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/export/ExportDatabaseConfigurationExecutorTest.java
 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/export/ExportDatabaseConfigurationExecutorTest.java
index 19f57b8fd9a..cef0c9da34a 100644
--- 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/export/ExportDatabaseConfigurationExecutorTest.java
+++ 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/export/ExportDatabaseConfigurationExecutorTest.java
@@ -18,6 +18,7 @@
 package 
org.apache.shardingsphere.proxy.backend.handler.distsql.ral.queryable.export;
 
 import lombok.SneakyThrows;
+import 
org.apache.shardingsphere.distsql.handler.engine.query.DistSQLQueryExecutor;
 import 
org.apache.shardingsphere.distsql.statement.type.ral.queryable.export.ExportDatabaseConfigurationStatement;
 import 
org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
 import 
org.apache.shardingsphere.infra.datasource.pool.props.creator.DataSourcePoolPropertiesCreator;
@@ -25,6 +26,7 @@ import 
org.apache.shardingsphere.infra.datasource.pool.props.domain.DataSourcePo
 import 
org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
 import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import 
org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnit;
+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.mode.manager.ContextManager;
@@ -38,12 +40,14 @@ import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.Datab
 import 
org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
 import org.apache.shardingsphere.test.infra.fixture.jdbc.MockedDataSource;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
 
 import javax.sql.DataSource;
 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.Collection;
 import java.util.Collections;
@@ -62,6 +66,19 @@ import static org.mockito.Mockito.when;
 
 class ExportDatabaseConfigurationExecutorTest {
     
+    @TempDir
+    private Path tempDir;
+    
+    private final ExportDatabaseConfigurationExecutor executor = 
(ExportDatabaseConfigurationExecutor) TypedSPILoader.getService(
+            DistSQLQueryExecutor.class, 
ExportDatabaseConfigurationStatement.class);
+    
+    @Test
+    void assertGetColumnNames() throws IOException {
+        Path tempFile = Files.createTempFile("export-db-config-", ".yaml");
+        ExportDatabaseConfigurationStatement sqlStatement = new 
ExportDatabaseConfigurationStatement(tempFile.toString(), 
mock(FromDatabaseSegment.class));
+        assertThat(executor.getColumnNames(sqlStatement), 
is(Collections.singleton("result")));
+    }
+    
     @Test
     void assertExecute() {
         ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, 
RETURNS_DEEP_STUBS);
@@ -69,7 +86,6 @@ class ExportDatabaseConfigurationExecutorTest {
         Map<String, StorageUnit> storageUnits = createStorageUnits();
         
when(database.getResourceMetaData().getStorageUnits()).thenReturn(storageUnits);
         
when(database.getRuleMetaData().getConfigurations()).thenReturn(Collections.singleton(createShardingRuleConfiguration()));
-        ExportDatabaseConfigurationExecutor executor = new 
ExportDatabaseConfigurationExecutor();
         executor.setDatabase(database);
         Collection<LocalDataQueryResultRow> actual = executor.getRows(new 
ExportDatabaseConfigurationStatement(null, mock(FromDatabaseSegment.class)), 
mock(ContextManager.class));
         assertThat(actual.size(), is(1));
@@ -82,28 +98,64 @@ class ExportDatabaseConfigurationExecutorTest {
                 .collect(Collectors.toMap(Entry::getKey, entry -> 
DataSourcePoolPropertiesCreator.create(entry.getValue()), (oldValue, 
currentValue) -> oldValue, LinkedHashMap::new));
         Map<String, StorageUnit> result = new LinkedHashMap<>(propsMap.size(), 
1F);
         for (Entry<String, DataSourcePoolProperties> entry : 
propsMap.entrySet()) {
-            StorageUnit storageUnit = mock(StorageUnit.class, 
RETURNS_DEEP_STUBS);
+            StorageUnit storageUnit = mock(StorageUnit.class);
             
when(storageUnit.getDataSourcePoolProperties()).thenReturn(entry.getValue());
             result.put(entry.getKey(), storageUnit);
         }
         return result;
     }
     
+    private ShardingRuleConfiguration createShardingRuleConfiguration() {
+        ShardingRuleConfiguration result = new ShardingRuleConfiguration();
+        result.getTables().add(createTableRuleConfiguration());
+        result.setDefaultDatabaseShardingStrategy(new 
StandardShardingStrategyConfiguration("order_id", "ds_inline"));
+        result.setDefaultTableShardingStrategy(new 
NoneShardingStrategyConfiguration());
+        result.getKeyGenerators().put("snowflake", new 
AlgorithmConfiguration("SNOWFLAKE", new Properties()));
+        result.getShardingAlgorithms().put("ds_inline", new 
AlgorithmConfiguration("INLINE", PropertiesBuilder.build(new 
Property("algorithm-expression", "ds_${order_id % 2}"))));
+        return result;
+    }
+    
+    private ShardingTableRuleConfiguration createTableRuleConfiguration() {
+        ShardingTableRuleConfiguration result = new 
ShardingTableRuleConfiguration("t_order", "ds_${0..1}.t_order_${0..1}");
+        result.setKeyGenerateStrategy(new 
KeyGenerateStrategyConfiguration("order_id", "snowflake"));
+        return result;
+    }
+    
+    @SneakyThrows({IOException.class, URISyntaxException.class})
+    private String loadExpectedRow() {
+        URL url = 
Objects.requireNonNull(ExportDatabaseConfigurationExecutorTest.class.getResource("/expected/export-database-configuration.yaml"));
+        return Files.readAllLines(Paths.get(url.toURI())).stream().filter(each 
-> !each.startsWith("#") && 
!each.trim().isEmpty()).collect(Collectors.joining(System.lineSeparator()))
+                + System.lineSeparator();
+    }
+    
     @Test
     void assertExecuteWithEmptyDatabase() {
         ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, 
RETURNS_DEEP_STUBS);
         when(database.getName()).thenReturn("empty_db");
         
when(database.getResourceMetaData().getStorageUnits()).thenReturn(Collections.emptyMap());
         
when(database.getRuleMetaData().getConfigurations()).thenReturn(Collections.emptyList());
-        ExportDatabaseConfigurationStatement sqlStatement = new 
ExportDatabaseConfigurationStatement(null, new FromDatabaseSegment(0, new 
DatabaseSegment(0, 0, new IdentifierValue("empty_db"))));
-        ExportDatabaseConfigurationExecutor executor = new 
ExportDatabaseConfigurationExecutor();
         executor.setDatabase(database);
-        Collection<LocalDataQueryResultRow> actual = 
executor.getRows(sqlStatement, mock(ContextManager.class));
+        Collection<LocalDataQueryResultRow> actual = executor.getRows(
+                new ExportDatabaseConfigurationStatement(null, new 
FromDatabaseSegment(0, new DatabaseSegment(0, 0, new 
IdentifierValue("empty_db")))), mock(ContextManager.class));
         assertThat(actual.size(), is(1));
         LocalDataQueryResultRow row = actual.iterator().next();
         assertThat(row.getCell(1), is("databaseName: empty_db" + 
System.lineSeparator()));
     }
     
+    @Test
+    void assertExecuteWithFilePath() throws IOException {
+        ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, 
RETURNS_DEEP_STUBS);
+        when(database.getName()).thenReturn("file_db");
+        
when(database.getResourceMetaData().getStorageUnits()).thenReturn(Collections.emptyMap());
+        
when(database.getRuleMetaData().getConfigurations()).thenReturn(Collections.emptyList());
+        Path tempFile = tempDir.resolve("export-db-config.yaml");
+        executor.setDatabase(database);
+        Collection<LocalDataQueryResultRow> actual = executor.getRows(new 
ExportDatabaseConfigurationStatement(tempFile.toString(), 
mock(FromDatabaseSegment.class)), mock(ContextManager.class));
+        LocalDataQueryResultRow row = actual.iterator().next();
+        assertThat(row.getCell(1), is(String.format("Successfully exported to: 
'%s'", tempFile)));
+        assertThat(new String(Files.readAllBytes(tempFile)), is("databaseName: 
file_db" + System.lineSeparator()));
+    }
+    
     private Map<String, DataSource> createDataSourceMap() {
         Map<String, DataSource> result = new LinkedHashMap<>(2, 1F);
         result.put("ds_0", createDataSource("demo_ds_0"));
@@ -120,27 +172,4 @@ class ExportDatabaseConfigurationExecutorTest {
         result.setMinPoolSize(1);
         return result;
     }
-    
-    private ShardingRuleConfiguration createShardingRuleConfiguration() {
-        ShardingRuleConfiguration result = new ShardingRuleConfiguration();
-        result.getTables().add(createTableRuleConfiguration());
-        result.setDefaultDatabaseShardingStrategy(new 
StandardShardingStrategyConfiguration("order_id", "ds_inline"));
-        result.setDefaultTableShardingStrategy(new 
NoneShardingStrategyConfiguration());
-        result.getKeyGenerators().put("snowflake", new 
AlgorithmConfiguration("SNOWFLAKE", new Properties()));
-        result.getShardingAlgorithms().put("ds_inline", new 
AlgorithmConfiguration("INLINE", PropertiesBuilder.build(new 
Property("algorithm-expression", "ds_${order_id % 2}"))));
-        return result;
-    }
-    
-    private ShardingTableRuleConfiguration createTableRuleConfiguration() {
-        ShardingTableRuleConfiguration result = new 
ShardingTableRuleConfiguration("t_order", "ds_${0..1}.t_order_${0..1}");
-        result.setKeyGenerateStrategy(new 
KeyGenerateStrategyConfiguration("order_id", "snowflake"));
-        return result;
-    }
-    
-    @SneakyThrows({IOException.class, URISyntaxException.class})
-    private String loadExpectedRow() {
-        URL url = 
Objects.requireNonNull(ExportDatabaseConfigurationExecutorTest.class.getResource("/expected/export-database-configuration.yaml"));
-        return Files.readAllLines(Paths.get(url.toURI())).stream().filter(each 
-> !each.startsWith("#") && 
!each.trim().isEmpty()).collect(Collectors.joining(System.lineSeparator()))
-                + System.lineSeparator();
-    }
 }
diff --git 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/export/ExportMetaDataExecutorTest.java
 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/export/ExportMetaDataExecutorTest.java
index df658fd44f0..5328b5bc986 100644
--- 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/export/ExportMetaDataExecutorTest.java
+++ 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/export/ExportMetaDataExecutorTest.java
@@ -21,6 +21,7 @@ import org.apache.commons.codec.binary.Base64;
 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.ExportMetaDataStatement;
 import org.apache.shardingsphere.globalclock.rule.GlobalClockRule;
 import 
org.apache.shardingsphere.globalclock.rule.builder.DefaultGlobalClockRuleConfigurationBuilder;
@@ -59,8 +60,12 @@ import 
org.apache.shardingsphere.proxy.backend.distsql.export.ExportedClusterInf
 import org.apache.shardingsphere.proxy.backend.distsql.export.ExportedMetaData;
 import org.apache.shardingsphere.test.infra.fixture.jdbc.MockedDataSource;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
 
 import javax.sql.DataSource;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -95,11 +100,21 @@ class ExportMetaDataExecutorTest {
     
     private final DatabaseType databaseType = 
TypedSPILoader.getService(DatabaseType.class, "FIXTURE");
     
+    private final ExportMetaDataExecutor executor = (ExportMetaDataExecutor) 
TypedSPILoader.getService(DistSQLQueryExecutor.class, 
ExportMetaDataStatement.class);
+    
+    @TempDir
+    private Path tempDir;
+    
+    @Test
+    void assertGetColumnNames() {
+        assertThat(executor.getColumnNames(new ExportMetaDataStatement(null)), 
is(Arrays.asList("id", "create_time", "cluster_info")));
+    }
+    
     @Test
     void assertExecuteWithEmptyMetaData() {
         ContextManager contextManager = mockEmptyContextManager();
         ExportMetaDataStatement sqlStatement = new 
ExportMetaDataStatement(null);
-        Collection<LocalDataQueryResultRow> actual = new 
ExportMetaDataExecutor().getRows(sqlStatement, contextManager);
+        Collection<LocalDataQueryResultRow> actual = 
executor.getRows(sqlStatement, contextManager);
         assertThat(actual.size(), is(1));
         LocalDataQueryResultRow row = actual.iterator().next();
         assertMetaData(row.getCell(3), 
Base64.encodeBase64String(EXPECTED_EMPTY_METADATA_VALUE.getBytes()));
@@ -129,12 +144,26 @@ class ExportMetaDataExecutorTest {
     @Test
     void assertExecute() {
         ContextManager contextManager = mockContextManager();
-        Collection<LocalDataQueryResultRow> actual = new 
ExportMetaDataExecutor().getRows(new ExportMetaDataStatement(null), 
contextManager);
+        Collection<LocalDataQueryResultRow> actual = executor.getRows(new 
ExportMetaDataStatement(null), contextManager);
         assertThat(actual.size(), is(1));
         LocalDataQueryResultRow row = actual.iterator().next();
         assertMetaData(row.getCell(3), 
Base64.encodeBase64String(EXPECTED_NOT_EMPTY_METADATA_VALUE.getBytes()));
     }
     
+    @Test
+    void assertExecuteWithFilePath() throws IOException {
+        ContextManager contextManager = mockContextManager();
+        
when(contextManager.getComputeNodeInstanceContext().getInstance().getMetaData().getId()).thenReturn("file_instance");
+        Path tempFile = tempDir.resolve("export-metadata.json");
+        ExportMetaDataStatement sqlStatement = new 
ExportMetaDataStatement(tempFile.toString());
+        Collection<LocalDataQueryResultRow> actual = 
executor.getRows(sqlStatement, contextManager);
+        LocalDataQueryResultRow row = actual.iterator().next();
+        assertThat(row.getCell(1), is("file_instance"));
+        assertThat(row.getCell(3), is(String.format("Successfully exported 
to:'%s'", tempFile)));
+        String fileContent = new String(Files.readAllBytes(tempFile));
+        assertMetaData(Base64.encodeBase64String(fileContent.getBytes()), 
Base64.encodeBase64String(EXPECTED_NOT_EMPTY_METADATA_VALUE.getBytes()));
+    }
+    
     private ContextManager mockContextManager() {
         ShardingSphereDatabase database = mockDatabase();
         ShardingSphereMetaData metaData = new 
ShardingSphereMetaData(Collections.singleton(database),
diff --git 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/tcl/TCLProxyBackendHandlerFactoryTest.java
 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/tcl/TCLProxyBackendHandlerFactoryTest.java
index ecf6fa8852d..f7d609168db 100644
--- 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/tcl/TCLProxyBackendHandlerFactoryTest.java
+++ 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/tcl/TCLProxyBackendHandlerFactoryTest.java
@@ -34,14 +34,15 @@ import 
org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import org.apache.shardingsphere.proxy.backend.handler.ProxyBackendHandler;
 import 
org.apache.shardingsphere.proxy.backend.handler.tcl.local.type.CommitProxyBackendHandler;
 import 
org.apache.shardingsphere.proxy.backend.handler.tcl.local.type.RollbackProxyBackendHandler;
+import 
org.apache.shardingsphere.proxy.backend.handler.tcl.xa.XATCLProxyBackendHandlerFactory;
 import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.tcl.CommitStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.tcl.RollbackStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.tcl.TCLStatement;
+import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.tcl.xa.XAStatement;
 import 
org.apache.shardingsphere.test.infra.framework.extension.mock.AutoMockExtension;
 import 
org.apache.shardingsphere.test.infra.framework.extension.mock.StaticMockSettings;
 import org.apache.shardingsphere.transaction.rule.TransactionRule;
-import org.hamcrest.Matcher;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.Answers;
@@ -60,13 +61,13 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 @ExtendWith(AutoMockExtension.class)
-@StaticMockSettings({ProxyContext.class, DatabaseProxyConnectorFactory.class})
+@StaticMockSettings({ProxyContext.class, DatabaseProxyConnectorFactory.class, 
XATCLProxyBackendHandlerFactory.class})
 class TCLProxyBackendHandlerFactoryTest {
     
     private final DatabaseType databaseType = 
TypedSPILoader.getService(DatabaseType.class, "FIXTURE");
     
     @Test
-    void 
assertTCLProxyBackendHandlerReturnedWhenTCLStatementInstanceOfCommitStatement() 
{
+    void 
assertTCLProxyBackendHandlerReturnedWhenTCLStatementInstanceOfCommitStatement() 
throws ReflectiveOperationException {
         ConnectionSession connectionSession = mock(ConnectionSession.class, 
Answers.RETURNS_DEEP_STUBS);
         ProxyDatabaseConnectionManager databaseConnectionManager = 
mock(ProxyDatabaseConnectionManager.class);
         
when(connectionSession.getDatabaseConnectionManager()).thenReturn(databaseConnectionManager);
@@ -80,11 +81,12 @@ class TCLProxyBackendHandlerFactoryTest {
         ProxyBackendHandler proxyBackendHandler = 
TCLProxyBackendHandlerFactory.newInstance(queryContext, connectionSession);
         assertThat(proxyBackendHandler, isA(CommitProxyBackendHandler.class));
         CommitProxyBackendHandler backendHandler = (CommitProxyBackendHandler) 
proxyBackendHandler;
-        assertFieldOfInstance(getTransactionManager(backendHandler), 
"connection", is(databaseConnectionManager));
+        ProxyBackendTransactionManager classInstance = 
getTransactionManager(backendHandler);
+        assertThat((ProxyDatabaseConnectionManager) 
Plugins.getMemberAccessor().get(classInstance.getClass().getDeclaredField("connection"),
 classInstance), is(databaseConnectionManager));
     }
     
     @Test
-    void 
assertTCLProxyBackendHandlerReturnedWhenTCLStatementInstanceOfRollbackStatement()
 {
+    void 
assertTCLProxyBackendHandlerReturnedWhenTCLStatementInstanceOfRollbackStatement()
 throws ReflectiveOperationException {
         ConnectionSession connectionSession = mock(ConnectionSession.class, 
Answers.RETURNS_DEEP_STUBS);
         ProxyDatabaseConnectionManager databaseConnectionManager = 
mock(ProxyDatabaseConnectionManager.class);
         
when(connectionSession.getDatabaseConnectionManager()).thenReturn(databaseConnectionManager);
@@ -99,7 +101,8 @@ class TCLProxyBackendHandlerFactoryTest {
         ProxyBackendHandler proxyBackendHandler = 
TCLProxyBackendHandlerFactory.newInstance(queryContext, connectionSession);
         assertThat(proxyBackendHandler, 
isA(RollbackProxyBackendHandler.class));
         RollbackProxyBackendHandler backendHandler = 
(RollbackProxyBackendHandler) proxyBackendHandler;
-        assertFieldOfInstance(getTransactionManager(backendHandler), 
"connection", is(databaseConnectionManager));
+        ProxyBackendTransactionManager classInstance = 
getTransactionManager(backendHandler);
+        assertThat((ProxyDatabaseConnectionManager) 
Plugins.getMemberAccessor().get(classInstance.getClass().getDeclaredField("connection"),
 classInstance), is(databaseConnectionManager));
     }
     
     private ContextManager mockContextManager() {
@@ -108,6 +111,11 @@ class TCLProxyBackendHandlerFactoryTest {
         return result;
     }
     
+    @SneakyThrows(ReflectiveOperationException.class)
+    private ProxyBackendTransactionManager getTransactionManager(final 
ProxyBackendHandler backendHandler) {
+        return (ProxyBackendTransactionManager) 
Plugins.getMemberAccessor().get(backendHandler.getClass().getDeclaredField("transactionManager"),
 backendHandler);
+    }
+    
     @Test
     void assertBroadcastProxyBackendHandlerReturnedWhenTCLStatementNotHit() {
         SQLStatementContext sqlStatementContext = 
mock(SQLStatementContext.class, RETURNS_DEEP_STUBS);
@@ -121,15 +129,13 @@ class TCLProxyBackendHandlerFactoryTest {
         assertThat(TCLProxyBackendHandlerFactory.newInstance(queryContext, 
mock(ConnectionSession.class)), isA(DatabaseProxyConnector.class));
     }
     
-    @SuppressWarnings("unchecked")
-    @SneakyThrows(ReflectiveOperationException.class)
-    private <S, T> void assertFieldOfInstance(final S classInstance, final 
String fieldName, final Matcher<T> matcher) {
-        T value = (T) 
Plugins.getMemberAccessor().get(classInstance.getClass().getDeclaredField(fieldName),
 classInstance);
-        assertThat(value, matcher);
-    }
-    
-    @SneakyThrows(ReflectiveOperationException.class)
-    private ProxyBackendTransactionManager getTransactionManager(final 
ProxyBackendHandler backendHandler) {
-        return (ProxyBackendTransactionManager) 
Plugins.getMemberAccessor().get(backendHandler.getClass().getDeclaredField("transactionManager"),
 backendHandler);
+    @Test
+    void assertXATCLProxyBackendHandlerReturnedWhenXAStatement() {
+        QueryContext queryContext = mock(QueryContext.class, 
RETURNS_DEEP_STUBS);
+        
when(queryContext.getSqlStatementContext().getSqlStatement()).thenReturn(mock(XAStatement.class));
+        ConnectionSession connectionSession = mock(ConnectionSession.class);
+        ProxyBackendHandler expected = mock(ProxyBackendHandler.class);
+        when(XATCLProxyBackendHandlerFactory.newInstance(queryContext, 
connectionSession)).thenReturn(expected);
+        assertThat(TCLProxyBackendHandlerFactory.newInstance(queryContext, 
connectionSession), is(expected));
     }
 }


Reply via email to