This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 6bfad9e5a114e53c5b6f211a2b236d4d93d2ff28 Author: Andrus Adamchik <[email protected]> AuthorDate: Wed May 13 15:29:51 2026 -0400 removing obsolete test mock dependency --- cayenne/pom.xml | 17 - .../cayenne/access/jdbc/BatchActionLockingIT.java | 20 +- .../access/jdbc/JDBCResultIteratorTest.java | 18 +- .../cayenne/access/types/BooleanTypeTest.java | 14 +- .../apache/cayenne/access/types/EnumTypeTest.java | 10 +- .../configuration/mock/MockDataSourceFactory.java | 4 +- .../runtime/DefaultDbAdapterFactoryTest.java | 16 +- .../runtime/JNDIDataSourceFactoryIT.java | 6 +- .../apache/cayenne/unit/jdbc/TestConnection.java | 227 ++++++++++ .../apache/cayenne/unit/jdbc/TestDataSource.java | 57 +++ .../cayenne/unit/jdbc/TestPreparedStatement.java | 137 ++++++ .../apache/cayenne/unit/jdbc/TestResultSet.java | 493 +++++++++++++++++++++ .../apache/cayenne/unit/jdbc/TestStatement.java | 105 +++++ pom.xml | 5 - 14 files changed, 1056 insertions(+), 73 deletions(-) diff --git a/cayenne/pom.xml b/cayenne/pom.xml index 686fc8930..af6a7b05d 100644 --- a/cayenne/pom.xml +++ b/cayenne/pom.xml @@ -62,23 +62,6 @@ <version>${project.version}</version> <scope>test</scope> </dependency> - <dependency> - <groupId>com.mockrunner</groupId> - <artifactId>mockrunner-jdbc</artifactId> - <scope>test</scope> - <exclusions> - <exclusion> - <!-- this one have old Xerces dependency that clashes with JDK's one --> - <groupId>nekohtml</groupId> - <artifactId>nekohtml</artifactId> - </exclusion> - <exclusion> - <!-- don't use anything related to this, and this is an old version --> - <groupId>ant</groupId> - <artifactId>ant</artifactId> - </exclusion> - </exclusions> - </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> diff --git a/cayenne/src/test/java/org/apache/cayenne/access/jdbc/BatchActionLockingIT.java b/cayenne/src/test/java/org/apache/cayenne/access/jdbc/BatchActionLockingIT.java index e791f9714..2fead147d 100644 --- a/cayenne/src/test/java/org/apache/cayenne/access/jdbc/BatchActionLockingIT.java +++ b/cayenne/src/test/java/org/apache/cayenne/access/jdbc/BatchActionLockingIT.java @@ -19,8 +19,6 @@ package org.apache.cayenne.access.jdbc; -import com.mockrunner.jdbc.PreparedStatementResultSetHandler; -import com.mockrunner.mock.jdbc.MockConnection; import org.apache.cayenne.access.DataNode; import org.apache.cayenne.access.MockOperationObserver; import org.apache.cayenne.access.OptimisticLockException; @@ -33,7 +31,7 @@ import org.apache.cayenne.map.DbAttribute; import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.EntityResolver; import org.apache.cayenne.query.DeleteBatchQuery; -import org.apache.cayenne.runtime.CayenneRuntime; +import org.apache.cayenne.unit.jdbc.TestConnection; import org.apache.cayenne.testdo.locking.SimpleLockingTestEntity; import org.apache.cayenne.unit.di.runtime.CayenneProjects; import org.apache.cayenne.unit.di.runtime.CayenneTestsEnv; @@ -78,12 +76,8 @@ public class BatchActionLockingIT { DeleteBatchTranslator batchQueryBuilder = new DeleteBatchTranslator(batchQuery, adapter); - MockConnection mockConnection = new MockConnection(); - PreparedStatementResultSetHandler preparedStatementResultSetHandler = mockConnection - .getPreparedStatementResultSetHandler(); - preparedStatementResultSetHandler.setExactMatch(false); - preparedStatementResultSetHandler.setCaseSensitive(false); - preparedStatementResultSetHandler.prepareUpdateCount("DELETE", 1); + TestConnection mockConnection = new TestConnection(); + mockConnection.prepareUpdateCount("DELETE", 1); boolean generatesKeys = false; @@ -120,12 +114,8 @@ public class BatchActionLockingIT { DeleteBatchTranslator batchQueryBuilder = new DeleteBatchTranslator(batchQuery, adapter); - MockConnection mockConnection = new MockConnection(); - PreparedStatementResultSetHandler preparedStatementResultSetHandler = mockConnection - .getPreparedStatementResultSetHandler(); - preparedStatementResultSetHandler.setExactMatch(false); - preparedStatementResultSetHandler.setCaseSensitive(false); - preparedStatementResultSetHandler.prepareUpdateCount("DELETE", 0); + TestConnection mockConnection = new TestConnection(); + mockConnection.prepareUpdateCount("DELETE", 0); boolean generatesKeys = false; DataNode node = new DataNode(); diff --git a/cayenne/src/test/java/org/apache/cayenne/access/jdbc/JDBCResultIteratorTest.java b/cayenne/src/test/java/org/apache/cayenne/access/jdbc/JDBCResultIteratorTest.java index 4fc83d6bb..f579764d7 100644 --- a/cayenne/src/test/java/org/apache/cayenne/access/jdbc/JDBCResultIteratorTest.java +++ b/cayenne/src/test/java/org/apache/cayenne/access/jdbc/JDBCResultIteratorTest.java @@ -19,9 +19,6 @@ package org.apache.cayenne.access.jdbc; -import com.mockrunner.mock.jdbc.MockConnection; -import com.mockrunner.mock.jdbc.MockResultSet; -import com.mockrunner.mock.jdbc.MockStatement; import org.apache.cayenne.DataRow; import org.apache.cayenne.access.jdbc.reader.DefaultRowReaderFactory; import org.apache.cayenne.access.jdbc.reader.RowReader; @@ -29,6 +26,9 @@ import org.apache.cayenne.access.types.ExtendedTypeMap; import org.apache.cayenne.dba.DbAdapter; import org.apache.cayenne.map.ObjAttribute; import org.apache.cayenne.query.MockQueryMetadata; +import org.apache.cayenne.unit.jdbc.TestConnection; +import org.apache.cayenne.unit.jdbc.TestResultSet; +import org.apache.cayenne.unit.jdbc.TestStatement; import org.junit.jupiter.api.Test; import java.sql.Connection; @@ -45,9 +45,9 @@ public class JDBCResultIteratorTest { @Test public void nextDataRow() throws Exception { - Connection c = new MockConnection(); - Statement s = new MockStatement(c); - MockResultSet rs = new MockResultSet("rs"); + Connection c = new TestConnection(); + Statement s = new TestStatement(c); + TestResultSet rs = new TestResultSet("rs"); rs.addColumn("a", new Object[] { "1", "2", "3" }); RowDescriptor descriptor = new RowDescriptorBuilder().setResultSet(rs).getDescriptor(new ExtendedTypeMap()); @@ -65,9 +65,9 @@ public class JDBCResultIteratorTest { @Test public void close() throws Exception { - Connection c = new MockConnection(); - MockStatement s = new MockStatement(c); - MockResultSet rs = new MockResultSet("rs"); + Connection c = new TestConnection(); + TestStatement s = new TestStatement(c); + TestResultSet rs = new TestResultSet("rs"); rs.addColumn("a", new Object[] { "1", "2", "3" }); RowReader<?> rowReader = mock(RowReader.class); diff --git a/cayenne/src/test/java/org/apache/cayenne/access/types/BooleanTypeTest.java b/cayenne/src/test/java/org/apache/cayenne/access/types/BooleanTypeTest.java index c8e402d85..b5a1eb76e 100644 --- a/cayenne/src/test/java/org/apache/cayenne/access/types/BooleanTypeTest.java +++ b/cayenne/src/test/java/org/apache/cayenne/access/types/BooleanTypeTest.java @@ -19,10 +19,9 @@ package org.apache.cayenne.access.types; -import java.sql.SQLException; import java.sql.Types; -import com.mockrunner.mock.jdbc.MockResultSet; +import org.apache.cayenne.unit.jdbc.TestResultSet; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -41,13 +40,10 @@ public class BooleanTypeTest { @Test public void materializeObjectFromResultSet() throws Exception { - MockResultSet rs = new MockResultSet("") { - - @Override - public boolean getBoolean(int i) throws SQLException { - return (i + 2) % 2 == 0; - } - }; + TestResultSet rs = new TestResultSet(""); + rs.addColumn("odd", new Object[]{Boolean.FALSE}); + rs.addColumn("even", new Object[]{Boolean.TRUE}); + rs.next(); BooleanType type = new BooleanType(); diff --git a/cayenne/src/test/java/org/apache/cayenne/access/types/EnumTypeTest.java b/cayenne/src/test/java/org/apache/cayenne/access/types/EnumTypeTest.java index 2d9a07630..c3c228d35 100644 --- a/cayenne/src/test/java/org/apache/cayenne/access/types/EnumTypeTest.java +++ b/cayenne/src/test/java/org/apache/cayenne/access/types/EnumTypeTest.java @@ -19,7 +19,7 @@ package org.apache.cayenne.access.types; -import com.mockrunner.mock.jdbc.MockResultSet; +import org.apache.cayenne.unit.jdbc.TestResultSet; import org.junit.jupiter.api.Test; import java.sql.Types; @@ -55,7 +55,7 @@ public class EnumTypeTest { public void materializeStringObject() throws Exception { EnumType type = new EnumType(MockEnum.class); - MockResultSet rs = new MockResultSet("Test"); + TestResultSet rs = new TestResultSet("Test"); rs.addColumn("Enum"); rs.addRow(new Object[] {"b"}); rs.next(); @@ -68,7 +68,7 @@ public class EnumTypeTest { public void materializeNumericObject() throws Exception { EnumType type = new EnumType(MockEnum.class); - MockResultSet rs = new MockResultSet("Test"); + TestResultSet rs = new TestResultSet("Test"); rs.addColumn("Enum"); rs.addRow(new Object[] {2}); rs.next(); @@ -81,7 +81,7 @@ public class EnumTypeTest { public void materializeStringObjectInnerEnum() throws Exception { EnumType type = new EnumType(InnerEnumHolder.InnerEnum.class); - MockResultSet rs = new MockResultSet("Test"); + TestResultSet rs = new TestResultSet("Test"); rs.addColumn("Enum"); rs.addRow(new Object[] {"b"}); rs.next(); @@ -94,7 +94,7 @@ public class EnumTypeTest { public void materializeNumericObjectInnerEnum() throws Exception { EnumType type = new EnumType(InnerEnumHolder.InnerEnum.class); - MockResultSet rs = new MockResultSet("Test"); + TestResultSet rs = new TestResultSet("Test"); rs.addColumn("Enum"); rs.addRow(new Object[] {2}); rs.next(); diff --git a/cayenne/src/test/java/org/apache/cayenne/configuration/mock/MockDataSourceFactory.java b/cayenne/src/test/java/org/apache/cayenne/configuration/mock/MockDataSourceFactory.java index 3baf7cb9e..ff9a5247a 100644 --- a/cayenne/src/test/java/org/apache/cayenne/configuration/mock/MockDataSourceFactory.java +++ b/cayenne/src/test/java/org/apache/cayenne/configuration/mock/MockDataSourceFactory.java @@ -23,11 +23,11 @@ import javax.sql.DataSource; import org.apache.cayenne.configuration.DataNodeDescriptor; import org.apache.cayenne.configuration.runtime.DataSourceFactory; -import com.mockrunner.mock.jdbc.MockDataSource; +import org.apache.cayenne.unit.jdbc.TestDataSource; public class MockDataSourceFactory implements DataSourceFactory { public DataSource getDataSource(DataNodeDescriptor nodeDescriptor) { - return new MockDataSource(); + return new TestDataSource(); } } diff --git a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DefaultDbAdapterFactoryTest.java b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DefaultDbAdapterFactoryTest.java index 86a0ae50a..75cf74369 100644 --- a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DefaultDbAdapterFactoryTest.java +++ b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DefaultDbAdapterFactoryTest.java @@ -18,8 +18,6 @@ ****************************************************************/ package org.apache.cayenne.configuration.runtime; -import com.mockrunner.mock.jdbc.MockConnection; -import com.mockrunner.mock.jdbc.MockDataSource; import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory; import org.apache.cayenne.access.types.DefaultValueObjectTypeRegistry; import org.apache.cayenne.access.types.ValueObjectTypeRegistry; @@ -48,6 +46,8 @@ import org.apache.cayenne.reflect.generic.DefaultValueComparisonStrategyFactory; import org.apache.cayenne.reflect.generic.ValueComparisonStrategyFactory; import org.apache.cayenne.resource.ClassLoaderResourceLocator; import org.apache.cayenne.resource.ResourceLocator; +import org.apache.cayenne.unit.jdbc.TestConnection; +import org.apache.cayenne.unit.jdbc.TestDataSource; import org.junit.jupiter.api.Test; import java.util.ArrayList; @@ -70,9 +70,9 @@ public class DefaultDbAdapterFactoryTest { List<DbAdapterDetector> detectors = new ArrayList<>(); detectors.add(md -> adapter); - MockConnection connection = new MockConnection(); + TestConnection connection = new TestConnection(); - MockDataSource dataSource = new MockDataSource(); + TestDataSource dataSource = new TestDataSource(); dataSource.setupConnection(connection); Module testModule = binder -> { @@ -124,7 +124,7 @@ public class DefaultDbAdapterFactoryTest { DefaultDbAdapterFactory factory = new DefaultDbAdapterFactory(detectors); injector.injectMembers(factory); - DbAdapter createdAdapter = factory.createAdapter(new DataNodeDescriptor(), new MockDataSource()); + DbAdapter createdAdapter = factory.createAdapter(new DataNodeDescriptor(), new TestDataSource()); assertNotNull(createdAdapter); assertTrue(createdAdapter instanceof AutoAdapter, "Unexpected class: " + createdAdapter.getClass().getName()); assertEquals("CREATE TABLE Test ()", createdAdapter.createTable(new DbEntity("Test"))); @@ -160,7 +160,7 @@ public class DefaultDbAdapterFactoryTest { DefaultDbAdapterFactory factory = new DefaultDbAdapterFactory(detectors); injector.injectMembers(factory); - DbAdapter createdAdapter = factory.createAdapter(nodeDescriptor, new MockDataSource()); + DbAdapter createdAdapter = factory.createAdapter(nodeDescriptor, new TestDataSource()); assertNotNull(createdAdapter); assertTrue(createdAdapter instanceof SybaseAdapter, "Unexpected class: " + createdAdapter.getClass().getName()); } @@ -175,9 +175,9 @@ public class DefaultDbAdapterFactoryTest { List<DbAdapterDetector> detectors = new ArrayList<>(); detectors.add(md -> adapter); - MockConnection connection = new MockConnection(); + TestConnection connection = new TestConnection(); - MockDataSource dataSource = new MockDataSource(); + TestDataSource dataSource = new TestDataSource(); dataSource.setupConnection(connection); Module testModule = binder -> { diff --git a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/JNDIDataSourceFactoryIT.java b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/JNDIDataSourceFactoryIT.java index 85a114888..5f107308e 100644 --- a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/JNDIDataSourceFactoryIT.java +++ b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/JNDIDataSourceFactoryIT.java @@ -18,8 +18,8 @@ ****************************************************************/ package org.apache.cayenne.configuration.runtime; -import com.mockrunner.mock.jdbc.MockDataSource; import org.apache.cayenne.configuration.DataNodeDescriptor; +import org.apache.cayenne.unit.jdbc.TestDataSource; import org.apache.cayenne.di.Injector; import org.apache.cayenne.unit.di.runtime.CayenneProjects; import org.apache.cayenne.unit.di.runtime.CayenneTestsEnv; @@ -45,7 +45,7 @@ public class JNDIDataSourceFactoryIT { JNDISetup.doSetup(); - MockDataSource dataSource = new MockDataSource(); + TestDataSource dataSource = new TestDataSource(); InitialContext context = new InitialContext(); context.bind(descriptor.getParameters(), dataSource); @@ -69,7 +69,7 @@ public class JNDIDataSourceFactoryIT { JNDISetup.doSetup(); - MockDataSource dataSource = new MockDataSource(); + TestDataSource dataSource = new TestDataSource(); InitialContext context = new InitialContext(); context.bind("java:comp/env/" + descriptor.getParameters(), dataSource); diff --git a/cayenne/src/test/java/org/apache/cayenne/unit/jdbc/TestConnection.java b/cayenne/src/test/java/org/apache/cayenne/unit/jdbc/TestConnection.java new file mode 100644 index 000000000..3411ca2bf --- /dev/null +++ b/cayenne/src/test/java/org/apache/cayenne/unit/jdbc/TestConnection.java @@ -0,0 +1,227 @@ +/***************************************************************** + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.unit.jdbc; + +import java.lang.reflect.Proxy; +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Savepoint; +import java.sql.Statement; +import java.sql.Struct; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Executor; + +/** + * Minimal JDBC {@link Connection} stub for tests. Tracks commits/rollbacks and + * returns {@link TestPreparedStatement}s whose {@code executeUpdate()} returns + * a value pre-configured via {@link #prepareUpdateCount(String, int)}. + */ +public class TestConnection implements Connection { + + private final List<UpdateCountRule> rules = new ArrayList<>(); + private int numberCommits; + private int numberRollbacks; + private boolean autoCommit = true; + private boolean closed; + + /** + * Registers an updateCount to be returned by {@link PreparedStatement#executeUpdate()} + * when the prepared SQL contains the given fragment (case-insensitive). + */ + public void prepareUpdateCount(String sqlFragment, int updateCount) { + rules.add(new UpdateCountRule(sqlFragment, updateCount)); + } + + public int getNumberCommits() { + return numberCommits; + } + + public int getNumberRollbacks() { + return numberRollbacks; + } + + @Override + public PreparedStatement prepareStatement(String sql) { + return new TestPreparedStatement(this, sql, updateCountFor(sql)); + } + + @Override + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) { + return prepareStatement(sql); + } + + @Override + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) { + return prepareStatement(sql); + } + + @Override + public PreparedStatement prepareStatement(String sql, String[] columnNames) { + return prepareStatement(sql); + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) { + return prepareStatement(sql); + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) { + return prepareStatement(sql); + } + + @Override + public Statement createStatement() { + return new TestStatement(this); + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency) { + return createStatement(); + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) { + return createStatement(); + } + + @Override + public void commit() { + numberCommits++; + } + + @Override + public void rollback() { + numberRollbacks++; + } + + @Override + public void rollback(Savepoint savepoint) { + numberRollbacks++; + } + + @Override + public boolean getAutoCommit() { + return autoCommit; + } + + @Override + public void setAutoCommit(boolean autoCommit) { + this.autoCommit = autoCommit; + } + + @Override + public void close() { + closed = true; + } + + @Override + public boolean isClosed() { + return closed; + } + + private int updateCountFor(String sql) { + String lower = sql == null ? "" : sql.toLowerCase(); + for (UpdateCountRule rule : rules) { + if (lower.contains(rule.fragment.toLowerCase())) { + return rule.updateCount; + } + } + return 0; + } + + private record UpdateCountRule(String fragment, int updateCount) {} + + // --- everything below is unused by tests --- + + private static UnsupportedOperationException uoe() { + return new UnsupportedOperationException("not implemented in TestConnection"); + } + + @Override public CallableStatement prepareCall(String sql) { throw uoe(); } + @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) { throw uoe(); } + @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) { throw uoe(); } + @Override public String nativeSQL(String sql) { return sql; } + @Override public DatabaseMetaData getMetaData() { return stubMetaData(); } + + private DatabaseMetaData stubMetaData() { + return (DatabaseMetaData) Proxy.newProxyInstance( + getClass().getClassLoader(), + new Class<?>[]{DatabaseMetaData.class}, + (proxy, method, args) -> { + Class<?> rt = method.getReturnType(); + if (rt == boolean.class) return false; + if (rt == int.class || rt == short.class || rt == byte.class) return 0; + if (rt == long.class) return 0L; + if (rt == float.class) return 0f; + if (rt == double.class) return 0d; + if (rt == ResultSet.class) return new TestResultSet(""); + if (rt == String.class) return ""; + if (rt == Connection.class) return this; + return null; + }); + } + @Override public void setReadOnly(boolean readOnly) {} + @Override public boolean isReadOnly() { return false; } + @Override public void setCatalog(String catalog) {} + @Override public String getCatalog() { return null; } + @Override public void setTransactionIsolation(int level) {} + @Override public int getTransactionIsolation() { return TRANSACTION_NONE; } + @Override public SQLWarning getWarnings() { return null; } + @Override public void clearWarnings() {} + @Override public Map<String, Class<?>> getTypeMap() { throw uoe(); } + @Override public void setTypeMap(Map<String, Class<?>> map) {} + @Override public void setHoldability(int holdability) {} + @Override public int getHoldability() { return 0; } + @Override public Savepoint setSavepoint() { throw uoe(); } + @Override public Savepoint setSavepoint(String name) { throw uoe(); } + @Override public void releaseSavepoint(Savepoint savepoint) {} + @Override public Clob createClob() { throw uoe(); } + @Override public Blob createBlob() { throw uoe(); } + @Override public NClob createNClob() { throw uoe(); } + @Override public SQLXML createSQLXML() { throw uoe(); } + @Override public boolean isValid(int timeout) { return !closed; } + @Override public void setClientInfo(String name, String value) throws SQLClientInfoException {} + @Override public void setClientInfo(Properties properties) throws SQLClientInfoException {} + @Override public String getClientInfo(String name) { return null; } + @Override public Properties getClientInfo() { return new Properties(); } + @Override public Array createArrayOf(String typeName, Object[] elements) { throw uoe(); } + @Override public Struct createStruct(String typeName, Object[] attributes) { throw uoe(); } + @Override public void setSchema(String schema) {} + @Override public String getSchema() { return null; } + @Override public void abort(Executor executor) {} + @Override public void setNetworkTimeout(Executor executor, int milliseconds) {} + @Override public int getNetworkTimeout() { return 0; } + @Override public <T> T unwrap(Class<T> iface) throws SQLException { throw new SQLException("not supported"); } + @Override public boolean isWrapperFor(Class<?> iface) { return false; } +} diff --git a/cayenne/src/test/java/org/apache/cayenne/unit/jdbc/TestDataSource.java b/cayenne/src/test/java/org/apache/cayenne/unit/jdbc/TestDataSource.java new file mode 100644 index 000000000..204aa7fcb --- /dev/null +++ b/cayenne/src/test/java/org/apache/cayenne/unit/jdbc/TestDataSource.java @@ -0,0 +1,57 @@ +/***************************************************************** + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.unit.jdbc; + +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.logging.Logger; + +import javax.sql.DataSource; + +/** + * Minimal JDBC {@link DataSource} stub for tests. Returns a configurable + * {@link Connection} (default: a fresh {@link TestConnection}) from {@link #getConnection()}. + */ +public class TestDataSource implements DataSource { + + private Connection connection = new TestConnection(); + + public void setupConnection(Connection connection) { + this.connection = connection; + } + + @Override + public Connection getConnection() { + return connection; + } + + @Override + public Connection getConnection(String username, String password) { + return connection; + } + + @Override public PrintWriter getLogWriter() { return null; } + @Override public void setLogWriter(PrintWriter out) {} + @Override public void setLoginTimeout(int seconds) {} + @Override public int getLoginTimeout() { return 0; } + @Override public Logger getParentLogger() { return Logger.getLogger("global"); } + @Override public <T> T unwrap(Class<T> iface) throws SQLException { throw new SQLException("not supported"); } + @Override public boolean isWrapperFor(Class<?> iface) { return false; } +} diff --git a/cayenne/src/test/java/org/apache/cayenne/unit/jdbc/TestPreparedStatement.java b/cayenne/src/test/java/org/apache/cayenne/unit/jdbc/TestPreparedStatement.java new file mode 100644 index 000000000..d57fb62d1 --- /dev/null +++ b/cayenne/src/test/java/org/apache/cayenne/unit/jdbc/TestPreparedStatement.java @@ -0,0 +1,137 @@ +/***************************************************************** + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.unit.jdbc; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.Date; +import java.sql.NClob; +import java.sql.ParameterMetaData; +import java.sql.PreparedStatement; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.RowId; +import java.sql.SQLXML; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Calendar; + +/** + * Minimal JDBC {@link PreparedStatement} stub for tests. + * Returns a pre-configured updateCount from {@link #executeUpdate()}; all parameter + * bind methods are no-ops. + */ +public class TestPreparedStatement extends TestStatement implements PreparedStatement { + + private final String sql; + private final int updateCount; + + public TestPreparedStatement(Connection connection, String sql, int updateCount) { + super(connection); + this.sql = sql; + this.updateCount = updateCount; + } + + public String getSql() { + return sql; + } + + @Override + public int executeUpdate() { + return updateCount; + } + + @Override + public boolean execute() { + return false; + } + + @Override + public ResultSet executeQuery() { + return new TestResultSet(sql); + } + + @Override + public ResultSet getGeneratedKeys() { + return new TestResultSet(sql); + } + + // --- parameter bind no-ops --- + + @Override public void setNull(int parameterIndex, int sqlType) {} + @Override public void setNull(int parameterIndex, int sqlType, String typeName) {} + @Override public void setBoolean(int parameterIndex, boolean x) {} + @Override public void setByte(int parameterIndex, byte x) {} + @Override public void setShort(int parameterIndex, short x) {} + @Override public void setInt(int parameterIndex, int x) {} + @Override public void setLong(int parameterIndex, long x) {} + @Override public void setFloat(int parameterIndex, float x) {} + @Override public void setDouble(int parameterIndex, double x) {} + @Override public void setBigDecimal(int parameterIndex, BigDecimal x) {} + @Override public void setString(int parameterIndex, String x) {} + @Override public void setBytes(int parameterIndex, byte[] x) {} + @Override public void setDate(int parameterIndex, Date x) {} + @Override public void setDate(int parameterIndex, Date x, Calendar cal) {} + @Override public void setTime(int parameterIndex, Time x) {} + @Override public void setTime(int parameterIndex, Time x, Calendar cal) {} + @Override public void setTimestamp(int parameterIndex, Timestamp x) {} + @Override public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) {} + @Override public void setAsciiStream(int parameterIndex, InputStream x, int length) {} + @Override public void setAsciiStream(int parameterIndex, InputStream x, long length) {} + @Override public void setAsciiStream(int parameterIndex, InputStream x) {} + @Override public void setUnicodeStream(int parameterIndex, InputStream x, int length) {} + @Override public void setBinaryStream(int parameterIndex, InputStream x, int length) {} + @Override public void setBinaryStream(int parameterIndex, InputStream x, long length) {} + @Override public void setBinaryStream(int parameterIndex, InputStream x) {} + @Override public void setCharacterStream(int parameterIndex, Reader reader, int length) {} + @Override public void setCharacterStream(int parameterIndex, Reader reader, long length) {} + @Override public void setCharacterStream(int parameterIndex, Reader reader) {} + @Override public void setNCharacterStream(int parameterIndex, Reader value, long length) {} + @Override public void setNCharacterStream(int parameterIndex, Reader value) {} + @Override public void setObject(int parameterIndex, Object x) {} + @Override public void setObject(int parameterIndex, Object x, int targetSqlType) {} + @Override public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) {} + @Override public void setRef(int parameterIndex, Ref x) {} + @Override public void setBlob(int parameterIndex, Blob x) {} + @Override public void setBlob(int parameterIndex, InputStream inputStream, long length) {} + @Override public void setBlob(int parameterIndex, InputStream inputStream) {} + @Override public void setClob(int parameterIndex, Clob x) {} + @Override public void setClob(int parameterIndex, Reader reader, long length) {} + @Override public void setClob(int parameterIndex, Reader reader) {} + @Override public void setNClob(int parameterIndex, NClob value) {} + @Override public void setNClob(int parameterIndex, Reader reader, long length) {} + @Override public void setNClob(int parameterIndex, Reader reader) {} + @Override public void setArray(int parameterIndex, Array x) {} + @Override public void setURL(int parameterIndex, URL x) {} + @Override public void setRowId(int parameterIndex, RowId x) {} + @Override public void setSQLXML(int parameterIndex, SQLXML xmlObject) {} + @Override public void setNString(int parameterIndex, String value) {} + @Override public void addBatch() {} + @Override public void clearParameters() {} + + @Override public ResultSetMetaData getMetaData() { throw uoe(); } + @Override public ParameterMetaData getParameterMetaData() { throw uoe(); } +} diff --git a/cayenne/src/test/java/org/apache/cayenne/unit/jdbc/TestResultSet.java b/cayenne/src/test/java/org/apache/cayenne/unit/jdbc/TestResultSet.java new file mode 100644 index 000000000..a9e54e8e6 --- /dev/null +++ b/cayenne/src/test/java/org/apache/cayenne/unit/jdbc/TestResultSet.java @@ -0,0 +1,493 @@ +/***************************************************************** + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.unit.jdbc; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Date; +import java.sql.NClob; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Statement; +import java.sql.Time; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.Map; + +/** + * Minimal in-memory JDBC {@link ResultSet} for tests. Replaces the parts of + * {@code com.mockrunner.mock.jdbc.MockResultSet} that Cayenne tests rely on. + * + * <p>Configure by calling {@link #addColumn(String)} or {@link #addColumn(String, Object[])} + * before reading. Then call {@link #next()} to advance the cursor. + */ +public class TestResultSet implements ResultSet { + + private final String name; + private final List<String> columnNames = new ArrayList<>(); + private final List<List<Object>> rows = new ArrayList<>(); + private int cursor = -1; + private boolean closed; + private boolean lastWasNull; + + public TestResultSet(String name) { + this.name = name; + } + + public void addColumn(String columnName) { + columnNames.add(columnName); + // pad existing rows so their length matches column count + for (List<Object> row : rows) { + while (row.size() < columnNames.size()) { + row.add(null); + } + } + } + + public void addColumn(String columnName, Object[] values) { + int colIdx = columnNames.size(); + columnNames.add(columnName); + for (int i = 0; i < values.length; i++) { + ensureRow(i); + List<Object> row = rows.get(i); + while (row.size() <= colIdx) { + row.add(null); + } + row.set(colIdx, values[i]); + } + } + + public void addRow(Object[] values) { + List<Object> row = new ArrayList<>(columnNames.size()); + for (int i = 0; i < columnNames.size(); i++) { + row.add(i < values.length ? values[i] : null); + } + rows.add(row); + } + + private void ensureRow(int index) { + while (rows.size() <= index) { + List<Object> row = new ArrayList<>(columnNames.size()); + for (int i = 0; i < columnNames.size(); i++) { + row.add(null); + } + rows.add(row); + } + } + + private Object value(int columnIndex) throws SQLException { + if (cursor < 0 || cursor >= rows.size()) { + throw new SQLException("No current row"); + } + if (columnIndex < 1 || columnIndex > columnNames.size()) { + throw new SQLException("Invalid column index: " + columnIndex); + } + Object v = rows.get(cursor).get(columnIndex - 1); + lastWasNull = (v == null); + return v; + } + + private int columnIndex(String columnLabel) throws SQLException { + for (int i = 0; i < columnNames.size(); i++) { + if (columnNames.get(i).equalsIgnoreCase(columnLabel)) { + return i + 1; + } + } + throw new SQLException("Unknown column: " + columnLabel); + } + + @Override + public boolean next() { + cursor++; + return cursor < rows.size(); + } + + @Override + public void close() { + closed = true; + } + + @Override + public boolean isClosed() { + return closed; + } + + @Override + public boolean wasNull() { + return lastWasNull; + } + + @Override + public ResultSetMetaData getMetaData() { + return new TestResultSetMetaData(columnNames); + } + + @Override + public Object getObject(int columnIndex) throws SQLException { + return value(columnIndex); + } + + @Override + public Object getObject(String columnLabel) throws SQLException { + return getObject(columnIndex(columnLabel)); + } + + @Override + public String getString(int columnIndex) throws SQLException { + Object v = value(columnIndex); + return v == null ? null : v.toString(); + } + + @Override + public String getString(String columnLabel) throws SQLException { + return getString(columnIndex(columnLabel)); + } + + @Override + public boolean getBoolean(int columnIndex) throws SQLException { + Object v = value(columnIndex); + if (v == null) { + return false; + } + if (v instanceof Boolean b) { + return b; + } + if (v instanceof Number n) { + return n.intValue() != 0; + } + return Boolean.parseBoolean(v.toString()); + } + + @Override + public boolean getBoolean(String columnLabel) throws SQLException { + return getBoolean(columnIndex(columnLabel)); + } + + @Override + public int getInt(int columnIndex) throws SQLException { + Object v = value(columnIndex); + if (v == null) { + return 0; + } + if (v instanceof Number n) { + return n.intValue(); + } + return Integer.parseInt(v.toString()); + } + + @Override + public int getInt(String columnLabel) throws SQLException { + return getInt(columnIndex(columnLabel)); + } + + @Override + public long getLong(int columnIndex) throws SQLException { + Object v = value(columnIndex); + if (v == null) { + return 0; + } + if (v instanceof Number n) { + return n.longValue(); + } + return Long.parseLong(v.toString()); + } + + @Override + public long getLong(String columnLabel) throws SQLException { + return getLong(columnIndex(columnLabel)); + } + + @Override + public double getDouble(int columnIndex) throws SQLException { + Object v = value(columnIndex); + if (v == null) { + return 0; + } + if (v instanceof Number n) { + return n.doubleValue(); + } + return Double.parseDouble(v.toString()); + } + + @Override + public double getDouble(String columnLabel) throws SQLException { + return getDouble(columnIndex(columnLabel)); + } + + @Override + public float getFloat(int columnIndex) throws SQLException { + return (float) getDouble(columnIndex); + } + + @Override + public float getFloat(String columnLabel) throws SQLException { + return getFloat(columnIndex(columnLabel)); + } + + @Override + public short getShort(int columnIndex) throws SQLException { + return (short) getInt(columnIndex); + } + + @Override + public short getShort(String columnLabel) throws SQLException { + return getShort(columnIndex(columnLabel)); + } + + @Override + public byte getByte(int columnIndex) throws SQLException { + return (byte) getInt(columnIndex); + } + + @Override + public byte getByte(String columnLabel) throws SQLException { + return getByte(columnIndex(columnLabel)); + } + + @Override + public byte[] getBytes(int columnIndex) throws SQLException { + Object v = value(columnIndex); + return v == null ? null : (byte[]) v; + } + + @Override + public byte[] getBytes(String columnLabel) throws SQLException { + return getBytes(columnIndex(columnLabel)); + } + + @Override public SQLWarning getWarnings() { return null; } + @Override public void clearWarnings() {} + @Override public String getCursorName() { return name; } + @Override public int findColumn(String columnLabel) throws SQLException { return columnIndex(columnLabel); } + @Override public boolean isBeforeFirst() { return cursor < 0; } + @Override public boolean isAfterLast() { return cursor >= rows.size(); } + @Override public boolean isFirst() { return cursor == 0; } + @Override public boolean isLast() { return cursor == rows.size() - 1; } + @Override public int getRow() { return cursor + 1; } + @Override public int getType() { return TYPE_FORWARD_ONLY; } + @Override public int getConcurrency() { return CONCUR_READ_ONLY; } + @Override public Statement getStatement() { return null; } + @Override public int getFetchDirection() { return FETCH_FORWARD; } + @Override public int getFetchSize() { return 0; } + @Override public int getHoldability() { return HOLD_CURSORS_OVER_COMMIT; } + + // --- everything below is unused by tests; throw to flag accidental reliance --- + + private static UnsupportedOperationException uoe() { + return new UnsupportedOperationException("not implemented in TestResultSet"); + } + + @Override public BigDecimal getBigDecimal(int columnIndex) { throw uoe(); } + @Override public BigDecimal getBigDecimal(String columnLabel) { throw uoe(); } + @Override public BigDecimal getBigDecimal(int columnIndex, int scale) { throw uoe(); } + @Override public BigDecimal getBigDecimal(String columnLabel, int scale) { throw uoe(); } + @Override public Date getDate(int columnIndex) { throw uoe(); } + @Override public Date getDate(String columnLabel) { throw uoe(); } + @Override public Date getDate(int columnIndex, Calendar cal) { throw uoe(); } + @Override public Date getDate(String columnLabel, Calendar cal) { throw uoe(); } + @Override public Time getTime(int columnIndex) { throw uoe(); } + @Override public Time getTime(String columnLabel) { throw uoe(); } + @Override public Time getTime(int columnIndex, Calendar cal) { throw uoe(); } + @Override public Time getTime(String columnLabel, Calendar cal) { throw uoe(); } + @Override public Timestamp getTimestamp(int columnIndex) { throw uoe(); } + @Override public Timestamp getTimestamp(String columnLabel) { throw uoe(); } + @Override public Timestamp getTimestamp(int columnIndex, Calendar cal) { throw uoe(); } + @Override public Timestamp getTimestamp(String columnLabel, Calendar cal) { throw uoe(); } + @Override public InputStream getAsciiStream(int columnIndex) { throw uoe(); } + @Override public InputStream getAsciiStream(String columnLabel) { throw uoe(); } + @Override public InputStream getUnicodeStream(int columnIndex) { throw uoe(); } + @Override public InputStream getUnicodeStream(String columnLabel) { throw uoe(); } + @Override public InputStream getBinaryStream(int columnIndex) { throw uoe(); } + @Override public InputStream getBinaryStream(String columnLabel) { throw uoe(); } + @Override public Reader getCharacterStream(int columnIndex) { throw uoe(); } + @Override public Reader getCharacterStream(String columnLabel) { throw uoe(); } + @Override public Reader getNCharacterStream(int columnIndex) { throw uoe(); } + @Override public Reader getNCharacterStream(String columnLabel) { throw uoe(); } + @Override public String getNString(int columnIndex) { throw uoe(); } + @Override public String getNString(String columnLabel) { throw uoe(); } + @Override public Object getObject(int columnIndex, Map<String, Class<?>> map) { throw uoe(); } + @Override public Object getObject(String columnLabel, Map<String, Class<?>> map) { throw uoe(); } + @Override public <T> T getObject(int columnIndex, Class<T> type) { throw uoe(); } + @Override public <T> T getObject(String columnLabel, Class<T> type) { throw uoe(); } + @Override public Ref getRef(int columnIndex) { throw uoe(); } + @Override public Ref getRef(String columnLabel) { throw uoe(); } + @Override public Blob getBlob(int columnIndex) { throw uoe(); } + @Override public Blob getBlob(String columnLabel) { throw uoe(); } + @Override public Clob getClob(int columnIndex) { throw uoe(); } + @Override public Clob getClob(String columnLabel) { throw uoe(); } + @Override public NClob getNClob(int columnIndex) { throw uoe(); } + @Override public NClob getNClob(String columnLabel) { throw uoe(); } + @Override public Array getArray(int columnIndex) { throw uoe(); } + @Override public Array getArray(String columnLabel) { throw uoe(); } + @Override public URL getURL(int columnIndex) { throw uoe(); } + @Override public URL getURL(String columnLabel) { throw uoe(); } + @Override public RowId getRowId(int columnIndex) { throw uoe(); } + @Override public RowId getRowId(String columnLabel) { throw uoe(); } + @Override public SQLXML getSQLXML(int columnIndex) { throw uoe(); } + @Override public SQLXML getSQLXML(String columnLabel) { throw uoe(); } + @Override public void beforeFirst() { throw uoe(); } + @Override public void afterLast() { throw uoe(); } + @Override public boolean first() { throw uoe(); } + @Override public boolean last() { throw uoe(); } + @Override public boolean absolute(int row) { throw uoe(); } + @Override public boolean relative(int rows) { throw uoe(); } + @Override public boolean previous() { throw uoe(); } + @Override public void setFetchDirection(int direction) { throw uoe(); } + @Override public void setFetchSize(int rows) { throw uoe(); } + @Override public boolean rowUpdated() { throw uoe(); } + @Override public boolean rowInserted() { throw uoe(); } + @Override public boolean rowDeleted() { throw uoe(); } + @Override public void insertRow() { throw uoe(); } + @Override public void updateRow() { throw uoe(); } + @Override public void deleteRow() { throw uoe(); } + @Override public void refreshRow() { throw uoe(); } + @Override public void cancelRowUpdates() { throw uoe(); } + @Override public void moveToInsertRow() { throw uoe(); } + @Override public void moveToCurrentRow() { throw uoe(); } + @Override public void updateNull(int columnIndex) { throw uoe(); } + @Override public void updateNull(String columnLabel) { throw uoe(); } + @Override public void updateBoolean(int columnIndex, boolean x) { throw uoe(); } + @Override public void updateBoolean(String columnLabel, boolean x) { throw uoe(); } + @Override public void updateByte(int columnIndex, byte x) { throw uoe(); } + @Override public void updateByte(String columnLabel, byte x) { throw uoe(); } + @Override public void updateShort(int columnIndex, short x) { throw uoe(); } + @Override public void updateShort(String columnLabel, short x) { throw uoe(); } + @Override public void updateInt(int columnIndex, int x) { throw uoe(); } + @Override public void updateInt(String columnLabel, int x) { throw uoe(); } + @Override public void updateLong(int columnIndex, long x) { throw uoe(); } + @Override public void updateLong(String columnLabel, long x) { throw uoe(); } + @Override public void updateFloat(int columnIndex, float x) { throw uoe(); } + @Override public void updateFloat(String columnLabel, float x) { throw uoe(); } + @Override public void updateDouble(int columnIndex, double x) { throw uoe(); } + @Override public void updateDouble(String columnLabel, double x) { throw uoe(); } + @Override public void updateBigDecimal(int columnIndex, BigDecimal x) { throw uoe(); } + @Override public void updateBigDecimal(String columnLabel, BigDecimal x) { throw uoe(); } + @Override public void updateString(int columnIndex, String x) { throw uoe(); } + @Override public void updateString(String columnLabel, String x) { throw uoe(); } + @Override public void updateNString(int columnIndex, String x) { throw uoe(); } + @Override public void updateNString(String columnLabel, String x) { throw uoe(); } + @Override public void updateBytes(int columnIndex, byte[] x) { throw uoe(); } + @Override public void updateBytes(String columnLabel, byte[] x) { throw uoe(); } + @Override public void updateDate(int columnIndex, Date x) { throw uoe(); } + @Override public void updateDate(String columnLabel, Date x) { throw uoe(); } + @Override public void updateTime(int columnIndex, Time x) { throw uoe(); } + @Override public void updateTime(String columnLabel, Time x) { throw uoe(); } + @Override public void updateTimestamp(int columnIndex, Timestamp x) { throw uoe(); } + @Override public void updateTimestamp(String columnLabel, Timestamp x) { throw uoe(); } + @Override public void updateAsciiStream(int columnIndex, InputStream x, int length) { throw uoe(); } + @Override public void updateAsciiStream(String columnLabel, InputStream x, int length) { throw uoe(); } + @Override public void updateAsciiStream(int columnIndex, InputStream x, long length) { throw uoe(); } + @Override public void updateAsciiStream(String columnLabel, InputStream x, long length) { throw uoe(); } + @Override public void updateAsciiStream(int columnIndex, InputStream x) { throw uoe(); } + @Override public void updateAsciiStream(String columnLabel, InputStream x) { throw uoe(); } + @Override public void updateBinaryStream(int columnIndex, InputStream x, int length) { throw uoe(); } + @Override public void updateBinaryStream(String columnLabel, InputStream x, int length) { throw uoe(); } + @Override public void updateBinaryStream(int columnIndex, InputStream x, long length) { throw uoe(); } + @Override public void updateBinaryStream(String columnLabel, InputStream x, long length) { throw uoe(); } + @Override public void updateBinaryStream(int columnIndex, InputStream x) { throw uoe(); } + @Override public void updateBinaryStream(String columnLabel, InputStream x) { throw uoe(); } + @Override public void updateCharacterStream(int columnIndex, Reader x, int length) { throw uoe(); } + @Override public void updateCharacterStream(String columnLabel, Reader x, int length) { throw uoe(); } + @Override public void updateCharacterStream(int columnIndex, Reader x, long length) { throw uoe(); } + @Override public void updateCharacterStream(String columnLabel, Reader x, long length) { throw uoe(); } + @Override public void updateCharacterStream(int columnIndex, Reader x) { throw uoe(); } + @Override public void updateCharacterStream(String columnLabel, Reader x) { throw uoe(); } + @Override public void updateNCharacterStream(int columnIndex, Reader x, long length) { throw uoe(); } + @Override public void updateNCharacterStream(String columnLabel, Reader x, long length) { throw uoe(); } + @Override public void updateNCharacterStream(int columnIndex, Reader x) { throw uoe(); } + @Override public void updateNCharacterStream(String columnLabel, Reader x) { throw uoe(); } + @Override public void updateObject(int columnIndex, Object x, int scaleOrLength) { throw uoe(); } + @Override public void updateObject(String columnLabel, Object x, int scaleOrLength) { throw uoe(); } + @Override public void updateObject(int columnIndex, Object x) { throw uoe(); } + @Override public void updateObject(String columnLabel, Object x) { throw uoe(); } + @Override public void updateRef(int columnIndex, Ref x) { throw uoe(); } + @Override public void updateRef(String columnLabel, Ref x) { throw uoe(); } + @Override public void updateBlob(int columnIndex, Blob x) { throw uoe(); } + @Override public void updateBlob(String columnLabel, Blob x) { throw uoe(); } + @Override public void updateBlob(int columnIndex, InputStream inputStream, long length) { throw uoe(); } + @Override public void updateBlob(String columnLabel, InputStream inputStream, long length) { throw uoe(); } + @Override public void updateBlob(int columnIndex, InputStream inputStream) { throw uoe(); } + @Override public void updateBlob(String columnLabel, InputStream inputStream) { throw uoe(); } + @Override public void updateClob(int columnIndex, Clob x) { throw uoe(); } + @Override public void updateClob(String columnLabel, Clob x) { throw uoe(); } + @Override public void updateClob(int columnIndex, Reader reader, long length) { throw uoe(); } + @Override public void updateClob(String columnLabel, Reader reader, long length) { throw uoe(); } + @Override public void updateClob(int columnIndex, Reader reader) { throw uoe(); } + @Override public void updateClob(String columnLabel, Reader reader) { throw uoe(); } + @Override public void updateNClob(int columnIndex, NClob nClob) { throw uoe(); } + @Override public void updateNClob(String columnLabel, NClob nClob) { throw uoe(); } + @Override public void updateNClob(int columnIndex, Reader reader, long length) { throw uoe(); } + @Override public void updateNClob(String columnLabel, Reader reader, long length) { throw uoe(); } + @Override public void updateNClob(int columnIndex, Reader reader) { throw uoe(); } + @Override public void updateNClob(String columnLabel, Reader reader) { throw uoe(); } + @Override public void updateArray(int columnIndex, Array x) { throw uoe(); } + @Override public void updateArray(String columnLabel, Array x) { throw uoe(); } + @Override public void updateRowId(int columnIndex, RowId x) { throw uoe(); } + @Override public void updateRowId(String columnLabel, RowId x) { throw uoe(); } + @Override public void updateSQLXML(int columnIndex, SQLXML xmlObject) { throw uoe(); } + @Override public void updateSQLXML(String columnLabel, SQLXML xmlObject) { throw uoe(); } + @Override public <T> T unwrap(Class<T> iface) { throw uoe(); } + @Override public boolean isWrapperFor(Class<?> iface) { return false; } + + private static final class TestResultSetMetaData implements ResultSetMetaData { + private final List<String> names; + + TestResultSetMetaData(List<String> names) { + this.names = names; + } + + @Override public int getColumnCount() { return names.size(); } + @Override public String getColumnLabel(int column) { return names.get(column - 1); } + @Override public String getColumnName(int column) { return names.get(column - 1); } + @Override public int getColumnType(int column) { return Types.OTHER; } + @Override public String getColumnTypeName(int column) { return "OTHER"; } + @Override public String getColumnClassName(int column) { return Object.class.getName(); } + @Override public int getPrecision(int column) { return 0; } + @Override public int getScale(int column) { return 0; } + @Override public int isNullable(int column) { return columnNullableUnknown; } + @Override public boolean isAutoIncrement(int column) { return false; } + @Override public boolean isCaseSensitive(int column) { return false; } + @Override public boolean isSearchable(int column) { return false; } + @Override public boolean isCurrency(int column) { return false; } + @Override public boolean isSigned(int column) { return false; } + @Override public int getColumnDisplaySize(int column) { return 0; } + @Override public String getSchemaName(int column) { return ""; } + @Override public String getTableName(int column) { return ""; } + @Override public String getCatalogName(int column) { return ""; } + @Override public boolean isReadOnly(int column) { return true; } + @Override public boolean isWritable(int column) { return false; } + @Override public boolean isDefinitelyWritable(int column) { return false; } + @Override public <T> T unwrap(Class<T> iface) throws SQLException { throw new SQLFeatureNotSupportedException(); } + @Override public boolean isWrapperFor(Class<?> iface) { return false; } + } +} diff --git a/cayenne/src/test/java/org/apache/cayenne/unit/jdbc/TestStatement.java b/cayenne/src/test/java/org/apache/cayenne/unit/jdbc/TestStatement.java new file mode 100644 index 000000000..d4de0ebae --- /dev/null +++ b/cayenne/src/test/java/org/apache/cayenne/unit/jdbc/TestStatement.java @@ -0,0 +1,105 @@ +/***************************************************************** + * 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.unit.jdbc; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLWarning; +import java.sql.Statement; + +/** + * Minimal JDBC {@link Statement} stub for tests. Implements close/isClosed semantics + * and exposes the originating {@link Connection}. + */ +public class TestStatement implements Statement { + + private final Connection connection; + private boolean closed; + + public TestStatement() { + this(null); + } + + public TestStatement(Connection connection) { + this.connection = connection; + } + + @Override + public Connection getConnection() { + return connection; + } + + @Override + public void close() { + closed = true; + } + + @Override + public boolean isClosed() { + return closed; + } + + // --- everything below is unused by tests --- + + static UnsupportedOperationException uoe() { + return new UnsupportedOperationException("not implemented in TestStatement"); + } + + @Override public ResultSet executeQuery(String sql) { throw uoe(); } + @Override public int executeUpdate(String sql) { throw uoe(); } + @Override public int executeUpdate(String sql, int autoGeneratedKeys) { throw uoe(); } + @Override public int executeUpdate(String sql, int[] columnIndexes) { throw uoe(); } + @Override public int executeUpdate(String sql, String[] columnNames) { throw uoe(); } + @Override public boolean execute(String sql) { throw uoe(); } + @Override public boolean execute(String sql, int autoGeneratedKeys) { throw uoe(); } + @Override public boolean execute(String sql, int[] columnIndexes) { throw uoe(); } + @Override public boolean execute(String sql, String[] columnNames) { throw uoe(); } + @Override public int getMaxFieldSize() { return 0; } + @Override public void setMaxFieldSize(int max) {} + @Override public int getMaxRows() { return 0; } + @Override public void setMaxRows(int max) {} + @Override public void setEscapeProcessing(boolean enable) {} + @Override public int getQueryTimeout() { return 0; } + @Override public void setQueryTimeout(int seconds) {} + @Override public void cancel() {} + @Override public SQLWarning getWarnings() { return null; } + @Override public void clearWarnings() {} + @Override public void setCursorName(String name) {} + @Override public ResultSet getResultSet() { return null; } + @Override public int getUpdateCount() { return -1; } + @Override public boolean getMoreResults() { return false; } + @Override public boolean getMoreResults(int current) { return false; } + @Override public void setFetchDirection(int direction) {} + @Override public int getFetchDirection() { return ResultSet.FETCH_FORWARD; } + @Override public void setFetchSize(int rows) {} + @Override public int getFetchSize() { return 0; } + @Override public int getResultSetConcurrency() { return ResultSet.CONCUR_READ_ONLY; } + @Override public int getResultSetType() { return ResultSet.TYPE_FORWARD_ONLY; } + @Override public int getResultSetHoldability() { return ResultSet.HOLD_CURSORS_OVER_COMMIT; } + @Override public void addBatch(String sql) {} + @Override public void clearBatch() {} + @Override public int[] executeBatch() { return new int[0]; } + @Override public ResultSet getGeneratedKeys() { throw uoe(); } + @Override public void setPoolable(boolean poolable) {} + @Override public boolean isPoolable() { return false; } + @Override public void closeOnCompletion() {} + @Override public boolean isCloseOnCompletion() { return false; } + @Override public <T> T unwrap(Class<T> iface) { throw uoe(); } + @Override public boolean isWrapperFor(Class<?> iface) { return false; } +} diff --git a/pom.xml b/pom.xml index 18945e6d2..94f0f5f35 100644 --- a/pom.xml +++ b/pom.xml @@ -373,11 +373,6 @@ <artifactId>jgoodies-looks</artifactId> <version>2.7.0</version> </dependency> - <dependency> - <groupId>com.mockrunner</groupId> - <artifactId>mockrunner-jdbc</artifactId> - <version>2.0.7</version> - </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId>
