/* * Copyright (c) 2002-2017 "Neo Technology," * Network Engine for Objects in Lund AB [http://neotechnology.com] * * This file is part of Neo4j. * * 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 org.neo4j.driver.internal; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; import java.net.URI; import java.util.Arrays; import java.util.List; import org.neo4j.driver.internal.cluster.LoadBalancer; import org.neo4j.driver.internal.cluster.RoutingSettings; import org.neo4j.driver.internal.net.BoltServerAddress; import org.neo4j.driver.internal.retry.RetryLogic; import org.neo4j.driver.internal.retry.RetrySettings; import org.neo4j.driver.internal.security.SecurityPlan; import org.neo4j.driver.internal.spi.ConnectionPool; import org.neo4j.driver.internal.spi.ConnectionProvider; import org.neo4j.driver.v1.AuthToken; import org.neo4j.driver.v1.AuthTokens; import org.neo4j.driver.v1.Config; import org.neo4j.driver.v1.Driver; import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.neo4j.driver.v1.AccessMode.READ; import static org.neo4j.driver.v1.Config.defaultConfig; @RunWith( Parameterized.class ) public class DriverFactoryTest { @Parameter public URI uri; @Parameters( name = "{0}" ) public static List<URI> uris() { return Arrays.asList( URI.create( "bolt://localhost:7687" ), URI.create( "bolt+routing://localhost:7687" ) ); } @Test public void connectionPoolClosedWhenDriverCreationFails() throws Exception { ConnectionPool connectionPool = mock( ConnectionPool.class ); DriverFactory factory = new ThrowingDriverFactory( connectionPool ); try { createDriver( factory ); fail( "Exception expected" ); } catch ( Exception e ) { assertThat( e, instanceOf( UnsupportedOperationException.class ) ); } verify( connectionPool ).close(); } @Test public void connectionPoolCloseExceptionIsSupressedWhenDriverCreationFails() throws Exception { ConnectionPool connectionPool = mock( ConnectionPool.class ); RuntimeException poolCloseError = new RuntimeException( "Pool close error" ); doThrow( poolCloseError ).when( connectionPool ).close(); DriverFactory factory = new ThrowingDriverFactory( connectionPool ); try { createDriver( factory ); fail( "Exception expected" ); } catch ( Exception e ) { assertThat( e, instanceOf( UnsupportedOperationException.class ) ); assertArrayEquals( new Throwable[]{poolCloseError}, e.getSuppressed() ); } verify( connectionPool ).close(); } @Test public void usesStandardSessionFactoryWhenNothingConfigured() { Config config = Config.defaultConfig(); SessionFactoryCapturingDriverFactory factory = new SessionFactoryCapturingDriverFactory(); createDriver( factory, config ); SessionFactory capturedFactory = factory.capturedSessionFactory; assertThat( capturedFactory.newInstance( READ, null ), instanceOf( NetworkSession.class ) ); } @Test public void usesLeakLoggingSessionFactoryWhenConfigured() { Config config = Config.build().withLeakedSessionsLogging().toConfig(); SessionFactoryCapturingDriverFactory factory = new SessionFactoryCapturingDriverFactory(); createDriver( factory, config ); SessionFactory capturedFactory = factory.capturedSessionFactory; assertThat( capturedFactory.newInstance( READ, null ), instanceOf( LeakLoggingNetworkSession.class ) ); } private Driver createDriver( DriverFactory driverFactory ) { return createDriver( driverFactory, defaultConfig() ); } private Driver createDriver( DriverFactory driverFactory, Config config ) { AuthToken auth = AuthTokens.none(); RoutingSettings routingSettings = new RoutingSettings( 42, 42, null ); return driverFactory.newInstance( uri, auth, routingSettings, RetrySettings.DEFAULT, config ); } private static class ThrowingDriverFactory extends DriverFactory { final ConnectionPool connectionPool; ThrowingDriverFactory( ConnectionPool connectionPool ) { this.connectionPool = connectionPool; } @Override protected InternalDriver createDriver( Config config, SecurityPlan securityPlan, SessionFactory sessionFactory ) { throw new UnsupportedOperationException( "Can't create direct driver" ); } @Override protected Driver createRoutingDriver( BoltServerAddress address, ConnectionPool connectionPool, Config config, RoutingSettings routingSettings, SecurityPlan securityPlan, RetryLogic retryLogic ) { throw new UnsupportedOperationException( "Can't create routing driver" ); } @Override protected ConnectionPool createConnectionPool( AuthToken authToken, SecurityPlan securityPlan, Config config ) { return connectionPool; } } private static class SessionFactoryCapturingDriverFactory extends DriverFactory { SessionFactory capturedSessionFactory; @Override protected InternalDriver createDriver( Config config, SecurityPlan securityPlan, SessionFactory sessionFactory ) { return null; } @Override protected LoadBalancer createLoadBalancer( BoltServerAddress address, ConnectionPool connectionPool, Config config, RoutingSettings routingSettings ) { return null; } @Override protected SessionFactory createSessionFactory( ConnectionProvider connectionProvider, RetryLogic retryLogic, Config config ) { SessionFactory sessionFactory = super.createSessionFactory( connectionProvider, retryLogic, config ); capturedSessionFactory = sessionFactory; return sessionFactory; } } }