diff --git a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java index 64c5fde..3c19f36 100644 --- a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java +++ b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java @@ -66,12 +66,15 @@ import java.util.Set; import javax.jcr.PropertyType; +import ch.qos.logback.classic.Level; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.jackrabbit.oak.api.Blob; import org.apache.jackrabbit.oak.api.CommitFailedException; import org.apache.jackrabbit.oak.api.Type; +import org.apache.jackrabbit.oak.commons.junit.LogCustomizer; import org.apache.jackrabbit.oak.plugins.index.IndexConstants; +import org.apache.jackrabbit.oak.plugins.index.IndexUpdate; import org.apache.jackrabbit.oak.plugins.index.IndexUpdateProvider; import org.apache.jackrabbit.oak.plugins.index.lucene.directory.DefaultDirectoryFactory; import org.apache.jackrabbit.oak.plugins.index.lucene.directory.LocalIndexDir; @@ -119,6 +122,7 @@ import org.apache.lucene.queries.CustomScoreProvider; import org.apache.lucene.queries.CustomScoreQuery; import org.apache.lucene.search.Query; import org.apache.lucene.store.Directory; +import org.hamcrest.core.IsCollectionContaining; import org.jetbrains.annotations.NotNull; import org.junit.After; import org.junit.Assert; @@ -915,6 +919,90 @@ public class LuceneIndexTest { assertEquals(indexPath, defn.getIndexName()); assertEquals(indexPath, defn.getIndexPath()); } + /* + Given a lucene index with a config error , it should not block other indexes to index content + and should log a meaningful Exception . Once fixed and reindexed - it should reindex content as expected. + */ + @Test + public void testConfigErrorInIndexDefintion() throws Exception { + LogCustomizer customLogs = LogCustomizer.forLogger(IndexUpdate.class.getName()).enable(Level.ERROR).create(); + + // Create 2 index def - one with config related error and one without + NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME); + newLucenePropertyIndexDefinition(index, "luceneTest", ImmutableSet.of("foo"), null); + newLucenePropertyIndexDefinition(index, "luceneTest2", ImmutableSet.of("foo2"), null); + + builder.child(INDEX_DEFINITIONS_NAME).child("luceneTest").setProperty(IndexConstants.ENTRY_COUNT_PROPERTY_NAME, ImmutableList.of(2L), Type.LONGS); + + NodeState before = builder.getNodeState(); + // Add some content that qualifies to be indexed by both of the above indexes (separately) + builder.child("a").setProperty("foo", "bar"); + builder.child("a").child("b").setProperty("foo", "bar"); + builder.child("a").child("b").child("c").setProperty("foo2", "bar"); + + NodeState after = builder.getNodeState(); + NodeState indexed; + try { + customLogs.starting(); + String expectedLogMessage = "Unable to get Index Editor for index at /oak:index/luceneTest . " + + "Please correct the index definition and reindex after correction. " + + "Additional Info : java.lang.IllegalStateException: Multiple values provided for property entryCount in index definition . Single value was expected"; + indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY); + tracker = new IndexTracker(); + tracker.update(indexed); + Assert.assertThat(customLogs.getLogs(), IsCollectionContaining.hasItems(expectedLogMessage)); + + } finally { + customLogs.finished(); + } + + AdvancedQueryIndex queryIndex = new LucenePropertyIndex(tracker); + FilterImpl filter = createFilter(NT_BASE); + filter.restrictProperty("foo", Operator.EQUAL, + PropertyValues.newString("bar")); + List plans = queryIndex.getPlans(filter, null, indexed); + + // Since the index serving property foo has a config error , no plan should be available + assertTrue(plans.size() == 0); + + // Now we check the config error in index1 should not impact the query results and content getting indexed for index 2 + FilterImpl filter2 = createFilter(NT_BASE); + filter2.restrictProperty("foo2", Operator.EQUAL, + PropertyValues.newString("bar")); + List plans2 = queryIndex.getPlans(filter2, null, indexed); + Cursor cursor2 = queryIndex.query(plans2.get(0), indexed); + + assertTrue(cursor2.hasNext()); + assertEquals("/a/b/c", cursor2.next().getPath()); + assertFalse(cursor2.hasNext()); + + // Now let's fix the config error in index1 and check it now indexes the correct data + + before = builder.getNodeState(); + builder.child(INDEX_DEFINITIONS_NAME).child("luceneTest").setProperty(IndexConstants.ENTRY_COUNT_PROPERTY_NAME, 2L, Type.LONG); + builder.child(INDEX_DEFINITIONS_NAME).child("luceneTest").setProperty(IndexConstants.REINDEX_PROPERTY_NAME, true); + + after = builder.getNodeState(); + try { + customLogs.starting(); + indexed = HOOK.processCommit(before, after, CommitInfo.EMPTY); + tracker.update(indexed); + // Since the config error is now fixed - there should not be any more errors here + assertTrue(customLogs.getLogs().size() == 0); + } finally { + customLogs.finished(); + } + + + plans = queryIndex.getPlans(filter, null, indexed); + Cursor cursor = queryIndex.query(plans.get(0), indexed); + + assertTrue(cursor.hasNext()); + assertEquals("/a/b", cursor.next().getPath()); + assertEquals("/a", cursor.next().getPath()); + assertFalse(cursor.hasNext()); + + } @After