diff --git a/community/community-it/kernel-it/src/test/java/recovery/RecoveryCleanupIT.java b/community/community-it/kernel-it/src/test/java/recovery/RecoveryCleanupIT.java index 255f3217f44f0..0f2f9ea1a25bc 100644 --- a/community/community-it/kernel-it/src/test/java/recovery/RecoveryCleanupIT.java +++ b/community/community-it/kernel-it/src/test/java/recovery/RecoveryCleanupIT.java @@ -188,7 +188,7 @@ private void nativeIndexMustLogCrashPointerCleanupDuringRecovery( GraphDatabaseS matchers.add( indexRecoveryFinishedLogMatcher( subType ) ); matchers.add( indexRecoveryLogMatcher( "Schema index cleanup job closed", subType ) ); } - matchers.forEach( logProvider::assertContainsExactlyOneMessageMatching ); + matchers.forEach( logProvider::assertContainsExactlyOneMessageMatchingInAnyOrder ); } private Matcher indexRecoveryLogMatcher( String logMessage, String subIndexProviderKey ) diff --git a/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java b/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java index 685c692008aab..36477c8a23a8f 100644 --- a/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java +++ b/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java @@ -613,19 +613,21 @@ public class GraphDatabaseSettings implements LoadableConfig public enum SchemaIndex { - NATIVE_BTREE10( "native-btree", "1.0" ), - NATIVE20( "lucene+native", "2.0" ), - NATIVE10( "lucene+native", "1.0" ), - LUCENE10( "lucene", "1.0" ); + NATIVE_BTREE10( "native-btree", "1.0", false ), + NATIVE20( "lucene+native", "2.0", true ), + NATIVE10( "lucene+native", "1.0", true ), + LUCENE10( "lucene", "1.0", true ); private final String providerKey; private final String providerVersion; + private final boolean deprecated; private final String providerName; - SchemaIndex( String providerKey, String providerVersion ) + SchemaIndex( String providerKey, String providerVersion, boolean deprecated ) { this.providerKey = providerKey; this.providerVersion = providerVersion; + this.deprecated = deprecated; this.providerName = toProviderName( providerKey, providerVersion ); } @@ -644,6 +646,11 @@ public String providerVersion() return providerVersion; } + public boolean deprecated() + { + return deprecated; + } + private static String toProviderName( String providerName, String providerVersion ) { return providerName + "-" + providerVersion; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/index/IndexingService.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/index/IndexingService.java index 54af7baeeaf33..7e563f246499e 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/index/IndexingService.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/index/IndexingService.java @@ -19,6 +19,7 @@ */ package org.neo4j.kernel.impl.api.index; +import org.apache.commons.lang3.mutable.MutableBoolean; import org.eclipse.collections.api.LongIterable; import org.eclipse.collections.api.block.procedure.primitive.LongObjectProcedure; import org.eclipse.collections.api.map.primitive.MutableLongObjectMap; @@ -31,16 +32,21 @@ import java.io.IOException; import java.io.UncheckedIOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.StringJoiner; import java.util.concurrent.ExecutionException; import java.util.function.Function; +import java.util.stream.Collectors; import org.neo4j.function.ThrowingConsumer; import org.neo4j.graphdb.ResourceIterator; +import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.helpers.collection.Iterators; import org.neo4j.internal.kernel.api.InternalIndexState; import org.neo4j.internal.kernel.api.TokenNameLookup; @@ -204,6 +210,7 @@ public void init() indexMapRef.modify( indexMap -> { Map> indexStates = new EnumMap<>( InternalIndexState.class ); + Map> indexProviders = new HashMap<>(); for ( StoreIndexDescriptor indexDescriptor : indexDescriptors ) { IndexProxy indexProxy; @@ -211,8 +218,11 @@ public void init() IndexProviderDescriptor providerDescriptor = indexDescriptor.providerDescriptor(); IndexProvider provider = providerMap.lookup( providerDescriptor ); InternalIndexState initialState = provider.getInitialState( indexDescriptor ); + IndexLogRecord indexLogRecord = new IndexLogRecord( indexDescriptor ); indexStates.computeIfAbsent( initialState, internalIndexState -> new ArrayList<>() ) - .add( new IndexLogRecord( indexDescriptor ) ); + .add( indexLogRecord ); + indexProviders.computeIfAbsent( providerDescriptor, indexProviderDescriptor -> new ArrayList<>() ) + .add( indexLogRecord ); log.debug( indexStateInfo( "init", initialState, indexDescriptor ) ); switch ( initialState ) @@ -237,6 +247,7 @@ public void init() indexMap.putIndexProxy( indexProxy ); } logIndexStateSummary( "init", indexStates ); + logIndexProviderSummary( "init", indexProviders ); return indexMap; } ); } @@ -269,14 +280,19 @@ public void start() indexMapRef.modify( indexMap -> { Map> indexStates = new EnumMap<>( InternalIndexState.class ); + Map> indexProviders = new HashMap<>(); // Find all indexes that are not already online, do not require rebuilding, and create them indexMap.forEachIndexProxy( ( indexId, proxy ) -> { InternalIndexState state = proxy.getState(); StoreIndexDescriptor descriptor = proxy.getDescriptor(); + IndexProviderDescriptor providerDescriptor = descriptor.providerDescriptor(); + IndexLogRecord indexLogRecord = new IndexLogRecord( descriptor ); indexStates.computeIfAbsent( state, internalIndexState -> new ArrayList<>() ) - .add( new IndexLogRecord( descriptor ) ); + .add( indexLogRecord ); + indexProviders.computeIfAbsent( providerDescriptor, indexProviderDescriptor -> new ArrayList<>() ) + .add( indexLogRecord ); log.debug( indexStateInfo( "start", state, descriptor ) ); switch ( state ) { @@ -295,6 +311,7 @@ public void start() } } ); logIndexStateSummary( "start", indexStates ); + logIndexProviderSummary( "start", indexProviders ); // Drop placeholder proxies for indexes that need to be rebuilt dropRecoveringIndexes( indexMap, rebuildingDescriptors.keySet() ); @@ -774,6 +791,30 @@ private void logIndexStateSummary( String method, Map> indexProviders ) + { + Set deprecatedIndexProviders = Arrays.stream( GraphDatabaseSettings.SchemaIndex.values() ) + .filter( GraphDatabaseSettings.SchemaIndex::deprecated ) + .map( GraphDatabaseSettings.SchemaIndex::providerName ) + .collect( Collectors.toSet() ); + StringJoiner joiner = new StringJoiner( ", ", format( "IndexingService.%s: Deprecated index providers in use: ", method ), "" ); + MutableBoolean anyDeprecated = new MutableBoolean(); + indexProviders.forEach( ( indexProviderDescriptor, indexLogRecords ) -> + { + if ( deprecatedIndexProviders.contains( indexProviderDescriptor.name() ) ) + { + anyDeprecated.setTrue(); + int numberOfIndexes = indexLogRecords.size(); + joiner.add( indexProviderDescriptor.name() + " (" + numberOfIndexes + (numberOfIndexes == 1 ? " index" : " indexes") + ")" ); + } + } ); + if ( anyDeprecated.getValue() ) + { + // todo use userLog here + log.info( joiner.toString() ); + } + } + private final class IndexPopulationStarter implements Function { private final boolean verifyBeforeFlipping; diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/index/IndexingServiceTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/index/IndexingServiceTest.java index 4b25c7484dab8..0f13db2365f72 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/index/IndexingServiceTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/index/IndexingServiceTest.java @@ -22,6 +22,7 @@ import org.eclipse.collections.api.map.primitive.LongObjectMap; import org.hamcrest.Description; import org.hamcrest.Matcher; +import org.hamcrest.Matchers; import org.hamcrest.TypeSafeMatcher; import org.junit.Before; import org.junit.Rule; @@ -128,6 +129,10 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.SchemaIndex.LUCENE10; +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.SchemaIndex.NATIVE10; +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.SchemaIndex.NATIVE20; +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.SchemaIndex.NATIVE_BTREE10; import static org.neo4j.graphdb.factory.GraphDatabaseSettings.default_schema_provider; import static org.neo4j.helpers.collection.Iterators.asCollection; import static org.neo4j.helpers.collection.Iterators.asResourceIterator; @@ -154,6 +159,12 @@ public class IndexingServiceTest public ExpectedException expectedException = ExpectedException.none(); private static final LogMatcherBuilder logMatch = inLog( IndexingService.class ); + private static final IndexProviderDescriptor lucene10Descriptor = new IndexProviderDescriptor( LUCENE10.providerKey(), LUCENE10.providerVersion() ); + private static final IndexProviderDescriptor native10Descriptor = new IndexProviderDescriptor( NATIVE10.providerKey(), NATIVE10.providerVersion() ); + private static final IndexProviderDescriptor native20Descriptor = new IndexProviderDescriptor( NATIVE20.providerKey(), NATIVE20.providerVersion() ); + private static final IndexProviderDescriptor nativeBtree10Descriptor = + new IndexProviderDescriptor( NATIVE_BTREE10.providerKey(), NATIVE_BTREE10.providerVersion() ); + private static final IndexProviderDescriptor fulltextDescriptor = new IndexProviderDescriptor( "fulltext", "1.0" ); private final SchemaState schemaState = mock( SchemaState.class ); private final int labelId = 7; private final int propertyKeyId = 15; @@ -363,11 +374,7 @@ public void shouldBringConstraintIndexOnlineWhenExplicitlyToldTo() throws Except public void shouldLogIndexStateOnInit() throws Exception { // given - IndexProvider provider = mock( IndexProvider.class ); - when( provider.getProviderDescriptor() ).thenReturn( PROVIDER_DESCRIPTOR ); - IndexAccessor indexAccessor = mock( IndexAccessor.class ); - when( provider.getOnlineAccessor( any( StoreIndexDescriptor.class ), any( IndexSamplingConfig.class ) ) ) - .thenReturn( indexAccessor ); + IndexProvider provider = mockIndexProviderWithAccessor( PROVIDER_DESCRIPTOR ); Config config = Config.defaults( default_schema_provider, PROVIDER_DESCRIPTOR.name() ); IndexProviderMap providerMap = life.add( new DefaultIndexProviderMap( buildIndexDependencies( provider ), config ) ); TokenNameLookup mockLookup = mock( TokenNameLookup.class ); @@ -407,8 +414,7 @@ public void shouldLogIndexStateOnInit() throws Exception public void shouldLogIndexStateOnStart() throws Exception { // given - IndexProvider provider = mock( IndexProvider.class ); - when( provider.getProviderDescriptor() ).thenReturn( PROVIDER_DESCRIPTOR ); + IndexProvider provider = mockIndexProviderWithAccessor( PROVIDER_DESCRIPTOR ); Config config = Config.defaults( default_schema_provider, PROVIDER_DESCRIPTOR.name() ); DefaultIndexProviderMap providerMap = new DefaultIndexProviderMap( buildIndexDependencies( provider ), config ); providerMap.init(); @@ -429,8 +435,6 @@ public void shouldLogIndexStateOnStart() throws Exception .thenReturn( InternalIndexState.POPULATING ); when( provider.getInitialState( failedIndex ) ) .thenReturn( InternalIndexState.FAILED ); - when( provider.getOnlineAccessor( any( StoreIndexDescriptor.class ), any( IndexSamplingConfig.class ) ) ).thenAnswer( - invocation -> mock( IndexAccessor.class ) ); indexingService.init(); @@ -454,6 +458,181 @@ public void shouldLogIndexStateOnStart() throws Exception ); } + @Test + public void shouldNotLogWhenNoDeprecatedIndexesOnInit() throws IOException + { + // given + StoreIndexDescriptor nativeBtree10Index = storeIndex( 5, 1, 5, nativeBtree10Descriptor ); + StoreIndexDescriptor fulltextIndex = storeIndex( 6, 1, 6, fulltextDescriptor ); + + IndexProvider lucene10Provider = mockIndexProviderWithAccessor( lucene10Descriptor ); + IndexProvider native10Provider = mockIndexProviderWithAccessor( native10Descriptor ); + IndexProvider native20Provider = mockIndexProviderWithAccessor( native20Descriptor ); + IndexProvider nativeBtree10Provider = mockIndexProviderWithAccessor( nativeBtree10Descriptor ); + IndexProvider fulltextProvider = mockIndexProviderWithAccessor( fulltextDescriptor ); + + when( nativeBtree10Provider.getInitialState( nativeBtree10Index ) ).thenReturn( ONLINE ); + when( fulltextProvider.getInitialState( fulltextIndex ) ).thenReturn( ONLINE ); + + Config config = Config.defaults( default_schema_provider, nativeBtree10Descriptor.name() ); + DependencyResolver dependencies = buildIndexDependencies( lucene10Provider, native10Provider, native20Provider, nativeBtree10Provider ); + DefaultIndexProviderMap providerMap = new DefaultIndexProviderMap( dependencies, config ); + providerMap.init(); + TokenNameLookup mockLookup = mock( TokenNameLookup.class ); + + IndexingService indexingService = IndexingServiceFactory.createIndexingService( config, + mock( JobScheduler.class ), providerMap, storeView, mockLookup, + Collections.singletonList( nativeBtree10Index ), logProvider, IndexingService.NO_MONITOR, + schemaState ); + + // when + indexingService.init(); + + // then + logProvider.assertNoMessagesContaining( "IndexingService.init: Deprecated index providers in use:" ); + logProvider.assertNoMessagesContaining( nativeBtree10Descriptor.name() ); + logProvider.assertNoMessagesContaining( fulltextDescriptor.name() ); + } + + @Test + public void shouldNotLogWhenNoDeprecatedIndexesOnStart() throws IOException + { + // given + StoreIndexDescriptor nativeBtree10Index = storeIndex( 5, 1, 5, nativeBtree10Descriptor ); + StoreIndexDescriptor fulltextIndex = storeIndex( 6, 1, 6, fulltextDescriptor ); + + IndexProvider lucene10Provider = mockIndexProviderWithAccessor( lucene10Descriptor ); + IndexProvider native10Provider = mockIndexProviderWithAccessor( native10Descriptor ); + IndexProvider native20Provider = mockIndexProviderWithAccessor( native20Descriptor ); + IndexProvider nativeBtree10Provider = mockIndexProviderWithAccessor( nativeBtree10Descriptor ); + IndexProvider fulltextProvider = mockIndexProviderWithAccessor( fulltextDescriptor ); + + when( nativeBtree10Provider.getInitialState( nativeBtree10Index ) ).thenReturn( ONLINE ); + when( fulltextProvider.getInitialState( fulltextIndex ) ).thenReturn( ONLINE ); + + Config config = Config.defaults( default_schema_provider, nativeBtree10Descriptor.name() ); + DependencyResolver dependencies = buildIndexDependencies( lucene10Provider, native10Provider, native20Provider, nativeBtree10Provider, fulltextProvider ); + DefaultIndexProviderMap providerMap = new DefaultIndexProviderMap( dependencies, config ); + providerMap.init(); + TokenNameLookup mockLookup = mock( TokenNameLookup.class ); + + + IndexingService indexingService = IndexingServiceFactory.createIndexingService( config, + mock( JobScheduler.class ), providerMap, storeView, mockLookup, + Collections.singletonList( nativeBtree10Index ), logProvider, IndexingService.NO_MONITOR, + schemaState ); + + // when + indexingService.init(); + logProvider.clear(); + indexingService.start(); + + // then + logProvider.assertNoMessagesContaining( "IndexingService.start: Deprecated index providers in use:" ); + logProvider.assertNoMessagesContaining( nativeBtree10Descriptor.name() ); + logProvider.assertNoMessagesContaining( fulltextDescriptor.name() ); + } + + @Test + public void shouldLogDeprecatedIndexesOnInit() throws IOException + { + // given + StoreIndexDescriptor lucene10Index = storeIndex( 1, 1, 1, lucene10Descriptor ); + StoreIndexDescriptor native10Index = storeIndex( 2, 1, 2, native10Descriptor ); + StoreIndexDescriptor native20Index1 = storeIndex( 3, 1, 3, native20Descriptor ); + StoreIndexDescriptor native20Index2 = storeIndex( 4, 1, 4, native20Descriptor ); + StoreIndexDescriptor nativeBtree10Index = storeIndex( 5, 1, 5, nativeBtree10Descriptor ); + StoreIndexDescriptor fulltextIndex = storeIndex( 6, 1, 6, fulltextDescriptor ); + + IndexProvider lucene10Provider = mockIndexProviderWithAccessor( lucene10Descriptor ); + IndexProvider native10Provider = mockIndexProviderWithAccessor( native10Descriptor ); + IndexProvider native20Provider = mockIndexProviderWithAccessor( native20Descriptor ); + IndexProvider nativeBtree10Provider = mockIndexProviderWithAccessor( nativeBtree10Descriptor ); + IndexProvider fulltextProvider = mockIndexProviderWithAccessor( fulltextDescriptor ); + + when( lucene10Provider.getInitialState( lucene10Index ) ).thenReturn( ONLINE ); + when( native10Provider.getInitialState( native10Index ) ).thenReturn( ONLINE ); + when( native20Provider.getInitialState( native20Index1 ) ).thenReturn( ONLINE ); + when( native20Provider.getInitialState( native20Index2 ) ).thenReturn( ONLINE ); + when( nativeBtree10Provider.getInitialState( nativeBtree10Index ) ).thenReturn( ONLINE ); + when( fulltextProvider.getInitialState( fulltextIndex ) ).thenReturn( ONLINE ); + + Config config = Config.defaults( default_schema_provider, nativeBtree10Descriptor.name() ); + DependencyResolver dependencies = buildIndexDependencies( lucene10Provider, native10Provider, native20Provider, nativeBtree10Provider ); + DefaultIndexProviderMap providerMap = new DefaultIndexProviderMap( dependencies, config ); + providerMap.init(); + TokenNameLookup mockLookup = mock( TokenNameLookup.class ); + + IndexingService indexingService = IndexingServiceFactory.createIndexingService( config, + mock( JobScheduler.class ), providerMap, storeView, mockLookup, + asList( lucene10Index, native10Index, native20Index1, native20Index2, nativeBtree10Index ), logProvider, IndexingService.NO_MONITOR, + schemaState ); + + // when + indexingService.init(); + + // then + logProvider.assertContainsExactlyOneMessageMatchingInAnyOrder( + Matchers.containsString( "IndexingService.init: Deprecated index providers in use:" ), + Matchers.containsString( lucene10Descriptor.name() + " (1 index)" ), + Matchers.containsString( native10Descriptor.name() + " (1 index)" ), + Matchers.containsString( native20Descriptor.name() + " (2 indexes)" ) + ); + logProvider.assertNoMessagesContaining( nativeBtree10Descriptor.name() ); + logProvider.assertNoMessagesContaining( fulltextDescriptor.name() ); + } + + @Test + public void shouldLogDeprecatedIndexesOnStart() throws IOException + { + // given + StoreIndexDescriptor lucene10Index = storeIndex( 1, 1, 1, lucene10Descriptor ); + StoreIndexDescriptor native10Index = storeIndex( 2, 1, 2, native10Descriptor ); + StoreIndexDescriptor native20Index1 = storeIndex( 3, 1, 3, native20Descriptor ); + StoreIndexDescriptor native20Index2 = storeIndex( 4, 1, 4, native20Descriptor ); + StoreIndexDescriptor nativeBtree10Index = storeIndex( 5, 1, 5, nativeBtree10Descriptor ); + StoreIndexDescriptor fulltextIndex = storeIndex( 6, 1, 6, fulltextDescriptor ); + + IndexProvider lucene10Provider = mockIndexProviderWithAccessor( lucene10Descriptor ); + IndexProvider native10Provider = mockIndexProviderWithAccessor( native10Descriptor ); + IndexProvider native20Provider = mockIndexProviderWithAccessor( native20Descriptor ); + IndexProvider nativeBtree10Provider = mockIndexProviderWithAccessor( nativeBtree10Descriptor ); + IndexProvider fulltextProvider = mockIndexProviderWithAccessor( fulltextDescriptor ); + + when( lucene10Provider.getInitialState( lucene10Index ) ).thenReturn( ONLINE ); + when( native10Provider.getInitialState( native10Index ) ).thenReturn( ONLINE ); + when( native20Provider.getInitialState( native20Index1 ) ).thenReturn( ONLINE ); + when( native20Provider.getInitialState( native20Index2 ) ).thenReturn( ONLINE ); + when( nativeBtree10Provider.getInitialState( nativeBtree10Index ) ).thenReturn( ONLINE ); + when( fulltextProvider.getInitialState( fulltextIndex ) ).thenReturn( ONLINE ); + + Config config = Config.defaults( default_schema_provider, nativeBtree10Descriptor.name() ); + DependencyResolver dependencies = buildIndexDependencies( lucene10Provider, native10Provider, native20Provider, nativeBtree10Provider ); + DefaultIndexProviderMap providerMap = new DefaultIndexProviderMap( dependencies, config ); + providerMap.init(); + TokenNameLookup mockLookup = mock( TokenNameLookup.class ); + + IndexingService indexingService = IndexingServiceFactory.createIndexingService( config, + mock( JobScheduler.class ), providerMap, storeView, mockLookup, + asList( lucene10Index, native10Index, native20Index1, native20Index2, nativeBtree10Index ), logProvider, IndexingService.NO_MONITOR, + schemaState ); + + // when + indexingService.init(); + logProvider.clear(); + indexingService.start(); + + // then + logProvider.assertContainsExactlyOneMessageMatchingInAnyOrder( + Matchers.containsString( "IndexingService.start: Deprecated index providers in use:" ), + Matchers.containsString( lucene10Descriptor.name() + " (1 index)" ), + Matchers.containsString( native10Descriptor.name() + " (1 index)" ), + Matchers.containsString( native20Descriptor.name() + " (2 indexes)" ) + ); + logProvider.assertNoMessagesContaining( nativeBtree10Descriptor.name() ); + logProvider.assertNoMessagesContaining( fulltextDescriptor.name() ); + } + @Test public void shouldFailToStartIfMissingIndexProvider() throws Exception { @@ -928,11 +1107,7 @@ public void shouldStoreIndexFailureWhenFailingToCreateOnlineAccessorAfterRecover public void shouldLogIndexStateOutliersOnInit() throws Exception { // given - IndexProvider provider = mock( IndexProvider.class ); - when( provider.getProviderDescriptor() ).thenReturn( PROVIDER_DESCRIPTOR ); - IndexAccessor indexAccessor = mock( IndexAccessor.class ); - when( provider.getOnlineAccessor( any( StoreIndexDescriptor.class ), any( IndexSamplingConfig.class ) ) ) - .thenReturn( indexAccessor ); + IndexProvider provider = mockIndexProviderWithAccessor( PROVIDER_DESCRIPTOR ); Config config = Config.defaults( default_schema_provider, PROVIDER_DESCRIPTOR.name() ); IndexProviderMap providerMap = life.add( new DefaultIndexProviderMap( buildIndexDependencies( provider ), config ) ); TokenNameLookup mockLookup = mock( TokenNameLookup.class ); @@ -978,11 +1153,7 @@ public void shouldLogIndexStateOutliersOnInit() throws Exception public void shouldLogIndexStateOutliersOnStart() throws Exception { // given - IndexProvider provider = mock( IndexProvider.class ); - when( provider.getProviderDescriptor() ).thenReturn( PROVIDER_DESCRIPTOR ); - IndexAccessor indexAccessor = mock( IndexAccessor.class ); - when( provider.getOnlineAccessor( any( StoreIndexDescriptor.class ), any( IndexSamplingConfig.class ) ) ) - .thenReturn( indexAccessor ); + IndexProvider provider = mockIndexProviderWithAccessor( PROVIDER_DESCRIPTOR ); Config config = Config.defaults( default_schema_provider, PROVIDER_DESCRIPTOR.name() ); DefaultIndexProviderMap providerMap = new DefaultIndexProviderMap( buildIndexDependencies( provider ), config ); providerMap.init(); @@ -1435,9 +1606,24 @@ indexMapReference, mock( IndexStoreView.class ), Collections.emptyList(), } private static DependencyResolver buildIndexDependencies( IndexProvider provider ) + { + return buildIndexDependencies( new IndexProvider[]{provider} ); + } + + private static DependencyResolver buildIndexDependencies( IndexProvider... providers ) { Dependencies dependencies = new Dependencies(); - dependencies.satisfyDependency( provider ); + dependencies.satisfyDependencies( (Object[]) providers ); return dependencies; } + + private IndexProvider mockIndexProviderWithAccessor( IndexProviderDescriptor descriptor ) throws IOException + { + IndexProvider provider = mock( IndexProvider.class ); + when( provider.getProviderDescriptor() ).thenReturn( descriptor ); + IndexAccessor indexAccessor = mock( IndexAccessor.class ); + when( provider.getOnlineAccessor( any( StoreIndexDescriptor.class ), any( IndexSamplingConfig.class ) ) ) + .thenReturn( indexAccessor ); + return provider; + } } diff --git a/community/logging/src/test/java/org/neo4j/logging/AssertableLogProvider.java b/community/logging/src/test/java/org/neo4j/logging/AssertableLogProvider.java index 6da7a34205cec..80c13e748c80d 100644 --- a/community/logging/src/test/java/org/neo4j/logging/AssertableLogProvider.java +++ b/community/logging/src/test/java/org/neo4j/logging/AssertableLogProvider.java @@ -764,14 +764,24 @@ public void assertContainsMessageMatching( Matcher messageMatcher ) } } - public void assertContainsExactlyOneMessageMatching( Matcher messageMatcher ) + @SafeVarargs + public final void assertContainsExactlyOneMessageMatchingInAnyOrder( Matcher... messageMatchers ) { boolean found = false; synchronized ( logCalls ) { for ( LogCall logCall : logCalls ) { - if ( messageMatcher.matches( logCall.message ) ) + boolean match = true; + for ( Matcher messageMatcher : messageMatchers ) + { + if ( !messageMatcher.matches( logCall.message ) ) + { + match = false; + break; + } + } + if ( match ) { if ( !found ) { @@ -780,16 +790,22 @@ public void assertContainsExactlyOneMessageMatching( Matcher messageMatc else { StringDescription description = new StringDescription(); - description.appendDescriptionOf( messageMatcher ); + for ( Matcher messageMatcher : messageMatchers ) + { + description.appendDescriptionOf( messageMatcher ); + } fail( format( "Expected exactly one log statement with message as %s, but multiple found. Actual log calls were:%n%s", - description.toString(), serialize( logCalls.iterator() ) ) ); + description.toString(), serialize( logCalls.iterator() ) ) ); } } } if ( !found ) { StringDescription description = new StringDescription(); - description.appendDescriptionOf( messageMatcher ); + for ( Matcher messageMatcher : messageMatchers ) + { + description.appendDescriptionOf( messageMatcher ); + } fail( format( "Expected at least one log statement with message as %s, but none found. Actual log calls were:\n%s", description.toString(), serialize( logCalls.iterator() ) ) ); diff --git a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/catchup/storecopy/StoreCopyClientIT.java b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/catchup/storecopy/StoreCopyClientIT.java index da8c48877b5d0..75e410212f2a2 100644 --- a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/catchup/storecopy/StoreCopyClientIT.java +++ b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/catchup/storecopy/StoreCopyClientIT.java @@ -326,7 +326,7 @@ public AdvertisedSocketAddress secondary() } catch ( StoreCopyFailedException e ) { - assertableLogProvider.assertContainsExactlyOneMessageMatching( + assertableLogProvider.assertContainsExactlyOneMessageMatchingInAnyOrder( both( containsString( "Connection refused:" ) ).and( containsString( "localhost/127.0.0.1:" + port ) ) ); } } @@ -356,7 +356,7 @@ public AdvertisedSocketAddress secondary() throws CatchupAddressResolutionExcept } catch ( StoreCopyFailedException e ) { - assertableLogProvider.assertContainsExactlyOneMessageMatching( startsWith( "Unable to resolve address for" ) ); + assertableLogProvider.assertContainsExactlyOneMessageMatchingInAnyOrder( startsWith( "Unable to resolve address for" ) ); assertableLogProvider.assertLogStringContains(catchupAddressResolutionException.getMessage() ); } } diff --git a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/diagnostics/CoreMonitorTest.java b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/diagnostics/CoreMonitorTest.java index a7bf49f7aaa45..37e6a52f67ecb 100644 --- a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/diagnostics/CoreMonitorTest.java +++ b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/diagnostics/CoreMonitorTest.java @@ -52,7 +52,7 @@ public void shouldNotDuplicateToAnyLog() ClusterId clusterId = new ClusterId( UUID.randomUUID() ); monitor.boundToCluster( clusterId ); - user.assertContainsExactlyOneMessageMatching( Matchers.equalToIgnoringCase( "Bound to cluster with id " + clusterId.uuid() ) ); - debug.assertContainsExactlyOneMessageMatching( Matchers.equalToIgnoringCase( "Bound to cluster with id " + clusterId.uuid() ) ); + user.assertContainsExactlyOneMessageMatchingInAnyOrder( Matchers.equalToIgnoringCase( "Bound to cluster with id " + clusterId.uuid() ) ); + debug.assertContainsExactlyOneMessageMatchingInAnyOrder( Matchers.equalToIgnoringCase( "Bound to cluster with id " + clusterId.uuid() ) ); } }