/* * Copyright 2012 NGDATA nv * * 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.lilyproject.indexer.integration; import java.util.ArrayList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import org.junit.Before; import org.junit.Test; import org.lilyproject.indexer.model.api.LResultToSolrMapper; import org.lilyproject.indexer.model.indexerconf.IndexCase; import org.lilyproject.indexer.model.indexerconf.IndexRecordFilter; import org.lilyproject.indexer.model.util.IndexInfo; import org.lilyproject.indexer.model.util.IndexesInfo; import org.lilyproject.repository.api.FieldTypes; import org.lilyproject.repository.api.Record; import org.lilyproject.repository.api.Repository; import org.lilyproject.repository.api.RepositoryException; import org.lilyproject.util.hbase.LilyHBaseSchema.Table; import org.lilyproject.util.hbase.RepoAndTableUtil; import org.lilyproject.util.repo.RecordEvent; import org.lilyproject.util.repo.RecordEvent.IndexRecordFilterData; import org.lilyproject.util.repo.RecordEvent.Type; import org.mockito.Mockito; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class IndexRecordFilterHookTest { private Record oldRecord; private Record newRecord; private Repository repository; private FieldTypes fieldTypes; private IndexesInfo indexesInfo; private IndexRecordFilterHook indexFilterHook; @Before public void setUp() { oldRecord = mock(Record.class); newRecord = mock(Record.class); repository = mock(Repository.class); fieldTypes = mock(FieldTypes.class); indexesInfo = mock(IndexesInfo.class); indexFilterHook = spy(new IndexRecordFilterHook(indexesInfo)); when(repository.getRepositoryName()).thenReturn(RepoAndTableUtil.DEFAULT_REPOSITORY); } @Test public void testBeforeUpdate() throws RepositoryException, InterruptedException { IndexInfo inclusion = createMockIndexInfo("include", true); when(indexesInfo.getIndexInfos()).thenReturn(Lists.newArrayList(inclusion)); RecordEvent recordEvent = new RecordEvent(); recordEvent.setType(Type.UPDATE); recordEvent.setTableName(Table.RECORD.name); indexFilterHook.beforeUpdate(newRecord, oldRecord, repository, fieldTypes, recordEvent); IndexRecordFilterData idxFilterData = recordEvent.getIndexRecordFilterData(); assertTrue(idxFilterData.getOldRecordExists()); assertTrue(idxFilterData.getNewRecordExists()); verify(indexFilterHook).calculateIndexInclusion(RepoAndTableUtil.DEFAULT_REPOSITORY, Table.RECORD.name, oldRecord, newRecord, idxFilterData); } @Test public void testBeforeCreate() throws RepositoryException, InterruptedException { IndexInfo inclusion = createMockIndexInfo("include", true); when(indexesInfo.getIndexInfos()).thenReturn(Lists.newArrayList(inclusion)); RecordEvent recordEvent = new RecordEvent(); recordEvent.setType(Type.CREATE); recordEvent.setTableName(Table.RECORD.name); indexFilterHook.beforeCreate(newRecord, repository, fieldTypes, recordEvent); IndexRecordFilterData idxFilterData = recordEvent.getIndexRecordFilterData(); assertFalse(idxFilterData.getOldRecordExists()); assertTrue(idxFilterData.getNewRecordExists()); verify(indexFilterHook).calculateIndexInclusion(RepoAndTableUtil.DEFAULT_REPOSITORY, Table.RECORD.name, null, newRecord, idxFilterData); } @Test public void testBeforeDelete() throws RepositoryException, InterruptedException { IndexInfo inclusion = createMockIndexInfo("include", true); when(indexesInfo.getIndexInfos()).thenReturn(Lists.newArrayList(inclusion)); RecordEvent recordEvent = new RecordEvent(); recordEvent.setType(Type.DELETE); recordEvent.setTableName(Table.RECORD.name); indexFilterHook.beforeDelete(oldRecord, repository, fieldTypes, recordEvent); IndexRecordFilterData idxFilterData = recordEvent.getIndexRecordFilterData(); assertTrue(idxFilterData.getOldRecordExists()); assertFalse(idxFilterData.getNewRecordExists()); verify(indexFilterHook).calculateIndexInclusion(RepoAndTableUtil.DEFAULT_REPOSITORY, Table.RECORD.name, oldRecord, null, idxFilterData); } @Test public void testCalculateIndexInclusion_MoreInclusionsThanExclusions() { IndexRecordFilterData indexFilterData = mock(IndexRecordFilterData.class); IndexInfo inclusionA = createMockIndexInfo("includeA", true); IndexInfo inclusionB = createMockIndexInfo("includeB", true); IndexInfo exclusion = createMockIndexInfo("exclude", false); when(indexesInfo.getIndexInfos()).thenReturn(Lists.newArrayList(inclusionA, inclusionB, exclusion)); indexFilterHook.calculateIndexInclusion(RepoAndTableUtil.DEFAULT_REPOSITORY, Table.RECORD.name, oldRecord, newRecord, indexFilterData); verify(indexFilterData).setSubscriptionInclusions(ImmutableSet.of("includeA", "includeB")); } @Test public void testCalculateIndexInclusion_MoreExclusionsThanInclusions() { IndexRecordFilterData indexFilterData = mock(IndexRecordFilterData.class); IndexInfo inclusion = createMockIndexInfo("include", true); IndexInfo exclusionA = createMockIndexInfo("excludeA", false); IndexInfo exclusionB = createMockIndexInfo("excludeB", false); when(this.indexesInfo.getIndexInfos()).thenReturn(Lists.newArrayList(inclusion, exclusionA, exclusionB)); indexFilterHook.calculateIndexInclusion(RepoAndTableUtil.DEFAULT_REPOSITORY, Table.RECORD.name, oldRecord, newRecord, indexFilterData); verify(indexFilterData).setSubscriptionExclusions(ImmutableSet.of("excludeA", "excludeB")); } @Test public void testCalculateIndexInclusion_AllIndexesIncluded() { IndexRecordFilterData indexFilterData = mock(IndexRecordFilterData.class); IndexInfo inclusion = createMockIndexInfo("include", true); when(indexesInfo.getIndexInfos()).thenReturn(Lists.newArrayList(inclusion)); indexFilterHook.calculateIndexInclusion(RepoAndTableUtil.DEFAULT_REPOSITORY, Table.RECORD.name, oldRecord, newRecord, indexFilterData); verify(indexFilterData).setSubscriptionInclusions(IndexRecordFilterData.ALL_INDEX_SUBSCRIPTIONS); } @Test public void testCalculateIndexInclusion_AllIndexesExcluded() { IndexRecordFilterData indexFilterData = mock(IndexRecordFilterData.class); IndexInfo inclusion = createMockIndexInfo("exclude", false); when(indexesInfo.getIndexInfos()).thenReturn(Lists.newArrayList(inclusion)); indexFilterHook.calculateIndexInclusion(RepoAndTableUtil.DEFAULT_REPOSITORY, Table.RECORD.name, oldRecord, newRecord, indexFilterData); verify(indexFilterData).setSubscriptionExclusions(IndexRecordFilterData.ALL_INDEX_SUBSCRIPTIONS); } @Test public void testCalculateIndexInclusion_NoIndexSubscriptions() { IndexRecordFilterData indexFilterData = mock(IndexRecordFilterData.class); when(indexesInfo.getIndexInfos()).thenReturn(Lists.<IndexInfo>newArrayList()); indexFilterHook.calculateIndexInclusion(RepoAndTableUtil.DEFAULT_REPOSITORY, Table.RECORD.name, oldRecord, newRecord, indexFilterData); verify(indexFilterData).setSubscriptionExclusions(IndexRecordFilterData.ALL_INDEX_SUBSCRIPTIONS); } @Test public void testCalculateIndexInclusion_RepoBasedExclusion() { IndexRecordFilterData indexFilterData = mock(IndexRecordFilterData.class); IndexInfo inclusionA = createMockIndexInfo("includeA", true); IndexInfo inclusionB = createMockIndexInfo("includeButNotInThisRepo", true); when(inclusionB.getRepositoryName()).thenReturn("someOtherRepo"); IndexInfo exclusion = createMockIndexInfo("exclude", false); when(indexesInfo.getIndexInfos()).thenReturn(Lists.newArrayList(inclusionA, inclusionB, exclusion)); indexFilterHook.calculateIndexInclusion(RepoAndTableUtil.DEFAULT_REPOSITORY, Table.RECORD.name, oldRecord, newRecord, indexFilterData); verify(indexFilterData).setSubscriptionExclusions(ImmutableSet.of("includeButNotInThisRepo", "exclude")); } @Test public void testCalculateIndexInclusion_ForNonDefaultRepository() { IndexRecordFilterData indexFilterData = mock(IndexRecordFilterData.class); IndexInfo inclusionA = createMockIndexInfo("inclusionA", true); IndexInfo exclusion = createMockIndexInfo("excludeA", false); IndexInfo inclusionB = createMockIndexInfo("inclusionB", true); when(inclusionB.getRepositoryName()).thenReturn("someOtherRepo"); when(this.indexesInfo.getIndexInfos()).thenReturn(Lists.newArrayList(inclusionA, exclusion, inclusionB)); indexFilterHook.calculateIndexInclusion("someOtherRepo", Table.RECORD.name, oldRecord, newRecord, indexFilterData); verify(indexFilterData).setSubscriptionExclusions(ImmutableSet.of("inclusionA", "excludeA")); } @Test public void testCalculateIndexInclusion_RepoBasedInclusion() { IndexRecordFilterData indexFilterData = mock(IndexRecordFilterData.class); IndexInfo inclusionA = createMockIndexInfo("inclusionA", true); IndexInfo exclusion = createMockIndexInfo("excludeA", false); IndexInfo inclusionB = createMockIndexInfo("inclusionB", true); ArrayList<IndexInfo> infos = Lists.newArrayList(inclusionA, exclusion, inclusionB); for (IndexInfo info : infos) { when(info.getRepositoryName()).thenReturn("someOtherRepo"); } when(this.indexesInfo.getIndexInfos()).thenReturn(infos); indexFilterHook.calculateIndexInclusion("someOtherRepo", Table.RECORD.name, oldRecord, newRecord, indexFilterData); verify(indexFilterData).setSubscriptionInclusions(ImmutableSet.of("inclusionA","inclusionB")); } private IndexInfo createMockIndexInfo(String queueSubscriptionId, boolean include) { IndexInfo indexInfo = mock(IndexInfo.class, Mockito.RETURNS_DEEP_STUBS); IndexRecordFilter indexRecordFilter = mock(IndexRecordFilter.class); when(indexInfo.getLilyIndexerConf().getRecordFilter()).thenReturn(indexRecordFilter); doReturn(include).when(indexFilterHook).indexIsApplicable(indexRecordFilter, Table.RECORD.name, oldRecord, newRecord); when(indexInfo.getIndexDefinition().getSubscriptionId()).thenReturn(queueSubscriptionId); when(indexInfo.getRepositoryName()).thenReturn(RepoAndTableUtil.DEFAULT_REPOSITORY); return indexInfo; } @Test public void testIndexIsApplicable_TrueForOldRecord() { IndexRecordFilter indexRecordFilter = mock(IndexRecordFilter.class); Record oldRecord = mock(Record.class); when(indexRecordFilter.getIndexCase(Table.RECORD.name, oldRecord)).thenReturn(mock(IndexCase.class)); assertTrue(indexFilterHook.indexIsApplicable(indexRecordFilter, Table.RECORD.name, oldRecord, null)); } @Test public void testIndexIsApplicable_FalseForOldRecord() { IndexRecordFilter indexRecordFilter = mock(IndexRecordFilter.class); Record oldRecord = mock(Record.class); when(indexRecordFilter.getIndexCase(Table.RECORD.name, oldRecord)).thenReturn(null); assertFalse(indexFilterHook.indexIsApplicable(indexRecordFilter, Table.RECORD.name, oldRecord, null)); } @Test public void testIndexIsApplicable_TrueForNewRecord() { IndexRecordFilter indexRecordFilter = mock(IndexRecordFilter.class); Record newRecord = mock(Record.class); when(indexRecordFilter.getIndexCase(Table.RECORD.name, newRecord)).thenReturn(mock(IndexCase.class)); assertTrue(indexFilterHook.indexIsApplicable(indexRecordFilter, Table.RECORD.name, null, newRecord)); } @Test public void testIndexIsApplicable_FalseForNewRecord() { IndexRecordFilter indexRecordFilter = mock(IndexRecordFilter.class); Record newRecord = mock(Record.class); when(indexRecordFilter.getIndexCase(Table.RECORD.name, newRecord)).thenReturn(null); assertFalse(indexFilterHook.indexIsApplicable(indexRecordFilter, Table.RECORD.name, null, newRecord)); } }