private void assertLogExistsForRecoveryOn( String labelAndProperty ) { logProvider.assertAtLeastOnce( inLog( IndexSamplingController.class ).debug( "Recovering index sampling for index %s", labelAndProperty ) ); }
@Test public void shouldLogOnSuccessfulStartup() throws Throwable { theDatabase.start(); logProvider.assertAtLeastOnce( inLog( LifecycleManagingDatabase.class ).info( "Started." ) ); }
@Test void shouldRequestIndexPopulationFailingWithFileNotFoundException() { // Given long faultyIndexId = 1; FileNotFoundException error = new FileNotFoundException( "/some/path/somewhere" ); LuceneIndexProvider provider = newFaultyIndexProvider( faultyIndexId, error ); // When StoreIndexDescriptor descriptor = forSchema( forLabel( 1, 1 ), provider.getProviderDescriptor() ).withId( faultyIndexId ); InternalIndexState initialState = provider.getInitialState( descriptor ); // Then assertThat( initialState, equalTo(InternalIndexState.POPULATING) ); logProvider.assertAtLeastOnce( loggedException( error ) ); }
@Test void shouldRequestIndexPopulationWhenFailingWithEOFException() { // Given long faultyIndexId = 1; EOFException error = new EOFException( "/some/path/somewhere" ); LuceneIndexProvider provider = newFaultyIndexProvider( faultyIndexId, error ); // When StoreIndexDescriptor descriptor = forSchema( forLabel( 1, 1 ), provider.getProviderDescriptor() ).withId( faultyIndexId ); InternalIndexState initialState = provider.getInitialState( descriptor ); // Then assertThat( initialState, equalTo(InternalIndexState.POPULATING) ); logProvider.assertAtLeastOnce( loggedException( error ) ); }
@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 shouldStoreIndexFailureWhenFailingToCreateOnlineAccessorAfterRecoveringPopulatingIndex() throws Exception { // given long indexId = 1; StoreIndexDescriptor indexRule = index.withId( indexId ); IndexingService indexing = newIndexingServiceWithMockedDependencies( populator, accessor, withData(), indexRule ); IOException exception = new IOException( "Expected failure" ); when( nameLookup.labelGetName( labelId ) ).thenReturn( "TheLabel" ); when( nameLookup.propertyKeyGetName( propertyKeyId ) ).thenReturn( "propertyKey" ); when( indexProvider.getInitialState( indexRule ) ).thenReturn( POPULATING ); when( indexProvider.getOnlineAccessor( any( StoreIndexDescriptor.class ), any( IndexSamplingConfig.class ) ) ) .thenThrow( exception ); life.start(); ArgumentCaptor<Boolean> closeArgs = ArgumentCaptor.forClass( Boolean.class ); // when waitForIndexesToGetIntoState( indexing, InternalIndexState.FAILED, indexId ); verify( populator, timeout( 10000 ).times( 2 ) ).close( closeArgs.capture() ); // then assertEquals( FAILED, indexing.getIndexProxy( 1 ).getState() ); assertEquals( asList( true, false ), closeArgs.getAllValues() ); assertThat( storedFailure(), containsString( format( "java.io.IOException: Expected failure%n\tat " ) ) ); internalLogProvider.assertAtLeastOnce( inLog( IndexPopulationJob.class ).error( equalTo( "Failed to populate index: [:TheLabel(propertyKey) [provider: {key=quantum-dex, version=25.0}]]" ), causedBy( exception ) ) ); internalLogProvider.assertNone( inLog( IndexPopulationJob.class ).info( "Index population completed. Index is now online: [%s]", ":TheLabel(propertyKey) [provider: {key=quantum-dex, version=25.0}]" ) ); }
@Test public void shouldLogTriggerSamplingOnAllIndexes() throws Exception { // given IndexingService indexingService = newIndexingServiceWithMockedDependencies( populator, accessor, withData() ); IndexSamplingMode mode = TRIGGER_REBUILD_ALL; // when indexingService.triggerIndexSampling( mode ); // then internalLogProvider.assertAtLeastOnce( logMatch.info( "Manual trigger for sampling all indexes [" + mode + "]" ) ); }
@Test public void shouldShutdownCleanly() throws Throwable { theDatabase.start(); theDatabase.stop(); logProvider.assertAtLeastOnce( inLog( LifecycleManagingDatabase.class ).info( "Stopped." ) ); }
@Test void shouldRequestIndexPopulationIfTheIndexIsCorrupt() { // Given long faultyIndexId = 1; CorruptIndexException error = new CorruptIndexException( "It's broken.", "" ); LuceneIndexProvider provider = newFaultyIndexProvider( faultyIndexId, error ); // When StoreIndexDescriptor descriptor = forSchema( forLabel( 1, 1 ), provider.getProviderDescriptor() ).withId( faultyIndexId ); InternalIndexState initialState = provider.getInitialState( descriptor ); // Then assertThat( initialState, equalTo(InternalIndexState.POPULATING) ); logProvider.assertAtLeastOnce( loggedException( error ) ); }
@Test public void shouldStoreIndexFailureWhenFailingToCreateOnlineAccessorAfterPopulating() throws Exception { // given long indexId = 1; IndexingService indexing = newIndexingServiceWithMockedDependencies( populator, accessor, withData() ); IOException exception = new IOException( "Expected failure" ); when( nameLookup.labelGetName( labelId ) ).thenReturn( "TheLabel" ); when( nameLookup.propertyKeyGetName( propertyKeyId ) ).thenReturn( "propertyKey" ); when( indexProvider.getOnlineAccessor( any( StoreIndexDescriptor.class ), any( IndexSamplingConfig.class ) ) ) .thenThrow( exception ); life.start(); ArgumentCaptor<Boolean> closeArgs = ArgumentCaptor.forClass( Boolean.class ); // when indexing.createIndexes( index.withId( indexId ) ); waitForIndexesToGetIntoState( indexing, InternalIndexState.FAILED, indexId ); verify( populator, timeout( 10000 ).times( 2 ) ).close( closeArgs.capture() ); // then assertEquals( FAILED, indexing.getIndexProxy( 1 ).getState() ); assertEquals( asList( true, false ), closeArgs.getAllValues() ); assertThat( storedFailure(), containsString( format( "java.io.IOException: Expected failure%n\tat " ) ) ); internalLogProvider.assertAtLeastOnce( inLog( IndexPopulationJob.class ).error( equalTo( "Failed to populate index: [:TheLabel(propertyKey) [provider: {key=quantum-dex, version=25.0}]]" ), causedBy( exception ) ) ); internalLogProvider.assertNone( inLog( IndexPopulationJob.class ).info( "Index population completed. Index is now online: [%s]", ":TheLabel(propertyKey) [provider: {key=quantum-dex, version=25.0}]" ) ); }
@Test public void shouldComplainIfServerPortIsAlreadyTaken() throws IOException { try ( ServerSocket socket = new ServerSocket( 0, 0, InetAddress.getLocalHost() ) ) { ListenSocketAddress contestedAddress = new ListenSocketAddress( socket.getInetAddress().getHostName(), socket.getLocalPort() ); AssertableLogProvider logProvider = new AssertableLogProvider(); CommunityNeoServer server = CommunityServerBuilder.server( logProvider ) .onAddress( contestedAddress ) .usingDataDir( folder.directory( name.getMethodName() ).getAbsolutePath() ) .build(); try { server.start(); fail( "Should have reported failure to start" ); } catch ( ServerStartupException e ) { assertThat( e.getMessage(), containsString( "Starting Neo4j failed" ) ); } logProvider.assertAtLeastOnce( AssertableLogProvider.inLog( containsString( "CommunityNeoServer" ) ).error( "Failed to start Neo4j on %s: %s", contestedAddress, format( "Address %s is already in use, cannot bind to it.", contestedAddress ) ) ); server.stop(); } }
@Test public void shouldLogDatabasePanicEvent() { // GIVEN AssertableLogProvider logProvider = new AssertableLogProvider(); DatabaseHealth databaseHealth = new DatabaseHealth( mock( DatabasePanicEventGenerator.class ), logProvider.getLog( DatabaseHealth.class ) ); databaseHealth.healed(); // WHEN String message = "Listen everybody... panic!"; Exception exception = new Exception( message ); databaseHealth.panic( exception ); // THEN logProvider.assertAtLeastOnce( inLog( DatabaseHealth.class ).error( is( "Database panic: The database has encountered a critical error, " + "and needs to be restarted. Please see database logs for more details." ), sameInstance( exception ) ) ); }
logProvider.assertAtLeastOnce( AssertableLogProvider.inLog( containsString( "CommunityNeoServer" ) ).error( "Failed to start Neo4j on %s: %s",
@Test public void logModuleSetUpError() { Config config = Config.defaults(); IdGeneratorFactory idGeneratorFactory = mock( IdGeneratorFactory.class ); Throwable openStoresError = new RuntimeException( "Can't set up modules" ); doThrow( openStoresError ).when( idGeneratorFactory ).create( any( File.class ), anyLong(), anyBoolean() ); CommunityIdTypeConfigurationProvider idTypeConfigurationProvider = new CommunityIdTypeConfigurationProvider(); AssertableLogProvider logProvider = new AssertableLogProvider(); SimpleLogService logService = new SimpleLogService( logProvider, logProvider ); PageCache pageCache = pageCacheRule.getPageCache( fs.get() ); Dependencies dependencies = new Dependencies(); dependencies.satisfyDependencies( idGeneratorFactory, idTypeConfigurationProvider, config, logService ); NeoStoreDataSource dataSource = dsRule.getDataSource( dir.databaseLayout(), fs.get(), pageCache, dependencies ); try { dataSource.start(); fail( "Exception expected" ); } catch ( Exception e ) { assertEquals( openStoresError, e ); } logProvider.assertAtLeastOnce( inLog( NeoStoreDataSource.class ).warn( equalTo( "Exception occurred while setting up store modules. Attempting to close things down." ), equalTo( openStoresError ) ) ); }
@Test public void shouldLogReasonForDroppingIndex() throws IOException { // given AssertableLogProvider logProvider = new AssertableLogProvider(); // when new FailedIndexProxy( forSchema( forLabel( 0, 0 ), IndexProviderDescriptor.UNDECIDED ).withId( 1 ).withoutCapabilities(), "foo", mock( IndexPopulator.class ), IndexPopulationFailure.failure( "it broke" ), indexCountsRemover, logProvider ).drop(); // then logProvider.assertAtLeastOnce( inLog( FailedIndexProxy.class ).info( "FailedIndexProxy#drop index on foo dropped due to:\nit broke" ) ); } }
@Test public void shouldReportFailureWhenAllThreadsInThreadPoolAreBusy() throws Throwable { // it's enough to get the bolt state machine into streaming mode to have // the thread sticked to the connection, causing all the available threads // to be busy (logically) connection1 = enterStreaming(); connection2 = enterStreaming(); try { connection3 = connectAndPerformBoltHandshake( newConnection() ); connection3.send( util.chunk( new InitMessage( "TestClient/1.1", emptyMap() ) ) ); assertThat( connection3, util.eventuallyReceives( msgFailure( Status.Request.NoThreadsAvailable, "There are no available threads to serve this request at the moment" ) ) ); userLogProvider.assertContainsMessageContaining( "since there are no available threads to serve it at the moment. You can retry at a later time" ); internalLogProvider.assertAtLeastOnce( AssertableLogProvider .inLog( startsWith( BoltConnection.class.getPackage().getName() ) ) .error( containsString( "since there are no available threads to serve it at the moment. You can retry at a later time" ), isA( RejectedExecutionException.class ) ) ); } finally { exitStreaming( connection1 ); exitStreaming( connection2 ); } }
@Test public void shouldLogUserReadableLabelAndPropertyNames() throws Exception { //noinspection deprecation GraphDatabaseAPI db = dbRule.getGraphDatabaseAPI(); String labelName = "User"; String property = "name"; // when createIndex( db, labelName, property ); // then LogMatcherBuilder match = inLog( IndexPopulationJob.class ); IndexProviderMap indexProviderMap = db.getDependencyResolver().resolveDependency( IndexProviderMap.class ); IndexProvider defaultProvider = indexProviderMap.getDefaultProvider(); IndexProviderDescriptor providerDescriptor = defaultProvider.getProviderDescriptor(); logProvider.assertAtLeastOnce( match.info( "Index population started: [%s]", ":User(name) [provider: {key=" + providerDescriptor.getKey() + ", version=" + providerDescriptor.getVersion() + "}]" ) ); assertEventually( (ThrowingSupplier<Object,Exception>) () -> null, new LogMessageMatcher( match, providerDescriptor ), 1, TimeUnit.MINUTES ); }
@Test public void shouldRebuildMissingCountsStoreOnStart() throws IOException, TransactionFailureException { // given createAliensAndHumans(); // when FileSystemAbstraction fs = shutdown(); deleteCounts( fs ); restart( fs ); // then try ( org.neo4j.internal.kernel.api.Transaction tx = ((GraphDatabaseAPI)db).getDependencyResolver().resolveDependency( Kernel.class ) .beginTransaction( explicit, AUTH_DISABLED ) ) { assertEquals( ALIENS + HUMANS, tx.dataRead().countsForNode( -1 ) ); assertEquals( ALIENS, tx.dataRead().countsForNode( labelId( ALIEN ) ) ); assertEquals( HUMANS, tx.dataRead().countsForNode( labelId( HUMAN ) ) ); } // and also LogMatcherBuilder matcherBuilder = inLog( MetaDataStore.class ); internalLogProvider.assertAtLeastOnce( matcherBuilder.warn( "Missing counts store, rebuilding it." ) ); internalLogProvider.assertAtLeastOnce( matcherBuilder.warn( "Counts store rebuild completed." ) ); }
@Test public void shouldLogTriggerSamplingOnAnIndexes() throws Exception { // given long indexId = 0; IndexSamplingMode mode = TRIGGER_REBUILD_ALL; IndexDescriptor descriptor = forSchema( forLabel( 0, 1 ), PROVIDER_DESCRIPTOR ); IndexingService indexingService = newIndexingServiceWithMockedDependencies( populator, accessor, withData(), descriptor.withId( indexId ) ); life.init(); life.start(); // when indexingService.triggerIndexSampling( descriptor.schema() , mode ); // then String userDescription = descriptor.schema().userDescription( nameLookup ); internalLogProvider.assertAtLeastOnce( logMatch.info( "Manual trigger for sampling index " + userDescription + " [" + mode + "]" ) ); }
@Test public void shouldRebuildMissingCountsStoreAfterRecovery() throws IOException, TransactionFailureException { // given createAliensAndHumans(); // when rotateLog(); deleteHumans(); FileSystemAbstraction fs = crash(); deleteCounts( fs ); restart( fs ); // then try ( org.neo4j.internal.kernel.api.Transaction tx = ((GraphDatabaseAPI)db).getDependencyResolver().resolveDependency( Kernel.class ) .beginTransaction( explicit, AUTH_DISABLED ) ) { assertEquals( ALIENS, tx.dataRead().countsForNode( -1 ) ); assertEquals( ALIENS, tx.dataRead().countsForNode( labelId( ALIEN ) ) ); assertEquals( 0, tx.dataRead().countsForNode( labelId( HUMAN ) ) ); } // and also LogMatcherBuilder matcherBuilder = inLog( MetaDataStore.class ); internalLogProvider.assertAtLeastOnce( matcherBuilder.warn( "Missing counts store, rebuilding it." ) ); internalLogProvider.assertAtLeastOnce( matcherBuilder.warn( "Counts store rebuild completed." ) ); }