| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.solr.handler.dataimport; |
| |
| import javax.sql.DataSource; |
| import java.io.File; |
| import java.io.IOException; |
| import java.nio.charset.StandardCharsets; |
| import java.sql.Connection; |
| import java.sql.Driver; |
| import java.sql.DriverManager; |
| import java.sql.ResultSet; |
| import java.sql.ResultSetMetaData; |
| import java.sql.SQLException; |
| import java.sql.Statement; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| |
| import org.apache.solr.common.util.SuppressForbidden; |
| import org.apache.solr.handler.dataimport.JdbcDataSource.ResultSetIterator; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.BeforeClass; |
| import org.junit.Ignore; |
| import org.junit.Test; |
| |
| import static org.mockito.Mockito.doThrow; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.reset; |
| import static org.mockito.Mockito.times; |
| import static org.mockito.Mockito.verify; |
| import static org.mockito.Mockito.when; |
| |
| /** |
| * <p> |
| * Test for JdbcDataSource |
| * </p> |
| * <p> |
| * Note: The tests are ignored for the lack of DB support for testing |
| * </p> |
| * |
| * |
| * @since solr 1.3 |
| */ |
| public class TestJdbcDataSource extends AbstractDataImportHandlerTestCase { |
| private Driver driver; |
| private DataSource dataSource; |
| private Connection connection; |
| private JdbcDataSource jdbcDataSource = new JdbcDataSource(); |
| List<Map<String, String>> fields = new ArrayList<>(); |
| |
| Context context = AbstractDataImportHandlerTestCase.getContext(null, null, |
| jdbcDataSource, Context.FULL_DUMP, fields, null); |
| |
| Properties props = new Properties(); |
| |
| String sysProp = System.getProperty("java.naming.factory.initial"); |
| |
| @BeforeClass |
| public static void beforeClass() { |
| assumeWorkingMockito(); |
| } |
| |
| @Override |
| @Before |
| public void setUp() throws Exception { |
| super.setUp(); |
| System.setProperty("java.naming.factory.initial", |
| MockInitialContextFactory.class.getName()); |
| |
| driver = mock(Driver.class); |
| dataSource = mock(DataSource.class); |
| connection = mock(Connection.class); |
| props.clear(); |
| } |
| |
| @Override |
| @After |
| public void tearDown() throws Exception { |
| if (sysProp == null) { |
| System.getProperties().remove("java.naming.factory.initial"); |
| } else { |
| System.setProperty("java.naming.factory.initial", sysProp); |
| } |
| super.tearDown(); |
| if (null != driver) { |
| reset(driver, dataSource, connection); |
| } |
| } |
| |
| @Test |
| public void testRetrieveFromJndi() throws Exception { |
| MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource); |
| |
| props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB"); |
| |
| when(dataSource.getConnection()).thenReturn(connection); |
| |
| Connection conn = jdbcDataSource.createConnectionFactory(context, props) |
| .call(); |
| |
| verify(connection).setAutoCommit(false); |
| verify(dataSource).getConnection(); |
| |
| assertSame("connection", conn, connection); |
| } |
| |
| @Test |
| public void testRetrieveFromJndiWithCredentials() throws Exception { |
| MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource); |
| |
| props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB"); |
| props.put("user", "Fred"); |
| props.put("password", "4r3d"); |
| props.put("holdability", "HOLD_CURSORS_OVER_COMMIT"); |
| |
| when(dataSource.getConnection("Fred", "4r3d")).thenReturn( |
| connection); |
| |
| Connection conn = jdbcDataSource.createConnectionFactory(context, props) |
| .call(); |
| |
| verify(connection).setAutoCommit(false); |
| verify(connection).setHoldability(1); |
| verify(dataSource).getConnection("Fred", "4r3d"); |
| |
| assertSame("connection", conn, connection); |
| } |
| |
| @Test |
| public void testRetrieveFromJndiWithCredentialsEncryptedAndResolved() throws Exception { |
| MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource); |
| |
| String user = "Fred"; |
| String plainPassword = "MyPassword"; |
| String encryptedPassword = "U2FsdGVkX18QMjY0yfCqlfBMvAB4d3XkwY96L7gfO2o="; |
| String propsNamespace = "exampleNamespace"; |
| |
| props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB"); |
| |
| props.put("user", "${" +propsNamespace +".user}"); |
| props.put("encryptKeyFile", "${" +propsNamespace +".encryptKeyFile}"); |
| props.put("password", "${" +propsNamespace +".password}"); |
| |
| when(dataSource.getConnection(user, plainPassword)).thenReturn( |
| connection); |
| |
| Map<String,Object> values = new HashMap<>(); |
| values.put("user", user); |
| values.put("encryptKeyFile", createEncryptionKeyFile()); |
| values.put("password", encryptedPassword); |
| context.getVariableResolver().addNamespace(propsNamespace, values); |
| |
| jdbcDataSource.init(context, props); |
| Connection conn = jdbcDataSource.getConnection(); |
| |
| verify(connection).setAutoCommit(false); |
| verify(dataSource).getConnection(user, plainPassword); |
| |
| assertSame("connection", conn, connection); |
| } |
| |
| @Test |
| public void testRetrieveFromJndiWithCredentialsWithEncryptedAndResolvedPwd() throws Exception { |
| MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource); |
| |
| Properties properties = new Properties(); |
| properties.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB"); |
| properties.put("user", "Fred"); |
| properties.put("encryptKeyFile", "${foo.bar}"); |
| properties.put("password", "U2FsdGVkX18QMjY0yfCqlfBMvAB4d3XkwY96L7gfO2o="); |
| when(dataSource.getConnection("Fred", "MyPassword")).thenReturn( |
| connection); |
| |
| Map<String,Object> values = new HashMap<>(); |
| values.put("bar", createEncryptionKeyFile()); |
| context.getVariableResolver().addNamespace("foo", values); |
| |
| jdbcDataSource.init(context, properties); |
| jdbcDataSource.getConnection(); |
| |
| verify(connection).setAutoCommit(false); |
| verify(dataSource).getConnection("Fred", "MyPassword"); |
| } |
| |
| @Test |
| public void testRetrieveFromJndiFailureNotHidden() throws Exception { |
| MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource); |
| |
| props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB"); |
| |
| SQLException sqlException = new SQLException("fake"); |
| when(dataSource.getConnection()).thenThrow(sqlException); |
| |
| SQLException ex = expectThrows(SQLException.class, |
| () -> jdbcDataSource.createConnectionFactory(context, props).call()); |
| assertSame(sqlException, ex); |
| |
| verify(dataSource).getConnection(); |
| } |
| |
| @Test |
| public void testClosesConnectionWhenExceptionThrownOnSetAutocommit() throws Exception { |
| MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource); |
| |
| props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB"); |
| |
| SQLException sqlException = new SQLException("fake"); |
| when(dataSource.getConnection()).thenReturn(connection); |
| doThrow(sqlException).when(connection).setAutoCommit(false); |
| |
| DataImportHandlerException ex = expectThrows(DataImportHandlerException.class, |
| () -> jdbcDataSource.createConnectionFactory(context, props).call()); |
| assertSame(sqlException, ex.getCause()); |
| |
| verify(dataSource).getConnection(); |
| verify(connection).setAutoCommit(false); |
| verify(connection).close(); |
| } |
| |
| @Test |
| public void testClosesStatementWhenExceptionThrownOnExecuteQuery() throws Exception { |
| MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource); |
| |
| props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB"); |
| when(dataSource.getConnection()).thenReturn(connection); |
| |
| jdbcDataSource.init(context, props); |
| |
| SQLException sqlException = new SQLException("fake"); |
| Statement statement = mock(Statement.class); |
| when(connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) |
| .thenReturn(statement); |
| when(statement.execute("query")).thenThrow(sqlException); |
| |
| DataImportHandlerException ex = expectThrows(DataImportHandlerException.class, |
| () -> jdbcDataSource.getData("query")); |
| assertSame(sqlException, ex.getCause()); |
| |
| verify(dataSource).getConnection(); |
| verify(connection).setAutoCommit(false); |
| verify(connection).createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); |
| verify(statement).setFetchSize(500); |
| verify(statement).setMaxRows(0); |
| verify(statement).execute("query"); |
| verify(statement).close(); |
| } |
| |
| @Test |
| public void testClosesStatementWhenResultSetNull() throws Exception { |
| MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource); |
| |
| props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB"); |
| when(dataSource.getConnection()).thenReturn(connection); |
| |
| jdbcDataSource.init(context, props); |
| |
| Statement statement = mock(Statement.class); |
| when(connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) |
| .thenReturn(statement); |
| when(statement.execute("query")).thenReturn(false); |
| when(statement.getUpdateCount()).thenReturn(-1); |
| |
| jdbcDataSource.getData("query"); |
| |
| verify(dataSource).getConnection(); |
| verify(connection).setAutoCommit(false); |
| verify(connection).createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); |
| verify(statement).setFetchSize(500); |
| verify(statement).setMaxRows(0); |
| verify(statement).execute("query"); |
| verify(statement).getUpdateCount(); |
| verify(statement).close(); |
| } |
| |
| @Test |
| public void testClosesStatementWhenHasNextCalledAndResultSetNull() throws Exception { |
| |
| MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource); |
| |
| props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB"); |
| when(dataSource.getConnection()).thenReturn(connection); |
| |
| jdbcDataSource.init(context, props); |
| |
| Statement statement = mock(Statement.class); |
| when(connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) |
| .thenReturn(statement); |
| when(statement.execute("query")).thenReturn(true); |
| ResultSet resultSet = mock(ResultSet.class); |
| when(statement.getResultSet()).thenReturn(resultSet); |
| ResultSetMetaData metaData = mock(ResultSetMetaData.class); |
| when(resultSet.getMetaData()).thenReturn(metaData); |
| when(metaData.getColumnCount()).thenReturn(0); |
| |
| Iterator<Map<String,Object>> data = jdbcDataSource.getData("query"); |
| |
| ResultSetIterator resultSetIterator = (ResultSetIterator) data.getClass().getDeclaredField("this$1").get(data); |
| resultSetIterator.setResultSet(null); |
| |
| data.hasNext(); |
| |
| verify(dataSource).getConnection(); |
| verify(connection).setAutoCommit(false); |
| verify(connection).createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); |
| verify(statement).setFetchSize(500); |
| verify(statement).setMaxRows(0); |
| verify(statement).execute("query"); |
| verify(statement).getResultSet(); |
| verify(statement).close(); |
| verify(resultSet).getMetaData(); |
| verify(metaData).getColumnCount(); |
| } |
| |
| @Test |
| public void testClosesResultSetAndStatementWhenDataSourceIsClosed() throws Exception { |
| |
| MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource); |
| |
| props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB"); |
| when(dataSource.getConnection()).thenReturn(connection); |
| |
| jdbcDataSource.init(context, props); |
| |
| Statement statement = mock(Statement.class); |
| when(connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) |
| .thenReturn(statement); |
| when(statement.execute("query")).thenReturn(true); |
| ResultSet resultSet = mock(ResultSet.class); |
| when(statement.getResultSet()).thenReturn(resultSet); |
| ResultSetMetaData metaData = mock(ResultSetMetaData.class); |
| when(resultSet.getMetaData()).thenReturn(metaData); |
| when(metaData.getColumnCount()).thenReturn(0); |
| |
| jdbcDataSource.getData("query"); |
| jdbcDataSource.close(); |
| |
| verify(dataSource).getConnection(); |
| verify(connection).setAutoCommit(false); |
| verify(connection).createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); |
| verify(statement).setFetchSize(500); |
| verify(statement).setMaxRows(0); |
| verify(statement).execute("query"); |
| verify(statement).getResultSet(); |
| verify(resultSet).getMetaData(); |
| verify(metaData).getColumnCount(); |
| verify(resultSet).close(); |
| verify(statement).close(); |
| verify(connection).commit(); |
| verify(connection).close(); |
| } |
| |
| @Test |
| public void testClosesCurrentResultSetIteratorWhenNewOneIsCreated() throws Exception { |
| |
| MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource); |
| |
| props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB"); |
| when(dataSource.getConnection()).thenReturn(connection); |
| |
| jdbcDataSource.init(context, props); |
| |
| Statement statement = mock(Statement.class); |
| when(connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) |
| .thenReturn(statement); |
| when(statement.execute("query")).thenReturn(true); |
| ResultSet resultSet = mock(ResultSet.class); |
| when(statement.getResultSet()).thenReturn(resultSet); |
| ResultSetMetaData metaData = mock(ResultSetMetaData.class); |
| when(resultSet.getMetaData()).thenReturn(metaData); |
| when(metaData.getColumnCount()).thenReturn(0); |
| when(statement.execute("other query")).thenReturn(false); |
| when(statement.getUpdateCount()).thenReturn(-1); |
| |
| jdbcDataSource.getData("query"); |
| jdbcDataSource.getData("other query"); |
| |
| verify(dataSource).getConnection(); |
| verify(connection).setAutoCommit(false); |
| verify(connection, times(2)).createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); |
| verify(statement, times(2)).setFetchSize(500); |
| verify(statement, times(2)).setMaxRows(0); |
| verify(statement).execute("query"); |
| verify(statement).getResultSet(); |
| verify(resultSet).getMetaData(); |
| verify(metaData).getColumnCount(); |
| verify(resultSet).close(); |
| verify(statement, times(2)).close(); |
| verify(statement).execute("other query"); |
| } |
| |
| @Test |
| public void testMultipleResultsSets_UpdateCountUpdateCountResultSet() throws Exception { |
| MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource); |
| props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB"); |
| when(dataSource.getConnection()).thenReturn(connection); |
| jdbcDataSource.init(context, props); |
| |
| Statement statement = mock(Statement.class); |
| when(connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) |
| .thenReturn(statement); |
| when(statement.execute("query")).thenReturn(false); |
| when(statement.getUpdateCount()).thenReturn(1); |
| when(statement.getMoreResults()).thenReturn(false).thenReturn(true); |
| ResultSet resultSet = mock(ResultSet.class); |
| when(statement.getResultSet()).thenReturn(resultSet); |
| ResultSetMetaData metaData = mock(ResultSetMetaData.class); |
| when(resultSet.getMetaData()).thenReturn(metaData); |
| when(metaData.getColumnCount()).thenReturn(0); |
| |
| final ResultSetIterator resultSetIterator = jdbcDataSource.new ResultSetIterator("query"); |
| assertSame(resultSet, resultSetIterator.getResultSet()); |
| |
| verify(connection).setAutoCommit(false); |
| verify(connection).createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); |
| verify(statement).setFetchSize(500); |
| verify(statement).setMaxRows(0); |
| verify(statement).execute("query"); |
| verify(statement, times(2)).getUpdateCount(); |
| verify(statement, times(2)).getMoreResults(); |
| } |
| |
| @Test |
| public void testMultipleResultsSets_ResultSetResultSet() throws Exception { |
| MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource); |
| props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB"); |
| when(dataSource.getConnection()).thenReturn(connection); |
| jdbcDataSource.init(context, props); |
| connection.setAutoCommit(false); |
| |
| Statement statement = mock(Statement.class); |
| when(connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) |
| .thenReturn(statement); |
| when(statement.execute("query")).thenReturn(true); |
| ResultSet resultSet1 = mock(ResultSet.class); |
| ResultSet resultSet2 = mock(ResultSet.class); |
| when(statement.getResultSet()).thenReturn(resultSet1).thenReturn(resultSet2).thenReturn(null); |
| when(statement.getMoreResults()).thenReturn(true).thenReturn(false); |
| ResultSetMetaData metaData1 = mock(ResultSetMetaData.class); |
| when(resultSet1.getMetaData()).thenReturn(metaData1); |
| when(metaData1.getColumnCount()).thenReturn(0); |
| when(resultSet1.next()).thenReturn(false); |
| ResultSetMetaData metaData2 = mock(ResultSetMetaData.class); |
| when(resultSet2.getMetaData()).thenReturn(metaData2); |
| when(metaData2.getColumnCount()).thenReturn(0); |
| when(resultSet2.next()).thenReturn(true).thenReturn(false); |
| when(statement.getUpdateCount()).thenReturn(-1); |
| |
| final ResultSetIterator resultSetIterator = jdbcDataSource.new ResultSetIterator("query"); |
| assertSame(resultSet1, resultSetIterator.getResultSet()); |
| assertTrue(resultSetIterator.hasnext()); |
| assertSame(resultSet2, resultSetIterator.getResultSet()); |
| assertFalse(resultSetIterator.hasnext()); |
| |
| verify(dataSource).getConnection(); |
| verify(connection, times(2)).setAutoCommit(false); |
| verify(connection).createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); |
| verify(statement).setFetchSize(500); |
| verify(statement).setMaxRows(0); |
| verify(statement).execute("query"); |
| verify(statement, times(2)).getResultSet(); |
| verify(resultSet1).getMetaData(); |
| verify(metaData1).getColumnCount(); |
| verify(resultSet1).next(); |
| verify(resultSet1).close(); |
| verify(resultSet2).getMetaData(); |
| verify(metaData2).getColumnCount(); |
| verify(resultSet2, times(2)).next(); |
| verify(resultSet2).close(); |
| verify(statement, times(2)).getMoreResults(); |
| verify(statement).getUpdateCount(); |
| verify(statement).close(); |
| } |
| |
| @Test |
| public void testRetrieveFromDriverManager() throws Exception { |
| // we're not (directly) using a Mockito based mock class here because it won't have a consistent class name |
| // that will work with DriverManager's class bindings |
| MockDriver mockDriver = new MockDriver(connection); |
| DriverManager.registerDriver(mockDriver); |
| try { |
| props.put(JdbcDataSource.DRIVER, MockDriver.class.getName()); |
| props.put(JdbcDataSource.URL, MockDriver.MY_JDBC_URL); |
| props.put("holdability", "HOLD_CURSORS_OVER_COMMIT"); |
| |
| Connection conn = jdbcDataSource.createConnectionFactory(context, props).call(); |
| |
| verify(connection).setAutoCommit(false); |
| verify(connection).setHoldability(1); |
| |
| assertSame("connection", conn, connection); |
| } catch(Exception e) { |
| throw e; |
| } finally { |
| DriverManager.deregisterDriver(mockDriver); |
| } |
| } |
| |
| |
| @Test |
| public void testEmptyResultSet() throws Exception { |
| MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource); |
| |
| props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB"); |
| when(dataSource.getConnection()).thenReturn(connection); |
| |
| jdbcDataSource.init(context, props); |
| |
| Statement statement = mock(Statement.class); |
| when(connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) |
| .thenReturn(statement); |
| when(statement.execute("query")).thenReturn(true); |
| ResultSet resultSet = mock(ResultSet.class); |
| when(statement.getResultSet()).thenReturn(resultSet); |
| ResultSetMetaData metaData = mock(ResultSetMetaData.class); |
| when(resultSet.getMetaData()).thenReturn(metaData); |
| when(metaData.getColumnCount()).thenReturn(0); |
| when(resultSet.next()).thenReturn(false); |
| when(statement.getMoreResults()).thenReturn(false); |
| when(statement.getUpdateCount()).thenReturn(-1); |
| |
| Iterator<Map<String,Object>> resultSetIterator = jdbcDataSource.getData("query"); |
| resultSetIterator.hasNext(); |
| resultSetIterator.hasNext(); |
| |
| verify(connection).setAutoCommit(false); |
| verify(connection).createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); |
| verify(statement).setFetchSize(500); |
| verify(statement).setMaxRows(0); |
| verify(statement).execute("query"); |
| verify(statement).getResultSet(); |
| verify(resultSet).getMetaData(); |
| verify(metaData).getColumnCount(); |
| verify(resultSet).next(); |
| verify(resultSet).close(); |
| verify(statement).getMoreResults(); |
| verify(statement).getUpdateCount(); |
| verify(statement).close(); |
| } |
| |
| @Test |
| @Ignore("Needs a Mock database server to work") |
| public void testBasic() throws Exception { |
| JdbcDataSource dataSource = new JdbcDataSource(); |
| Properties p = new Properties(); |
| p.put("driver", "com.mysql.jdbc.Driver"); |
| p.put("url", "jdbc:mysql://127.0.0.1/autos"); |
| p.put("user", "root"); |
| p.put("password", ""); |
| |
| List<Map<String, String>> flds = new ArrayList<>(); |
| Map<String, String> f = new HashMap<>(); |
| f.put("column", "trim_id"); |
| f.put("type", "long"); |
| flds.add(f); |
| f = new HashMap<>(); |
| f.put("column", "msrp"); |
| f.put("type", "float"); |
| flds.add(f); |
| |
| Context c = getContext(null, null, |
| dataSource, Context.FULL_DUMP, flds, null); |
| dataSource.init(c, p); |
| Iterator<Map<String, Object>> i = dataSource |
| .getData("select make,model,year,msrp,trim_id from atrimlisting where make='Acura'"); |
| int count = 0; |
| Object msrp = null; |
| Object trim_id = null; |
| while (i.hasNext()) { |
| Map<String, Object> map = i.next(); |
| msrp = map.get("msrp"); |
| trim_id = map.get("trim_id"); |
| count++; |
| } |
| assertEquals(5, count); |
| assertEquals(Float.class, msrp.getClass()); |
| assertEquals(Long.class, trim_id.getClass()); |
| } |
| |
| private String createEncryptionKeyFile() throws IOException { |
| File tmpdir = createTempDir().toFile(); |
| byte[] content = "secret".getBytes(StandardCharsets.UTF_8); |
| createFile(tmpdir, "enckeyfile.txt", content, false); |
| return new File(tmpdir, "enckeyfile.txt").getAbsolutePath(); |
| } |
| |
| /** |
| * A stub driver that returns our mocked connection for connection URL {@link #MY_JDBC_URL}. |
| * <p> |
| * This class is used instead of a Mockito mock because {@link DriverManager} uses the class |
| * name to lookup the driver and also requires the driver to behave in a sane way, if other |
| * drivers are registered in the runtime. A simple Mockito mock is likely to break |
| * depending on JVM runtime version. So this class implements a full {@link Driver}, |
| * so {@code DriverManager} can do whatever it wants to find the correct driver for a URL. |
| */ |
| public static final class MockDriver implements Driver { |
| public static final String MY_JDBC_URL = "jdbc:fakedb"; |
| private final Connection conn; |
| |
| public MockDriver() throws SQLException { |
| throw new AssertionError("The driver should never be directly instantiated by DIH's JdbcDataSource"); |
| } |
| |
| MockDriver(Connection conn) throws SQLException { |
| this.conn = conn; |
| } |
| |
| @Override |
| public boolean acceptsURL(String url) throws java.sql.SQLException { |
| return MY_JDBC_URL.equals(url); |
| } |
| |
| @Override |
| public Connection connect(String url, Properties info) throws java.sql.SQLException { |
| return acceptsURL(url) ? conn : null; |
| } |
| |
| @Override |
| public int getMajorVersion() { |
| return 1; |
| } |
| |
| @Override |
| public int getMinorVersion() { |
| return 0; |
| } |
| |
| @SuppressForbidden(reason="Required by JDBC") |
| @Override |
| public java.util.logging.Logger getParentLogger() throws java.sql.SQLFeatureNotSupportedException { |
| throw new java.sql.SQLFeatureNotSupportedException(); |
| } |
| |
| @Override |
| public java.sql.DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { |
| return new java.sql.DriverPropertyInfo[0]; |
| } |
| |
| @Override |
| public boolean jdbcCompliant() { |
| // we are not fully compliant: |
| return false; |
| } |
| } |
| } |