You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by "zhangliang.apache.org via notifications" <no...@shardingsphere.apache.org> on 2026/10/31 08:38:09 UTC
(shardingsphere) branch master updated: Use existing engines for dynamic JSON and YAML serialization (#40432)
This is an automated email from the ASF dual-hosted git repository.
terrymanu 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 4505cb5594a Use existing engines for dynamic JSON and YAML serialization (#40432)
4505cb5594a is described below
commit 4505cb5594a905b3e22878b986c13510cf9e2aba
Author: Liang Zhang <zh...@apache.org>
AuthorDate: Sat Oct 31 16:38:02 2026 +0800
Use existing engines for dynamic JSON and YAML serialization (#40432)
---
.../export/DatabaseExportMetaDataGenerator.java | 29 ++++-----
.../MigrationJobExecutorCallbackTest.java | 31 ++++-----
.../server/http/StreamableHttpMCPServlet.java | 6 +-
.../server/http/StreamableHttpMCPServletTest.java | 49 +++++++++++++-
.../util/DatabaseExportMetaDataGeneratorTest.java | 75 ++++++++++++++++++++++
.../framework/helper/PipelineCaseHelper.java | 4 +-
.../type/GitHubTestParameterLoadStrategyTest.java | 37 ++++++++---
7 files changed, 179 insertions(+), 52 deletions(-)
diff --git a/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/configuration/export/DatabaseExportMetaDataGenerator.java b/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/configuration/export/DatabaseExportMetaDataGenerator.java
index 3bfc669f844..4dbd08ad8cd 100644
--- a/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/configuration/export/DatabaseExportMetaDataGenerator.java
+++ b/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/configuration/export/DatabaseExportMetaDataGenerator.java
@@ -31,6 +31,8 @@ import org.apache.shardingsphere.infra.yaml.config.swapper.rule.YamlRuleConfigur
import java.util.Collection;
import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
import java.util.Map.Entry;
/**
@@ -55,33 +57,34 @@ public final class DatabaseExportMetaDataGenerator {
}
private void appendDatabaseName(final String databaseName, final StringBuilder stringBuilder) {
- stringBuilder.append("databaseName: ").append(databaseName).append(System.lineSeparator());
+ stringBuilder.append(YamlEngine.marshal(Collections.singletonMap("databaseName", databaseName)));
}
private void appendDataSourceConfigurations(final ShardingSphereDatabase database, final StringBuilder stringBuilder) {
if (database.getResourceMetaData().getStorageUnits().isEmpty()) {
return;
}
- stringBuilder.append("dataSources:").append(System.lineSeparator());
+ Map<String, Map<String, Object>> dataSources = new LinkedHashMap<>(database.getResourceMetaData().getStorageUnits().size(), 1F);
for (Entry<String, StorageUnit> entry : database.getResourceMetaData().getStorageUnits().entrySet()) {
- appendDataSourceConfiguration(entry.getKey(), entry.getValue().getDataSourcePoolProperties(), stringBuilder);
+ Map<String, Object> props = createDataSourceConfiguration(entry.getValue().getDataSourcePoolProperties());
+ dataSources.put(entry.getKey(), props.isEmpty() ? null : props);
}
+ stringBuilder.append(YamlEngine.marshal(Collections.singletonMap("dataSources", dataSources)));
}
- private void appendDataSourceConfiguration(final String dataSourceName, final DataSourcePoolProperties props, final StringBuilder stringBuilder) {
- stringBuilder.append(createIndentation(2)).append(dataSourceName).append(':').append(System.lineSeparator());
+ private Map<String, Object> createDataSourceConfiguration(final DataSourcePoolProperties props) {
+ Map<String, Object> result = new LinkedHashMap<>(props.getConnectionPropertySynonyms().getStandardProperties().size() + props.getPoolPropertySynonyms().getStandardProperties().size(), 1F);
for (Entry<String, Object> entry : props.getConnectionPropertySynonyms().getStandardProperties().entrySet()) {
if (null != entry.getValue()) {
- String value = entry.getValue().toString();
- stringBuilder.append(createIndentation(4)).append(entry.getKey()).append(": ").append(value).append(System.lineSeparator());
+ result.put(entry.getKey(), entry.getValue());
}
}
for (Entry<String, Object> entry : props.getPoolPropertySynonyms().getStandardProperties().entrySet()) {
if (null != entry.getValue()) {
- String value = entry.getValue().toString();
- stringBuilder.append(createIndentation(4)).append(entry.getKey()).append(": ").append(value).append(System.lineSeparator());
+ result.put(entry.getKey(), entry.getValue());
}
}
+ return result;
}
@SuppressWarnings({"rawtypes", "unchecked"})
@@ -101,12 +104,4 @@ public final class DatabaseExportMetaDataGenerator {
stringBuilder.append(YamlEngine.marshal(Collections.singletonList(entry.getValue().swapToYamlConfiguration(entry.getKey()))));
}
}
-
- private String createIndentation(final int count) {
- StringBuilder result = new StringBuilder();
- for (int i = 0; i < count; i++) {
- result.append(" ");
- }
- return result.toString();
- }
}
diff --git a/kernel/data-pipeline/scenario/migration/core/src/test/java/org/apache/shardingsphere/data/pipeline/scenario/migration/MigrationJobExecutorCallbackTest.java b/kernel/data-pipeline/scenario/migration/core/src/test/java/org/apache/shardingsphere/data/pipeline/scenario/migration/MigrationJobExecutorCallbackTest.java
index ceaa77d6d91..909b182b64d 100644
--- a/kernel/data-pipeline/scenario/migration/core/src/test/java/org/apache/shardingsphere/data/pipeline/scenario/migration/MigrationJobExecutorCallbackTest.java
+++ b/kernel/data-pipeline/scenario/migration/core/src/test/java/org/apache/shardingsphere/data/pipeline/scenario/migration/MigrationJobExecutorCallbackTest.java
@@ -54,6 +54,7 @@ import org.apache.shardingsphere.infra.metadata.database.schema.QualifiedTable;
import org.apache.shardingsphere.infra.metadata.identifier.ShardingSphereIdentifier;
import org.apache.shardingsphere.infra.spi.type.ordered.OrderedSPILoader;
import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+import org.apache.shardingsphere.infra.util.yaml.YamlEngine;
import org.apache.shardingsphere.infra.yaml.config.pojo.YamlRootConfiguration;
import org.apache.shardingsphere.mode.manager.ContextManager;
import org.junit.jupiter.api.Test;
@@ -229,13 +230,18 @@ class MigrationJobExecutorCallbackTest {
}
private String createSourceDataSourceYaml(final int maxPoolSize, final int maximumPoolSize) {
- return SOURCE_DATA_SOURCE_NAME + ":\n"
- + " dataSourceClassName: com.zaxxer.hikari.HikariDataSource\n"
- + " url: " + SOURCE_JDBC_URL + "\n"
- + " username: root\n"
- + " password: root\n"
- + " maxPoolSize: " + maxPoolSize + "\n"
- + " maximumPoolSize: " + maximumPoolSize + "\n";
+ return YamlEngine.marshal(Collections.singletonMap(SOURCE_DATA_SOURCE_NAME, createDataSourceProperties(SOURCE_JDBC_URL, maxPoolSize, maximumPoolSize)));
+ }
+
+ private Map<String, Object> createDataSourceProperties(final String jdbcUrl, final int maxPoolSize, final int maximumPoolSize) {
+ Map<String, Object> result = new LinkedHashMap<>(6, 1F);
+ result.put("dataSourceClassName", "com.zaxxer.hikari.HikariDataSource");
+ result.put("url", jdbcUrl);
+ result.put("username", "root");
+ result.put("password", "root");
+ result.put("maxPoolSize", maxPoolSize);
+ result.put("maximumPoolSize", maximumPoolSize);
+ return result;
}
private void mockProxyContext(final MockedStatic<PipelineContextManager> pipelineContextManager) {
@@ -303,17 +309,6 @@ class MigrationJobExecutorCallbackTest {
return result;
}
- private Map<String, Object> createDataSourceProperties(final String jdbcUrl, final int maxPoolSize, final int maximumPoolSize) {
- Map<String, Object> result = new LinkedHashMap<>(6, 1F);
- result.put("dataSourceClassName", "com.zaxxer.hikari.HikariDataSource");
- result.put("url", jdbcUrl);
- result.put("username", "root");
- result.put("password", "root");
- result.put("maxPoolSize", maxPoolSize);
- result.put("maximumPoolSize", maximumPoolSize);
- return result;
- }
-
private TransmissionProcessContext mockProcessContext() {
TransmissionProcessContext result = mock(TransmissionProcessContext.class);
when(result.getProcessConfiguration()).thenReturn(new PipelineProcessConfiguration(new PipelineReadConfiguration(1, 10, 10, null),
diff --git a/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/StreamableHttpMCPServlet.java b/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/StreamableHttpMCPServlet.java
index 571ba12d75d..58f82c40681 100644
--- a/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/StreamableHttpMCPServlet.java
+++ b/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/StreamableHttpMCPServlet.java
@@ -33,6 +33,7 @@ import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponseWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.infra.exception.ShardingSpherePreconditions;
+import org.apache.shardingsphere.infra.util.json.JsonEngine;
import org.apache.shardingsphere.mcp.api.session.MCPSessionIdentity;
import org.apache.shardingsphere.mcp.bootstrap.config.HttpTransportConfiguration;
import org.apache.shardingsphere.mcp.bootstrap.transport.HttpTransportHostUtils;
@@ -72,8 +73,6 @@ final class StreamableHttpMCPServlet extends HttpServlet implements McpStreamabl
private final HttpServletStreamableServerTransportProvider delegate;
- private final McpJsonMapper jsonMapper;
-
private final ServerTransportSecurityValidator securityValidator;
private final MCPSessionManager sessionManager;
@@ -92,7 +91,6 @@ final class StreamableHttpMCPServlet extends HttpServlet implements McpStreamabl
new OriginHeaderConstraint(HttpTransportHostUtils.isLoopbackHost(config.getBindHost())),
new ProtocolVersionHeaderConstraint(), sessionAttributionResolver);
delegate = createDelegate(jsonMapper, config.getEndpointPath());
- this.jsonMapper = jsonMapper;
this.sessionManager = sessionManager;
sessionExecutionCoordinator = new MCPSessionExecutionCoordinator(sessionManager);
closed = new AtomicBoolean();
@@ -237,7 +235,7 @@ final class StreamableHttpMCPServlet extends HttpServlet implements McpStreamabl
McpError error = MCPTransportErrorFactory.createError(cause);
response.setStatus(cause.getStatusCode());
response.setContentType(JSON_CONTENT_TYPE);
- response.getWriter().write(jsonMapper.writeValueAsString(Map.of("jsonrpc", McpSchema.JSONRPC_VERSION, "error", error.getJsonRpcError())));
+ response.getWriter().write(JsonEngine.marshal(Map.of("jsonrpc", McpSchema.JSONRPC_VERSION, "error", error.getJsonRpcError())));
}
private Map<String, List<String>> extractHeaders(final HttpServletRequest request) {
diff --git a/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/StreamableHttpMCPServletTest.java b/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/StreamableHttpMCPServletTest.java
index d7df6b7e6db..96ee2e2a8c7 100644
--- a/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/StreamableHttpMCPServletTest.java
+++ b/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/StreamableHttpMCPServletTest.java
@@ -27,11 +27,14 @@ import io.modelcontextprotocol.spec.ProtocolVersions;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
+import org.apache.shardingsphere.infra.util.json.JsonEngine;
import org.apache.shardingsphere.mcp.api.session.MCPSessionIdentity;
import org.apache.shardingsphere.mcp.bootstrap.config.HttpTransportConfiguration;
import org.apache.shardingsphere.mcp.bootstrap.config.SessionAttributionSourceConfiguration;
import org.apache.shardingsphere.mcp.bootstrap.transport.MCPTransportConstants;
import org.apache.shardingsphere.mcp.bootstrap.transport.MCPTransportJsonMapperFactory;
+import org.apache.shardingsphere.mcp.bootstrap.transport.server.http.validator.MCPTransportSecurityException;
+import org.apache.shardingsphere.mcp.bootstrap.transport.server.http.validator.ShardingSphereServerTransportSecurityValidator;
import org.apache.shardingsphere.mcp.core.session.MCPSessionManager;
import org.apache.shardingsphere.test.infra.framework.extension.log.LogCaptureAssertion;
import org.apache.shardingsphere.test.infra.framework.extension.log.LogCaptureExtension;
@@ -49,10 +52,12 @@ import reactor.core.publisher.Mono;
import java.io.IOException;
import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -69,6 +74,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
@@ -265,13 +271,29 @@ class StreamableHttpMCPServletTest {
when(request.getHeaderNames()).thenReturn(Collections.enumeration(List.of("Origin")));
when(request.getHeaders("Origin")).thenReturn(Collections.enumeration(List.of("https://example.com")));
HttpServletResponse response = mock(HttpServletResponse.class);
- when(response.getWriter()).thenReturn(mock(PrintWriter.class));
+ StringWriter actualResponseBody = new StringWriter();
+ when(response.getWriter()).thenReturn(new PrintWriter(actualResponseBody));
createServlet(mock(MCPSessionManager.class)).service(request, response);
verify(response).setStatus(HttpServletResponse.SC_FORBIDDEN);
+ verify(response).setContentType("application/json");
+ assertTransportSecurityError(actualResponseBody, "Origin is not allowed by MCP HTTP transport policy.");
verify(response, never()).sendError(HttpServletResponse.SC_BAD_REQUEST, "Accept must include text/event-stream.");
verify(getDelegate(), never()).service(any(HttpServletRequest.class), any(HttpServletResponse.class));
}
+ private void assertTransportSecurityError(final StringWriter responseBody, final String expectedMessage) {
+ Map<?, ?> actual = JsonEngine.unmarshal(responseBody.toString(), Map.class);
+ assertThat(actual.keySet(), is(Set.of("jsonrpc", "error")));
+ assertThat(actual.get("jsonrpc"), is(McpSchema.JSONRPC_VERSION));
+ Map<?, ?> actualError = (Map<?, ?>) actual.get("error");
+ assertThat(actualError.keySet(), is(Set.of("code", "message", "data")));
+ assertThat(actualError.get("code"), is(McpSchema.ErrorCodes.INVALID_PARAMS));
+ assertThat(actualError.get("message"), is(expectedMessage));
+ Map<?, ?> actualData = (Map<?, ?>) actualError.get("data");
+ assertThat(actualData.get("summary"), is(expectedMessage));
+ assertThat(actualData.get("response_mode"), is("recovery"));
+ }
+
@Test
void assertRejectUnsupportedEventStreamGet() throws ServletException, IOException {
MCPSessionManager sessionManager = new MCPSessionManager(Map.of());
@@ -415,14 +437,37 @@ class StreamableHttpMCPServletTest {
when(request.getHeaderNames()).thenReturn(Collections.enumeration(List.of("Origin")));
when(request.getHeaders("Origin")).thenReturn(Collections.enumeration(List.of("https://example.com")));
HttpServletResponse response = mock(HttpServletResponse.class);
- when(response.getWriter()).thenReturn(mock(PrintWriter.class));
+ StringWriter actualResponseBody = new StringWriter();
+ when(response.getWriter()).thenReturn(new PrintWriter(actualResponseBody));
createServlet(mock(MCPSessionManager.class)).service(request, response);
verify(response).setStatus(HttpServletResponse.SC_FORBIDDEN);
+ verify(response).setContentType("application/json");
+ assertTransportSecurityError(actualResponseBody, "Origin is not allowed by MCP HTTP transport policy.");
verify(request, never()).getContentType();
verify(response, never()).sendError(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, "Content-Type must be application/json.");
verify(getDelegate(), never()).service(any(HttpServletRequest.class), any(HttpServletResponse.class));
}
+ @Test
+ void assertServiceTransportSecurityErrorEscaping() throws ServletException, IOException {
+ String expectedMessage = "foo_\"quoted\"\\path\nmessage";
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ when(request.getMethod()).thenReturn("POST");
+ HttpServletResponse response = mock(HttpServletResponse.class);
+ StringWriter actualResponseBody = new StringWriter();
+ when(response.getWriter()).thenReturn(new PrintWriter(actualResponseBody));
+ try (
+ MockedConstruction<ShardingSphereServerTransportSecurityValidator> ignored = mockConstruction(ShardingSphereServerTransportSecurityValidator.class,
+ (mock, context) -> doThrow(new MCPTransportSecurityException(403, expectedMessage, MCPTransportSecurityException.CATEGORY_ORIGIN_NOT_ALLOWED)).when(mock)
+ .validateHeaders(anyMap()))) {
+ createServlet(mock(MCPSessionManager.class)).service(request, response);
+ }
+ verify(response).setStatus(HttpServletResponse.SC_FORBIDDEN);
+ verify(response).setContentType("application/json");
+ assertTransportSecurityError(actualResponseBody, expectedMessage);
+ verify(getDelegate(), never()).service(any(HttpServletRequest.class), any(HttpServletResponse.class));
+ }
+
@Test
void assertServicePostWithNegotiatedProtocolHeader() throws ServletException, IOException {
HttpServletRequest request = mock(HttpServletRequest.class);
diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/util/DatabaseExportMetaDataGeneratorTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/util/DatabaseExportMetaDataGeneratorTest.java
index b5ec7e28ee2..e55fbd10bcd 100644
--- a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/util/DatabaseExportMetaDataGeneratorTest.java
+++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/util/DatabaseExportMetaDataGeneratorTest.java
@@ -18,6 +18,7 @@
package org.apache.shardingsphere.proxy.backend.util;
import org.apache.shardingsphere.distsql.handler.executor.configuration.export.DatabaseExportMetaDataGenerator;
+import org.apache.shardingsphere.distsql.handler.executor.configuration.yaml.YamlDatabaseConfiguration;
import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
import org.apache.shardingsphere.infra.datasource.pool.props.domain.DataSourcePoolProperties;
import org.apache.shardingsphere.infra.datasource.pool.props.domain.synonym.ConnectionPropertySynonyms;
@@ -26,8 +27,11 @@ import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import org.apache.shardingsphere.infra.metadata.database.resource.ResourceMetaData;
import org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnit;
import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
+import org.apache.shardingsphere.infra.util.yaml.YamlEngine;
import org.apache.shardingsphere.single.config.SingleRuleConfiguration;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
import java.util.Arrays;
import java.util.Collection;
@@ -37,9 +41,12 @@ import java.util.Map;
import java.util.Map.Entry;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -73,6 +80,7 @@ class DatabaseExportMetaDataGeneratorTest {
assertThat(actual, not(containsString("idleTimeout")));
assertThat(actual, containsString("rules:"));
assertThat(actual, containsString("defaultDataSource: write_ds"));
+ assertThat(YamlEngine.unmarshal(actual, YamlDatabaseConfiguration.class).getRules().size(), is(1));
}
private ShardingSphereDatabase mockDatabase() {
@@ -122,4 +130,71 @@ class DatabaseExportMetaDataGeneratorTest {
result.setDefaultDataSource("write_ds");
return result;
}
+
+ @ParameterizedTest(name = "{index}: {0}")
+ @ValueSource(strings = {"foo: bar # baz\n'quoted' \"value\" \\δΈ", "null", "true", "00123"})
+ void assertGenerateYAMLFormatWithSpecialCharacters(final String value) {
+ ShardingSphereDatabase database = mockEmptyDatabase();
+ when(database.getName()).thenReturn(value);
+ Map<String, Object> expectedProps = new LinkedHashMap<>(5, 1F);
+ expectedProps.put("url", value);
+ expectedProps.put("username", value);
+ expectedProps.put("password", value);
+ expectedProps.put("maxPoolSize", 30);
+ expectedProps.put("readOnly", true);
+ Map<String, Object> props = new LinkedHashMap<>(expectedProps);
+ props.put("minPoolSize", null);
+ props.put("connectionInitSql", "SELECT 1");
+ Map<String, StorageUnit> storageUnits = mockStorageUnits(Collections.singletonMap(value, new DataSourcePoolProperties("com.zaxxer.hikari.HikariDataSource", props)));
+ when(database.getResourceMetaData().getStorageUnits()).thenReturn(storageUnits);
+ Map<?, ?> actual = YamlEngine.unmarshal(new DatabaseExportMetaDataGenerator(database).generateYAMLFormat(), Map.class);
+ assertThat(actual.get("databaseName"), is(value));
+ Map<?, ?> actualDataSources = (Map<?, ?>) actual.get("dataSources");
+ assertThat(actualDataSources.keySet(), contains(value));
+ assertThat(actualDataSources.get(value), is(expectedProps));
+ }
+
+ @Test
+ void assertGenerateYAMLFormatWithDataSourceOrderAndPoolTypes() {
+ ShardingSphereDatabase database = mockEmptyDatabase();
+ Map<String, Object> props = new LinkedHashMap<>(4, 1F);
+ props.put("password", "");
+ props.put("maxPoolSize", 30);
+ props.put("connectionTimeoutMilliseconds", 30000L);
+ props.put("readOnly", false);
+ Map<String, DataSourcePoolProperties> dataSources = new LinkedHashMap<>(2, 1F);
+ dataSources.put("foo_ds", new DataSourcePoolProperties("com.zaxxer.hikari.HikariDataSource", props));
+ dataSources.put("bar_ds", createDataSourcePoolProperties());
+ Map<String, StorageUnit> storageUnits = mockStorageUnits(dataSources);
+ when(database.getResourceMetaData().getStorageUnits()).thenReturn(storageUnits);
+ String actualYaml = new DatabaseExportMetaDataGenerator(database).generateYAMLFormat();
+ Map<?, ?> actual = YamlEngine.unmarshal(actualYaml, Map.class);
+ assertThat(((Map<?, ?>) actual.get("dataSources")).keySet(), contains("foo_ds", "bar_ds"));
+ YamlDatabaseConfiguration actualConfig = YamlEngine.unmarshal(actualYaml, YamlDatabaseConfiguration.class);
+ assertThat(actualConfig.getDataSources().get("foo_ds").getPassword(), is(""));
+ assertThat(actualConfig.getDataSources().get("foo_ds").getMaxPoolSize(), is(30));
+ assertThat(actualConfig.getDataSources().get("foo_ds").getConnectionTimeoutMilliseconds(), is(30000L));
+ assertFalse(actualConfig.getDataSources().get("foo_ds").getReadOnly());
+ }
+
+ @Test
+ void assertGenerateYAMLFormatWithEmptyDataSource() {
+ ShardingSphereDatabase database = mockEmptyDatabase();
+ Map<String, Object> props = new LinkedHashMap<>(1, 1F);
+ props.put("url", null);
+ Map<String, StorageUnit> storageUnits = mockStorageUnits(Collections.singletonMap("foo_ds", new DataSourcePoolProperties("com.zaxxer.hikari.HikariDataSource", props)));
+ when(database.getResourceMetaData().getStorageUnits()).thenReturn(storageUnits);
+ Map<?, ?> actual = YamlEngine.unmarshal(new DatabaseExportMetaDataGenerator(database).generateYAMLFormat(), Map.class);
+ Map<?, ?> actualDataSources = (Map<?, ?>) actual.get("dataSources");
+ assertThat(actualDataSources.keySet(), contains("foo_ds"));
+ assertNull(actualDataSources.get("foo_ds"));
+ }
+
+ @Test
+ void assertGenerateYAMLFormatWithOnlyEmptyRules() {
+ ShardingSphereDatabase database = mockEmptyDatabase();
+ when(database.getRuleMetaData().getConfigurations()).thenReturn(Collections.singletonList(new SingleRuleConfiguration()));
+ Map<?, ?> actual = YamlEngine.unmarshal(new DatabaseExportMetaDataGenerator(database).generateYAMLFormat(), Map.class);
+ assertThat(actual.keySet(), contains("databaseName"));
+ }
}
diff --git a/test/e2e/operation/pipeline/src/test/java/org/apache/shardingsphere/test/e2e/operation/pipeline/framework/helper/PipelineCaseHelper.java b/test/e2e/operation/pipeline/src/test/java/org/apache/shardingsphere/test/e2e/operation/pipeline/framework/helper/PipelineCaseHelper.java
index 2ff2fa76e28..f7f36ed44da 100644
--- a/test/e2e/operation/pipeline/src/test/java/org/apache/shardingsphere/test/e2e/operation/pipeline/framework/helper/PipelineCaseHelper.java
+++ b/test/e2e/operation/pipeline/src/test/java/org/apache/shardingsphere/test/e2e/operation/pipeline/framework/helper/PipelineCaseHelper.java
@@ -24,11 +24,13 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.data.pipeline.cdc.util.RandomStrings;
import org.apache.shardingsphere.infra.algorithm.core.context.AlgorithmSQLContext;
import org.apache.shardingsphere.infra.algorithm.keygen.spi.KeyGenerateAlgorithm;
+import org.apache.shardingsphere.infra.util.json.JsonEngine;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.time.LocalDateTime;
+import java.util.Collections;
import java.util.concurrent.ThreadLocalRandom;
import static org.mockito.Mockito.mock;
@@ -72,7 +74,7 @@ public final class PipelineCaseHelper {
} else {
value = generateString(length);
}
- return String.format("{\"test\":\"%s\"}", value);
+ return JsonEngine.marshal(Collections.singletonMap("test", value));
}
/**
diff --git a/test/it/parser/src/test/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/strategy/type/GitHubTestParameterLoadStrategyTest.java b/test/it/parser/src/test/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/strategy/type/GitHubTestParameterLoadStrategyTest.java
index a1c7346b8fc..497352df841 100644
--- a/test/it/parser/src/test/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/strategy/type/GitHubTestParameterLoadStrategyTest.java
+++ b/test/it/parser/src/test/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/strategy/type/GitHubTestParameterLoadStrategyTest.java
@@ -17,6 +17,7 @@
package org.apache.shardingsphere.test.it.sql.parser.external.loader.strategy.type;
+import org.apache.shardingsphere.infra.util.json.JsonEngine;
import org.apache.shardingsphere.test.it.sql.parser.external.loader.summary.FileSummary;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
@@ -30,6 +31,9 @@ import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -50,9 +54,12 @@ class GitHubTestParameterLoadStrategyTest {
URI sourceURI = URI.create("https://github.com/owner/repo/" + sourceType + "/" + ref + "/" + casePath);
String apiURL = "https://api.github.com/repos/owner/repo/contents/" + casePath + "?ref=" + ref;
String downloadURL = "https://raw.githubusercontent.com/owner/repo/" + ref + "/cases/sample.sql";
- String fileContent = "{\"name\":\"sample.sql\",\"type\":\"file\",\"download_url\":\"" + downloadURL + "\"}";
+ Map<String, String> fileResponse = new LinkedHashMap<>(3, 1F);
+ fileResponse.put("name", "sample.sql");
+ fileResponse.put("type", "file");
+ fileResponse.put("download_url", downloadURL);
try (MockedStatic<URI> uriMock = mockStatic(URI.class)) {
- mockContent(uriMock, apiURL, "blob".equals(sourceType) ? fileContent : "[" + fileContent + "]");
+ mockContent(uriMock, apiURL, JsonEngine.marshal("blob".equals(sourceType) ? fileResponse : Collections.singletonList(fileResponse)));
Collection<FileSummary> actual = new GitHubTestParameterLoadStrategy().loadSQLCaseFileSummaries(sourceURI);
assertThat(actual.size(), is(1));
FileSummary actualFileSummary = actual.iterator().next();
@@ -78,18 +85,28 @@ class GitHubTestParameterLoadStrategyTest {
@Test
void assertLoadSQLCaseFileSummariesRecursively() throws IOException {
String ref = "f58ab18a90460cd297249bc80b13d84b2671bf0c";
- URI sourceURI = URI.create("https://github.com/owner/repo/tree/" + ref + "/cases");
+ String downloadURL = "https://raw.githubusercontent.com/owner/repo/" + ref + "/cases/sample.sql";
+ Map<String, String> fileResponse = new LinkedHashMap<>(3, 1F);
+ fileResponse.put("name", "sample.sql");
+ fileResponse.put("type", "file");
+ fileResponse.put("download_url", downloadURL);
String childURL = "https://github.com/owner/repo/tree/" + ref + "/cases/nested";
- URI childURI = URI.create(childURL);
+ Map<String, String> directoryResponse = new LinkedHashMap<>(3, 1F);
+ directoryResponse.put("name", "nested");
+ directoryResponse.put("type", "dir");
+ directoryResponse.put("html_url", childURL);
+ String childDownloadURL = "https://raw.githubusercontent.com/owner/repo/" + ref + "/cases/nested/child.sql";
+ Map<String, String> childResponse = new LinkedHashMap<>(3, 1F);
+ childResponse.put("name", "child.sql");
+ childResponse.put("type", "file");
+ childResponse.put("download_url", childDownloadURL);
String apiURL = "https://api.github.com/repos/owner/repo/contents/cases?ref=" + ref;
String childApiURL = "https://api.github.com/repos/owner/repo/contents/cases/nested?ref=" + ref;
- String downloadURL = "https://raw.githubusercontent.com/owner/repo/" + ref + "/cases/sample.sql";
- String childDownloadURL = "https://raw.githubusercontent.com/owner/repo/" + ref + "/cases/nested/child.sql";
- String content = "[{\"name\":\"sample.sql\",\"type\":\"file\",\"download_url\":\"" + downloadURL + "\"},{\"name\":\"nested\",\"type\":\"dir\",\"html_url\":\"" + childURL + "\"}]";
- String childContent = "[{\"name\":\"child.sql\",\"type\":\"file\",\"download_url\":\"" + childDownloadURL + "\"}]";
+ URI sourceURI = URI.create("https://github.com/owner/repo/tree/" + ref + "/cases");
+ URI childURI = URI.create(childURL);
try (MockedStatic<URI> uriMock = mockStatic(URI.class)) {
- mockContent(uriMock, apiURL, content);
- mockContent(uriMock, childApiURL, childContent);
+ mockContent(uriMock, apiURL, JsonEngine.marshal(Arrays.asList(fileResponse, directoryResponse)));
+ mockContent(uriMock, childApiURL, JsonEngine.marshal(Collections.singletonList(childResponse)));
uriMock.when(() -> URI.create(childURL)).thenReturn(childURI);
Collection<FileSummary> actual = new GitHubTestParameterLoadStrategy().loadSQLCaseFileSummaries(sourceURI);
assertThat(actual.stream().map(FileSummary::getFileName).collect(Collectors.toList()), is(Arrays.asList("sample.sql", "child.sql")));