From f93a721c997d4e1d8021905e0b1f13e2dade6284 Mon Sep 17 00:00:00 2001 From: funkye Date: Mon, 11 Mar 2024 21:49:47 +0800 Subject: [PATCH] optimize: rm-datasource compatible (#6402) --- changes/en-us/2.x.md | 1 + changes/zh-cn/2.x.md | 1 + compatible/pom.xml | 44 +- .../seata/rm/datasource/DataSourceProxy.java | 74 +- .../datasource/undo/UndoExecutorHolder.java | 25 - .../rm/datasource/undo/UndoLogManager.java | 25 - .../rm/datasource/xa/DataSourceProxyXA.java | 70 +- .../io/seata/sqlparser/EscapeHandler.java | 25 - .../seata/sqlparser/SQLRecognizerFactory.java | 21 - .../druid/SQLOperateRecognizerHolder.java | 26 - .../sqlparser/struct/TableMetaCache.java | 26 - .../io/seata/sqlparser/util/DbTypeParser.java | 21 - .../rm/datasource/DataSourceProxyTest.java | 100 ++ .../io/seata/rm/datasource/mock/MockBlob.java | 84 ++ .../io/seata/rm/datasource/mock/MockClob.java | 95 ++ .../rm/datasource/mock/MockConnection.java | 71 ++ .../rm/datasource/mock/MockDataSource.java | 72 ++ .../datasource/mock/MockDatabaseMetaData.java | 1013 +++++++++++++++++ .../seata/rm/datasource/mock/MockDriver.java | 202 ++++ .../mock/MockExecuteHandlerImpl.java | 96 ++ .../mock/MockParameterMetaData.java | 89 ++ .../mock/MockPreparedStatement.java | 66 ++ .../rm/datasource/mock/MockResultSet.java | 172 +++ .../mock/MockResultSetMetaData.java | 169 +++ .../datasource/xa/DataSourceProxyXATest.java | 134 +++ .../TccActionInterceptorParserTest.java | 92 +- .../tm/api/DefaultFailureHandlerImplTest.java | 4 +- .../xa/ConnectionProxyXATest.java | 4 +- .../xa/DataSourceProxyXANativeTest.java | 4 +- .../xa/DataSourceProxyXATest.java | 4 +- .../{ => datasource}/xa/XAXidBuilderTest.java | 2 +- 31 files changed, 2590 insertions(+), 242 deletions(-) delete mode 100644 compatible/src/main/java/io/seata/rm/datasource/undo/UndoExecutorHolder.java delete mode 100644 compatible/src/main/java/io/seata/rm/datasource/undo/UndoLogManager.java delete mode 100644 compatible/src/main/java/io/seata/sqlparser/EscapeHandler.java delete mode 100644 compatible/src/main/java/io/seata/sqlparser/SQLRecognizerFactory.java delete mode 100644 compatible/src/main/java/io/seata/sqlparser/druid/SQLOperateRecognizerHolder.java delete mode 100644 compatible/src/main/java/io/seata/sqlparser/struct/TableMetaCache.java delete mode 100644 compatible/src/main/java/io/seata/sqlparser/util/DbTypeParser.java create mode 100644 compatible/src/test/java/io/seata/rm/datasource/DataSourceProxyTest.java create mode 100644 compatible/src/test/java/io/seata/rm/datasource/mock/MockBlob.java create mode 100644 compatible/src/test/java/io/seata/rm/datasource/mock/MockClob.java create mode 100644 compatible/src/test/java/io/seata/rm/datasource/mock/MockConnection.java create mode 100644 compatible/src/test/java/io/seata/rm/datasource/mock/MockDataSource.java create mode 100644 compatible/src/test/java/io/seata/rm/datasource/mock/MockDatabaseMetaData.java create mode 100644 compatible/src/test/java/io/seata/rm/datasource/mock/MockDriver.java create mode 100644 compatible/src/test/java/io/seata/rm/datasource/mock/MockExecuteHandlerImpl.java create mode 100644 compatible/src/test/java/io/seata/rm/datasource/mock/MockParameterMetaData.java create mode 100644 compatible/src/test/java/io/seata/rm/datasource/mock/MockPreparedStatement.java create mode 100644 compatible/src/test/java/io/seata/rm/datasource/mock/MockResultSet.java create mode 100644 compatible/src/test/java/io/seata/rm/datasource/mock/MockResultSetMetaData.java create mode 100644 compatible/src/test/java/io/seata/rm/datasource/xa/DataSourceProxyXATest.java rename rm-datasource/src/test/java/org/apache/seata/rm/{ => datasource}/xa/ConnectionProxyXATest.java (98%) rename rm-datasource/src/test/java/org/apache/seata/rm/{ => datasource}/xa/DataSourceProxyXANativeTest.java (94%) rename rm-datasource/src/test/java/org/apache/seata/rm/{ => datasource}/xa/DataSourceProxyXATest.java (97%) rename rm-datasource/src/test/java/org/apache/seata/rm/{ => datasource}/xa/XAXidBuilderTest.java (97%) diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md index 1f8275e60e3..64b06a9ec22 100644 --- a/changes/en-us/2.x.md +++ b/changes/en-us/2.x.md @@ -108,6 +108,7 @@ Add changes here for all PR submitted to the 2.x branch. - [[#6391](https://github.com/apache/incubator-seata/pull/6091)] forbid duplicate registration of TCC resources - [[#6393](https://github.com/apache/incubator-seata/pull/6393)] determine the version before sync metadata and add retry mechanism - [[#6387](https://github.com/apache/incubator-seata/pull/6387)] optimize tcc use compatible +- [[#6402](https://github.com/apache/incubator-seata/pull/6402)] optimize rm-datasource use compatible ### refactor: - [[#6269](https://github.com/apache/incubator-seata/pull/6269)] standardize Seata Exception diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md index bdf42b02e59..fb990bd9563 100644 --- a/changes/zh-cn/2.x.md +++ b/changes/zh-cn/2.x.md @@ -112,6 +112,7 @@ - [[#6391](https://github.com/apache/incubator-seata/pull/6091)] 禁止重复注册TCC资源 - [[#6393](https://github.com/apache/incubator-seata/pull/6393)] 元数据同步前判断版本,并增加重试功能 - [[#6387](https://github.com/apache/incubator-seata/pull/6387)] 优化tcc使用兼容 +- [[#6402](https://github.com/apache/incubator-seata/pull/6402)] 优化rm-datasource向下兼容 ### refactor: diff --git a/compatible/pom.xml b/compatible/pom.xml index 5d4de46dbbb..fc9fcc0a106 100644 --- a/compatible/pom.xml +++ b/compatible/pom.xml @@ -30,6 +30,11 @@ 8 8 + 4.11.0 + 1.2.7 + 5.1.42 + 2.7.2 + 3.12.2 @@ -54,12 +59,12 @@ org.apache.seata - seata-metrics-api + seata-sqlparser-druid ${project.version} org.apache.seata - seata-sqlparser-druid + seata-metrics-api ${project.version} @@ -122,6 +127,41 @@ seata-tcc ${project.version} + + com.alibaba + druid + provided + ${druid.version} + + + org.mockito + mockito-core + ${mockito.version} + test + + + org.mockito + mockito-inline + ${mockito.version} + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + mysql + mysql-connector-java + ${mysql.version} + test + + + org.mariadb.jdbc + mariadb-java-client + ${mariadb.version} + test + diff --git a/compatible/src/main/java/io/seata/rm/datasource/DataSourceProxy.java b/compatible/src/main/java/io/seata/rm/datasource/DataSourceProxy.java index ad6188e06f5..7304caf1f1f 100644 --- a/compatible/src/main/java/io/seata/rm/datasource/DataSourceProxy.java +++ b/compatible/src/main/java/io/seata/rm/datasource/DataSourceProxy.java @@ -16,19 +16,87 @@ */ package io.seata.rm.datasource; +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.util.logging.Logger; import javax.sql.DataSource; +import org.apache.seata.core.model.BranchType; +import org.apache.seata.rm.datasource.SeataDataSourceProxy; /** * The type Data source proxy. * */ -public class DataSourceProxy extends org.apache.seata.rm.datasource.DataSourceProxy { +public class DataSourceProxy implements SeataDataSourceProxy { + private final org.apache.seata.rm.datasource.DataSourceProxy dataSourceProxy; public DataSourceProxy(DataSource targetDataSource) { - super(targetDataSource); + this.dataSourceProxy = new org.apache.seata.rm.datasource.DataSourceProxy(targetDataSource); } public DataSourceProxy(DataSource targetDataSource, String resourceGroupId) { - super(targetDataSource, resourceGroupId); + this.dataSourceProxy = new org.apache.seata.rm.datasource.DataSourceProxy(targetDataSource, resourceGroupId); } + + @Override + public DataSource getTargetDataSource() { + return dataSourceProxy.getTargetDataSource(); + } + + @Override + public BranchType getBranchType() { + return dataSourceProxy.getBranchType(); + } + + @Override + public Connection getConnection() throws SQLException { + return dataSourceProxy.getConnection(); + } + + @Override + public Connection getConnection(String username, String password) throws SQLException { + return dataSourceProxy.getConnection(username, password); + } + + @Override + public T unwrap(Class iface) throws SQLException { + return dataSourceProxy.unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return dataSourceProxy.isWrapperFor(iface); + } + + @Override + public PrintWriter getLogWriter() throws SQLException { + return dataSourceProxy.getLogWriter(); + } + + @Override + public void setLogWriter(PrintWriter out) throws SQLException { + dataSourceProxy.setLogWriter(out); + } + + @Override + public void setLoginTimeout(int seconds) throws SQLException { + dataSourceProxy.setLoginTimeout(seconds); + } + + @Override + public int getLoginTimeout() throws SQLException { + return dataSourceProxy.getLoginTimeout(); + } + + @Override + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + return dataSourceProxy.getParentLogger(); + } + + public String getResourceId() { + return dataSourceProxy.getResourceId(); + } + } diff --git a/compatible/src/main/java/io/seata/rm/datasource/undo/UndoExecutorHolder.java b/compatible/src/main/java/io/seata/rm/datasource/undo/UndoExecutorHolder.java deleted file mode 100644 index e8abfc206c2..00000000000 --- a/compatible/src/main/java/io/seata/rm/datasource/undo/UndoExecutorHolder.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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 io.seata.rm.datasource.undo; - - -/** - * The Type UndoExecutorHolder - * - */ -public interface UndoExecutorHolder extends org.apache.seata.rm.datasource.undo.UndoExecutorHolder { -} diff --git a/compatible/src/main/java/io/seata/rm/datasource/undo/UndoLogManager.java b/compatible/src/main/java/io/seata/rm/datasource/undo/UndoLogManager.java deleted file mode 100644 index 502b15f737b..00000000000 --- a/compatible/src/main/java/io/seata/rm/datasource/undo/UndoLogManager.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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 io.seata.rm.datasource.undo; - - -/** - * The type Undo log manager. - * - */ -public interface UndoLogManager extends org.apache.seata.rm.datasource.undo.UndoLogManager { -} diff --git a/compatible/src/main/java/io/seata/rm/datasource/xa/DataSourceProxyXA.java b/compatible/src/main/java/io/seata/rm/datasource/xa/DataSourceProxyXA.java index c90c515e9fa..ba10e9fa8c9 100644 --- a/compatible/src/main/java/io/seata/rm/datasource/xa/DataSourceProxyXA.java +++ b/compatible/src/main/java/io/seata/rm/datasource/xa/DataSourceProxyXA.java @@ -16,19 +16,83 @@ */ package io.seata.rm.datasource.xa; +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.util.logging.Logger; import javax.sql.DataSource; +import org.apache.seata.core.model.BranchType; +import org.apache.seata.rm.datasource.SeataDataSourceProxy; /** * DataSource proxy for XA mode. * */ -public class DataSourceProxyXA extends org.apache.seata.rm.datasource.xa.DataSourceProxyXA { +public class DataSourceProxyXA implements SeataDataSourceProxy { + + private final org.apache.seata.rm.datasource.xa.DataSourceProxyXA dataSourceProxyXA; public DataSourceProxyXA(DataSource dataSource) { - super(dataSource); + this.dataSourceProxyXA = new org.apache.seata.rm.datasource.xa.DataSourceProxyXA(dataSource); } public DataSourceProxyXA(DataSource dataSource, String resourceGroupId) { - super(dataSource, resourceGroupId); + this.dataSourceProxyXA = new org.apache.seata.rm.datasource.xa.DataSourceProxyXA(dataSource, resourceGroupId); + } + + @Override + public DataSource getTargetDataSource() { + return dataSourceProxyXA.getTargetDataSource(); + } + + @Override + public BranchType getBranchType() { + return dataSourceProxyXA.getBranchType(); + } + + @Override + public Connection getConnection() throws SQLException { + return dataSourceProxyXA.getConnection(); + } + + @Override + public Connection getConnection(String username, String password) throws SQLException { + return dataSourceProxyXA.getConnection(username, password); + } + + @Override + public T unwrap(Class iface) throws SQLException { + return dataSourceProxyXA.unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return dataSourceProxyXA.isWrapperFor(iface); + } + + @Override + public PrintWriter getLogWriter() throws SQLException { + return dataSourceProxyXA.getLogWriter(); + } + + @Override + public void setLogWriter(PrintWriter out) throws SQLException { + dataSourceProxyXA.setLogWriter(out); + } + + @Override + public void setLoginTimeout(int seconds) throws SQLException { + dataSourceProxyXA.setLoginTimeout(seconds); + } + + @Override + public int getLoginTimeout() throws SQLException { + return dataSourceProxyXA.getLoginTimeout(); + } + + @Override + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + return dataSourceProxyXA.getParentLogger(); } } diff --git a/compatible/src/main/java/io/seata/sqlparser/EscapeHandler.java b/compatible/src/main/java/io/seata/sqlparser/EscapeHandler.java deleted file mode 100644 index 2976b0daf20..00000000000 --- a/compatible/src/main/java/io/seata/sqlparser/EscapeHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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 io.seata.sqlparser; - - -/** - * The interface Keyword checker. - * - */ -public interface EscapeHandler extends org.apache.seata.sqlparser.EscapeHandler { -} diff --git a/compatible/src/main/java/io/seata/sqlparser/SQLRecognizerFactory.java b/compatible/src/main/java/io/seata/sqlparser/SQLRecognizerFactory.java deleted file mode 100644 index 63d6a43b74c..00000000000 --- a/compatible/src/main/java/io/seata/sqlparser/SQLRecognizerFactory.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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 io.seata.sqlparser; - - -public interface SQLRecognizerFactory extends org.apache.seata.sqlparser.SQLRecognizerFactory { -} diff --git a/compatible/src/main/java/io/seata/sqlparser/druid/SQLOperateRecognizerHolder.java b/compatible/src/main/java/io/seata/sqlparser/druid/SQLOperateRecognizerHolder.java deleted file mode 100644 index bfe8a96c772..00000000000 --- a/compatible/src/main/java/io/seata/sqlparser/druid/SQLOperateRecognizerHolder.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 io.seata.sqlparser.druid; - - -/** - * The interface SQLOperateRecognizerHolder - * - */ -public interface SQLOperateRecognizerHolder extends org.apache.seata.sqlparser.druid.SQLOperateRecognizerHolder { - -} diff --git a/compatible/src/main/java/io/seata/sqlparser/struct/TableMetaCache.java b/compatible/src/main/java/io/seata/sqlparser/struct/TableMetaCache.java deleted file mode 100644 index bcc2c0e50e3..00000000000 --- a/compatible/src/main/java/io/seata/sqlparser/struct/TableMetaCache.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 io.seata.sqlparser.struct; - - -/** - * The type Table meta cache. - * - */ -public interface TableMetaCache extends org.apache.seata.sqlparser.struct.TableMetaCache { - -} diff --git a/compatible/src/main/java/io/seata/sqlparser/util/DbTypeParser.java b/compatible/src/main/java/io/seata/sqlparser/util/DbTypeParser.java deleted file mode 100644 index 73b85f9e403..00000000000 --- a/compatible/src/main/java/io/seata/sqlparser/util/DbTypeParser.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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 io.seata.sqlparser.util; - - -public interface DbTypeParser extends org.apache.seata.sqlparser.util.DbTypeParser { -} diff --git a/compatible/src/test/java/io/seata/rm/datasource/DataSourceProxyTest.java b/compatible/src/test/java/io/seata/rm/datasource/DataSourceProxyTest.java new file mode 100644 index 00000000000..0460ebeff91 --- /dev/null +++ b/compatible/src/test/java/io/seata/rm/datasource/DataSourceProxyTest.java @@ -0,0 +1,100 @@ +/* + * 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 io.seata.rm.datasource; + +import java.sql.Connection; + +import javax.sql.DataSource; + +import com.alibaba.druid.pool.DruidDataSource; +import io.seata.rm.datasource.mock.MockDataSource; +import io.seata.rm.datasource.mock.MockDriver; +import org.apache.seata.rm.datasource.undo.UndoLogManagerFactory; +import org.apache.seata.rm.datasource.undo.mysql.MySQLUndoLogManager; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +public class DataSourceProxyTest { + + @Test + public void test_constructor() { + DataSource dataSource = new MockDataSource(); + DataSourceProxy dataSourceProxy = new DataSourceProxy(dataSource); + Assertions.assertEquals(dataSourceProxy.getTargetDataSource(), dataSource); + + DataSourceProxy dataSourceProxy2 = new DataSourceProxy(dataSourceProxy); + Assertions.assertEquals(dataSourceProxy2.getTargetDataSource(), dataSource); + } + + @Test + public void testNotSupportDb() { + final MockDriver mockDriver = new MockDriver(); + final String username = "username"; + final String jdbcUrl = "jdbc:mock:xxx"; + + // create data source + final DruidDataSource dataSource = new DruidDataSource(); + dataSource.setUrl(jdbcUrl); + dataSource.setDriver(mockDriver); + dataSource.setUsername(username); + dataSource.setPassword("password"); + + Throwable throwable = Assertions.assertThrows(IllegalStateException.class, () -> new DataSourceProxy(dataSource)); + assertThat(throwable).hasMessageContaining("AT mode don't support the the dbtype"); + } + + + @Test + public void testUndologTableNotExist() { + DataSource dataSource = new MockDataSource(); + + MockedStatic undoLogManagerFactoryMockedStatic = Mockito.mockStatic(UndoLogManagerFactory.class); + + MySQLUndoLogManager mysqlUndoLogManager = mock(MySQLUndoLogManager.class); + undoLogManagerFactoryMockedStatic.when(()->UndoLogManagerFactory.getUndoLogManager(anyString())) + .thenReturn(mysqlUndoLogManager); + + doReturn(false).when(mysqlUndoLogManager).hasUndoLogTable(any(Connection.class)); + + Throwable throwable = Assertions.assertThrows(IllegalStateException.class, () -> new DataSourceProxy(dataSource)); + undoLogManagerFactoryMockedStatic.close(); + + assertThat(throwable).hasMessageContaining("table not exist"); + } + + // to skip the db & undolog table check + public static DataSourceProxy getDataSourceProxy(DataSource dataSource) { + try (MockedStatic undoLogManagerFactoryMockedStatic = Mockito.mockStatic(UndoLogManagerFactory.class)) { + MySQLUndoLogManager mysqlUndoLogManager = mock(MySQLUndoLogManager.class); + undoLogManagerFactoryMockedStatic.when(() -> UndoLogManagerFactory.getUndoLogManager(anyString())).thenReturn(mysqlUndoLogManager); + + doReturn(true).when(mysqlUndoLogManager).hasUndoLogTable(any(Connection.class)); + + // create data source proxy + return new DataSourceProxy(dataSource); + } + } +} diff --git a/compatible/src/test/java/io/seata/rm/datasource/mock/MockBlob.java b/compatible/src/test/java/io/seata/rm/datasource/mock/MockBlob.java new file mode 100644 index 00000000000..7921e495bd3 --- /dev/null +++ b/compatible/src/test/java/io/seata/rm/datasource/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 io.seata.rm.datasource.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/compatible/src/test/java/io/seata/rm/datasource/mock/MockClob.java b/compatible/src/test/java/io/seata/rm/datasource/mock/MockClob.java new file mode 100644 index 00000000000..c5231d1e427 --- /dev/null +++ b/compatible/src/test/java/io/seata/rm/datasource/mock/MockClob.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 io.seata.rm.datasource.mock; + +import java.io.ByteArrayInputStream; +import java.io.CharArrayReader; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +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/compatible/src/test/java/io/seata/rm/datasource/mock/MockConnection.java b/compatible/src/test/java/io/seata/rm/datasource/mock/MockConnection.java new file mode 100644 index 00000000000..e87db43cff1 --- /dev/null +++ b/compatible/src/test/java/io/seata/rm/datasource/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 io.seata.rm.datasource.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/compatible/src/test/java/io/seata/rm/datasource/mock/MockDataSource.java b/compatible/src/test/java/io/seata/rm/datasource/mock/MockDataSource.java new file mode 100644 index 00000000000..7854c43b0eb --- /dev/null +++ b/compatible/src/test/java/io/seata/rm/datasource/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 io.seata.rm.datasource.mock; + +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.util.logging.Logger; + +import javax.sql.DataSource; + +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/compatible/src/test/java/io/seata/rm/datasource/mock/MockDatabaseMetaData.java b/compatible/src/test/java/io/seata/rm/datasource/mock/MockDatabaseMetaData.java new file mode 100644 index 00000000000..a4abb1489ef --- /dev/null +++ b/compatible/src/test/java/io/seata/rm/datasource/mock/MockDatabaseMetaData.java @@ -0,0 +1,1013 @@ +/* + * 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 io.seata.rm.datasource.mock; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.RowIdLifetime; +import java.sql.SQLException; +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 Object[][] columnsMetasReturnValue; + + private Object[][] indexMetasReturnValue; + + private Object[][] pkMetasReturnValue; + + private Object[][] mockColumnsMetasReturnValue; + + /** + * 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(); + } + + @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 null; + } + + @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/compatible/src/test/java/io/seata/rm/datasource/mock/MockDriver.java b/compatible/src/test/java/io/seata/rm/datasource/mock/MockDriver.java new file mode 100644 index 00000000000..968bf33777f --- /dev/null +++ b/compatible/src/test/java/io/seata/rm/datasource/mock/MockDriver.java @@ -0,0 +1,202 @@ +/* + * 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 io.seata.rm.datasource.mock; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Properties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.druid.mock.MockStatementBase; +import com.alibaba.druid.mock.handler.MockExecuteHandler; +import com.google.common.collect.Lists; + +/** + * 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; + + /** + * + */ + 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[][]{}); + } + + public MockDriver(Object[][] mockColumnsMetasReturnValue, Object[][] mockIndexMetasReturnValue, Object[][] mockPkMetasReturnValue) { + this(Lists.newArrayList(), new Object[][]{}, mockColumnsMetasReturnValue, mockIndexMetasReturnValue, mockPkMetasReturnValue); + } + + public MockDriver(List mockReturnValueColumnLabels, Object[][] mockReturnValue, Object[][] mockColumnsMetasReturnValue, Object[][] mockIndexMetasReturnValue) { + this(mockReturnValueColumnLabels, mockReturnValue, mockColumnsMetasReturnValue, mockIndexMetasReturnValue, new Object[][]{}); + } + + public MockDriver(List mockReturnValueColumnLabels, Object[][] mockReturnValue, Object[][] mockColumnsMetasReturnValue, Object[][] mockIndexMetasReturnValue, Object[][] mockPkMetasReturnValue) { + this(mockReturnValueColumnLabels, mockReturnValue, mockColumnsMetasReturnValue, mockIndexMetasReturnValue, mockPkMetasReturnValue, new Object[][]{}); + } + + /** + * Instantiate a new MockDriver + */ + public MockDriver(List mockReturnValueColumnLabels, Object[][] mockReturnValue, Object[][] mockColumnsMetasReturnValue, Object[][] mockIndexMetasReturnValue, Object[][] mockPkMetasReturnValue, Object[][] mockOnUpdateColumnsReturnValue) { + 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; + } + + /** + * 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; + } +} diff --git a/compatible/src/test/java/io/seata/rm/datasource/mock/MockExecuteHandlerImpl.java b/compatible/src/test/java/io/seata/rm/datasource/mock/MockExecuteHandlerImpl.java new file mode 100644 index 00000000000..5d711164ad6 --- /dev/null +++ b/compatible/src/test/java/io/seata/rm/datasource/mock/MockExecuteHandlerImpl.java @@ -0,0 +1,96 @@ +/* + * 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 io.seata.rm.datasource.mock; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.seata.sqlparser.druid.mysql.MySQLSelectForUpdateRecognizer; +import org.apache.seata.sqlparser.util.JdbcConstants; + +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; + + +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/compatible/src/test/java/io/seata/rm/datasource/mock/MockParameterMetaData.java b/compatible/src/test/java/io/seata/rm/datasource/mock/MockParameterMetaData.java new file mode 100644 index 00000000000..093958fbc74 --- /dev/null +++ b/compatible/src/test/java/io/seata/rm/datasource/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 io.seata.rm.datasource.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/compatible/src/test/java/io/seata/rm/datasource/mock/MockPreparedStatement.java b/compatible/src/test/java/io/seata/rm/datasource/mock/MockPreparedStatement.java new file mode 100644 index 00000000000..d9fc98c2cf0 --- /dev/null +++ b/compatible/src/test/java/io/seata/rm/datasource/mock/MockPreparedStatement.java @@ -0,0 +1,66 @@ +/* + * 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 io.seata.rm.datasource.mock; + +import java.sql.ParameterMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; + +import com.alibaba.druid.mock.MockStatementBase; +import com.alibaba.druid.util.jdbc.PreparedStatementBase; + +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/compatible/src/test/java/io/seata/rm/datasource/mock/MockResultSet.java b/compatible/src/test/java/io/seata/rm/datasource/mock/MockResultSet.java new file mode 100644 index 00000000000..84d2d00142e --- /dev/null +++ b/compatible/src/test/java/io/seata/rm/datasource/mock/MockResultSet.java @@ -0,0 +1,172 @@ +/* + * 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 io.seata.rm.datasource.mock; + +import java.sql.Blob; +import java.sql.Clob; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +import org.apache.seata.sqlparser.struct.ColumnMeta; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.druid.util.jdbc.ResultSetBase; +import com.google.common.collect.Lists; + + +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/compatible/src/test/java/io/seata/rm/datasource/mock/MockResultSetMetaData.java b/compatible/src/test/java/io/seata/rm/datasource/mock/MockResultSetMetaData.java new file mode 100644 index 00000000000..b36d5cbd803 --- /dev/null +++ b/compatible/src/test/java/io/seata/rm/datasource/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 io.seata.rm.datasource.mock; + +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.List; + +import org.apache.seata.common.util.ReflectionUtil; +import org.apache.seata.sqlparser.struct.ColumnMeta; + + +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/compatible/src/test/java/io/seata/rm/datasource/xa/DataSourceProxyXATest.java b/compatible/src/test/java/io/seata/rm/datasource/xa/DataSourceProxyXATest.java new file mode 100644 index 00000000000..51d83dc1b6e --- /dev/null +++ b/compatible/src/test/java/io/seata/rm/datasource/xa/DataSourceProxyXATest.java @@ -0,0 +1,134 @@ +/* + * 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 io.seata.rm.datasource.xa; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.Driver; +import java.sql.SQLException; + +import javax.sql.DataSource; +import javax.sql.PooledConnection; +import javax.sql.XAConnection; + +import com.alibaba.druid.pool.DruidDataSource; + +import com.mysql.jdbc.JDBC4MySQLConnection; +import com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper; +import io.seata.rm.datasource.mock.MockDataSource; +import io.seata.core.context.RootContext; +import org.apache.seata.rm.datasource.xa.ConnectionProxyXA; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + + +import static org.mockito.ArgumentMatchers.any; + +/** + * Tests for DataSourceProxyXA + */ +public class DataSourceProxyXATest { + + + @Test + public void test_constructor() { + DataSource dataSource = new MockDataSource(); + + DataSourceProxyXA dataSourceProxy = new DataSourceProxyXA(dataSource); + Assertions.assertEquals(dataSourceProxy.getTargetDataSource(), dataSource); + + DataSourceProxyXA dataSourceProxy2 = new DataSourceProxyXA(dataSourceProxy); + Assertions.assertEquals(dataSourceProxy2.getTargetDataSource(), dataSource); + } + + @Test + public void testGetConnection() throws SQLException { + // Mock + Driver driver = Mockito.mock(Driver.class); + JDBC4MySQLConnection connection = Mockito.mock(JDBC4MySQLConnection.class); + Mockito.when(connection.getAutoCommit()).thenReturn(true); + DatabaseMetaData metaData = Mockito.mock(DatabaseMetaData.class); + Mockito.when(metaData.getURL()).thenReturn("jdbc:mysql:xxx"); + Mockito.when(connection.getMetaData()).thenReturn(metaData); + Mockito.when(driver.connect(any(), any())).thenReturn(connection); + + DruidDataSource druidDataSource = new DruidDataSource(); + druidDataSource.setDriver(driver); + DataSourceProxyXA dataSourceProxyXA = new DataSourceProxyXA(druidDataSource); + RootContext.unbind(); + Connection connFromDataSourceProxyXA = dataSourceProxyXA.getConnection(); + Assertions.assertFalse(connFromDataSourceProxyXA instanceof ConnectionProxyXA); + RootContext.bind("test"); + connFromDataSourceProxyXA = dataSourceProxyXA.getConnection(); + Assertions.assertTrue(connFromDataSourceProxyXA instanceof ConnectionProxyXA); + ConnectionProxyXA connectionProxyXA = (ConnectionProxyXA)dataSourceProxyXA.getConnection(); + + Connection wrappedConnection = connectionProxyXA.getWrappedConnection(); + Assertions.assertTrue(wrappedConnection instanceof PooledConnection); + + Connection wrappedPhysicalConn = ((PooledConnection)wrappedConnection).getConnection(); + Assertions.assertSame(wrappedPhysicalConn, connection); + + XAConnection xaConnection = connectionProxyXA.getWrappedXAConnection(); + Connection connectionInXA = xaConnection.getConnection(); + Assertions.assertTrue(connectionInXA instanceof JDBC4ConnectionWrapper); + tearDown(); + } + + @Test + public void testGetMariaXaConnection() throws SQLException, ClassNotFoundException { + // Mock + Driver driver = Mockito.mock(Driver.class); + Class clazz = Class.forName("org.mariadb.jdbc.MariaDbConnection"); + Connection connection = (Connection)(Mockito.mock(clazz)); + Mockito.when(connection.getAutoCommit()).thenReturn(true); + DatabaseMetaData metaData = Mockito.mock(DatabaseMetaData.class); + Mockito.when(metaData.getURL()).thenReturn("jdbc:mariadb:xxx"); + Mockito.when(connection.getMetaData()).thenReturn(metaData); + Mockito.when(driver.connect(any(), any())).thenReturn(connection); + + DruidDataSource druidDataSource = new DruidDataSource(); + druidDataSource.setDriver(driver); + DataSourceProxyXA dataSourceProxyXA = new DataSourceProxyXA(druidDataSource); + RootContext.unbind(); + Connection connFromDataSourceProxyXA = dataSourceProxyXA.getConnection(); + Assertions.assertFalse(connFromDataSourceProxyXA instanceof ConnectionProxyXA); + RootContext.bind("test"); + connFromDataSourceProxyXA = dataSourceProxyXA.getConnection(); + + Assertions.assertTrue(connFromDataSourceProxyXA instanceof ConnectionProxyXA); + ConnectionProxyXA connectionProxyXA = (ConnectionProxyXA)dataSourceProxyXA.getConnection(); + + Connection wrappedConnection = connectionProxyXA.getWrappedConnection(); + Assertions.assertTrue(wrappedConnection instanceof PooledConnection); + + Connection wrappedPhysicalConn = ((PooledConnection)wrappedConnection).getConnection(); + Assertions.assertSame(wrappedPhysicalConn, connection); + + XAConnection xaConnection = connectionProxyXA.getWrappedXAConnection(); + Connection connectionInXA = xaConnection.getConnection(); + Assertions.assertEquals("org.mariadb.jdbc.MariaDbConnection", connectionInXA.getClass().getName()); + } + + @AfterEach + public void tearDown() { + RootContext.unbind(); + } +} diff --git a/compatible/src/test/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java b/compatible/src/test/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java index b8dc1f9a92a..3f6cb45e958 100644 --- a/compatible/src/test/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java +++ b/compatible/src/test/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java @@ -45,11 +45,14 @@ import org.apache.seata.tm.TransactionManagerHolder; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; class TccActionInterceptorParserTest { + private static ResourceManager resourceManager; + @BeforeAll public static void init() throws IOException { System.setProperty("config.type", "file"); @@ -58,6 +61,34 @@ public static void init() throws IOException { System.setProperty("service.vgroupMapping.default_tx_group", "default"); } + @BeforeEach + private void before() { + resourceManager = new TCCResourceManager() { + + @Override + public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid, String applicationData, String lockKeys) throws TransactionException { + + long branchId = System.currentTimeMillis(); + + List branches = applicationDataMap.computeIfAbsent(xid, s -> new ArrayList<>()); + BranchSessionMock branchSessionMock = new BranchSessionMock(); + branchSessionMock.setXid(xid); + branchSessionMock.setBranchType(branchType); + branchSessionMock.setResourceId(resourceId); + branchSessionMock.setApplicationData(applicationData); + branchSessionMock.setBranchId(branchId); + + branches.add(branchSessionMock); + + return branchId; + } + }; + RootContext.unbind(); + DefaultResourceManager.get(); + DefaultResourceManager.mockResourceManager(BranchType.TCC, resourceManager); + TransactionManagerHolder.set(transactionManager); + } + @Test void parserInterfaceToProxy() { @@ -77,14 +108,9 @@ void parserInterfaceToProxy() { @Test public void testNestTcc_should_commit() throws Exception { //given - RootContext.unbind(); - DefaultResourceManager.get(); - DefaultResourceManager.mockResourceManager(BranchType.TCC, resourceManager); - - TransactionManagerHolder.set(transactionManager); TccActionImpl tccAction = new TccActionImpl(); - TccAction tccActionProxy = ProxyUtil.createProxy(tccAction); + TccAction tccActionProxy = ProxyUtil.createProxy(tccAction, "oldtccAction"); Assertions.assertNotNull(tccActionProxy); NestTccActionImpl nestTccAction = new NestTccActionImpl(); @@ -98,7 +124,7 @@ public void testNestTcc_should_commit() throws Exception { //when - NestTccAction nestTccActionProxy = ProxyUtil.createProxy(nestTccAction); + NestTccAction nestTccActionProxy = ProxyUtil.createProxy(nestTccAction, "oldnestTccAction"); //then Assertions.assertNotNull(nestTccActionProxy); @@ -131,15 +157,9 @@ public void testNestTcc_should_commit() throws Exception { @Test public void testNestTcc_should_rollback() throws Exception { - //given - RootContext.unbind(); - DefaultResourceManager.get(); - DefaultResourceManager.mockResourceManager(BranchType.TCC, resourceManager); - - TransactionManagerHolder.set(transactionManager); TccActionImpl tccAction = new TccActionImpl(); - TccAction tccActionProxy = ProxyUtil.createProxy(tccAction); + TccAction tccActionProxy = ProxyUtil.createProxy(tccAction, "oldtccAction"); Assertions.assertNotNull(tccActionProxy); NestTccActionImpl nestTccAction = new NestTccActionImpl(); @@ -153,7 +173,7 @@ public void testNestTcc_should_rollback() throws Exception { //when - NestTccAction nestTccActionProxy = ProxyUtil.createProxy(nestTccAction); + NestTccAction nestTccActionProxy = ProxyUtil.createProxy(nestTccAction, "oldnestTccAction"); //then Assertions.assertNotNull(nestTccActionProxy); @@ -186,15 +206,9 @@ public void testNestTcc_should_rollback() throws Exception { @Test public void testNestTcc_required_new_should_rollback_commit() throws Exception { - //given - RootContext.unbind(); - DefaultResourceManager.get(); - DefaultResourceManager.mockResourceManager(BranchType.TCC, resourceManager); - - TransactionManagerHolder.set(transactionManager); TccActionImpl tccAction = new TccActionImpl(); - TccAction tccActionProxy = ProxyUtil.createProxy(tccAction); + TccAction tccActionProxy = ProxyUtil.createProxy(tccAction, "oldtccAction"); Assertions.assertNotNull(tccActionProxy); NestTccActionImpl nestTccAction = new NestTccActionImpl(); @@ -207,7 +221,7 @@ public void testNestTcc_required_new_should_rollback_commit() throws Exception { Assertions.assertNotNull(proxyInvocationHandler); //when - NestTccAction nestTccActionProxy = ProxyUtil.createProxy(nestTccAction); + NestTccAction nestTccActionProxy = ProxyUtil.createProxy(nestTccAction, "oldtccActionProxy"); //then Assertions.assertNotNull(nestTccActionProxy); @@ -241,15 +255,9 @@ public void testNestTcc_required_new_should_rollback_commit() throws Exception { @Test public void testNestTcc_required_new_should_both_commit() throws Exception { - //given - RootContext.unbind(); - DefaultResourceManager.get(); - DefaultResourceManager.mockResourceManager(BranchType.TCC, resourceManager); - - TransactionManagerHolder.set(transactionManager); TccActionImpl tccAction = new TccActionImpl(); - TccAction tccActionProxy = ProxyUtil.createProxy(tccAction); + TccAction tccActionProxy = ProxyUtil.createProxy(tccAction, "oldtccAction"); Assertions.assertNotNull(tccActionProxy); NestTccActionImpl nestTccAction = new NestTccActionImpl(); @@ -262,7 +270,7 @@ public void testNestTcc_required_new_should_both_commit() throws Exception { Assertions.assertNotNull(proxyInvocationHandler); //when - NestTccAction nestTccActionProxy = ProxyUtil.createProxy(nestTccAction); + NestTccAction nestTccActionProxy = ProxyUtil.createProxy(nestTccAction, "oldnestTccActionProxy"); //then Assertions.assertNotNull(nestTccActionProxy); @@ -329,27 +337,6 @@ public GlobalStatus globalReport(String xid, GlobalStatus globalStatus) throws T }; - private static ResourceManager resourceManager = new TCCResourceManager() { - - @Override - public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid, String applicationData, String lockKeys) throws TransactionException { - - long branchId = System.currentTimeMillis(); - - List branches = applicationDataMap.computeIfAbsent(xid, s -> new ArrayList<>()); - BranchSessionMock branchSessionMock = new BranchSessionMock(); - branchSessionMock.setXid(xid); - branchSessionMock.setBranchType(branchType); - branchSessionMock.setResourceId(resourceId); - branchSessionMock.setApplicationData(applicationData); - branchSessionMock.setBranchId(branchId); - - branches.add(branchSessionMock); - - return branchId; - } - }; - public static void commitAll(String xid) throws TransactionException { List branches = applicationDataMap.computeIfAbsent(xid, s -> new ArrayList<>()); @@ -365,5 +352,4 @@ public static void rollbackAll(String xid) throws TransactionException { resourceManager.branchRollback(branch.getBranchType(), branch.getXid(), branch.getBranchId(), branch.getResourceId(), branch.getApplicationData()); } } - } diff --git a/compatible/src/test/java/io/seata/tm/api/DefaultFailureHandlerImplTest.java b/compatible/src/test/java/io/seata/tm/api/DefaultFailureHandlerImplTest.java index 58893984989..260e2e09e60 100644 --- a/compatible/src/test/java/io/seata/tm/api/DefaultFailureHandlerImplTest.java +++ b/compatible/src/test/java/io/seata/tm/api/DefaultFailureHandlerImplTest.java @@ -88,7 +88,7 @@ void onCommitFailure() throws Exception{ // get timer Class c = Class.forName("io.seata.tm.api.DefaultFailureHandlerImpl"); - Field field = c.getSuperclass().getDeclaredField("TIMER"); + Field field = c.getDeclaredField("TIMER"); field.setAccessible(true); HashedWheelTimer timer = (HashedWheelTimer) field.get(failureHandler); // assert timer pendingCount: first time is 1 @@ -115,7 +115,7 @@ void onRollbackFailure() throws Exception { // get timer Class c = Class.forName("io.seata.tm.api.DefaultFailureHandlerImpl"); - Field field = c.getSuperclass().getDeclaredField("TIMER"); + Field field = c.getDeclaredField("TIMER"); field.setAccessible(true); HashedWheelTimer timer = (HashedWheelTimer) field.get(failureHandler); // assert timer pendingCount: first time is 1 diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/xa/ConnectionProxyXATest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/ConnectionProxyXATest.java similarity index 98% rename from rm-datasource/src/test/java/org/apache/seata/rm/xa/ConnectionProxyXATest.java rename to rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/ConnectionProxyXATest.java index 18a48ace9e7..76d3670a09c 100644 --- a/rm-datasource/src/test/java/org/apache/seata/rm/xa/ConnectionProxyXATest.java +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/ConnectionProxyXATest.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.seata.rm.xa; +package org.apache.seata.rm.datasource.xa; import org.apache.seata.core.context.RootContext; import org.apache.seata.core.model.BranchType; @@ -22,8 +22,6 @@ import org.apache.seata.core.model.ResourceManager; import org.apache.seata.rm.BaseDataSourceResource; import org.apache.seata.rm.DefaultResourceManager; -import org.apache.seata.rm.datasource.xa.ConnectionProxyXA; -import org.apache.seata.rm.datasource.xa.StatementProxyXA; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/xa/DataSourceProxyXANativeTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/DataSourceProxyXANativeTest.java similarity index 94% rename from rm-datasource/src/test/java/org/apache/seata/rm/xa/DataSourceProxyXANativeTest.java rename to rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/DataSourceProxyXANativeTest.java index 9bb5dfd0627..472b9e9ff1d 100644 --- a/rm-datasource/src/test/java/org/apache/seata/rm/xa/DataSourceProxyXANativeTest.java +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/DataSourceProxyXANativeTest.java @@ -14,10 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.seata.rm.xa; +package org.apache.seata.rm.datasource.xa; -import org.apache.seata.rm.datasource.xa.ConnectionProxyXA; -import org.apache.seata.rm.datasource.xa.DataSourceProxyXANative; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.mockito.Mockito; diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/xa/DataSourceProxyXATest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/DataSourceProxyXATest.java similarity index 97% rename from rm-datasource/src/test/java/org/apache/seata/rm/xa/DataSourceProxyXATest.java rename to rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/DataSourceProxyXATest.java index d72210e5e5a..417bda69f36 100644 --- a/rm-datasource/src/test/java/org/apache/seata/rm/xa/DataSourceProxyXATest.java +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/DataSourceProxyXATest.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.seata.rm.xa; +package org.apache.seata.rm.datasource.xa; import java.sql.Connection; import java.sql.DatabaseMetaData; @@ -31,8 +31,6 @@ import com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper; import org.apache.seata.core.context.RootContext; import org.apache.seata.rm.datasource.mock.MockDataSource; -import org.apache.seata.rm.datasource.xa.ConnectionProxyXA; -import org.apache.seata.rm.datasource.xa.DataSourceProxyXA; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/xa/XAXidBuilderTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/XAXidBuilderTest.java similarity index 97% rename from rm-datasource/src/test/java/org/apache/seata/rm/xa/XAXidBuilderTest.java rename to rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/XAXidBuilderTest.java index e1af73dafb1..60cd0785558 100644 --- a/rm-datasource/src/test/java/org/apache/seata/rm/xa/XAXidBuilderTest.java +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/xa/XAXidBuilderTest.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.seata.rm.xa; +package org.apache.seata.rm.datasource.xa; import org.apache.seata.rm.datasource.xa.XAXid; import org.apache.seata.rm.datasource.xa.XAXidBuilder;