Refine search
@Test public void processNextBatchShouldCloseConnectionAndLogOnUnexpectedException() { RuntimeException exception = new RuntimeException( "unexpected exception" ); BoltConnection connection = newConnection(); connection.enqueue( machine -> { throw exception; } ); connection.processNextBatch(); verify( stateMachine ).close(); logProvider.assertExactly( AssertableLogProvider.inLog( containsString( BoltServer.class.getPackage().getName() ) ).error( containsString( "Unexpected error detected in bolt session" ), is( exception ) ) ); }
@Test public void shouldNotLogConnectionResetErrors() throws Exception { // Given AssertableLogProvider logProvider = new AssertableLogProvider(); HouseKeeper keeper = new HouseKeeper( null, logProvider.getLog( HouseKeeper.class ) ); Channel channel = mock( Channel.class ); when( channel.toString() ).thenReturn( "[some channel info]" ); ChannelHandlerContext ctx = mock( ChannelHandlerContext.class ); when( ctx.channel() ).thenReturn( channel ); when( ctx.executor() ).thenReturn( mock( EventExecutor.class ) ); IOException connResetError = new IOException( "Connection reset by peer" ); // When keeper.exceptionCaught( ctx, connResetError ); // Then logProvider.assertExactly( AssertableLogProvider.inLog( HouseKeeper.class ).warn( "Fatal error occurred when handling a client connection, " + "remote peer unexpectedly closed connection: %s", channel ) ); }
@Test public void processNextBatchShouldCloseConnectionOnFatalAuthenticationError() { BoltConnection connection = newConnection(); connection.enqueue( machine -> { throw new BoltConnectionAuthFatality( "auth failure", new RuntimeException( "inner error" ) ); } ); connection.processNextBatch(); verify( stateMachine ).close(); logProvider.assertNone( AssertableLogProvider.inLog( containsString( BoltServer.class.getPackage().getName() ) ).warn( any( String.class ) ) ); }
@Test public void processNextBatchShouldCloseConnectionAndLogOnFatalBoltError() { BoltConnectionFatality exception = new BoltProtocolBreachFatality( "fatal bolt error" ); BoltConnection connection = newConnection(); connection.enqueue( machine -> { throw exception; } ); connection.processNextBatch(); verify( stateMachine ).close(); logProvider.assertExactly( AssertableLogProvider.inLog( containsString( BoltServer.class.getPackage().getName() ) ).error( containsString( "Protocol breach detected in bolt session" ), is( exception ) ) ); }
@Test public void shouldNotAuthorizeInvalidCredentials() throws Exception { // Given final AuthorizationEnabledFilter filter = new AuthorizationEnabledFilter( () -> authManager, logProvider ); String credentials = Base64.encodeBase64String( "foo:bar".getBytes( StandardCharsets.UTF_8 ) ); BasicLoginContext loginContext = mock( BasicLoginContext.class ); AuthSubject authSubject = mock( AuthSubject.class ); when( servletRequest.getMethod() ).thenReturn( "GET" ); when( servletRequest.getContextPath() ).thenReturn( "/db/data" ); when( servletRequest.getHeader( HttpHeaders.AUTHORIZATION ) ).thenReturn( "BASIC " + credentials ); when( servletRequest.getRemoteAddr() ).thenReturn( "remote_ip_address" ); when( authManager.login( authTokenArgumentMatcher( authToken( "foo", "bar" ) ) ) ).thenReturn( loginContext ); when( loginContext.subject() ).thenReturn( authSubject ); when( authSubject.getAuthenticationResult() ).thenReturn( AuthenticationResult.FAILURE ); // When filter.doFilter( servletRequest, servletResponse, filterChain ); // Then verifyNoMoreInteractions( filterChain ); logProvider.assertExactly( inLog( AuthorizationEnabledFilter.class ) .warn( "Failed authentication attempt for '%s' from %s", "foo", "remote_ip_address" ) ); verify( servletResponse ).setStatus( 401 ); verify( servletResponse ).addHeader( HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8" ); assertThat( outputStream.toString( StandardCharsets.UTF_8.name() ), containsString( "\"code\" : \"Neo.ClientError.Security.Unauthorized\"" ) ); assertThat( outputStream.toString( StandardCharsets.UTF_8.name() ), containsString( "\"message\" : \"Invalid username or password.\"" ) ); }
@Test public void shouldLogConnectionResetErrorsAtWarningLevelAndClosesContext() throws Exception { // Given ChannelHandlerContext context = channelHandlerContextMock(); AssertableLogProvider logging = new AssertableLogProvider(); TransportSelectionHandler handler = new TransportSelectionHandler( null, null, false, false, logging, null ); IOException connResetError = new IOException( "Connection reset by peer" ); // When handler.exceptionCaught( context, connResetError ); // Then verify( context ).close(); logging.assertExactly( inLog( TransportSelectionHandler.class ) .warn( "Fatal error occurred when initialising pipeline, " + "remote peer unexpectedly closed connection: %s", context.channel() ) ); }
@Test public void shouldLogOnUnexpectedExceptionsAndClosesContext() throws Throwable { // Given ChannelHandlerContext context = channelHandlerContextMock(); AssertableLogProvider logging = new AssertableLogProvider(); TransportSelectionHandler handler = new TransportSelectionHandler( null, null, false, false, logging, null ); // When Throwable cause = new Throwable( "Oh no!" ); handler.exceptionCaught( context, cause ); // Then verify( context ).close(); logging.assertExactly( inLog( TransportSelectionHandler.class ) .error( equalTo( "Fatal error occurred when initialising pipeline: " + context.channel() ), sameInstance( cause ) ) ); }
@Test public void shouldAbbreviateWellKnownIOErrors() { // given OutputStream output = mock( OutputStream.class, new ThrowsException( new IOException( "Broken pipe" ) ) ); AssertableLogProvider logProvider = new AssertableLogProvider(); ExecutionResultSerializer serializer = getSerializerWith( output, null, logProvider ); // when serializer.finish(); // then logProvider.assertExactly( AssertableLogProvider.inLog( ExecutionResultSerializer.class ) .error( "Unable to reply to request, because the client has closed the connection (Broken pipe)." ) ); }
@Test public void failingJobShouldLogAndStopConnection() throws Throwable { AtomicBoolean stopped = new AtomicBoolean(); String id = UUID.randomUUID().toString(); BoltConnection connection = newConnection( id ); doThrow( new RuntimeException( "some unexpected error" ) ).when( connection ).processNextBatch(); doAnswer( inv -> stopped.getAndSet( true ) ).when( connection ).stop(); boltScheduler.start(); boltScheduler.created( connection ); boltScheduler.enqueued( connection, Jobs.noop() ); Predicates.await( () -> stopped.get(), 1, MINUTES ); assertFalse( boltScheduler.isActive( connection ) ); verify( connection ).processNextBatch(); verify( connection ).stop(); logProvider.assertExactly( AssertableLogProvider.inLog( containsString( BoltServer.class.getPackage().getName() ) ).error( containsString( "Unexpected error during job scheduling for session" ), matchesExceptionMessage( containsString( "some unexpected error" ) ) ) ); }
@Test public void shouldLogBoltConnectionAuthFatalityError() { BoltConnection connection = newConnection(); connection.enqueue( machine -> { throw new BoltConnectionAuthFatality( new AuthenticationException( Status.Security.Unauthorized, "inner error" ) ); } ); connection.processNextBatch(); verify( stateMachine ).close(); logProvider.assertExactly( AssertableLogProvider.inLog( containsString( BoltServer.class.getPackage().getName() ) ).warn( containsString( "inner error" ) ) ); }
@Test public void shouldLogIOErrors() { // given IOException failure = new IOException(); OutputStream output = mock( OutputStream.class, new ThrowsException( failure ) ); AssertableLogProvider logProvider = new AssertableLogProvider(); ExecutionResultSerializer serializer = getSerializerWith( output, null, logProvider ); // when serializer.finish(); // then logProvider.assertExactly( AssertableLogProvider.inLog( ExecutionResultSerializer.class ).error( is( "Failed to generate JSON output." ), sameInstance( failure ) ) ); }
@Test public void mustLogAfterResetWithCountLimit() { int limit = 10; logger.setCountLimit( limit ); String[] lines = logLines( limit + 1 ); logger.reset(); String[] moreLines = logLines( 1, limit + 1 ); assertLoggedLines( ArrayUtils.addAll( ArrayUtils.subarray( lines, 0, limit ), moreLines ), 1 + limit ); logProvider.assertNone( currentLog( inLog( CappedLogger.class ), containsString( lines[limit] ) ) ); logProvider.assertContainsMessageMatching( containsString( moreLines[0] ) ); }
@Test public void shouldLogExceptionOnExceptionCaught() { AssertableLogProvider logProvider = new AssertableLogProvider(); BoltConnection connection = mock( BoltConnection.class ); channel = new EmbeddedChannel( new HouseKeeper( connection, logProvider.getLog( HouseKeeper.class ) ) ); RuntimeException exception = new RuntimeException( "some exception" ); channel.pipeline().fireExceptionCaught( exception ); verify( connection ).stop(); logProvider.assertExactly( inLog( HouseKeeper.class ).error( startsWith( "Fatal error occurred when handling a client connection" ), equalTo( exception ) ) ); }
@Test public void shouldLogShortWarningOnClientDisconnectMidwayThroughQuery() throws Exception { // Connections dying is not exceptional per-se, so we don't need to fill the log with // eye-catching stack traces; but it could be indicative of some issue, so log a brief // warning in the debug log at least. // Given PackOutputClosedException outputClosed = new PackOutputClosedException( "Output closed", "<client>" ); Neo4jError txTerminated = Neo4jError.from( new TransactionTerminatedException( Status.Transaction.Terminated ) ); // When AssertableLogProvider logProvider = emulateFailureWritingError( txTerminated, outputClosed ); // Then logProvider.assertExactly( inLog( "Test" ).warn( equalTo( "Client %s disconnected while query was running. Session has been cleaned up. " + "This can be caused by temporary network problems, but if you see this often, ensure your " + "applications are properly waiting for operations to complete before exiting." ), equalTo( "<client>" ) ) ); }
@Test public void shouldLogJobFailure() throws Exception { // Given createNode( map( name, "irrelephant" ), FIRST ); AssertableLogProvider logProvider = new AssertableLogProvider(); FlippableIndexProxy index = mock( FlippableIndexProxy.class ); IndexPopulator populator = spy( indexPopulator( false ) ); IndexPopulationJob job = newIndexPopulationJob( populator, index, indexStoreView, logProvider, EntityType.NODE, indexDescriptor( FIRST, name, false ) ); Throwable failure = new IllegalStateException( "not successful" ); doThrow( failure ).when( populator ).create(); // When job.run(); // Then LogMatcherBuilder match = inLog( IndexPopulationJob.class ); logProvider.assertAtLeastOnce( match.error( is( "Failed to populate index: [:FIRST(name)]" ), sameInstance( failure ) ) ); }
@Test public void mustNotLogMessagesWithinConfiguredTimeLimit() { FakeClock clock = getDefaultFakeClock(); logger.setTimeLimit( 1, TimeUnit.MILLISECONDS, clock ); logMethod.log( logger, "### AAA ###" ); logMethod.log( logger, "### BBB ###" ); clock.forward( 1, TimeUnit.MILLISECONDS ); logMethod.log( logger, "### CCC ###" ); logProvider.assertContainsMessageMatching( containsString( "### AAA ###" ) ); logProvider.assertNone( currentLog( inLog( CappedLogger.class ), containsString( "### BBB ###" ) ) ); logProvider.assertContainsMessageMatching( containsString( "### CCC ###" ) ); }