diff --git a/seata-spring-boot-starter/pom.xml b/seata-spring-boot-starter/pom.xml index 24f449166b0..45462b3ecaa 100644 --- a/seata-spring-boot-starter/pom.xml +++ b/seata-spring-boot-starter/pom.xml @@ -71,6 +71,23 @@ rocketmq-client true + + org.springframework.boot + spring-boot-test + + + ch.qos.logback + logback-classic + + + test + + + org.apache.seata + seata-mock-server + ${project.version} + test + diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/AutoConfigurationBaseTest.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/AutoConfigurationBaseTest.java new file mode 100644 index 00000000000..196c38a1383 --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/AutoConfigurationBaseTest.java @@ -0,0 +1,23 @@ +package org.apache.seata.spring.boot.autoconfigure; + +import org.apache.seata.config.ConfigurationFactory; +import org.apache.seata.mockserver.MockServer; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.springframework.context.annotation.Configuration; + +@Configuration(proxyBeanMethods = false) +public class AutoConfigurationBaseTest { + public static final int MOCK_SERVER_PORT = 8099; + + @BeforeAll + public static void before() { + ConfigurationFactory.reload(); + MockServer.start(MOCK_SERVER_PORT); + } + + @AfterAll + public static void after() { + MockServer.close(); + } +} diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/PropertyBeanPostProcessorTest.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/PropertyBeanPostProcessorTest.java index f0148ab8a1e..a162e12406b 100644 --- a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/PropertyBeanPostProcessorTest.java +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/PropertyBeanPostProcessorTest.java @@ -16,12 +16,9 @@ */ package org.apache.seata.spring.boot.autoconfigure; -import org.apache.seata.spring.boot.autoconfigure.properties.SeataProperties; -import org.apache.seata.spring.boot.autoconfigure.properties.SpringCloudAlibabaConfiguration; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -35,18 +32,6 @@ public static void initContext() { } - @Bean - public SeataProperties seataProperties() { - SeataProperties seataProperties = new SeataProperties(); - seataProperties.setApplicationId("test-id"); - return seataProperties; - } - - @Bean - public SpringCloudAlibabaConfiguration springCloudAlibabaConfiguration() { - return new SpringCloudAlibabaConfiguration(); - } - @AfterAll public static void closeContext() { context.close(); diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataAutoConfigurationTest.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataAutoConfigurationTest.java new file mode 100644 index 00000000000..f894d4647b6 --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataAutoConfigurationTest.java @@ -0,0 +1,52 @@ +package org.apache.seata.spring.boot.autoconfigure; + + +import org.apache.seata.spring.annotation.GlobalTransactionScanner; +import org.apache.seata.spring.boot.autoconfigure.properties.SeataProperties; +import org.apache.seata.spring.boot.autoconfigure.properties.SpringCloudAlibabaConfiguration; +import org.apache.seata.spring.boot.autoconfigure.provider.SpringApplicationContextProvider; +import org.apache.seata.tm.api.FailureHandler; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.apache.seata.common.Constants.BEAN_NAME_SPRING_APPLICATION_CONTEXT_PROVIDER; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {SeataAutoConfigurationTest.TestConfig.class, SeataAutoConfiguration.class}) +@Import({SeataProperties.class,SpringCloudAlibabaConfiguration.class}) +public class SeataAutoConfigurationTest extends AutoConfigurationBaseTest{ + + @Autowired + private GlobalTransactionScanner scanner; + + @Autowired + private FailureHandler failureHandler; + + @Test + void testSeataAutoConfiguration() { + assertNotNull(failureHandler); + assertNotNull(scanner); + assertEquals(scanner.getTxServiceGroup(), "default_tx_group"); + } + + @Configuration + static class TestConfig { + + @Bean(BEAN_NAME_SPRING_APPLICATION_CONTEXT_PROVIDER) + @ConditionalOnMissingBean(name = {BEAN_NAME_SPRING_APPLICATION_CONTEXT_PROVIDER}) + public org.apache.seata.spring.boot.autoconfigure.provider.SpringApplicationContextProvider springApplicationContextProvider() { + return new SpringApplicationContextProvider(); + } + + } +} \ No newline at end of file diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataDataSourceAutoConfigurationTest.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataDataSourceAutoConfigurationTest.java new file mode 100644 index 00000000000..276ad2a5cf6 --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataDataSourceAutoConfigurationTest.java @@ -0,0 +1,40 @@ +package org.apache.seata.spring.boot.autoconfigure; + +import org.apache.seata.spring.annotation.datasource.SeataAutoDataSourceProxyCreator; +import org.apache.seata.spring.boot.autoconfigure.mock.MockDataSource; +import org.apache.seata.spring.boot.autoconfigure.properties.SeataProperties; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.sql.DataSource; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {SeataDataSourceAutoConfigurationTest.TestConfig.class,SeataDataSourceAutoConfiguration.class}) +public class SeataDataSourceAutoConfigurationTest extends AutoConfigurationBaseTest{ + + @Autowired + private SeataAutoDataSourceProxyCreator seataAutoDataSourceProxyCreator; + + @Test + public void assertDataSourceProxyNotNull() { + assertNotNull(seataAutoDataSourceProxyCreator); + } + + @Configuration + @SpringBootApplication + static class TestConfig { + @Bean + public DataSource mockDataSource() { + return new MockDataSource(); + } + } + +} diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataSagaAutoConfigurationTest.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataSagaAutoConfigurationTest.java new file mode 100644 index 00000000000..3bea91736e1 --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataSagaAutoConfigurationTest.java @@ -0,0 +1,78 @@ +package org.apache.seata.spring.boot.autoconfigure; + +import org.apache.seata.saga.engine.StateMachineConfig; +import org.apache.seata.saga.engine.StateMachineEngine; +import org.apache.seata.saga.engine.config.DbStateMachineConfig; +import org.apache.seata.spring.boot.autoconfigure.mock.MockDataSource; +import org.apache.seata.spring.boot.autoconfigure.properties.SagaAsyncThreadPoolProperties; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; +import javax.sql.DataSource; +import java.sql.SQLException; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ThreadPoolExecutor; + +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {SeataSagaAutoConfigurationTest.TestConfig.class, SeataSagaAutoConfiguration.class}) +public class SeataSagaAutoConfigurationTest extends AutoConfigurationBaseTest { + + @Autowired + private StateMachineConfig stateMachineConfig; + + @Autowired + private StateMachineEngine stateMachineEngine; + + @Resource(name = "seataSagaRejectedExecutionHandler") + private RejectedExecutionHandler rejectedExecutionHandler; + + @Autowired + private ThreadPoolExecutor threadPoolExecutor; + + + @Test + public void assertDbStateMachineConfigNotNull() { + assertNotNull(stateMachineConfig); + Assertions.assertEquals(((DbStateMachineConfig) stateMachineConfig).getApplicationId(), "test"); + } + + @Test + public void assertStateMachineEngine() { + assertNotNull(stateMachineEngine); + } + + @Test + public void testSagaAsyncThreadPoolExecutorConfiguration() { + assertNotNull(rejectedExecutionHandler); + assertNotNull(threadPoolExecutor); + Assertions.assertEquals(threadPoolExecutor.getCorePoolSize(), 1); + Assertions.assertEquals(threadPoolExecutor.getMaximumPoolSize(), 20); + } + + @Configuration + static class TestConfig { + @Bean + public DataSource mockDataSource() { + return new MockDataSource(); + } + + @Bean + public SagaAsyncThreadPoolProperties mockSagaAsyncThreadPoolProperties() { + SagaAsyncThreadPoolProperties sagaAsyncThreadPoolProperties = new SagaAsyncThreadPoolProperties(); + sagaAsyncThreadPoolProperties.setCorePoolSize(1); + sagaAsyncThreadPoolProperties.setMaxPoolSize(20); + sagaAsyncThreadPoolProperties.setKeepAliveTime(60); + return sagaAsyncThreadPoolProperties; + } + } + +} \ No newline at end of file diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockBlob.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockBlob.java new file mode 100644 index 00000000000..9d520ede2c3 --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockBlob.java @@ -0,0 +1,84 @@ +/* + * 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.seata.spring.boot.autoconfigure.mock; + +import java.io.InputStream; +import java.io.OutputStream; +import java.sql.Blob; +import java.sql.SQLException; + + +public class MockBlob implements Blob { + + public MockBlob() { + } + + @Override + public long length() throws SQLException { + return 0; + } + + @Override + public byte[] getBytes(long pos, int length) throws SQLException { + return new byte[0]; + } + + @Override + public InputStream getBinaryStream() throws SQLException { + return null; + } + + @Override + public long position(byte[] pattern, long start) throws SQLException { + return 0; + } + + @Override + public long position(Blob pattern, long start) throws SQLException { + return 0; + } + + @Override + public int setBytes(long pos, byte[] bytes) throws SQLException { + return 0; + } + + @Override + public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException { + return 0; + } + + @Override + public OutputStream setBinaryStream(long pos) throws SQLException { + return null; + } + + @Override + public void truncate(long len) throws SQLException { + + } + + @Override + public void free() throws SQLException { + + } + + @Override + public InputStream getBinaryStream(long pos, long length) throws SQLException { + return null; + } +} diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockClob.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockClob.java new file mode 100644 index 00000000000..bedecdfd455 --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockClob.java @@ -0,0 +1,90 @@ +/* + * 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.seata.spring.boot.autoconfigure.mock; + +import java.io.*; +import java.sql.Clob; +import java.sql.SQLException; + + +public class MockClob implements Clob { + + @Override + public long length() throws SQLException { + return 0; + } + + @Override + public String getSubString(long pos, int length) throws SQLException { + return null; + } + + @Override + public Reader getCharacterStream() throws SQLException { + return new CharArrayReader(new char[0]); + } + + @Override + public InputStream getAsciiStream() throws SQLException { + return new ByteArrayInputStream(new byte[0]); + } + + @Override + public long position(String searchstr, long start) throws SQLException { + return 0; + } + + @Override + public long position(Clob searchstr, long start) throws SQLException { + return 0; + } + + @Override + public int setString(long pos, String str) throws SQLException { + return 0; + } + + @Override + public int setString(long pos, String str, int offset, int len) throws SQLException { + return 0; + } + + @Override + public OutputStream setAsciiStream(long pos) throws SQLException { + return null; + } + + @Override + public Writer setCharacterStream(long pos) throws SQLException { + return null; + } + + @Override + public void truncate(long len) throws SQLException { + + } + + @Override + public void free() throws SQLException { + + } + + @Override + public Reader getCharacterStream(long pos, long length) throws SQLException { + return null; + } +} diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockConnection.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockConnection.java new file mode 100644 index 00000000000..86bc92bc04c --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockConnection.java @@ -0,0 +1,71 @@ +/* + * 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.seata.spring.boot.autoconfigure.mock; + +import java.sql.DatabaseMetaData; +import java.sql.SQLException; +import java.sql.Savepoint; +import java.util.Properties; + +/** + * Mock connection + */ +public class MockConnection extends com.alibaba.druid.mock.MockConnection { + + private MockDriver mockDriver; + + /** + * Instantiate a new MockConnection + * @param driver + * @param url + * @param connectProperties + */ + public MockConnection(MockDriver driver, String url, Properties connectProperties) { + super(driver, url, connectProperties); + this.mockDriver = driver; + } + + @Override + public DatabaseMetaData getMetaData() throws SQLException { + return new MockDatabaseMetaData(this); + } + + @Override + public void releaseSavepoint(Savepoint savepoint) throws SQLException { + + } + + @Override + public void rollback() { + + } + + @Override + public void rollback(Savepoint savepoint) { + + } + + @Override + public MockDriver getDriver() { + return mockDriver; + } + + @Override + public String getSchema() { + return null; + } +} diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockConnectionProxy.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockConnectionProxy.java new file mode 100644 index 00000000000..dfdb1314cb2 --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockConnectionProxy.java @@ -0,0 +1,42 @@ +/* + * 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.seata.spring.boot.autoconfigure.mock; + +import org.apache.seata.rm.datasource.ConnectionProxy; +import org.apache.seata.rm.datasource.DataSourceProxy; + +import java.sql.Connection; +import java.sql.SQLException; + + +public class MockConnectionProxy extends ConnectionProxy { + /** + * Instantiates a new Connection proxy. + * + * @param dataSourceProxy the data source proxy + * @param targetConnection the target connection + */ + public MockConnectionProxy(DataSourceProxy dataSourceProxy, + Connection targetConnection) { + super(dataSourceProxy, targetConnection); + } + + @Override + public void checkLock(String lockKeys) throws SQLException { + //do nothing + } +} diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockDataSource.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockDataSource.java new file mode 100644 index 00000000000..55db6408cb0 --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockDataSource.java @@ -0,0 +1,72 @@ +/* + * 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.seata.spring.boot.autoconfigure.mock; + +import javax.sql.DataSource; +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.util.logging.Logger; + + +public class MockDataSource implements DataSource { + @Override + public Connection getConnection() throws SQLException { + return new MockConnection(new MockDriver(), "jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true", null); + } + + @Override + public Connection getConnection(String username, String password) throws SQLException { + return null; + } + + @Override + public T unwrap(Class iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } + + @Override + public PrintWriter getLogWriter() throws SQLException { + return null; + } + + @Override + public void setLogWriter(PrintWriter out) throws SQLException { + + } + + @Override + public void setLoginTimeout(int seconds) throws SQLException { + + } + + @Override + public int getLoginTimeout() throws SQLException { + return 0; + } + + @Override + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + return null; + } +} diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockDatabaseMetaData.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockDatabaseMetaData.java new file mode 100644 index 00000000000..b5f6b341b4a --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockDatabaseMetaData.java @@ -0,0 +1,1019 @@ +/* + * 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.seata.spring.boot.autoconfigure.mock; + +import java.sql.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + */ +public class MockDatabaseMetaData implements DatabaseMetaData { + + protected MockConnection connection; + + private static List columnMetaColumnLabels = Arrays.asList( + "TABLE_CAT", + "TABLE_SCHEM", + "TABLE_NAME", + "COLUMN_NAME", + "DATA_TYPE", + "TYPE_NAME", + "COLUMN_SIZE", + "DECIMAL_DIGITS", + "NUM_PREC_RADIX", + "NULLABLE", + "REMARKS", + "COLUMN_DEF", + "SQL_DATA_TYPE", + "SQL_DATETIME_SUB", + "CHAR_OCTET_LENGTH", + "ORDINAL_POSITION", + "IS_NULLABLE", + "IS_AUTOINCREMENT" + ); + + private static List indexMetaColumnLabels = Arrays.asList( + "INDEX_NAME", + "COLUMN_NAME", + "NON_UNIQUE", + "INDEX_QUALIFIER", + "TYPE", + "ORDINAL_POSITION", + "ASC_OR_DESC", + "CARDINALITY" + ); + + private static List pkMetaColumnLabels = Arrays.asList( + "PK_NAME" + ); + + private static List mockColumnsMetasLabels = Arrays.asList( + "SCOPE", + "COLUMN_NAME", + "DATA_TYPE", + "TYPE_NAME", + "COLUMN_SIZE", + "BUFFER_LENGTH", + "DECIMAL_DIGITS", + "PSEUDO_COLUMN" + ); + + private static List tableMetaColumnLabels = Arrays.asList( + "TABLE_CAT", + "TABLE_SCHEM", + "TABLE_NAME" + ); + + private Object[][] columnsMetasReturnValue; + + private Object[][] indexMetasReturnValue; + + private Object[][] pkMetasReturnValue; + + private Object[][] mockColumnsMetasReturnValue; + + private Object[][] mockTableMetasReturnValue; + + /** + * Instantiate a new MockDatabaseMetaData + */ + public MockDatabaseMetaData(MockConnection connection) { + this.connection = connection; + this.columnsMetasReturnValue = connection.getDriver().getMockColumnsMetasReturnValue(); + this.indexMetasReturnValue = connection.getDriver().getMockIndexMetasReturnValue(); + this.pkMetasReturnValue = connection.getDriver().getMockPkMetasReturnValue(); + this.mockColumnsMetasReturnValue = connection.getDriver().getMockOnUpdateColumnsReturnValue(); + this.mockTableMetasReturnValue = connection.getDriver().getMockTableMetasReturnValue(); + } + + @Override + public boolean allProceduresAreCallable() throws SQLException { + return false; + } + + @Override + public boolean allTablesAreSelectable() throws SQLException { + return false; + } + + @Override + public String getURL() throws SQLException { + return this.connection.getUrl(); + } + + @Override + public String getUserName() throws SQLException { + return this.connection.getConnectProperties().getProperty("user"); + } + + @Override + public boolean isReadOnly() throws SQLException { + return false; + } + + @Override + public boolean nullsAreSortedHigh() throws SQLException { + return false; + } + + @Override + public boolean nullsAreSortedLow() throws SQLException { + return false; + } + + @Override + public boolean nullsAreSortedAtStart() throws SQLException { + return false; + } + + @Override + public boolean nullsAreSortedAtEnd() throws SQLException { + return false; + } + + @Override + public String getDatabaseProductName() throws SQLException { + return null; + } + + @Override + public String getDatabaseProductVersion() throws SQLException { + return null; + } + + @Override + public String getDriverName() throws SQLException { + return null; + } + + @Override + public String getDriverVersion() throws SQLException { + return null; + } + + @Override + public int getDriverMajorVersion() { + return 0; + } + + @Override + public int getDriverMinorVersion() { + return 0; + } + + @Override + public boolean usesLocalFiles() throws SQLException { + return false; + } + + @Override + public boolean usesLocalFilePerTable() throws SQLException { + return false; + } + + @Override + public boolean supportsMixedCaseIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesUpperCaseIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesLowerCaseIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesMixedCaseIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { + return false; + } + + @Override + public String getIdentifierQuoteString() throws SQLException { + return null; + } + + @Override + public String getSQLKeywords() throws SQLException { + return null; + } + + @Override + public String getNumericFunctions() throws SQLException { + return null; + } + + @Override + public String getStringFunctions() throws SQLException { + return null; + } + + @Override + public String getSystemFunctions() throws SQLException { + return null; + } + + @Override + public String getTimeDateFunctions() throws SQLException { + return null; + } + + @Override + public String getSearchStringEscape() throws SQLException { + return null; + } + + @Override + public String getExtraNameCharacters() throws SQLException { + return null; + } + + @Override + public boolean supportsAlterTableWithAddColumn() throws SQLException { + return false; + } + + @Override + public boolean supportsAlterTableWithDropColumn() throws SQLException { + return false; + } + + @Override + public boolean supportsColumnAliasing() throws SQLException { + return false; + } + + @Override + public boolean nullPlusNonNullIsNull() throws SQLException { + return false; + } + + @Override + public boolean supportsConvert() throws SQLException { + return false; + } + + @Override + public boolean supportsConvert(int fromType, int toType) throws SQLException { + return false; + } + + @Override + public boolean supportsTableCorrelationNames() throws SQLException { + return false; + } + + @Override + public boolean supportsDifferentTableCorrelationNames() throws SQLException { + return false; + } + + @Override + public boolean supportsExpressionsInOrderBy() throws SQLException { + return false; + } + + @Override + public boolean supportsOrderByUnrelated() throws SQLException { + return false; + } + + @Override + public boolean supportsGroupBy() throws SQLException { + return false; + } + + @Override + public boolean supportsGroupByUnrelated() throws SQLException { + return false; + } + + @Override + public boolean supportsGroupByBeyondSelect() throws SQLException { + return false; + } + + @Override + public boolean supportsLikeEscapeClause() throws SQLException { + return false; + } + + @Override + public boolean supportsMultipleResultSets() throws SQLException { + return false; + } + + @Override + public boolean supportsMultipleTransactions() throws SQLException { + return false; + } + + @Override + public boolean supportsNonNullableColumns() throws SQLException { + return false; + } + + @Override + public boolean supportsMinimumSQLGrammar() throws SQLException { + return false; + } + + @Override + public boolean supportsCoreSQLGrammar() throws SQLException { + return false; + } + + @Override + public boolean supportsExtendedSQLGrammar() throws SQLException { + return false; + } + + @Override + public boolean supportsANSI92EntryLevelSQL() throws SQLException { + return false; + } + + @Override + public boolean supportsANSI92IntermediateSQL() throws SQLException { + return false; + } + + @Override + public boolean supportsANSI92FullSQL() throws SQLException { + return false; + } + + @Override + public boolean supportsIntegrityEnhancementFacility() throws SQLException { + return false; + } + + @Override + public boolean supportsOuterJoins() throws SQLException { + return false; + } + + @Override + public boolean supportsFullOuterJoins() throws SQLException { + return false; + } + + @Override + public boolean supportsLimitedOuterJoins() throws SQLException { + return false; + } + + @Override + public String getSchemaTerm() throws SQLException { + return null; + } + + @Override + public String getProcedureTerm() throws SQLException { + return null; + } + + @Override + public String getCatalogTerm() throws SQLException { + return null; + } + + @Override + public boolean isCatalogAtStart() throws SQLException { + return false; + } + + @Override + public String getCatalogSeparator() throws SQLException { + return null; + } + + @Override + public boolean supportsSchemasInDataManipulation() throws SQLException { + return false; + } + + @Override + public boolean supportsSchemasInProcedureCalls() throws SQLException { + return false; + } + + @Override + public boolean supportsSchemasInTableDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsSchemasInIndexDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsCatalogsInDataManipulation() throws SQLException { + return false; + } + + @Override + public boolean supportsCatalogsInProcedureCalls() throws SQLException { + return false; + } + + @Override + public boolean supportsCatalogsInTableDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsCatalogsInIndexDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsPositionedDelete() throws SQLException { + return false; + } + + @Override + public boolean supportsPositionedUpdate() throws SQLException { + return false; + } + + @Override + public boolean supportsSelectForUpdate() throws SQLException { + return false; + } + + @Override + public boolean supportsStoredProcedures() throws SQLException { + return false; + } + + @Override + public boolean supportsSubqueriesInComparisons() throws SQLException { + return false; + } + + @Override + public boolean supportsSubqueriesInExists() throws SQLException { + return false; + } + + @Override + public boolean supportsSubqueriesInIns() throws SQLException { + return false; + } + + @Override + public boolean supportsSubqueriesInQuantifieds() throws SQLException { + return false; + } + + @Override + public boolean supportsCorrelatedSubqueries() throws SQLException { + return false; + } + + @Override + public boolean supportsUnion() throws SQLException { + return false; + } + + @Override + public boolean supportsUnionAll() throws SQLException { + return false; + } + + @Override + public boolean supportsOpenCursorsAcrossCommit() throws SQLException { + return false; + } + + @Override + public boolean supportsOpenCursorsAcrossRollback() throws SQLException { + return false; + } + + @Override + public boolean supportsOpenStatementsAcrossCommit() throws SQLException { + return false; + } + + @Override + public boolean supportsOpenStatementsAcrossRollback() throws SQLException { + return false; + } + + @Override + public int getMaxBinaryLiteralLength() throws SQLException { + return 0; + } + + @Override + public int getMaxCharLiteralLength() throws SQLException { + return 0; + } + + @Override + public int getMaxColumnNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxColumnsInGroupBy() throws SQLException { + return 0; + } + + @Override + public int getMaxColumnsInIndex() throws SQLException { + return 0; + } + + @Override + public int getMaxColumnsInOrderBy() throws SQLException { + return 0; + } + + @Override + public int getMaxColumnsInSelect() throws SQLException { + return 0; + } + + @Override + public int getMaxColumnsInTable() throws SQLException { + return 0; + } + + @Override + public int getMaxConnections() throws SQLException { + return 0; + } + + @Override + public int getMaxCursorNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxIndexLength() throws SQLException { + return 0; + } + + @Override + public int getMaxSchemaNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxProcedureNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxCatalogNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxRowSize() throws SQLException { + return 0; + } + + @Override + public boolean doesMaxRowSizeIncludeBlobs() throws SQLException { + return false; + } + + @Override + public int getMaxStatementLength() throws SQLException { + return 0; + } + + @Override + public int getMaxStatements() throws SQLException { + return 0; + } + + @Override + public int getMaxTableNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxTablesInSelect() throws SQLException { + return 0; + } + + @Override + public int getMaxUserNameLength() throws SQLException { + return 0; + } + + @Override + public int getDefaultTransactionIsolation() throws SQLException { + return 0; + } + + @Override + public boolean supportsTransactions() throws SQLException { + return false; + } + + @Override + public boolean supportsTransactionIsolationLevel(int level) throws SQLException { + return false; + } + + @Override + public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { + return false; + } + + @Override + public boolean supportsDataManipulationTransactionsOnly() throws SQLException { + return false; + } + + @Override + public boolean dataDefinitionCausesTransactionCommit() throws SQLException { + return false; + } + + @Override + public boolean dataDefinitionIgnoredInTransactions() throws SQLException { + return false; + } + + @Override + public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) + throws SQLException { + return null; + } + + @Override + public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, + String columnNamePattern) throws SQLException { + return null; + } + + @Override + public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) + throws SQLException { + return new MockResultSet(this.connection.createStatement()) + .mockResultSet(tableMetaColumnLabels, mockTableMetasReturnValue); + } + + @Override + public ResultSet getSchemas() throws SQLException { + return null; + } + + @Override + public ResultSet getCatalogs() throws SQLException { + return null; + } + + @Override + public ResultSet getTableTypes() throws SQLException { + return null; + } + + @Override + public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) + throws SQLException { + List metas = new ArrayList<>(); + for (Object[] meta : columnsMetasReturnValue) { + if (tableNamePattern.equals(meta[2].toString())) { + metas.add(meta); + } + } + if(metas.isEmpty()){ + metas = Arrays.asList(columnsMetasReturnValue); + } + return new MockResultSet(this.connection.createStatement()) + .mockResultSet(columnMetaColumnLabels, metas.toArray(new Object[0][])); + } + + @Override + public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) + throws SQLException { + return null; + } + + @Override + public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) + throws SQLException { + return null; + } + + @Override + public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) + throws SQLException { + return null; + } + + @Override + public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException { + return new MockResultSet(this.connection.createStatement()).mockResultSet(mockColumnsMetasLabels, mockColumnsMetasReturnValue); + } + + @Override + public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException { + return new MockResultSet(this.connection.createStatement()).mockResultSet(pkMetaColumnLabels, pkMetasReturnValue); + } + + @Override + public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException { + return null; + } + + @Override + public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException { + return null; + } + + @Override + public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, + String foreignCatalog, String foreignSchema, String foreignTable) + throws SQLException { + return null; + } + + @Override + public ResultSet getTypeInfo() throws SQLException { + return null; + } + + @Override + public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) + throws SQLException { + return new MockResultSet(this.connection.createStatement()) + .mockResultSet(indexMetaColumnLabels, indexMetasReturnValue); + } + + @Override + public boolean supportsResultSetType(int type) throws SQLException { + return false; + } + + @Override + public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException { + return false; + } + + @Override + public boolean ownUpdatesAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean ownDeletesAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean ownInsertsAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean othersUpdatesAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean othersDeletesAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean othersInsertsAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean updatesAreDetected(int type) throws SQLException { + return false; + } + + @Override + public boolean deletesAreDetected(int type) throws SQLException { + return false; + } + + @Override + public boolean insertsAreDetected(int type) throws SQLException { + return false; + } + + @Override + public boolean supportsBatchUpdates() throws SQLException { + return false; + } + + @Override + public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) + throws SQLException { + return null; + } + + @Override + public Connection getConnection() throws SQLException { + return connection; + } + + @Override + public boolean supportsSavepoints() throws SQLException { + return true; + } + + @Override + public boolean supportsNamedParameters() throws SQLException { + return false; + } + + @Override + public boolean supportsMultipleOpenResults() throws SQLException { + return false; + } + + @Override + public boolean supportsGetGeneratedKeys() throws SQLException { + return false; + } + + @Override + public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException { + return null; + } + + @Override + public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { + return null; + } + + @Override + public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, + String attributeNamePattern) throws SQLException { + return null; + } + + @Override + public boolean supportsResultSetHoldability(int holdability) throws SQLException { + return false; + } + + @Override + public int getResultSetHoldability() throws SQLException { + return 0; + } + + @Override + public int getDatabaseMajorVersion() throws SQLException { + return 0; + } + + @Override + public int getDatabaseMinorVersion() throws SQLException { + return 0; + } + + @Override + public int getJDBCMajorVersion() throws SQLException { + return 0; + } + + @Override + public int getJDBCMinorVersion() throws SQLException { + return 0; + } + + @Override + public int getSQLStateType() throws SQLException { + return 0; + } + + @Override + public boolean locatorsUpdateCopy() throws SQLException { + return false; + } + + @Override + public boolean supportsStatementPooling() throws SQLException { + return false; + } + + @Override + public RowIdLifetime getRowIdLifetime() throws SQLException { + return null; + } + + @Override + public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { + return null; + } + + @Override + public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { + return false; + } + + @Override + public boolean autoCommitFailureClosesAllResultSets() throws SQLException { + return false; + } + + @Override + public ResultSet getClientInfoProperties() throws SQLException { + return null; + } + + @Override + public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) + throws SQLException { + return null; + } + + @Override + public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, + String columnNamePattern) throws SQLException { + return null; + } + + @Override + public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, + String columnNamePattern) throws SQLException { + return null; + } + + @Override + public boolean generatedKeyAlwaysReturned() throws SQLException { + return false; + } + + @Override + public T unwrap(Class iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } + + public void setColumnsMetasReturnValue(Object[][] columnsMetasReturnValue) { + this.columnsMetasReturnValue = columnsMetasReturnValue; + } + + public void setIndexMetasReturnValue(Object[][] indexMetasReturnValue) { + this.indexMetasReturnValue = indexMetasReturnValue; + } +} diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockDriver.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockDriver.java new file mode 100644 index 00000000000..c56442b12b7 --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockDriver.java @@ -0,0 +1,223 @@ +/* + * 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.seata.spring.boot.autoconfigure.mock; + +import com.alibaba.druid.mock.MockStatementBase; +import com.alibaba.druid.mock.handler.MockExecuteHandler; +import com.google.common.collect.Lists; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Properties; + +/** + * Mock driver + */ +public class MockDriver extends com.alibaba.druid.mock.MockDriver { + + private static final Logger LOGGER = LoggerFactory.getLogger(MockDriver.class); + + /** + * the mock column labels of return value + */ + private List mockReturnValueColumnLabels; + + /** + * the mock value of return value + */ + private Object[][] mockReturnValue; + + /** + * the mock value of columns meta return value + */ + private Object[][] mockColumnsMetasReturnValue; + + /** + * the mock value of index meta return value + */ + private Object[][] mockIndexMetasReturnValue; + + /** + * the mock value of pk meta return value + */ + private Object[][] mockPkMetasReturnValue; + + /** + * the mock value of table meta return value + */ + private Object[][] mockTableMetasReturnValue; + + /** + * + */ + private Object[][] mockOnUpdateColumnsReturnValue; + + /** + * the mock execute handler + */ + private MockExecuteHandler mockExecuteHandler; + + public MockDriver() { + this(Lists.newArrayList(), new Object[][]{}, new Object[][]{}, new Object[][]{}, new Object[][]{}); + } + + public MockDriver(Object[][] mockColumnsMetasReturnValue, Object[][] mockIndexMetasReturnValue) { + this(Lists.newArrayList(), new Object[][]{}, mockColumnsMetasReturnValue, mockIndexMetasReturnValue, new Object[][]{}, new Object[][]{}); + } + + public MockDriver(Object[][] mockColumnsMetasReturnValue, Object[][] mockIndexMetasReturnValue, Object[][] mockPkMetasReturnValue) { + this(Lists.newArrayList(), new Object[][]{}, mockColumnsMetasReturnValue, mockIndexMetasReturnValue, mockPkMetasReturnValue, new Object[][]{}); + } + + public MockDriver(Object[][] mockColumnsMetasReturnValue, Object[][] mockIndexMetasReturnValue, Object[][] mockPkMetasReturnValue, Object[][] mockTableMetasReturnValue) { + this(Lists.newArrayList(), new Object[][]{}, mockColumnsMetasReturnValue, mockIndexMetasReturnValue, mockPkMetasReturnValue, mockTableMetasReturnValue); + } + + public MockDriver(List mockReturnValueColumnLabels, Object[][] mockReturnValue, Object[][] mockColumnsMetasReturnValue, Object[][] mockIndexMetasReturnValue) { + this(mockReturnValueColumnLabels, mockReturnValue, mockColumnsMetasReturnValue, mockIndexMetasReturnValue, new Object[][]{}, new Object[][]{}); + } + + public MockDriver(List mockReturnValueColumnLabels, Object[][] mockReturnValue, Object[][] mockColumnsMetasReturnValue, Object[][] mockIndexMetasReturnValue, Object[][] mockPkMetasReturnValue) { + this(mockReturnValueColumnLabels, mockReturnValue, mockColumnsMetasReturnValue, mockIndexMetasReturnValue, mockPkMetasReturnValue, new Object[][]{}, new Object[][]{}); + } + + public MockDriver(List mockReturnValueColumnLabels, Object[][] mockReturnValue, Object[][] mockColumnsMetasReturnValue, Object[][] mockIndexMetasReturnValue, Object[][] mockPkMetasReturnValue, Object[][] mockTableMetasReturnValue) { + this(mockReturnValueColumnLabels, mockReturnValue, mockColumnsMetasReturnValue, mockIndexMetasReturnValue, mockPkMetasReturnValue, new Object[][]{}, mockTableMetasReturnValue); + } + + /** + * Instantiate a new MockDriver + */ + public MockDriver(List mockReturnValueColumnLabels, Object[][] mockReturnValue, Object[][] mockColumnsMetasReturnValue, Object[][] mockIndexMetasReturnValue, Object[][] mockPkMetasReturnValue, Object[][] mockOnUpdateColumnsReturnValue, Object[][] mockTableMetasReturnValue) { + this.mockReturnValueColumnLabels = mockReturnValueColumnLabels; + this.mockReturnValue = mockReturnValue; + this.mockColumnsMetasReturnValue = mockColumnsMetasReturnValue; + this.mockIndexMetasReturnValue = mockIndexMetasReturnValue; + this.mockPkMetasReturnValue = mockPkMetasReturnValue; + this.setMockExecuteHandler(new MockExecuteHandlerImpl(mockReturnValueColumnLabels, mockReturnValue, mockColumnsMetasReturnValue)); + this.mockOnUpdateColumnsReturnValue = mockOnUpdateColumnsReturnValue; + this.mockTableMetasReturnValue = mockTableMetasReturnValue; + } + + /** + * Instantiate a new MockConnection + * @param driver + * @param url + * @param connectProperties + * @return + */ + @Override + public MockConnection createMockConnection(com.alibaba.druid.mock.MockDriver driver, String url, + Properties connectProperties) { + return new MockConnection(this, url, connectProperties); + } + + @Override + public ResultSet executeQuery(MockStatementBase stmt, String sql) throws SQLException { + if ("show rule".equals(sql)) { + throw new SQLException("throw exception for polardb-x test sql"); + } + return this.mockExecuteHandler.executeQuery(stmt, sql); + } + + public MockPreparedStatement createSeataMockPreparedStatement(MockConnection conn, String sql) { + return new MockPreparedStatement(conn, sql); + } + + /** + * mock the return value + * @return + */ + public Object[][] getMockReturnValue() { + return mockReturnValue; + } + + /** + * get the return value + * @param mockReturnValue + */ + public void setMockReturnValue(Object[][] mockReturnValue) { + this.mockReturnValue = mockReturnValue == null ? new Object[][]{} : mockReturnValue; + } + + /** + * mock the return value of columns meta + * @param mockColumnsMetasReturnValue + */ + public void setMockColumnsMetasReturnValue(Object[][] mockColumnsMetasReturnValue) { + this.mockColumnsMetasReturnValue = mockColumnsMetasReturnValue == null ? new Object[][]{} : mockColumnsMetasReturnValue; + } + + /** + * get the return value of columns meta + * @return + */ + public Object[][] getMockColumnsMetasReturnValue() { + return mockColumnsMetasReturnValue; + } + + /** + * mock the return value of index meta + * @param mockIndexMetasReturnValue + */ + public void setMockIndexMetasReturnValue(Object[][] mockIndexMetasReturnValue) { + this.mockIndexMetasReturnValue = mockIndexMetasReturnValue == null ? new Object[][]{} : mockIndexMetasReturnValue; + } + + /** + * get the return value of index meta + * @return + */ + public Object[][] getMockIndexMetasReturnValue() { + return mockIndexMetasReturnValue; + } + + /** + * get the return value of pk meta + * @return + */ + public Object[][] getMockPkMetasReturnValue() { + return mockPkMetasReturnValue; + } + + /** + * set the mock execute handler + * @param mockExecuteHandler + */ + public void setMockExecuteHandler(MockExecuteHandler mockExecuteHandler){ + this.mockExecuteHandler = mockExecuteHandler; + } + + public Object[][] getMockOnUpdateColumnsReturnValue() { + return mockOnUpdateColumnsReturnValue; + } + + public void setMockOnUpdateColumnsReturnValue(Object[][] mockOnUpdateColumnsReturnValue) { + this.mockOnUpdateColumnsReturnValue = mockOnUpdateColumnsReturnValue; + } + + public Object[][] getMockTableMetasReturnValue() { + return mockTableMetasReturnValue; + } + + public void setMockTableMetasReturnValue(Object[][] mockTableMetasReturnValue) { + this.mockTableMetasReturnValue = mockTableMetasReturnValue; + } +} diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockExecuteHandlerImpl.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockExecuteHandlerImpl.java new file mode 100644 index 00000000000..af5c7dbc8d7 --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockExecuteHandlerImpl.java @@ -0,0 +1,95 @@ +/* + * 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.seata.spring.boot.autoconfigure.mock; + +import com.alibaba.druid.mock.MockStatementBase; +import com.alibaba.druid.mock.handler.MockExecuteHandler; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; +import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; +import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import org.apache.seata.sqlparser.druid.mysql.MySQLSelectForUpdateRecognizer; +import org.apache.seata.sqlparser.util.JdbcConstants; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + + +public class MockExecuteHandlerImpl implements MockExecuteHandler { + + /** + * the mock value of return value + */ + private Object[][] mockReturnValue; + + /** + * the mock column labels of return value + */ + private List mockReturnValueColumnLabels; + + /** + * the mock column meta + */ + private Object[][] mockColumnsMetasReturnValue; + + /** + * Instantiate MockExecuteHandlerImpl + * @param mockReturnValue + */ + public MockExecuteHandlerImpl(List mockReturnValueColumnLabels, Object[][] mockReturnValue, Object[][] mockColumnsMetasReturnValue) { + this.mockReturnValueColumnLabels = mockReturnValueColumnLabels; + this.mockReturnValue = mockReturnValue; + this.mockColumnsMetasReturnValue = mockColumnsMetasReturnValue; + } + + @Override + public ResultSet executeQuery(MockStatementBase statement, String sql) throws SQLException { + MockResultSet resultSet = new MockResultSet(statement); + //mock the return value + resultSet.mockResultSet(mockReturnValueColumnLabels, mockReturnValue); + //mock the rs meta data + List asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL); + List metas = new ArrayList<>(); + if(asts.get(0) instanceof SQLSelectStatement) { + SQLSelectStatement ast = (SQLSelectStatement) asts.get(0); + SQLSelectQueryBlock queryBlock = ast.getSelect().getQueryBlock(); + String tableName = ""; + if (queryBlock.getFrom() instanceof SQLExprTableSource) { + MySQLSelectForUpdateRecognizer recognizer = new MySQLSelectForUpdateRecognizer(sql, ast); + tableName = recognizer.getTableName(); + } else { + //select * from t inner join t1... + tableName = queryBlock.getFrom().toString(); + } + for (Object[] meta : mockColumnsMetasReturnValue) { + if (tableName.equalsIgnoreCase(meta[2].toString())) { + metas.add(meta); + } + } + } + if(metas.isEmpty()){ + //eg:select * from dual + metas = Arrays.asList(mockColumnsMetasReturnValue); + } + resultSet.mockResultSetMetaData(metas.toArray(new Object[0][])); + return resultSet; + } +} diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockLockConflictConnectionProxy.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockLockConflictConnectionProxy.java new file mode 100644 index 00000000000..1f0b23e512b --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockLockConflictConnectionProxy.java @@ -0,0 +1,49 @@ +/* + * 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.seata.spring.boot.autoconfigure.mock; + +import org.apache.seata.rm.datasource.ConnectionProxy; +import org.apache.seata.rm.datasource.DataSourceProxy; +import org.apache.seata.rm.datasource.exec.LockConflictException; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Savepoint; + + +public class MockLockConflictConnectionProxy extends ConnectionProxy { + /** + * Instantiates a new Connection proxy. + * + * @param dataSourceProxy the data source proxy + * @param targetConnection the target connection + */ + public MockLockConflictConnectionProxy(DataSourceProxy dataSourceProxy, + Connection targetConnection) { + super(dataSourceProxy, targetConnection); + } + + @Override + public void releaseSavepoint(Savepoint savepoint) throws SQLException { + super.releaseSavepoint(savepoint); + } + + @Override + public void checkLock(String lockKeys) throws SQLException { + throw new LockConflictException("mock lock conflict"); + } +} diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockMariadbDataSource.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockMariadbDataSource.java new file mode 100644 index 00000000000..0742eb6a6de --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockMariadbDataSource.java @@ -0,0 +1,28 @@ +/* + * 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.seata.spring.boot.autoconfigure.mock; + +import java.sql.Connection; +import java.sql.SQLException; + + +public class MockMariadbDataSource extends MockDataSource { + @Override + public Connection getConnection() throws SQLException { + return new MockConnection(new MockDriver(), "jdbc:mariadb://127.0.0.1:3306/seata?rewriteBatchedStatements=true", null); + } +} diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockParameterMetaData.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockParameterMetaData.java new file mode 100644 index 00000000000..423471fe556 --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockParameterMetaData.java @@ -0,0 +1,89 @@ +/* + * 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.seata.spring.boot.autoconfigure.mock; + +import java.sql.ParameterMetaData; +import java.sql.SQLException; + + +public class MockParameterMetaData implements ParameterMetaData { + + private int parameterCount; + + public MockParameterMetaData(String sql) { + for (int i = 0; i < sql.length(); i++) { + if (sql.charAt(i) == '?') { + parameterCount++; + } + } + } + + @Override + public int getParameterCount() throws SQLException { + return parameterCount; + } + + @Override + public int isNullable(int param) throws SQLException { + return 0; + } + + @Override + public boolean isSigned(int param) throws SQLException { + return false; + } + + @Override + public int getPrecision(int param) throws SQLException { + return 0; + } + + @Override + public int getScale(int param) throws SQLException { + return 0; + } + + @Override + public int getParameterType(int param) throws SQLException { + return 0; + } + + @Override + public String getParameterTypeName(int param) throws SQLException { + return null; + } + + @Override + public String getParameterClassName(int param) throws SQLException { + return null; + } + + @Override + public int getParameterMode(int param) throws SQLException { + return 0; + } + + @Override + public T unwrap(Class iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } +} diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockPreparedStatement.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockPreparedStatement.java new file mode 100644 index 00000000000..05be25cc217 --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockPreparedStatement.java @@ -0,0 +1,67 @@ +/* + * 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.seata.spring.boot.autoconfigure.mock; + +import com.alibaba.druid.mock.MockStatementBase; +import com.alibaba.druid.util.jdbc.PreparedStatementBase; + +import java.sql.ParameterMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; + + +public class MockPreparedStatement extends PreparedStatementBase implements MockStatementBase { + + private final String sql; + + private ParameterMetaData parameterMetaData; + + public MockPreparedStatement(MockConnection conn, String sql){ + super(conn); + this.sql = sql; + parameterMetaData = new MockParameterMetaData(sql); + } + + @Override + public ResultSet executeQuery() throws SQLException { + MockConnection conn = getConnection(); + + if (conn != null && conn.getDriver() != null) { + return conn.getDriver().executeQuery(this, sql); + } + return null; + } + + @Override + public int executeUpdate() throws SQLException { + return 0; + } + + @Override + public boolean execute() throws SQLException { + return false; + } + + @Override + public ParameterMetaData getParameterMetaData() throws SQLException { + return this.parameterMetaData; + } + + public MockConnection getConnection() throws SQLException { + return (MockConnection) super.getConnection(); + } +} diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockResultSet.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockResultSet.java new file mode 100644 index 00000000000..ba3d6b0c8c5 --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockResultSet.java @@ -0,0 +1,167 @@ +/* + * 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.seata.spring.boot.autoconfigure.mock; + +import com.alibaba.druid.util.jdbc.ResultSetBase; +import com.google.common.collect.Lists; +import org.apache.seata.sqlparser.struct.ColumnMeta; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + + +public class MockResultSet extends ResultSetBase { + + private List columnMetas; + + private int rowIndex = -1; + + /** + * the column label + */ + private List columnLabels; + + /** + * the return value + */ + private List rows; + + private static final Logger LOGGER = LoggerFactory.getLogger(MockResultSet.class); + + /** + * Instantiates a new Mock result set. + * @param statement + */ + public MockResultSet(Statement statement) { + super(statement); + this.rows = new ArrayList<>(); + this.columnMetas = Lists.newArrayList(); + } + + /** + * mock result set + * @param mockColumnLabels + * @param mockReturnValue + * @return + */ + public MockResultSet mockResultSet(List mockColumnLabels, Object[][] mockReturnValue){ + this.columnLabels = mockColumnLabels; + for (int i = 0; i < mockReturnValue.length; i++) { + Object[] row = mockReturnValue[i]; + this.getRows().add(row); + } + return this; + } + + public void mockResultSetMetaData(Object[][] mockColumnsMetasReturnValue) { + for (Object[] meta : mockColumnsMetasReturnValue) { + ColumnMeta columnMeta = new ColumnMeta(); + columnMeta.setTableName(meta[2].toString()); + columnMeta.setColumnName(meta[3].toString()); + this.columnMetas.add(columnMeta); + } + } + + @Override + public ResultSetMetaData getMetaData() throws SQLException { + return new MockResultSetMetaData(columnMetas); + } + + public MockResultSetMetaData getMockMetaData() { + return new MockResultSetMetaData(columnMetas); + } + + @Override + public boolean next() throws SQLException { + if (closed) { + throw new SQLException(); + } + + if (rowIndex < rows.size() - 1) { + rowIndex++; + return true; + } + return false; + } + + @Override + public int findColumn(String columnLabel) throws SQLException { + if (columnLabels.indexOf(columnLabel) != -1) { + return columnLabels.indexOf(columnLabel) + 1; + } + if (columnLabels.indexOf(columnLabel.toLowerCase()) != -1) { + return columnLabels.indexOf(columnLabel.toLowerCase()) + 1; + } + if (columnLabels.indexOf(columnLabel.toUpperCase()) != -1) { + return columnLabels.indexOf(columnLabel.toUpperCase()) + 1; + } + return -1; + } + + @Override + public Blob getBlob(String columnLabel) throws SQLException { + return getBlob(findColumn(columnLabel)); + } + + @Override + public Blob getBlob(int columnIndex) throws SQLException { + byte[] bytes = getObjectInternal(columnIndex).toString().getBytes(); + return new MockBlob(); + } + + @Override + public Clob getClob(String columnLabel) throws SQLException { + return getClob(findColumn(columnLabel)); + } + + @Override + public Clob getClob(int columnIndex) throws SQLException { + char[] chars = getObjectInternal(columnIndex).toString().toCharArray(); + return new MockClob(); + } + + public Object getObjectInternal(int columnIndex) { + Object[] row = rows.get(rowIndex); + return row[columnIndex - 1]; + } + + @Override + public boolean previous() throws SQLException { + if (closed) { + throw new SQLException(); + } + + if (rowIndex >= 0) { + rowIndex--; + return true; + } + return false; + } + + @Override + public void updateObject(int columnIndex, Object x) throws SQLException { + Object[] row = rows.get(rowIndex); + row[columnIndex - 1] = x; + } + + public List getRows() { + return rows; + } +} diff --git a/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockResultSetMetaData.java b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockResultSetMetaData.java new file mode 100644 index 00000000000..1f3c379dad4 --- /dev/null +++ b/seata-spring-boot-starter/src/test/java/org/apache/seata/spring/boot/autoconfigure/mock/MockResultSetMetaData.java @@ -0,0 +1,169 @@ +/* + * 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.seata.spring.boot.autoconfigure.mock; + +import org.apache.seata.common.util.ReflectionUtil; +import org.apache.seata.sqlparser.struct.ColumnMeta; + +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.List; + + +public class MockResultSetMetaData implements ResultSetMetaData { + + private List columns; + + public MockResultSetMetaData(List columns) { + this.columns = columns; + } + + public List getColumns() { + return columns; + } + + @Override + public int getColumnCount() throws SQLException { + return columns.size(); + } + + @Override + public boolean isAutoIncrement(int column) throws SQLException { + return getColumn(column).isAutoincrement(); + } + + @Override + public boolean isCaseSensitive(int column) throws SQLException { + return false; + } + + @Override + public boolean isSearchable(int column) throws SQLException { + return false; + } + + @Override + public boolean isCurrency(int column) throws SQLException { + return false; + } + + @Override + public int isNullable(int column) throws SQLException { + return 0; + } + + @Override + public boolean isSigned(int column) throws SQLException { + return false; + } + + @Override + public int getColumnDisplaySize(int column) throws SQLException { + return 0; + } + + @Override + public String getColumnLabel(int column) throws SQLException { + return null; + } + + @Override + public String getColumnName(int column) throws SQLException { + return getColumn(column).getColumnName(); + } + + @Override + public String getSchemaName(int column) throws SQLException { + return null; + } + + @Override + public int getPrecision(int column) throws SQLException { + return 0; + } + + @Override + public int getScale(int column) throws SQLException { + return 0; + } + + @Override + public String getTableName(int column) throws SQLException { + ColumnMeta columnMeta = getColumn(column); + try { + Object tableName = ReflectionUtil.getFieldValue(columnMeta, "tableName"); + return tableName.toString(); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + return null; + } + } + + @Override + public String getCatalogName(int column) throws SQLException { + return null; + } + + @Override + public int getColumnType(int column) throws SQLException { + return 0; + } + + @Override + public String getColumnTypeName(int column) throws SQLException { + return null; + } + + @Override + public boolean isReadOnly(int column) throws SQLException { + return false; + } + + @Override + public boolean isWritable(int column) throws SQLException { + return false; + } + + @Override + public boolean isDefinitelyWritable(int column) throws SQLException { + return false; + } + + @Override + public String getColumnClassName(int column) throws SQLException { + return null; + } + + @Override + public T unwrap(Class iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } + + /** + * get column + * @param column + * @return + */ + public ColumnMeta getColumn(int column){ + return columns.get(column - 1); + } +} diff --git a/seata-spring-boot-starter/src/test/resources/application.properties b/seata-spring-boot-starter/src/test/resources/application.properties new file mode 100644 index 00000000000..14308264e8f --- /dev/null +++ b/seata-spring-boot-starter/src/test/resources/application.properties @@ -0,0 +1,199 @@ +# +# 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. +# +spring.application.name=test +seata.enabled=true +seata.client.http.interceptor-enabled=true +seata.scan-packages=firstPackage,secondPackage +seata.excludes-for-scanning=firstBeanNameForExclude,secondBeanNameForExclude +seata.excludes-for-auto-proxying=firstClassNameForExclude,secondClassNameForExclude +seata.application-id=applicationName +seata.tx-service-group=default_tx_group +#seata.tx-service-group=mock_tx_group +seata.access-key=aliyunAccessKey +seata.secret-key=aliyunSecretKey +seata.enable-auto-data-source-proxy=true +seata.enableAutoDataSourceProxy=true +seata.data-source-proxy-mode=AT +seata.use-jdk-proxy=false +seata.expose-proxy=false +seata.client.rm.async-commit-buffer-limit=10000 +seata.client.rm.report-retry-count=5 +seata.client.rm.table-meta-check-enable=false +seata.client.rm.report-success-enable=false +seata.client.rm.saga-branch-register-enable=false +seata.client.rm.saga-json-parser=fastjson +seata.client.rm.saga-retry-persist-mode-update=false +seata.client.rm.saga-compensate-persist-mode-update=false +seata.client.rm.tcc-action-interceptor-order=-2147482648 +seata.client.rm.sql-parser-type=druid +seata.client.rm.lock.retry-interval=10 +seata.client.rm.lock.retry-times=30 +seata.client.rm.lock.retry-policy-branch-rollback-on-conflict=true +seata.client.rm.branchExecutionTimeoutXA=60000 +seata.client.rm.connectionTwoPhaseHoldTimeoutXA=10000 +seata.client.rm.applicationDataLimit=64000 +seata.client.rm.applicationDataLimitCheck=false +seata.client.tm.commit-retry-count=5 +seata.client.tm.rollback-retry-count=5 +seata.client.tm.default-global-transaction-timeout=60000 +seata.client.tm.degrade-check=false +seata.client.tm.degrade-check-allow-times=10 +seata.client.tm.degrade-check-period=2000 +seata.client.tm.interceptor-order=-2147482648 +seata.client.undo.data-validation=true +seata.client.undo.log-serialization=jackson +seata.client.undo.only-care-update-columns=true +seata.client.undo.log-table=undo_log +seata.client.undo.compress.enable=true +seata.client.undo.compress.type=zip +seata.client.undo.compress.threshold=64k +seata.client.load-balance.type=XID +seata.client.load-balance.virtual-nodes=10 +seata.log.exception-rate=100 +seata.service.vgroup-mapping.default_tx_group=default +seata.service.grouplist.default=127.0.0.1:8099 +seata.service.disable-global-transaction=false +seata.transport.protocol=seata +seata.transport.shutdown.wait=3 +seata.transport.thread-factory.boss-thread-prefix=NettyBoss +seata.transport.thread-factory.worker-thread-prefix=NettyServerNIOWorker +seata.transport.thread-factory.server-executor-thread-prefix=NettyServerBizHandler +seata.transport.thread-factory.share-boss-worker=false +seata.transport.thread-factory.client-selector-thread-prefix=NettyClientSelector +seata.transport.thread-factory.client-selector-thread-size=1 +seata.transport.thread-factory.client-worker-thread-prefix=NettyClientWorkerThread +seata.transport.thread-factory.worker-thread-size=default +seata.transport.thread-factory.boss-thread-size=1 +seata.transport.type=TCP +seata.transport.server=NIO +seata.transport.heartbeat=true +seata.transport.serialization=seata +seata.transport.compressor=none +seata.transport.enable-tm-client-batch-send-request=false +seata.transport.enable-rm-client-batch-send-request=true +seata.transport.rpc-rm-request-timeout=15000 +seata.transport.rpc-tm-request-timeout=30000 + +seata.config.type=file + +seata.config.consul.server-addr=127.0.0.1:8500 +seata.config.consul.acl-token= + +seata.config.apollo.apollo-meta=http://192.168.1.204:8801 +seata.config.apollo.apollo-accesskey-secret= +seata.config.apollo.app-id=seata-server +seata.config.apollo.namespace=application +seata.config.apollo.cluster= + +seata.config.etcd3.server-addr=http://localhost:2379 + +seata.config.nacos.namespace= +seata.config.nacos.server-addr=127.0.0.1:8848 +seata.config.nacos.group=SEATA_GROUP +seata.config.nacos.contextPath= +seata.config.nacos.data-id=seata.properties +##1.The following configuration is for the open source version of Nacos +seata.config.nacos.username= +seata.config.nacos.password= +##2.The following configuration is for the MSE Nacos on aliyun +#seata.config.nacos.access-key= +#seata.config.nacos.secret-key= +##3.The following configuration is used to deploy on Aliyun ECS or ACK without authentication +#seata.config.nacos.ram-role-name= + +seata.config.zk.server-addr=127.0.0.1:2181 +seata.config.zk.session-timeout=6000 +seata.config.zk.connect-timeout=2000 +seata.config.zk.username= +seata.config.zk.password= +seata.config.zk.node-path=/seata/seata.properties + +seata.config.custom.name= + +seata.registry.type=file + +seata.registry.raft.server-addr= +seata.registry.raft.metadata-max-age-ms=30000 +seata.registry.raft.username=seata +seata.registry.raft.password=seata +seata.registry.raft.tokenValidityInMilliseconds=1740000 +seata.registry.consul.server-addr=127.0.0.1:8500 + +seata.registry.etcd3.server-addr=http://localhost:2379 + +seata.registry.eureka.weight=1 +seata.registry.eureka.service-url=http://localhost:8761/eureka + +seata.registry.seata.server-addr=127.0.0.1:8081 +seata.registry.seata.namespace=public +seata.registry.seata.heartbeat-period=5000 + +seata.registry.nacos.application=seata-server +seata.registry.nacos.server-addr=127.0.0.1:8848 +seata.registry.nacos.group=SEATA_GROUP +seata.registry.nacos.namespace= +seata.registry.nacos.contextPath= +seata.registry.nacos.clientApplication=${spring.application.name} +##1.The following configuration is for the open source version of Nacos +seata.registry.nacos.username= +seata.registry.nacos.password= +##2.The following configuration is for the MSE Nacos on aliyun +#seata.registry.nacos.access-key= +#seata.registry.nacos.secret-key= +##3.The following configuration is used to deploy on Aliyun ECS or ACK without authentication +#seata.registry.nacos.ram-role-name= +##if use Nacos naming meta-data for SLB service registry, specify nacos address pattern rules here +#seata.registry.nacos.slb-pattern= + +seata.registry.redis.server-addr=localhost:6379 +seata.registry.redis.db=0 +seata.registry.redis.password= +seata.registry.redis.timeout=0 + +seata.registry.sofa.server-addr=127.0.0.1:9603 +seata.registry.sofa.region=DEFAULT_ZONE +seata.registry.sofa.datacenter=DefaultDataCenter +seata.registry.sofa.group=SEATA_GROUP +seata.registry.sofa.address-wait-time=3000 +seata.registry.sofa.application=default + +seata.registry.zk.server-addr=127.0.0.1:2181 +seata.registry.zk.session-timeout=6000 +seata.registry.zk.connect-timeout=2000 +seata.registry.zk.username= +seata.registry.zk.password= + +seata.registry.custom.name= + +seata.tcc.fence.log-table-name=tcc_fence_log +seata.tcc.fence.clean-period=1h +#You can choose from the following options: fastjson, jackson, gson +seata.tcc.context-json-parser-type=fastjson + + +seata.saga.enabled=true +seata.saga.state-machine.table-prefix=seata_ +seata.saga.state-machine.enable-async=true +seata.saga.state-machine.async-thread-pool.core-pool-size=1 +seata.saga.state-machine.async-thread-pool.max-pool-size=20 +seata.saga.state-machine.async-thread-pool.keep-alive-time=60 +seata.saga.state-machine.trans-operation-timeout=1800000 +seata.saga.state-machine.service-invoke-timeout=300000 +seata.saga.state-machine.auto-register-resources=true +seata.saga.state-machine.resources[0]=classpath*:seata/saga/statelang/**/*.json +seata.saga.state-machine.default-tenant-id=000001 +seata.saga.state-machine.charset=UTF-8 diff --git a/seata-spring-boot-starter/src/test/resources/file.conf b/seata-spring-boot-starter/src/test/resources/file.conf new file mode 100644 index 00000000000..94863827468 --- /dev/null +++ b/seata-spring-boot-starter/src/test/resources/file.conf @@ -0,0 +1,78 @@ +# +# 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. +# + +transport { + # tcp, unix-domain-socket + type = "TCP" + #NIO, NATIVE + server = "NIO" + #enable heartbeat + heartbeat = true + # the tm client batch send request enable + enableTmClientBatchSendRequest = true + # the rm client batch send request enable + enableRmClientBatchSendRequest = true + #thread factory for netty + threadFactory { + bossThreadPrefix = "NettyBoss" + workerThreadPrefix = "NettyServerNIOWorker" + serverExecutorThread-prefix = "NettyServerBizHandler" + shareBossWorker = false + clientSelectorThreadPrefix = "NettyClientSelector" + clientSelectorThreadSize = 1 + clientWorkerThreadPrefix = "NettyClientWorkerThread" + # netty boss thread size + bossThreadSize = 1 + #auto default pin or 8 + workerThreadSize = "default" + } + shutdown { + # when destroy server, wait seconds + wait = 3 + } + serialization = "seata" + compressor = "none" + + enableRmClientChannelCheckFailFast = false + enableTmClientChannelCheckFailFast = false +} + + +service { + #transaction service group mapping + vgroupMapping.default_tx_group = "default" + vgroupMapping.mock_tx_group = "mock" + #only support when registry.type=file, please don't set multiple addresses + default.grouplist = "127.0.0.1:8091" + mock.grouplist = "127.0.0.1:8099" + #disable seata + disableGlobalTransaction = false +} + +client { + rm { + reportSuccessEnable = false + sagaBranchRegisterEnable = false + sagaJsonParser = jackson + sagaRetryPersistModeUpdate = false + sagaCompensatePersistModeUpdate = false + } + loadBalance { + type = "XID" + virtualNodes = 10 + } +} diff --git a/seata-spring-boot-starter/src/test/resources/registry.conf b/seata-spring-boot-starter/src/test/resources/registry.conf new file mode 100644 index 00000000000..bab6e8ec0ef --- /dev/null +++ b/seata-spring-boot-starter/src/test/resources/registry.conf @@ -0,0 +1,90 @@ +# +# 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. +# + +registry { + # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa + type = "file" + + nacos { + serverAddr = "localhost" + namespace = "" + cluster = "default" + } + eureka { + serviceUrl = "http://localhost:8761/eureka" + application = "default" + weight = "1" + } + redis { + serverAddr = "localhost:6379" + db = "0" + } + zk { + cluster = "default" + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + } + consul { + cluster = "default" + serverAddr = "127.0.0.1:8500" + } + etcd3 { + cluster = "default" + serverAddr = "http://localhost:2379" + } + sofa { + serverAddr = "127.0.0.1:9603" + application = "default" + region = "DEFAULT_ZONE" + datacenter = "DefaultDataCenter" + cluster = "default" + group = "SEATA_GROUP" + addressWaitTime = "3000" + } + file { + name = "file.conf" + } +} + +config { + # file、nacos 、apollo、zk、consul、etcd3 + type = "file" + + nacos { + serverAddr = "localhost" + namespace = "" + } + consul { + serverAddr = "127.0.0.1:8500" + } + apollo { + appId = "seata-server" + apolloMeta = "http://192.168.1.204:8801" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + } + etcd3 { + serverAddr = "http://localhost:2379" + } + file { + name = "file.conf" + } +}