/* * Copyright 2014, Stratio. * * Licensed 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 com.stratio.deep.jdbc.reader; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.*; import static org.testng.Assert.assertEquals; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.Map; import com.healthmarketscience.sqlbuilder.BinaryCondition; import com.healthmarketscience.sqlbuilder.ComboCondition; import com.healthmarketscience.sqlbuilder.Condition; import com.healthmarketscience.sqlbuilder.SelectQuery; import com.healthmarketscience.sqlbuilder.dbspec.basic.DbColumn; import com.stratio.deep.jdbc.config.JdbcDeepJobConfig; import org.apache.spark.Partition; import org.apache.spark.rdd.JdbcPartition; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest({ JdbcReader.class }) public class JdbcReaderTest { private static final String COLUMN_NAME1_CONSTANT = "column_name_1"; private static final String COLUMN_NAME2_CONSTANT = "column_name_2"; private static final String COLUMN_VALUE1_CONSTANT = "column_value_1"; private static final String COLUMN_VALUE2_CONSTANT = "column_value_2"; private static final String JDBC_CELL_EXTRACTOR_CLASSNAME_CONSTANT = "com.stratio.deep.jdbc.extractor.JdbcNativeCellExtractor"; private static final String WHATEVER_CONSTANT = "whatever"; private static final int NUM_PARTITIONS = 2; @Mock private JdbcDeepJobConfig<?> config; @Mock private ResultSet resultSet; @Mock private ResultSetMetaData metadata; @Mock private JdbcPartition partition; @Mock private Connection conn; @Mock private Statement statement; @Test public void testRowMappingWhenCallingNext() throws SQLException, IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { // Stubbing external objects when(resultSet.getMetaData()).thenReturn(metadata); when(metadata.getColumnCount()).thenReturn(2); when(metadata.getColumnName(1)).thenReturn(COLUMN_NAME1_CONSTANT); when(metadata.getColumnName(2)).thenReturn(COLUMN_NAME2_CONSTANT); when(resultSet.getObject(1)).thenReturn(COLUMN_VALUE1_CONSTANT); when(resultSet.getObject(2)).thenReturn(COLUMN_VALUE2_CONSTANT); // Setting up test scenario JdbcReader reader = new JdbcReader(config); Class<?> clazz = JdbcReader.class; Field resultSetField = clazz.getDeclaredField("resultSet"); resultSetField.setAccessible(true); resultSetField.set(reader, resultSet); Map<String, Object> rowMap = reader.next(); // Assertions assertEquals((String) rowMap.get(COLUMN_NAME1_CONSTANT), COLUMN_VALUE1_CONSTANT, "Column value not expected"); assertEquals((String) rowMap.get(COLUMN_NAME2_CONSTANT), COLUMN_VALUE2_CONSTANT, "Column value not expected"); verify(resultSet, times(1)).next(); } @Test public void testFirstNextWithSecondNext() throws NoSuchFieldException, SecurityException, SQLException, IllegalArgumentException, IllegalAccessException { // Stubbing external objects when(resultSet.next()).thenReturn(true); when(resultSet.getMetaData()).thenReturn(metadata); when(metadata.getColumnCount()).thenReturn(0); // Setting up test scenario JdbcReader reader = new JdbcReader(config); Class<?> clazz = JdbcReader.class; Field hasNextField = clazz.getDeclaredField("hasNext"); hasNextField.setAccessible(true); Field resultSetField = clazz.getDeclaredField("resultSet"); resultSetField.setAccessible(true); hasNextField.set(reader, true); resultSetField.set(reader, resultSet); reader.next(); // Assertions assertEquals(hasNextField.get(reader), true, "hasNext field should be set to TRUE"); verify(resultSet, times(1)).next(); } @Test public void testFirstNextWithNoSecondNext() throws SQLException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { // Stubbing external objects when(resultSet.next()).thenReturn(false); when(resultSet.getMetaData()).thenReturn(metadata); when(metadata.getColumnCount()).thenReturn(0); // Setting up test scenario JdbcReader reader = new JdbcReader(config); Class<?> clazz = JdbcReader.class; Field hasNextField = clazz.getDeclaredField("hasNext"); hasNextField.setAccessible(true); Field resultSetField = clazz.getDeclaredField("resultSet"); resultSetField.setAccessible(true); hasNextField.set(reader, true); resultSetField.set(reader, resultSet); reader.next(); // Assertions assertEquals(hasNextField.get(reader), false, "hasNext field should be set to FALSE"); verify(resultSet, times(1)).next(); } @Test(expected = SQLException.class) public void testNextWithoutNext() throws SQLException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { // Stubbing external objects when(resultSet.getMetaData()).thenThrow(SQLException.class); // Setting up test scenario JdbcReader reader = new JdbcReader(config); Class<?> clazz = JdbcReader.class; Field hasNextField = clazz.getDeclaredField("hasNext"); hasNextField.setAccessible(true); Field resultSetField = clazz.getDeclaredField("resultSet"); resultSetField.setAccessible(true); hasNextField.set(reader, false); resultSetField.set(reader, resultSet); reader.next(); // Assertions assertEquals(hasNextField.get(reader), false, "hasNext field should be set to FALSE"); verify(resultSet, times(1)).next(); } @Test public void testNextRowOnInitWhenResultSetIsEmpty() throws Exception { // Stubbing external objects PowerMockito.mockStatic(DriverManager.class); when(config.getDriverClass()).thenReturn(JDBC_CELL_EXTRACTOR_CLASSNAME_CONSTANT); when(config.getConnectionUrl()).thenReturn(WHATEVER_CONSTANT); when(config.getUsername()).thenReturn(WHATEVER_CONSTANT); when(config.getPassword()).thenReturn(WHATEVER_CONSTANT); when(config.getQuery()).thenReturn(mock(SelectQuery.class)); when(DriverManager.getConnection(anyString(), anyString(), anyString())).thenReturn(conn); when(conn.createStatement()).thenReturn(statement); when(statement.executeQuery(anyString())).thenReturn(resultSet); when(resultSet.next()).thenReturn(false); // Setting up test scenario JdbcReader reader = new JdbcReader(config); reader.init(partition); // Assertions Class<?> clazz = JdbcReader.class; Field hasNextField = clazz.getDeclaredField("hasNext"); hasNextField.setAccessible(true); assertEquals(hasNextField.get(reader), false, "hasNext field should be set to FALSE"); } @Test public void testNextRowOnInitWhenResultSetIsNotEmpty() throws Exception { // Stubbing external objects PowerMockito.mockStatic(DriverManager.class); when(config.getDriverClass()).thenReturn(JDBC_CELL_EXTRACTOR_CLASSNAME_CONSTANT); when(config.getConnectionUrl()).thenReturn(WHATEVER_CONSTANT); when(config.getUsername()).thenReturn(WHATEVER_CONSTANT); when(config.getPassword()).thenReturn(WHATEVER_CONSTANT); when(config.getQuery()).thenReturn(mock(SelectQuery.class)); when(DriverManager.getConnection(anyString(), anyString(), anyString())).thenReturn(conn); when(conn.createStatement()).thenReturn(statement); when(statement.executeQuery(anyString())).thenReturn(resultSet); when(resultSet.next()).thenReturn(true); // Setting up test scenario JdbcReader reader = new JdbcReader(config); reader.init(partition); // Assertions Class<?> clazz = JdbcReader.class; Field hasNextField = clazz.getDeclaredField("hasNext"); hasNextField.setAccessible(true); assertEquals(hasNextField.get(reader), true, "hasNext field should be set to TRUE"); } @Test public void testConditionIsAddedForPartitioning() throws Exception { PowerMockito.mockStatic(DriverManager.class); SelectQuery selectQuery = PowerMockito.mock(SelectQuery.class); ComboCondition comboCondition = PowerMockito.mock(ComboCondition.class); when(selectQuery.getWhereClause()).thenReturn(comboCondition); when(comboCondition.addCondition(any(Condition.class))).thenReturn(comboCondition); when(config.getDriverClass()).thenReturn(JDBC_CELL_EXTRACTOR_CLASSNAME_CONSTANT); when(config.getConnectionUrl()).thenReturn(WHATEVER_CONSTANT); when(config.getUsername()).thenReturn(WHATEVER_CONSTANT); when(config.getPassword()).thenReturn(WHATEVER_CONSTANT); when(config.getPartitionKey()).thenReturn(PowerMockito.mock(DbColumn.class)); when(config.getNumPartitions()).thenReturn(NUM_PARTITIONS); when(config.getQuery()).thenReturn(selectQuery); when(DriverManager.getConnection(anyString(), anyString(), anyString())).thenReturn(conn); when(partition.lower()).thenReturn(0L); when(partition.upper()).thenReturn(100L); when(conn.createStatement()).thenReturn(statement); when(statement.executeQuery(anyString())).thenReturn(resultSet); when(resultSet.next()).thenReturn(true); JdbcReader reader = new JdbcReader(config); reader.init(partition); verify(comboCondition, times(2)).addCondition(any((BinaryCondition.class))); } @Test public void testNoConditionsAddedIfNotPartitioning() throws Exception { PowerMockito.mockStatic(DriverManager.class); SelectQuery selectQuery = PowerMockito.mock(SelectQuery.class); ComboCondition comboCondition = PowerMockito.mock(ComboCondition.class); when(selectQuery.getWhereClause()).thenReturn(comboCondition); when(comboCondition.addCondition(any(Condition.class))).thenReturn(comboCondition); when(config.getDriverClass()).thenReturn(JDBC_CELL_EXTRACTOR_CLASSNAME_CONSTANT); when(config.getConnectionUrl()).thenReturn(WHATEVER_CONSTANT); when(config.getUsername()).thenReturn(WHATEVER_CONSTANT); when(config.getPassword()).thenReturn(WHATEVER_CONSTANT); when(config.getQuery()).thenReturn(selectQuery); when(DriverManager.getConnection(anyString(), anyString(), anyString())).thenReturn(conn); when(conn.createStatement()).thenReturn(statement); when(statement.executeQuery(anyString())).thenReturn(resultSet); when(resultSet.next()).thenReturn(true); JdbcReader reader = new JdbcReader(config); reader.init(partition); verify(comboCondition, times(0)).addCondition(any((BinaryCondition.class))); } }