/* * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU General Public License, version 2 as published by the Free Software * Foundation. * * You should have received a copy of the GNU General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * * Copyright 2006 - 2016 Pentaho Corporation. All rights reserved. */ package org.pentaho.platform.engine.services.connection.datasource.dbcp; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.HashMap; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.pentaho.database.DatabaseDialectException; import org.pentaho.database.IDatabaseDialect; import org.pentaho.database.IDriverLocator; import org.pentaho.database.dialect.GenericDatabaseDialect; import org.pentaho.database.model.DatabaseAccessType; import org.pentaho.database.model.DatabaseConnection; import org.pentaho.database.model.IDatabaseConnection; import org.pentaho.database.model.IDatabaseType; import org.pentaho.database.service.DatabaseDialectService; import org.pentaho.database.service.IDatabaseDialectService; import org.pentaho.database.util.DatabaseTypeHelper; import org.pentaho.platform.api.data.DBDatasourceServiceException; import org.pentaho.test.platform.engine.core.MicroPlatform; import org.springframework.jdbc.datasource.DriverManagerDataSource; import com.google.common.collect.ImmutableMap; @RunWith( MockitoJUnitRunner.class ) public class PooledDatasourceHelperTest { private static final String SOLUTION_PATH = "src/test/resources/solution"; private MicroPlatform mp; @Mock( extraInterfaces = { IDriverLocator.class } ) private IDatabaseDialect driverLocatorDialect; @Mock private IDatabaseDialect plainDialect; @Mock private IDatabaseConnection connection; @Mock private IDatabaseDialectService dialectService; @Mock private IDatabaseType databaseType; private final String nativeDriverName = "some.native.driver"; private final String jdbcUrl = "jdbc:some://server:port"; @Before public void before() throws DatabaseDialectException { when( dialectService.getDialect( connection ) ).thenReturn( driverLocatorDialect ); when( connection.getDatabaseType() ).thenReturn( databaseType ); when( connection.getDatabaseType().getShortName() ).thenReturn( "SomeDBType" ); when( driverLocatorDialect.getNativeDriver() ).thenReturn( nativeDriverName ); when( driverLocatorDialect.getURLWithExtraOptions( connection ) ).thenReturn( jdbcUrl ); when( plainDialect.getNativeDriver() ).thenReturn( nativeDriverName ); when( plainDialect.getURLWithExtraOptions( connection ) ).thenReturn( jdbcUrl ); } @Test public void testSetupPooledDataSourceForJNDI() { try { IDatabaseConnection databaseConnection = mock( IDatabaseConnection.class ); when( databaseConnection.getAccessType() ).thenReturn( DatabaseAccessType.JNDI ); PooledDatasourceHelper.setupPooledDataSource( databaseConnection ); fail( "Expecting the exception to be thrown" ); } catch ( DBDatasourceServiceException ex ) { assertNotNull( ex ); } } @Test public void testCreatePoolNoDialectService() throws Exception { DatabaseDialectService dialectService = new DatabaseDialectService( false ); final DatabaseTypeHelper databaseTypeHelper = new DatabaseTypeHelper( dialectService.getDatabaseTypes() ); final DatabaseConnection con = new DatabaseConnection(); con.setId( "Postgres" ); con.setName( "Postgres" ); con.setAccessType( DatabaseAccessType.NATIVE ); con.setDatabaseType( databaseTypeHelper.getDatabaseTypeByShortName( "GENERIC" ) ); con.setUsername( "pentaho_user" ); con.setPassword( "password" ); final HashMap<String, String> attrs = new HashMap<>(); attrs.put( DatabaseConnection.ATTRIBUTE_CUSTOM_DRIVER_CLASS, "org.postgresql.Driver" ); attrs.put( DatabaseConnection.ATTRIBUTE_CUSTOM_URL, "jdbc:postgresql://localhost:5432/hibernate" ); con.setAttributes( attrs ); try { PooledDatasourceHelper.setupPooledDataSource( con ); fail( "Expecting the exception to be thrown" ); } catch ( DBDatasourceServiceException ex ) { assertNotNull( ex ); } } @Test public void testCreatePoolNoDialect() throws Exception { DatabaseDialectService dialectService = new DatabaseDialectService( false ); mp = new MicroPlatform( SOLUTION_PATH ); mp.defineInstance( IDatabaseDialectService.class, dialectService ); mp.start(); final DatabaseConnection con = new DatabaseConnection(); con.setId( "Postgres" ); con.setName( "Postgres" ); con.setAccessType( DatabaseAccessType.NATIVE ); con.setUsername( "pentaho_user" ); con.setPassword( "password" ); final HashMap<String, String> attrs = new HashMap<>(); attrs.put( DatabaseConnection.ATTRIBUTE_CUSTOM_DRIVER_CLASS, "" ); attrs.put( DatabaseConnection.ATTRIBUTE_CUSTOM_URL, "jdbc:postgresql://localhost:5432/hibernate" ); con.setAttributes( attrs ); try { PooledDatasourceHelper.setupPooledDataSource( con ); fail( "Expecting the exception to be thrown" ); } catch ( DBDatasourceServiceException ex ) { assertNotNull( ex ); } } @Test public void testCreatePoolNoClassName() throws Exception { DatabaseDialectService dialectService = new DatabaseDialectService( false ); final DatabaseTypeHelper databaseTypeHelper = new DatabaseTypeHelper( dialectService.getDatabaseTypes() ); mp = new MicroPlatform( SOLUTION_PATH ); mp.defineInstance( IDatabaseDialectService.class, dialectService ); mp.start(); final DatabaseConnection con = new DatabaseConnection(); con.setId( "Postgres" ); con.setName( "Postgres" ); con.setAccessType( DatabaseAccessType.NATIVE ); con.setDatabaseType( databaseTypeHelper.getDatabaseTypeByShortName( "GENERIC" ) ); con.setUsername( "pentaho_user" ); con.setPassword( "password" ); final HashMap<String, String> attrs = new HashMap<>(); attrs.put( DatabaseConnection.ATTRIBUTE_CUSTOM_DRIVER_CLASS, "" ); attrs.put( DatabaseConnection.ATTRIBUTE_CUSTOM_URL, "jdbc:postgresql://localhost:5432/hibernate" ); con.setAttributes( attrs ); try { PooledDatasourceHelper.setupPooledDataSource( con ); fail( "Expecting the exception to be thrown" ); } catch ( DBDatasourceServiceException ex ) { assertNotNull( ex ); } } @Test public void testCreateDatasourceNoDialect() throws Exception { DatabaseDialectService dialectService = new DatabaseDialectService( false ); final DatabaseConnection con = new DatabaseConnection(); con.setId( "Postgres" ); con.setName( "Postgres" ); con.setAccessType( DatabaseAccessType.NATIVE ); con.setUsername( "pentaho_user" ); con.setPassword( "password" ); final HashMap<String, String> attrs = new HashMap<>(); attrs.put( DatabaseConnection.ATTRIBUTE_CUSTOM_DRIVER_CLASS, "org.postgresql.Driver" ); attrs.put( DatabaseConnection.ATTRIBUTE_CUSTOM_URL, "jdbc:postgresql://localhost:5432/hibernate" ); con.setAttributes( attrs ); try { PooledDatasourceHelper.convert( con, () -> dialectService ); fail( "Expecting the exception to be thrown" ); } catch ( DBDatasourceServiceException ex ) { assertNotNull( ex ); } } @Test public void testCreateDatasourceNoClassName() throws Exception { DatabaseDialectService dialectService = new DatabaseDialectService( false ); final DatabaseTypeHelper databaseTypeHelper = new DatabaseTypeHelper( dialectService.getDatabaseTypes() ); final DatabaseConnection con = new DatabaseConnection(); con.setId( "Postgres" ); con.setName( "Postgres" ); con.setAccessType( DatabaseAccessType.NATIVE ); con.setDatabaseType( databaseTypeHelper.getDatabaseTypeByShortName( "GENERIC" ) ); con.setUsername( "pentaho_user" ); con.setPassword( "password" ); final HashMap<String, String> attrs = new HashMap<>(); attrs.put( DatabaseConnection.ATTRIBUTE_CUSTOM_DRIVER_CLASS, "" ); attrs.put( DatabaseConnection.ATTRIBUTE_CUSTOM_URL, "jdbc:postgresql://localhost:5432/hibernate" ); con.setAttributes( attrs ); try { PooledDatasourceHelper.convert( con, () -> dialectService ); fail( "Expecting the exception to be thrown" ); } catch ( DBDatasourceServiceException ex ) { assertNotNull( ex ); } } @Test public void testThatFailedDriverInitThrowsInConvert() throws DBDatasourceServiceException { when( ( (IDriverLocator) driverLocatorDialect ).initialize( nativeDriverName ) ).thenReturn( false ); try { PooledDatasourceHelper.convert( connection, () -> dialectService ); fail( "Expected exception" ); } catch ( Exception e ) { assertThat( e.getMessage(), containsString( nativeDriverName ) ); } } @Test public void testSuccessfulDriverInitInConvertNonGeneric() throws DBDatasourceServiceException { when( ( (IDriverLocator) driverLocatorDialect ).initialize( nativeDriverName ) ).thenReturn( true ); PooledDatasourceHelper.convert( connection, () -> dialectService ); verify( ( (IDriverLocator) driverLocatorDialect ), times( 1 ) ).initialize( nativeDriverName ); } @Test public void testSuccessfulDriverInitInConvertGeneric() throws DBDatasourceServiceException { when( databaseType.getShortName() ).thenReturn( "GENERIC" ); when( connection.getAttributes() ).thenReturn( ImmutableMap.of( GenericDatabaseDialect.ATTRIBUTE_CUSTOM_DRIVER_CLASS, nativeDriverName ) ); when( connection.getUsername() ).thenReturn( "suzy" ); when( connection.getPassword() ).thenReturn( "password" ); when( ( (IDriverLocator) driverLocatorDialect ).initialize( nativeDriverName ) ).thenReturn( true ); DriverManagerDataSource dataSource = (DriverManagerDataSource) PooledDatasourceHelper.convert( connection, () -> dialectService ); verify( ( (IDriverLocator) driverLocatorDialect ), times( 1 ) ).initialize( nativeDriverName ); assertThat( dataSource.getUrl(), is( jdbcUrl ) ); assertThat( dataSource.getUsername(), is( "suzy" ) ); assertThat( dataSource.getPassword(), is( "password" ) ); } @Test public void testDialectWithoutLocatorAndDriverNotPresent() throws DBDatasourceServiceException { when( dialectService.getDialect( connection ) ).thenReturn( plainDialect ); try { PooledDatasourceHelper.convert( connection, () -> dialectService ); fail( "Expected exception, driver class should not be present." ); } catch ( Exception e ) { assertThat( e, instanceOf( DBDatasourceServiceException.class ) ); assertThat( e.getCause().getMessage(), containsString( nativeDriverName ) ); } } @Test public void testDialectWithNoDriverSpecified() throws DBDatasourceServiceException { when( dialectService.getDialect( connection ) ).thenReturn( driverLocatorDialect ); when( driverLocatorDialect.getNativeDriver() ).thenReturn( "" ); try { PooledDatasourceHelper.convert( connection, () -> dialectService ); fail( "Expected exception, driver class not specified in dialect." ); } catch ( Exception e ) { assertThat( e, instanceOf( DBDatasourceServiceException.class ) ); } } @Test public void testNoDialectService() throws DBDatasourceServiceException { try { PooledDatasourceHelper.convert( connection, () -> null ); fail( "Expected an exception. No dialect service." ); } catch ( Exception e ) { assertThat( e, instanceOf( DBDatasourceServiceException.class ) ); } } @After public void after() { if ( mp != null ) { mp.stop(); } } }