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 5e970629030 Add GraalVM Reachability Metadata and corresponding 
nativeTest for Etcd integration (#29755)
5e970629030 is described below

commit 5e97062903090f10f9f43eec9d0b3db38595d267
Author: Ling Hengqian <[email protected]>
AuthorDate: Thu Jan 18 14:46:06 2024 +0800

    Add GraalVM Reachability Metadata and corresponding nativeTest for Etcd 
integration (#29755)
---
 infra/expr/type/espresso/pom.xml                   |   2 +-
 .../logback-core/1.2.12/reflect-config.json        |  10 --
 .../com.zaxxer/HikariCP/4.0.3/reflect-config.json  |   5 +-
 .../4.1.99.Final/reflect-config.json               |   7 +
 .../calcite-core/1.35.0/reflect-config.json        |   5 -
 .../groovy/4.0.10/reflect-config.json              |   8 --
 .../reflect-config.json                            |  47 +++----
 pom.xml                                            |   6 +-
 test/native/native-image-filter/extra-filter.json  |   9 +-
 test/native/pom.xml                                |  12 ++
 .../test/natived/jdbc/databases/MySQLTest.java     |   7 +-
 .../test/natived/jdbc/mode/cluster/EtcdTest.java   | 143 +++++++++++++++++++++
 .../natived/jdbc/mode/cluster/ZookeeperTest.java   |   4 +-
 .../resource-config.json                           |   5 +-
 .../test-native/yaml/databases/mysql.yaml          |   6 +-
 .../mode/cluster/{zookeeper.yaml => etcd.yaml}     |  12 +-
 .../test-native/yaml/mode/cluster/zookeeper.yaml   |   2 +-
 17 files changed, 217 insertions(+), 73 deletions(-)

diff --git a/infra/expr/type/espresso/pom.xml b/infra/expr/type/espresso/pom.xml
index 9d4b935d03d..4b04bfdb79f 100644
--- a/infra/expr/type/espresso/pom.xml
+++ b/infra/expr/type/espresso/pom.xml
@@ -52,7 +52,7 @@
         <dependency>
             <groupId>org.graalvm.truffle</groupId>
             <artifactId>truffle-api</artifactId>
-            <version>${graalvm.version}</version>
+            <version>${graal-sdk.version}</version>
         </dependency>
     </dependencies>
     
diff --git 
a/infra/reachability-metadata/src/main/resources/META-INF/native-image/ch.qos.logback/logback-core/1.2.12/reflect-config.json
 
b/infra/reachability-metadata/src/main/resources/META-INF/native-image/ch.qos.logback/logback-core/1.2.12/reflect-config.json
index 642c144850d..d0579f62230 100644
--- 
a/infra/reachability-metadata/src/main/resources/META-INF/native-image/ch.qos.logback/logback-core/1.2.12/reflect-config.json
+++ 
b/infra/reachability-metadata/src/main/resources/META-INF/native-image/ch.qos.logback/logback-core/1.2.12/reflect-config.json
@@ -54,11 +54,6 @@
   "name":"ch.qos.logback.core.OutputStreamAppender",
   
"methods":[{"name":"setEncoder","parameterTypes":["ch.qos.logback.core.encoder.Encoder"]
 }]
 },
-{
-  
"condition":{"typeReachable":"ch.qos.logback.core.joran.action.NestedComplexPropertyIA"},
-  "name":"ch.qos.logback.core.encoder.Encoder",
-  "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }]
-},
 {
   
"condition":{"typeReachable":"ch.qos.logback.core.joran.util.PropertySetter"},
   "name":"ch.qos.logback.core.encoder.LayoutWrappingEncoder",
@@ -69,11 +64,6 @@
   "name":"ch.qos.logback.core.pattern.PatternLayoutEncoderBase",
   "methods":[{"name":"setPattern","parameterTypes":["java.lang.String"] }]
 },
-{
-  
"condition":{"typeReachable":"ch.qos.logback.core.joran.action.NestedComplexPropertyIA"},
-  "name":"ch.qos.logback.core.spi.ContextAware",
-  "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }]
-},
 {
   
"condition":{"typeReachable":"ch.qos.logback.core.joran.action.StatusListenerAction"},
   "name":"ch.qos.logback.core.status.NopStatusListener",
diff --git 
a/infra/reachability-metadata/src/main/resources/META-INF/native-image/com.zaxxer/HikariCP/4.0.3/reflect-config.json
 
b/infra/reachability-metadata/src/main/resources/META-INF/native-image/com.zaxxer/HikariCP/4.0.3/reflect-config.json
index 1360182ea86..cea847997c2 100644
--- 
a/infra/reachability-metadata/src/main/resources/META-INF/native-image/com.zaxxer/HikariCP/4.0.3/reflect-config.json
+++ 
b/infra/reachability-metadata/src/main/resources/META-INF/native-image/com.zaxxer/HikariCP/4.0.3/reflect-config.json
@@ -4,12 +4,11 @@
   "name":"com.zaxxer.hikari.HikariConfig",
   "queryAllPublicMethods":true,
   "fields":[{"name":"dataSourceProperties"}, {"name":"jdbcUrl"}],
-  "methods":[{"name":"getCatalog","parameterTypes":[] }, 
{"name":"getConnectionInitSql","parameterTypes":[] }, 
{"name":"getConnectionTestQuery","parameterTypes":[] }, 
{"name":"getConnectionTimeout","parameterTypes":[] }, 
{"name":"getDataSource","parameterTypes":[] }, 
{"name":"getDataSourceClassName","parameterTypes":[] }, 
{"name":"getDataSourceJNDI","parameterTypes":[] }, 
{"name":"getDataSourceProperties","parameterTypes":[] }, 
{"name":"getDriverClassName","parameterTypes":[] }, {"name": [...]
+  "methods":[{"name":"getCatalog","parameterTypes":[] }, 
{"name":"getConnectionInitSql","parameterTypes":[] }, 
{"name":"getConnectionTestQuery","parameterTypes":[] }, 
{"name":"getConnectionTimeout","parameterTypes":[] }, 
{"name":"getDataSource","parameterTypes":[] }, 
{"name":"getDataSourceClassName","parameterTypes":[] }, 
{"name":"getDataSourceJNDI","parameterTypes":[] }, 
{"name":"getDataSourceProperties","parameterTypes":[] }, 
{"name":"getDriverClassName","parameterTypes":[] }, {"name": [...]
 },
 {
   "condition":{"typeReachable":"com.zaxxer.hikari.HikariDataSource"},
   "name":"com.zaxxer.hikari.HikariDataSource",
-  "fields":[{"name":"dataSourceProperties"}, {"name":"jdbcUrl"}],
-  "methods":[{"name":"<init>","parameterTypes":[] }, 
{"name":"getAllowPoolSuspension","parameterTypes":[] }, 
{"name":"getAutoCommit","parameterTypes":[] }, 
{"name":"getIsolateInternalQueries","parameterTypes":[] }, 
{"name":"getReadOnly","parameterTypes":[] }, 
{"name":"getRegisterMbeans","parameterTypes":[] }, 
{"name":"isClosed","parameterTypes":[] }, 
{"name":"isRunning","parameterTypes":[] }]
+  "methods":[{"name":"<init>","parameterTypes":[] }, 
{"name":"isClosed","parameterTypes":[] }, 
{"name":"isRunning","parameterTypes":[] }]
 }
 ]
diff --git 
a/infra/reachability-metadata/src/main/resources/META-INF/native-image/io.netty/netty-transport-classes-epoll/4.1.99.Final/reflect-config.json
 
b/infra/reachability-metadata/src/main/resources/META-INF/native-image/io.netty/netty-transport-classes-epoll/4.1.99.Final/reflect-config.json
new file mode 100644
index 00000000000..8fdd338e44c
--- /dev/null
+++ 
b/infra/reachability-metadata/src/main/resources/META-INF/native-image/io.netty/netty-transport-classes-epoll/4.1.99.Final/reflect-config.json
@@ -0,0 +1,7 @@
+[
+{
+  "condition":{"typeReachable":"io.netty.channel.epoll.EpollChannelOption"},
+  "name":"io.netty.channel.epoll.EpollChannelOption",
+  "fields":[{"name":"TCP_USER_TIMEOUT"}]
+}
+]
diff --git 
a/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.calcite/calcite-core/1.35.0/reflect-config.json
 
b/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.calcite/calcite-core/1.35.0/reflect-config.json
index a1b09266a6f..bd8b1564304 100644
--- 
a/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.calcite/calcite-core/1.35.0/reflect-config.json
+++ 
b/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.calcite/calcite-core/1.35.0/reflect-config.json
@@ -1,9 +1,4 @@
 [
-{
-  "condition":{"typeReachable":"org.apache.calcite.linq4j.tree.Types"},
-  "name":"java.lang.Boolean",
-  "fields":[{"name":"FALSE"}, {"name":"TRUE"}]
-},
 {
   "condition":{"typeReachable":"org.apache.calcite.linq4j.tree.Types"},
   "name":"org.apache.calcite.DataContext",
diff --git 
a/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.groovy/groovy/4.0.10/reflect-config.json
 
b/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.groovy/groovy/4.0.10/reflect-config.json
index 4b68994f5ab..4a3e110b86d 100644
--- 
a/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.groovy/groovy/4.0.10/reflect-config.json
+++ 
b/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.groovy/groovy/4.0.10/reflect-config.json
@@ -99,14 +99,6 @@
   
"condition":{"typeReachable":"org.codehaus.groovy.reflection.GeneratedMetaMethod$DgmMethodRecord"},
   "name":"groovy.util.BufferedIterator"
 },
-{
-  
"condition":{"typeReachable":"org.codehaus.groovy.reflection.GeneratedMetaMethod$DgmMethodRecord"},
-  "name":"java.lang.Boolean"
-},
-{
-  
"condition":{"typeReachable":"org.codehaus.groovy.reflection.GeneratedMetaMethod$DgmMethodRecord"},
-  "name":"java.lang.Thread"
-},
 {
   
"condition":{"typeReachable":"org.codehaus.groovy.reflection.GeneratedMetaMethod$DgmMethodRecord"},
   "name":"org.codehaus.groovy.runtime.GStringImpl"
diff --git 
a/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere/shardingsphere-infra-reachability-metadata/reflect-config.json
 
b/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere/shardingsphere-infra-reachability-metadata/reflect-config.json
index 79f4c06a060..7108cb96269 100644
--- 
a/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere/shardingsphere-infra-reachability-metadata/reflect-config.json
+++ 
b/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere/shardingsphere-infra-reachability-metadata/reflect-config.json
@@ -1,4 +1,9 @@
 [
+{
+  
"condition":{"typeReachable":"org.apache.shardingsphere.mode.manager.cluster.NewClusterContextManagerBuilder"},
+  "name":"java.lang.Boolean",
+  "fields":[{"name":"FALSE"}, {"name":"TRUE"}]
+},
 {
   
"condition":{"typeReachable":"org.apache.shardingsphere.infra.util.yaml.YamlEngine"},
   "name":"java.util.Properties",
@@ -98,7 +103,7 @@
   
"name":"org.apache.shardingsphere.encrypt.yaml.config.rule.YamlEncryptColumnItemRuleConfiguration",
   "allDeclaredFields":true,
   "allPublicMethods":true,
-  "methods":[{"name":"<init>","parameterTypes":[] }, 
{"name":"setEncryptorName","parameterTypes":["java.lang.String"] }, 
{"name":"setName","parameterTypes":["java.lang.String"] }]
+  "methods":[{"name":"<init>","parameterTypes":[] }]
 },
 {
   
"condition":{"typeReachable":"org.apache.shardingsphere.infra.util.yaml.YamlEngine"},
@@ -113,7 +118,7 @@
   
"name":"org.apache.shardingsphere.encrypt.yaml.config.rule.YamlEncryptColumnRuleConfiguration",
   "allDeclaredFields":true,
   "allPublicMethods":true,
-  "methods":[{"name":"<init>","parameterTypes":[] }, 
{"name":"setAssistedQuery","parameterTypes":["org.apache.shardingsphere.encrypt.yaml.config.rule.YamlEncryptColumnItemRuleConfiguration"]
 }, 
{"name":"setCipher","parameterTypes":["org.apache.shardingsphere.encrypt.yaml.config.rule.YamlEncryptColumnItemRuleConfiguration"]
 }]
+  "methods":[{"name":"<init>","parameterTypes":[] }]
 },
 {
   
"condition":{"typeReachable":"org.apache.shardingsphere.infra.util.yaml.YamlEngine"},
@@ -266,7 +271,7 @@
   
"name":"org.apache.shardingsphere.infra.yaml.schema.pojo.YamlShardingSphereColumn",
   "allDeclaredFields":true,
   "allPublicMethods":true,
-  "methods":[{"name":"<init>","parameterTypes":[] }, 
{"name":"setCaseSensitive","parameterTypes":["boolean"] }, 
{"name":"setDataType","parameterTypes":["int"] }, 
{"name":"setGenerated","parameterTypes":["boolean"] }, 
{"name":"setName","parameterTypes":["java.lang.String"] }, 
{"name":"setPrimaryKey","parameterTypes":["boolean"] }, 
{"name":"setUnsigned","parameterTypes":["boolean"] }, 
{"name":"setVisible","parameterTypes":["boolean"] }]
+  "methods":[{"name":"<init>","parameterTypes":[] }]
 },
 {
   
"condition":{"typeReachable":"org.apache.shardingsphere.metadata.persist.service.schema.NewTableMetaDataPersistService"},
@@ -279,7 +284,7 @@
   
"name":"org.apache.shardingsphere.infra.yaml.schema.pojo.YamlShardingSphereIndex",
   "allDeclaredFields":true,
   "allPublicMethods":true,
-  "methods":[{"name":"<init>","parameterTypes":[] }, 
{"name":"setName","parameterTypes":["java.lang.String"] }]
+  "methods":[{"name":"<init>","parameterTypes":[] }]
 },
 {
   
"condition":{"typeReachable":"org.apache.shardingsphere.metadata.persist.service.schema.NewTableMetaDataPersistService"},
@@ -292,7 +297,7 @@
   
"name":"org.apache.shardingsphere.infra.yaml.schema.pojo.YamlShardingSphereTable",
   "allDeclaredFields":true,
   "allPublicMethods":true,
-  "methods":[{"name":"<init>","parameterTypes":[] }, 
{"name":"setColumns","parameterTypes":["java.util.Map"] }, 
{"name":"setIndexes","parameterTypes":["java.util.Map"] }, 
{"name":"setName","parameterTypes":["java.lang.String"] }]
+  "methods":[{"name":"<init>","parameterTypes":[] }]
 },
 {
   
"condition":{"typeReachable":"org.apache.shardingsphere.metadata.persist.service.database.NewDatabaseMetaDataPersistService"},
@@ -401,7 +406,7 @@
   
"name":"org.apache.shardingsphere.mask.yaml.config.rule.YamlMaskColumnRuleConfiguration",
   "allDeclaredFields":true,
   "allPublicMethods":true,
-  "methods":[{"name":"<init>","parameterTypes":[] }, 
{"name":"setMaskAlgorithm","parameterTypes":["java.lang.String"] }]
+  "methods":[{"name":"<init>","parameterTypes":[] }]
 },
 {
   
"condition":{"typeReachable":"org.apache.shardingsphere.infra.util.yaml.YamlEngine"},
@@ -507,6 +512,11 @@
   "name":"org.apache.shardingsphere.mode.process.ProcessSubscriber",
   "queryAllDeclaredMethods":true
 },
+{
+  
"condition":{"typeReachable":"org.apache.shardingsphere.mode.manager.cluster.NewClusterContextManagerBuilder"},
+  
"name":"org.apache.shardingsphere.mode.repository.cluster.etcd.EtcdRepository",
+  "methods":[{"name":"<init>","parameterTypes":[] }]
+},
 {
   
"condition":{"typeReachable":"org.apache.shardingsphere.mode.manager.cluster.NewClusterContextManagerBuilder"},
   
"name":"org.apache.shardingsphere.mode.repository.cluster.zookeeper.ZookeeperRepository",
@@ -530,17 +540,12 @@
   
"name":"org.apache.shardingsphere.mode.subsciber.NewConfigurationChangedSubscriber",
   "queryAllDeclaredMethods":true
 },
-{
-  
"condition":{"typeReachable":"org.apache.shardingsphere.mode.manager.cluster.NewClusterContextManagerBuilder"},
-  "name":"org.apache.shardingsphere.mode.subsciber.RuleItemChangedSubscriber",
-  "queryAllDeclaredMethods":true
-},
 {
   
"condition":{"typeReachable":"org.apache.shardingsphere.infra.util.yaml.YamlEngine"},
   
"name":"org.apache.shardingsphere.parser.yaml.config.YamlSQLParserCacheOptionRuleConfiguration",
   "allDeclaredFields":true,
   "allPublicMethods":true,
-  "methods":[{"name":"<init>","parameterTypes":[] }, 
{"name":"setInitialCapacity","parameterTypes":["int"] }, 
{"name":"setMaximumSize","parameterTypes":["long"] }]
+  "methods":[{"name":"<init>","parameterTypes":[] }]
 },
 {
   
"condition":{"typeReachable":"org.apache.shardingsphere.infra.util.yaml.YamlEngine"},
@@ -806,7 +811,7 @@
   
"name":"org.apache.shardingsphere.sharding.yaml.config.strategy.keygen.YamlKeyGenerateStrategyConfiguration",
   "allDeclaredFields":true,
   "allPublicMethods":true,
-  "methods":[{"name":"<init>","parameterTypes":[] }, 
{"name":"setColumn","parameterTypes":["java.lang.String"] }, 
{"name":"setKeyGeneratorName","parameterTypes":["java.lang.String"] }]
+  "methods":[{"name":"<init>","parameterTypes":[] }]
 },
 {
   
"condition":{"typeReachable":"org.apache.shardingsphere.infra.util.yaml.YamlEngine"},
@@ -842,7 +847,7 @@
   
"name":"org.apache.shardingsphere.sharding.yaml.config.strategy.sharding.YamlStandardShardingStrategyConfiguration",
   "allDeclaredFields":true,
   "allPublicMethods":true,
-  "methods":[{"name":"<init>","parameterTypes":[] }, 
{"name":"setShardingAlgorithmName","parameterTypes":["java.lang.String"] }, 
{"name":"setShardingColumn","parameterTypes":["java.lang.String"] }]
+  "methods":[{"name":"<init>","parameterTypes":[] }]
 },
 {
   
"condition":{"typeReachable":"org.apache.shardingsphere.infra.util.yaml.YamlEngine"},
@@ -1049,16 +1054,6 @@
   
"name":"org.apache.shardingsphere.sql.parser.sqlserver.visitor.statement.type.SQLServerDMLStatementVisitor",
   "methods":[{"name":"<init>","parameterTypes":[] }]
 },
-{
-  
"condition":{"typeReachable":"org.apache.shardingsphere.infra.connection.refresher.type.table.CreateTableStatementSchemaRefresher"},
-  
"name":"org.apache.shardingsphere.sqlfederation.optimizer.planner.util.SQLFederationFunctionUtils",
-  "queryAllPublicMethods":true
-},
-{
-  
"condition":{"typeReachable":"org.apache.shardingsphere.infra.connection.refresher.type.table.DropTableStatementSchemaRefresher"},
-  
"name":"org.apache.shardingsphere.sqlfederation.optimizer.planner.util.SQLFederationFunctionUtils",
-  "queryAllPublicMethods":true
-},
 {
   
"condition":{"typeReachable":"org.apache.shardingsphere.infra.rule.builder.global.GlobalRulesBuilder"},
   
"name":"org.apache.shardingsphere.sqlfederation.optimizer.planner.util.SQLFederationFunctionUtils"
@@ -1068,10 +1063,6 @@
   
"name":"org.apache.shardingsphere.sqlfederation.optimizer.planner.util.SQLFederationFunctionUtils",
   "queryAllPublicMethods":true
 },
-{
-  
"condition":{"typeReachable":"org.apache.shardingsphere.mode.manager.context.ConfigurationContextManager"},
-  
"name":"org.apache.shardingsphere.sqlfederation.optimizer.planner.util.SQLFederationFunctionUtils"
-},
 {
   
"condition":{"typeReachable":"org.apache.shardingsphere.mode.manager.context.ResourceMetaDataContextManager"},
   
"name":"org.apache.shardingsphere.sqlfederation.optimizer.planner.util.SQLFederationFunctionUtils"
diff --git a/pom.xml b/pom.xml
index d418d8b2b3e..3fc7b7a3f71 100644
--- a/pom.xml
+++ b/pom.xml
@@ -106,6 +106,7 @@
         <zookeeper.version>3.9.1</zookeeper.version>
         <audience-annotations.version>0.12.0</audience-annotations.version>
         <jetcd.version>0.7.6</jetcd.version>
+        <vertx.version>4.4.4</vertx.version>
         <consul.api.version>1.4.5</consul.api.version>
         
         <grpc.version>1.58.0</grpc.version>
@@ -145,7 +146,7 @@
         <testcontainers.version>1.19.3</testcontainers.version>
         <commons-csv.version>1.9.0</commons-csv.version>
         
-        <graalvm.version>21.2.0</graalvm.version>
+        <graal-sdk.version>21.2.0</graal-sdk.version>
         
         <!-- 3rd party library plugin versions -->
         <protobuf-maven-plugin.version>0.6.1</protobuf-maven-plugin.version>
@@ -1079,9 +1080,10 @@
                             <extensions>true</extensions>
                             <configuration>
                                 <buildArgs>
+                                    <buildArg>-J-Xmx7g</buildArg>
                                     <buildArg>-H:+AddAllCharsets</buildArg>
                                 </buildArgs>
-                                
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
+                                <quickBuild>true</quickBuild>
                                 <metadataRepository>
                                     <enabled>true</enabled>
                                     <version>0.3.5</version>
diff --git a/test/native/native-image-filter/extra-filter.json 
b/test/native/native-image-filter/extra-filter.json
index ed118a9185c..678ab3bf98e 100644
--- a/test/native/native-image-filter/extra-filter.json
+++ b/test/native/native-image-filter/extra-filter.json
@@ -10,9 +10,12 @@
     {"includeClasses": "java.util.Properties"},
     {"excludeClasses": "javax.security.auth.x500.**"},
     {"excludeClasses": "javax.smartcardio.**"},
+    {"excludeClasses": "jdk.internal.misc.**"},
     {"excludeClasses": "sun.misc.**"},
+    {"excludeClasses": "sun.nio.ch.**"},
     {"excludeClasses": "sun.security.**"},
 
+    {"excludeClasses": "android.app.**"},
     {"excludeClasses": "com.fasterxml.jackson.databind.**"},
     {"excludeClasses": "com.github.benmanes.caffeine.cache.**"},
     {"excludeClasses": "com.github.dockerjava.api.**"},
@@ -21,8 +24,11 @@
     {"excludeClasses": "com.microsoft.sqlserver.jdbc.**"},
     {"excludeClasses": "com.mysql.cj.**"},
     {"excludeClasses": "com.zaxxer.hikari.**"},
-    {"excludeClasses": "javax.xml.**"},
+    {"excludeClasses": "io.grpc.**"},
+    {"excludeClasses": "io.netty.**"},
+    {"excludeClasses": "io.vertx.core.**"},
     {"excludeClasses": "groovy.**"},
+    {"excludeClasses": "libcore.io.**"},
     {"excludeClasses": "org.apache.calcite.**"},
     {"excludeClasses": "org.apache.zookeeper.**"},
     {"excludeClasses": "org.codehaus.groovy.**"},
@@ -30,6 +36,7 @@
     {"excludeClasses": "org.locationtech.jts.geom.**"},
     {"excludeClasses": "org.opengauss.**"},
     {"excludeClasses": "org.postgresql.**"},
+    {"excludeClasses": "org.robolectric.**"},
     {"excludeClasses": "org.slf4j.event.**"},
     {"excludeClasses": "org.testcontainers.**"}
   ],
diff --git a/test/native/pom.xml b/test/native/pom.xml
index 96d87fb8d2b..12184e976ea 100644
--- a/test/native/pom.xml
+++ b/test/native/pom.xml
@@ -45,6 +45,18 @@
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            
<artifactId>shardingsphere-cluster-mode-repository-etcd</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.vertx</groupId>
+            <artifactId>vertx-grpc</artifactId>
+            <version>${vertx.version}</version>
+            <scope>test</scope>
+        </dependency>
         
         <dependency>
             <groupId>org.awaitility</groupId>
diff --git 
a/test/native/src/test/java/org/apache/shardingsphere/test/natived/jdbc/databases/MySQLTest.java
 
b/test/native/src/test/java/org/apache/shardingsphere/test/natived/jdbc/databases/MySQLTest.java
index 038cc5c8e57..59d18801f56 100644
--- 
a/test/native/src/test/java/org/apache/shardingsphere/test/natived/jdbc/databases/MySQLTest.java
+++ 
b/test/native/src/test/java/org/apache/shardingsphere/test/natived/jdbc/databases/MySQLTest.java
@@ -45,13 +45,15 @@ import java.util.Properties;
  */
 class MySQLTest {
     
+    private static final Integer MYSQL_PORT_ON_HOST = 60107;
+    
     private static final String USERNAME = "root";
     
     private static final String PASSWORD = "123456";
     
     private static final String DATABASE = "test";
     
-    private static final String JDBC_URL = "jdbc:mysql://localhost:65107/" + 
DATABASE;
+    private static final String JDBC_URL = "jdbc:mysql://localhost:" + 
MYSQL_PORT_ON_HOST + "/" + DATABASE;
     
     private TestShardingService testShardingService;
     
@@ -63,7 +65,8 @@ class MySQLTest {
                 GenericContainer<?> mySQLContainer = new 
GenericContainer<>(DockerImageName.parse("mysql:8.2.0-oracle"))
                         .withEnv("MYSQL_DATABASE", DATABASE)
                         .withEnv("MYSQL_ROOT_PASSWORD", PASSWORD)
-                        .withCreateContainerCmdModifier(cmd -> 
cmd.withHostConfig(new HostConfig().withPortBindings(new 
PortBinding(Ports.Binding.bindPort(65107), new ExposedPort(3306)))))) {
+                        .withCreateContainerCmdModifier(
+                                cmd -> cmd.withHostConfig(new 
HostConfig().withPortBindings(new 
PortBinding(Ports.Binding.bindPort(MYSQL_PORT_ON_HOST), new 
ExposedPort(3306)))))) {
             mySQLContainer.start();
             beforeAll();
             DataSource dataSource = 
YamlShardingSphereDataSourceFactory.createDataSource(FileTestUtils.readFromFileURLString("test-native/yaml/databases/mysql.yaml"));
diff --git 
a/test/native/src/test/java/org/apache/shardingsphere/test/natived/jdbc/mode/cluster/EtcdTest.java
 
b/test/native/src/test/java/org/apache/shardingsphere/test/natived/jdbc/mode/cluster/EtcdTest.java
new file mode 100644
index 00000000000..5684ea34abe
--- /dev/null
+++ 
b/test/native/src/test/java/org/apache/shardingsphere/test/natived/jdbc/mode/cluster/EtcdTest.java
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.test.natived.jdbc.mode.cluster;
+
+import com.github.dockerjava.api.model.ExposedPort;
+import com.github.dockerjava.api.model.HostConfig;
+import com.github.dockerjava.api.model.PortBinding;
+import com.github.dockerjava.api.model.Ports;
+import org.apache.hc.client5.http.classic.methods.HttpGet;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.client5.http.impl.classic.HttpClients;
+import org.apache.hc.core5.http.HttpStatus;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+import 
org.apache.shardingsphere.driver.api.yaml.YamlShardingSphereDataSourceFactory;
+import org.apache.shardingsphere.test.natived.jdbc.commons.FileTestUtils;
+import org.apache.shardingsphere.test.natived.jdbc.commons.TestShardingService;
+import org.awaitility.Awaitility;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledInNativeImage;
+import org.slf4j.LoggerFactory;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.containers.output.Slf4jLogConsumer;
+import org.testcontainers.containers.wait.strategy.Wait;
+import org.testcontainers.utility.DockerImageName;
+
+import javax.sql.DataSource;
+import java.io.IOException;
+import java.sql.SQLException;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+class EtcdTest {
+    
+    private static final Integer ETCD_CLIENT_PORT_ON_HOST = 62290;
+    
+    private static final Integer ETCD_CLIENT_PORT = 2379;
+    
+    private static final Integer ETCD_PEER_PORT = 2380;
+    
+    private TestShardingService testShardingService;
+    
+    @SuppressWarnings("resource")
+    @Test
+    @EnabledInNativeImage
+    void assertShardingInLocalTransactions() throws SQLException, IOException {
+        String node = "etcd0";
+        Collection<String> nodes = Collections.singletonList(node);
+        try (
+                GenericContainer<?> container = new 
GenericContainer<>(DockerImageName.parse("quay.io/coreos/etcd:v3.5.11"))
+                        .withCreateContainerCmdModifier(
+                                cmd -> cmd.withHostConfig(new 
HostConfig().withPortBindings(new 
PortBinding(Ports.Binding.bindPort(ETCD_CLIENT_PORT_ON_HOST), new 
ExposedPort(ETCD_CLIENT_PORT)))))
+                        .withNetworkAliases(node)
+                        .withLogConsumer(new 
Slf4jLogConsumer(LoggerFactory.getLogger(getClass())).withPrefix(node))
+                        .withCommand(createCommand(node, nodes))
+                        .withEnv("ETCD_LOG_LEVEL", "info")
+                        .withEnv("ETCD_LOGGER", "zap")
+                        
.waitingFor(Wait.forHttp("/health").forPort(ETCD_CLIENT_PORT))) {
+            container.start();
+            beforeAll();
+            DataSource dataSource = 
YamlShardingSphereDataSourceFactory.createDataSource(FileTestUtils.readFromFileURLString("test-native/yaml/mode/cluster/etcd.yaml"));
+            testShardingService = new TestShardingService(dataSource);
+            initEnvironment();
+            testShardingService.processSuccess();
+            testShardingService.cleanEnvironment();
+        }
+    }
+    
+    private void initEnvironment() throws SQLException {
+        
testShardingService.getOrderRepository().createTableIfNotExistsInMySQL();
+        
testShardingService.getOrderItemRepository().createTableIfNotExistsInMySQL();
+        testShardingService.getAddressRepository().createTableIfNotExists();
+        testShardingService.getOrderRepository().truncateTable();
+        testShardingService.getOrderItemRepository().truncateTable();
+        testShardingService.getAddressRepository().truncateTable();
+    }
+    
+    private void beforeAll() {
+        
Awaitility.await().atMost(Duration.ofSeconds(30L)).ignoreExceptions().until(this::verifyEtcdClusterRunning);
+    }
+    
+    @SuppressWarnings("HttpUrlsUsage")
+    private String[] createCommand(final String node, final Collection<String> 
nodes) {
+        List<String> cmd = new ArrayList<>();
+        cmd.add("etcd");
+        cmd.add("--name");
+        cmd.add(node);
+        cmd.add("--advertise-client-urls");
+        cmd.add("http" + "://0.0.0.0:" + ETCD_CLIENT_PORT);
+        cmd.add("--listen-client-urls");
+        cmd.add("http" + "://0.0.0.0:" + ETCD_CLIENT_PORT);
+        Collection<String> shouldMountDataDirectory = 
Arrays.asList("--data-dir", "/tmp/etcd-data");
+        cmd.addAll(shouldMountDataDirectory);
+        if (nodes.size() > 1) {
+            cmd.add("--initial-advertise-peer-urls");
+            cmd.add("http://"; + node + ":" + ETCD_PEER_PORT);
+            cmd.add("--listen-peer-urls");
+            cmd.add("http://0.0.0.0:"; + ETCD_PEER_PORT);
+            cmd.add("--initial-cluster");
+            cmd.add(nodes.stream().map(e -> e + "=http://"; + e + ":" + 
ETCD_PEER_PORT).collect(Collectors.joining(",")));
+            cmd.add("--initial-cluster-state");
+            cmd.add("new");
+            Collection<String> clusterToken = 
Arrays.asList("--initial-cluster-token", UUID.randomUUID().toString());
+            cmd.addAll(clusterToken);
+        }
+        return cmd.toArray(new String[0]);
+    }
+    
+    private Boolean verifyEtcdClusterRunning() throws IOException {
+        boolean flag = false;
+        HttpGet httpGet = new HttpGet("http://localhost:"; + 
ETCD_CLIENT_PORT_ON_HOST + "/health");
+        try (
+                CloseableHttpClient httpclient = HttpClients.createDefault();
+                CloseableHttpResponse response = httpclient.execute(httpGet)) {
+            if (HttpStatus.SC_OK == response.getCode()) {
+                flag = true;
+            }
+            EntityUtils.consume(response.getEntity());
+        }
+        return flag;
+    }
+}
diff --git 
a/test/native/src/test/java/org/apache/shardingsphere/test/natived/jdbc/mode/cluster/ZookeeperTest.java
 
b/test/native/src/test/java/org/apache/shardingsphere/test/natived/jdbc/mode/cluster/ZookeeperTest.java
index d2c14bf4a01..d1c9ee4f2bb 100644
--- 
a/test/native/src/test/java/org/apache/shardingsphere/test/natived/jdbc/mode/cluster/ZookeeperTest.java
+++ 
b/test/native/src/test/java/org/apache/shardingsphere/test/natived/jdbc/mode/cluster/ZookeeperTest.java
@@ -55,9 +55,9 @@ class ZookeeperTest {
     @EnabledInNativeImage
     void assertShardingInLocalTransactions() throws SQLException, IOException {
         try (
-                GenericContainer<?> zookeeperContainer = new 
GenericContainer<>(DockerImageName.parse("zookeeper:3.9.1-jre-17"))
+                GenericContainer<?> container = new 
GenericContainer<>(DockerImageName.parse("zookeeper:3.9.1-jre-17"))
                         .withCreateContainerCmdModifier(cmd -> 
cmd.withHostConfig(new HostConfig().withPortBindings(new 
PortBinding(Ports.Binding.bindPort(62372), new ExposedPort(2181)))))) {
-            zookeeperContainer.start();
+            container.start();
             beforeAll();
             DataSource dataSource = 
YamlShardingSphereDataSourceFactory.createDataSource(FileTestUtils.readFromFileURLString("test-native/yaml/mode/cluster/zookeeper.yaml"));
             testShardingService = new TestShardingService(dataSource);
diff --git 
a/test/native/src/test/resources/META-INF/native-image/shardingsphere-test-native-test-metadata/resource-config.json
 
b/test/native/src/test/resources/META-INF/native-image/shardingsphere-test-native-test-metadata/resource-config.json
index 67d2b4b3676..1e4da5ce950 100644
--- 
a/test/native/src/test/resources/META-INF/native-image/shardingsphere-test-native-test-metadata/resource-config.json
+++ 
b/test/native/src/test/resources/META-INF/native-image/shardingsphere-test-native-test-metadata/resource-config.json
@@ -1,7 +1,7 @@
 {
   "resources":{
   "includes":[{
-    
"condition":{"typeReachable":"org.apache.shardingsphere.test.natived.jdbc.databases.MSSQLServerTest"},
+    
"condition":{"typeReachable":"org.apache.shardingsphere.mode.metadata.NewMetaDataContextsFactory"},
     "pattern":"\\Qcontainer-license-acceptance.txt\\E"
   }, {
     "condition":{"typeReachable":"ch.qos.logback.core.util.Loader"},
@@ -36,6 +36,9 @@
   }, {
     
"condition":{"typeReachable":"org.apache.shardingsphere.test.natived.jdbc.mode.cluster.ZookeeperTest"},
     "pattern":"\\Qtest-native/yaml/mode/cluster/zookeeper.yaml\\E"
+  }, {
+    
"condition":{"typeReachable":"org.apache.shardingsphere.test.natived.jdbc.mode.cluster.EtcdTest"},
+    "pattern":"\\Qtest-native/yaml/mode/cluster/etcd.yaml\\E"
   }]},
   "bundles":[]
 }
diff --git 
a/test/native/src/test/resources/test-native/yaml/databases/mysql.yaml 
b/test/native/src/test/resources/test-native/yaml/databases/mysql.yaml
index 8853f2ef924..5f70ee338df 100644
--- a/test/native/src/test/resources/test-native/yaml/databases/mysql.yaml
+++ b/test/native/src/test/resources/test-native/yaml/databases/mysql.yaml
@@ -24,19 +24,19 @@ dataSources:
   ds_0:
     dataSourceClassName: com.zaxxer.hikari.HikariDataSource
     driverClassName: com.mysql.cj.jdbc.Driver
-    jdbcUrl: jdbc:mysql://localhost:65107/demo_ds_0
+    jdbcUrl: jdbc:mysql://localhost:60107/demo_ds_0
     username: root
     password: 123456
   ds_1:
     dataSourceClassName: com.zaxxer.hikari.HikariDataSource
     driverClassName: com.mysql.cj.jdbc.Driver
-    jdbcUrl: jdbc:mysql://localhost:65107/demo_ds_1
+    jdbcUrl: jdbc:mysql://localhost:60107/demo_ds_1
     username: root
     password: 123456
   ds_2:
     dataSourceClassName: com.zaxxer.hikari.HikariDataSource
     driverClassName: com.mysql.cj.jdbc.Driver
-    jdbcUrl: jdbc:mysql://localhost:65107/demo_ds_2
+    jdbcUrl: jdbc:mysql://localhost:60107/demo_ds_2
     username: root
     password: 123456
 
diff --git 
a/test/native/src/test/resources/test-native/yaml/mode/cluster/zookeeper.yaml 
b/test/native/src/test/resources/test-native/yaml/mode/cluster/etcd.yaml
similarity index 83%
copy from 
test/native/src/test/resources/test-native/yaml/mode/cluster/zookeeper.yaml
copy to test/native/src/test/resources/test-native/yaml/mode/cluster/etcd.yaml
index 6df3f7c47e8..76763d3438f 100644
--- 
a/test/native/src/test/resources/test-native/yaml/mode/cluster/zookeeper.yaml
+++ b/test/native/src/test/resources/test-native/yaml/mode/cluster/etcd.yaml
@@ -18,28 +18,28 @@
 mode:
   type: Cluster
   repository:
-    type: ZooKeeper
+    type: etcd
     props:
-      namespace: governance
-      server-lists: localhost:62372
+      namespace: governance-etcd-data-source
+      server-lists: http://localhost:62290
 
 dataSources:
   ds_0:
     dataSourceClassName: com.zaxxer.hikari.HikariDataSource
     driverClassName: org.h2.Driver
-    jdbcUrl: 
jdbc:h2:mem:cluster_zookeeper_ds_0;MODE=MYSQL;IGNORECASE=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE
+    jdbcUrl: 
jdbc:h2:mem:cluster_etcd_ds_0;MODE=MYSQL;IGNORECASE=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE
     username: root
     password: 123456
   ds_1:
     dataSourceClassName: com.zaxxer.hikari.HikariDataSource
     driverClassName: org.h2.Driver
-    jdbcUrl: 
jdbc:h2:mem:cluster_zookeeper_ds_1;MODE=MYSQL;IGNORECASE=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE
+    jdbcUrl: 
jdbc:h2:mem:cluster_etcd_ds_1;MODE=MYSQL;IGNORECASE=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE
     username: root
     password: 123456
   ds_2:
     dataSourceClassName: com.zaxxer.hikari.HikariDataSource
     driverClassName: org.h2.Driver
-    jdbcUrl: 
jdbc:h2:mem:cluster_zookeeper_ds_2;MODE=MYSQL;IGNORECASE=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE
+    jdbcUrl: 
jdbc:h2:mem:cluster_etcd_ds_2;MODE=MYSQL;IGNORECASE=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE
     username: root
     password: 123456
 
diff --git 
a/test/native/src/test/resources/test-native/yaml/mode/cluster/zookeeper.yaml 
b/test/native/src/test/resources/test-native/yaml/mode/cluster/zookeeper.yaml
index 6df3f7c47e8..fbf8d05b50a 100644
--- 
a/test/native/src/test/resources/test-native/yaml/mode/cluster/zookeeper.yaml
+++ 
b/test/native/src/test/resources/test-native/yaml/mode/cluster/zookeeper.yaml
@@ -20,7 +20,7 @@ mode:
   repository:
     type: ZooKeeper
     props:
-      namespace: governance
+      namespace: governance-zookeeper-data-source
       server-lists: localhost:62372
 
 dataSources:


Reply via email to