/*
* Copyright 2010-2013 the original author or authors.
*
* 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.springframework.data.gemfire;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.isA;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.query.Index;
import org.apache.geode.cache.query.IndexExistsException;
import org.apache.geode.cache.query.IndexInvalidException;
import org.apache.geode.cache.query.IndexNameConflictException;
import org.apache.geode.cache.query.IndexStatistics;
import org.apache.geode.cache.query.QueryService;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.data.gemfire.config.xml.GemfireConstants;
import org.springframework.data.util.ReflectionUtils;
/**
* The IndexFactoryBeanTest class is a test suite of test cases testing the contract and functionality
* of the IndexFactoryBean class.
*
* @author John Blum
* @see org.junit.Test
* @see org.springframework.data.gemfire.IndexFactoryBean
* @see org.apache.geode.cache.Cache
* @see org.apache.geode.cache.client.ClientCache
* @see org.apache.geode.cache.query.Index
* @see org.apache.geode.cache.query.QueryService
* @since 1.5.2
*/
public class IndexFactoryBeanTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
private Cache mockCache = mock(Cache.class, "IndexFactoryBeanTest.MockCache");
private IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
private QueryService mockQueryService = mock(QueryService.class, "IndexFactoryBeanTest.MockQueryService");
protected IndexFactoryBean newIndexFactoryBean() {
IndexFactoryBean indexFactoryBean = new IndexFactoryBean() {
@Override QueryService lookupQueryService() {
return mockQueryService;
}
};
indexFactoryBean.setCache(mockCache);
return indexFactoryBean;
}
@After
public void tearDown() {
indexFactoryBean.setBeanFactory(null);
indexFactoryBean.setCache(null);
indexFactoryBean.setDefine(false);
}
@Test
public void afterPropertiesSetIsSuccessful() throws Exception {
BeanFactory mockBeanFactory = mock(BeanFactory.class, "testAfterPropertiesSetIsSuccessful.MockBeanFactory");
Cache mockCache = mock(Cache.class, "testAfterPropertiesSetIsSuccessful.MockCache");
Index mockIndex = mock(Index.class, "testAfterPropertiesSetIsSuccessful.MockIndex");
QueryService mockQueryService = mock(QueryService.class, "testAfterPropertiesSetIsSuccessful.MockQueryService");
when(mockBeanFactory.containsBean(eq(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE))).thenReturn(false);
when(mockCache.getQueryService()).thenReturn(mockQueryService);
when(mockQueryService.createKeyIndex(eq("TestKeyIndex"), eq("id"), eq("/Example"))).thenReturn(mockIndex);
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setBeanFactory(mockBeanFactory);
indexFactoryBean.setCache(mockCache);
indexFactoryBean.setDefine(false);
indexFactoryBean.setExpression("id");
indexFactoryBean.setFrom("/Example");
indexFactoryBean.setName("TestKeyIndex");
indexFactoryBean.setType("key");
indexFactoryBean.afterPropertiesSet();
assertEquals(mockIndex, indexFactoryBean.getObject());
assertSame(mockIndex, indexFactoryBean.getObject()); // assert Index really is a 'Singleton'
assertTrue(Index.class.isAssignableFrom(indexFactoryBean.getObjectType()));
assertTrue(indexFactoryBean.isSingleton());
verify(mockBeanFactory, times(1)).containsBean(
eq(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE));
verify(mockCache, times(1)).getQueryService();
verify(mockQueryService, times(1)).createKeyIndex(eq("TestKeyIndex"), eq("id"), eq("/Example"));
}
@Test(expected = IllegalArgumentException.class)
public void afterPropertiesSetWithNullCache() throws Exception {
try {
new IndexFactoryBean().afterPropertiesSet();
}
catch (IllegalArgumentException expected) {
assertEquals("The GemFire Cache reference must not be null!", expected.getMessage());
throw expected;
}
}
@Test(expected = IllegalArgumentException.class)
public void afterPropertiesSetWithNullQueryService() throws Exception {
try {
IndexFactoryBean indexFactoryBean = new IndexFactoryBean() {
@Override QueryService lookupQueryService() {
return null;
}
};
indexFactoryBean.setCache(mockCache);
indexFactoryBean.afterPropertiesSet();
}
catch (IllegalArgumentException expected) {
assertEquals("QueryService is required to create an Index", expected.getMessage());
throw expected;
}
}
@Test(expected = IllegalArgumentException.class)
public void afterPropertiesSetWithUnspecifiedExpression() throws Exception {
try {
newIndexFactoryBean().afterPropertiesSet();
}
catch (IllegalArgumentException expected) {
assertEquals("Index 'expression' is required", expected.getMessage());
throw expected;
}
}
@Test
public void afterPropertiesSetWithUnspecifiedFromClause() throws Exception {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectCause(is(nullValue(Throwable.class)));
expectedException.expectMessage("Index 'from clause' is required");
IndexFactoryBean indexFactoryBean = newIndexFactoryBean();
indexFactoryBean.setExpression("id");
indexFactoryBean.afterPropertiesSet();
}
@Test(expected = IllegalArgumentException.class)
public void afterPropertiesSetWithUnspecifiedIndexName() throws Exception {
try {
IndexFactoryBean indexFactoryBean = newIndexFactoryBean();
indexFactoryBean.setExpression("id");
indexFactoryBean.setFrom("/Example");
indexFactoryBean.afterPropertiesSet();
}
catch (IllegalArgumentException expected) {
assertEquals("Index 'name' is required", expected.getMessage());
throw expected;
}
}
@Test(expected = IllegalArgumentException.class)
public void afterPropertiesSetUsingImportsWithInvalidType() throws Exception {
try {
IndexFactoryBean indexFactoryBean = newIndexFactoryBean();
indexFactoryBean.setExpression("id");
indexFactoryBean.setFrom("/Example");
indexFactoryBean.setImports("org.example.DomainType");
indexFactoryBean.setName("TestIndex");
indexFactoryBean.setType("PriMary_Key");
indexFactoryBean.afterPropertiesSet();
}
catch (IllegalArgumentException expected) {
assertEquals("'imports' are not supported with a KEY Index", expected.getMessage());
throw expected;
}
}
@Test
public void doLookupQueryService() {
QueryService mockQueryServiceOne = mock(QueryService.class, "testLookupQueryService.MockQueryService.One");
QueryService mockQueryServiceTwo = mock(QueryService.class, "testLookupQueryService.MockQueryService.Two");
Cache mockCache = mock(Cache.class, "testDoLookupQueryService.MockCache");
when(mockCache.getQueryService()).thenReturn(mockQueryServiceTwo);
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setCache(mockCache);
indexFactoryBean.setQueryService(mockQueryServiceOne);
assertSame(mockQueryServiceOne, indexFactoryBean.doLookupQueryService());
verify(mockCache, never()).getQueryService();
}
@Test
public void doLookupQueryServiceOnClientCache() {
ClientCache mockClientCache = mock(ClientCache.class, "testDoLookupQueryServiceOnClientCache.MockClientCache");
QueryService mockQueryService = mock(QueryService.class, "testDoLookupQueryServiceOnClientCache.MockQueryService");
when(mockClientCache.getLocalQueryService()).thenReturn(mockQueryService);
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setCache(mockClientCache);
indexFactoryBean.setQueryService(null);
assertSame(mockQueryService, indexFactoryBean.doLookupQueryService());
verify(mockClientCache, times(1)).getLocalQueryService();
verify(mockClientCache, never()).getQueryService();
}
@Test
public void doLookupQueryServiceOnPeerCache() {
Cache mockCache = mock(Cache.class, "testDoLookupQueryServiceOnPeerCache.MockCache");
QueryService mockQueryService = mock(QueryService.class, "testDoLookupQueryServiceOnPeerCache.MockQueryService");
when(mockCache.getQueryService()).thenReturn(mockQueryService);
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setCache(mockCache);
indexFactoryBean.setQueryService(null);
assertSame(mockQueryService, indexFactoryBean.doLookupQueryService());
verify(mockCache, times(1)).getQueryService();
}
@Test
public void lookupQueryServiceFromBeanFactory() {
BeanFactory mockBeanFactory = mock(BeanFactory.class, "testLookupQueryServiceFromBeanFactory.MockBeanFactory");
QueryService mockQueryService = mock(QueryService.class, "testLookupQueryServiceFromBeanFactory.MockQueryService");
when(mockBeanFactory.containsBean(eq(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE)))
.thenReturn(true);
when(mockBeanFactory.getBean(eq(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE),
eq(QueryService.class))).thenReturn(mockQueryService);
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setBeanFactory(mockBeanFactory);
QueryService actualQueryService = indexFactoryBean.lookupQueryService();
assertSame(mockQueryService, actualQueryService);
verify(mockBeanFactory, times(1)).containsBean(eq(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE));
verify(mockBeanFactory, times(1)).getBean(eq(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE),
eq(QueryService.class));
}
@Test
public void lookupQueryServiceFromCache() {
BeanFactory mockBeanFactory = mock(BeanFactory.class, "testLookupQueryServiceFromCache.MockBeanFactory");
when(mockBeanFactory.containsBean(eq(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE)))
.thenReturn(false);
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setBeanFactory(mockBeanFactory);
indexFactoryBean.setDefine(false);
indexFactoryBean.setQueryService(mockQueryService);
QueryService actualQueryService = indexFactoryBean.lookupQueryService();
assertSame(mockQueryService, actualQueryService);
verify(mockBeanFactory, times(1)).containsBean(eq(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE));
verify(mockBeanFactory, never()).getBean(eq(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE),
eq(QueryService.class));
}
@Test
public void registerQueryServiceBeanWhenIndexIsCreated() {
ConfigurableBeanFactory mockBeanFactory = mock(ConfigurableBeanFactory.class,
"testRegisterQueryServiceBeanWhenIndexIsCreated.MockBeanFactory");
QueryService mockQueryService = mock(QueryService.class, "testRegisterQueryServiceBeanWhenIndexIsCreated.MockQueryService");
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setBeanFactory(mockBeanFactory);
indexFactoryBean.setDefine(false);
assertSame(mockQueryService, indexFactoryBean.registerQueryServiceBean(mockQueryService));
verify(mockBeanFactory, never()).registerSingleton(
eq(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE), same(mockQueryService));
}
@Test
public void registerQueryServiceBeanWhenIndexIsDefined() {
ConfigurableBeanFactory mockBeanFactory = mock(ConfigurableBeanFactory.class,
"testRegisterQueryServiceBeanWhenIndexIsDefined.MockBeanFactory");
QueryService mockQueryService = mock(QueryService.class, "testRegisterQueryServiceBeanWhenIndexIsDefined.MockQueryService");
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setBeanFactory(mockBeanFactory);
indexFactoryBean.setDefine(true);
assertSame(mockQueryService, indexFactoryBean.registerQueryServiceBean(mockQueryService));
verify(mockBeanFactory, times(1)).registerSingleton(
eq(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE), same(mockQueryService));
}
@Test
public void createIndexReturningNewKeyIndex() throws Exception {
Index mockIndex = mock(Index.class, "createIndexReturningNewKeyIndex.MockIndex");
QueryService mockQueryService = mock(QueryService.class, "createIndexReturningNewKeyIndex.MockQueryService");
when(mockQueryService.getIndexes()).thenReturn(Collections.<Index>emptyList());
when(mockQueryService.createKeyIndex(eq("KeyIndex"), eq("id"), eq("/Example"))).thenReturn(mockIndex);
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setExpression("id");
indexFactoryBean.setFrom("/Example");
indexFactoryBean.setName("KeyIndex");
indexFactoryBean.setOverride(false);
indexFactoryBean.setType("key");
Index actualIndex = indexFactoryBean.createIndex(mockQueryService, "KeyIndex");
assertSame(mockIndex, actualIndex);
verify(mockQueryService, times(1)).createKeyIndex(eq("KeyIndex"), eq("id"), eq("/Example"));
}
@Test
public void createIndexReturningNewHashIndex() throws Exception {
Index mockIndex = mock(Index.class, "createIndexReturningNewHashIndex.MockIndex");
QueryService mockQueryService = mock(QueryService.class, "createIndexReturningNewHashIndex.MockQueryService");
when(mockQueryService.getIndexes()).thenReturn(Collections.<Index>emptyList());
when(mockQueryService.createHashIndex(eq("HashIndex"), eq("name"), eq("/Animals"), eq("org.example.Dog")))
.thenReturn(mockIndex);
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setExpression("name");
indexFactoryBean.setFrom("/Animals");
indexFactoryBean.setImports("org.example.Dog");
indexFactoryBean.setName("HashIndex");
indexFactoryBean.setOverride(false);
indexFactoryBean.setType("HasH");
Index actualIndex = indexFactoryBean.createIndex(mockQueryService, "HashIndex");
assertSame(mockIndex, actualIndex);
verify(mockQueryService, times(1)).createHashIndex(eq("HashIndex"), eq("name"), eq("/Animals"),
eq("org.example.Dog"));
}
@Test
public void createIndexReturningNewFunctionalIndex() throws Exception {
Index mockIndex = mock(Index.class, "createIndexReturningNewFunctionalIndex.MockIndex");
QueryService mockQueryService = mock(QueryService.class,
"createIndexReturningNewFunctionalIndex.MockQueryService");
when(mockQueryService.getIndexes()).thenReturn(Collections.<Index>emptyList());
when(mockQueryService.createIndex(eq("FunctionalIndex"), eq("someField"), eq("/Example")))
.thenReturn(mockIndex);
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setExpression("someField");
indexFactoryBean.setFrom("/Example");
indexFactoryBean.setImports(" ");
indexFactoryBean.setName("FunctionalIndex");
indexFactoryBean.setOverride(false);
indexFactoryBean.setType((String) null);
Index actualIndex = indexFactoryBean.createIndex(mockQueryService, "FunctionalIndex");
assertSame(mockIndex, actualIndex);
verify(mockQueryService, times(1)).createIndex(eq("FunctionalIndex"), eq("someField"), eq("/Example"));
}
@Test
public void createIndexOverridesExistingIndex() throws Exception {
Index mockExistingIndex = mock(Index.class, "createIndexOverridesExistingIndex.MockExistingIndex");
Index mockOverridingIndex = mock(Index.class, "createIndexOverridesExistingIndex.MockOverridingIndex");
QueryService mockQueryService = mock(QueryService.class, "createIndexOverridesExistingIndex.MockQueryService");
when(mockExistingIndex.getName()).thenReturn("ExistingIndex");
when(mockOverridingIndex.getName()).thenReturn("OverridingIndex");
when(mockQueryService.getIndexes()).thenReturn(Collections.singletonList(mockExistingIndex));
when(mockQueryService.createHashIndex(eq("ExistingIndex"), eq("someField"), eq("/Example"),
eq("example.DomainType"))).thenReturn(mockOverridingIndex);
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setExpression("someField");
indexFactoryBean.setFrom("/Example");
indexFactoryBean.setImports("example.DomainType");
indexFactoryBean.setName("OverridingIndex");
indexFactoryBean.setType("HASH");
Index actualIndex = indexFactoryBean.createIndex(mockQueryService, "ExistingIndex");
assertSame(mockOverridingIndex, actualIndex);
verifyZeroInteractions(mockOverridingIndex);
verify(mockExistingIndex, times(1)).getName();
verify(mockQueryService, times(1)).removeIndex(same(mockExistingIndex));
verify(mockQueryService, times(1)).createHashIndex(eq("ExistingIndex"), eq("someField"), eq("/Example"),
eq("example.DomainType"));
}
@Test
public void createIndexReturnsExistingIndex() throws Exception {
Index mockExistingIndex = mock(Index.class, "createIndexReturnsExistingIndex.MockExistingIndex");
Index mockNewIndex = mock(Index.class, "createIndexReturnsExistingIndex.MockNewIndex");
QueryService mockQueryService = mock(QueryService.class, "createIndexReturnsExistingIndex.MockQueryService");
when(mockExistingIndex.getName()).thenReturn("ExistingIndex");
when(mockNewIndex.getName()).thenReturn("NewIndex");
when(mockQueryService.getIndexes()).thenReturn(Arrays.asList(mockExistingIndex, mockNewIndex));
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setName("ExistingIndex");
indexFactoryBean.setOverride(false);
Index actualIndex = indexFactoryBean.createIndex(mockQueryService, "ExistingIndex");
assertSame(mockExistingIndex, actualIndex);
verify(mockExistingIndex, times(1)).getName();
verify(mockNewIndex, never()).getName();
verify(mockQueryService, times(1)).getIndexes();
}
@Test
public void createIndexThrowsIndexNameConflictExceptionOnOverride() throws Exception {
Index mockExistingIndex = mock(Index.class,
"createIndexThrowsIndexNameConflictExceptionOnOverride.MockExistingIndex");
QueryService mockQueryService = mock(QueryService.class,
"createIndexThrowsIndexNameConflictExceptionOnOverride.MockQueryService");
when(mockExistingIndex.getName()).thenReturn("ExistingIndex");
when(mockQueryService.getIndexes()).thenReturn(Collections.singletonList(mockExistingIndex));
when(mockQueryService.createIndex(any(String.class), any(String.class), any(String.class)))
.thenThrow(new IndexNameConflictException("TEST"));
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setExpression("someField");
indexFactoryBean.setFrom("/Example");
indexFactoryBean.setName("ExistingIndex");
indexFactoryBean.setType("Functional");
try {
expectedException.expect(GemfireIndexException.class);
expectedException.expectCause(isA(IndexNameConflictException.class));
expectedException.expectMessage(
"Failed to remove the existing Index on override before re-creating Index with name (ExistingIndex)");
indexFactoryBean.createIndex(mockQueryService, "ExistingIndex");
}
finally {
verify(mockExistingIndex, times(1)).getName();
verify(mockQueryService, times(1)).getIndexes();
verify(mockQueryService, times(1)).createIndex(eq("ExistingIndex"), eq("someField"), eq("/Example"));
}
}
@Test
public void createIndexThrowsIndexExistsException() throws Exception {
QueryService mockQueryService = mock(QueryService.class,
"createIndexThrowsIndexExistsException.MockQueryService");
when(mockQueryService.getIndexes()).thenReturn(null);
when(mockQueryService.createKeyIndex(eq("NewIndex"), eq("someField"), eq("/Example")))
.thenThrow(new IndexExistsException("TEST"));
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setExpression("someField");
indexFactoryBean.setFrom("/Example");
indexFactoryBean.setName("NewIndex");
indexFactoryBean.setOverride(true);
indexFactoryBean.setType("PRIMARY_KEY");
try {
expectedException.expect(GemfireIndexException.class);
expectedException.expectCause(isA(IndexExistsException.class));
expectedException.expectMessage(
"An Index with a different name having the same definition as this Index (NewIndex) already exists");
indexFactoryBean.createIndex(mockQueryService, "NewIndex");
}
finally {
verify(mockQueryService, times(1)).getIndexes();
verify(mockQueryService, never()).removeIndex(any(Index.class));
verify(mockQueryService, times(1)).createKeyIndex(eq("NewIndex"), eq("someField"), eq("/Example"));
}
}
@Test
public void createIndexAddsExistingIndexOnAnyException() throws Exception {
final Index mockExistingIndex = mock(Index.class, "createIndexAddsExistingIndexOnAnyException.MockExistingIndex");
final Index mockIndexTwo = mock(Index.class, "createIndexAddsExistingIndexOnException.MockIndexTwo");
final List<Index> indexes = new ArrayList<Index>(1);
indexes.add(mockIndexTwo);
QueryService mockQueryService = mock(QueryService.class,
"createIndexAddsExistingIndexOnAnyException.MockQueryService");
when(mockExistingIndex.getName()).thenReturn("ExistingIndex");
when(mockIndexTwo.getName()).thenReturn("NewIndex");
when(mockQueryService.getIndexes()).then(new Answer<Collection<Index>>() {
private boolean called = false;
private synchronized boolean wasCalledOnce() {
boolean localCalled = this.called;
this.called = true;
return localCalled;
}
@Override
public Collection<Index> answer(final InvocationOnMock invocationOnMock) throws Throwable {
return (wasCalledOnce() ? indexes : Collections.singletonList(mockExistingIndex));
}
});
when(mockQueryService.createIndex(eq("ExistingIndex"), eq("someField"), eq("/Example")))
.thenThrow(new RuntimeException("TEST"));
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setExpression("someField");
indexFactoryBean.setFrom("/Example");
indexFactoryBean.setName("ExistingIndex");
indexFactoryBean.setOverride(true);
indexFactoryBean.setType("FUNCTIONAL");
assertEquals(1, indexes.size());
assertFalse(indexes.contains(mockExistingIndex));
Index actualIndex = indexFactoryBean.createIndex(mockQueryService, "ExistingIndex");
assertThat(actualIndex, is(sameInstance(mockExistingIndex)));
assertThat(indexes.size(), is(equalTo(2)));
assertThat(indexes.contains(mockExistingIndex), is(true));
assertThat(indexes.contains(mockIndexTwo), is(true));
verify(mockQueryService, times(3)).getIndexes();
verify(mockQueryService, times(1)).removeIndex(same(mockExistingIndex));
verify(mockQueryService, times(1)).createIndex(eq("ExistingIndex"), eq("someField"), eq("/Example"));
}
@Test(expected = RuntimeException.class)
public void createIndexThrowsExceptionOnAbsoluteFailure() throws Exception {
Index mockExistingIndex = mock(Index.class, "createIndexThrowsExceptionOnAbsoluteFailure.MockIndex.Existing");
QueryService mockQueryService = mock(QueryService.class,
"createIndexThrowsExceptionOnAbsoluteFailure.MockQueryService");
when(mockExistingIndex.getName()).thenReturn("ExistingIndex");
when(mockQueryService.getIndexes()).thenReturn(Collections.singletonList(mockExistingIndex));
when(mockQueryService.createIndex(eq("ExistingIndex"), eq("someField"), eq("/Example")))
.thenThrow(new RuntimeException("test"));
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setExpression("someField");
indexFactoryBean.setFrom("/Example");
indexFactoryBean.setName("ExistingIndex");
try {
indexFactoryBean.createIndex(mockQueryService, "ExistingIndex");
}
catch (RuntimeException expected) {
assertEquals("test", expected.getMessage());
throw expected;
}
finally {
verify(mockQueryService, times(2)).getIndexes();
verify(mockQueryService, times(1)).removeIndex(same(mockExistingIndex));
verify(mockQueryService, times(1)).createIndex(eq("ExistingIndex"), eq("someField"), eq("/Example"));
}
}
@Test
public void createFunctionalIndex() throws Exception {
Index mockIndex = mock(Index.class, "testCreateFunctionalIndex.MockIndex");
QueryService mockQueryService = mock(QueryService.class, "testCreateFunctionalIndex.MockQueryService");
when(mockQueryService.createIndex(eq("FunctionalIndex"), eq("purchaseDate"), eq("/Orders")))
.thenReturn(mockIndex);
Index actualIndex = indexFactoryBean.createFunctionalIndex(mockQueryService, "FunctionalIndex",
"purchaseDate", "/Orders", null);
assertSame(mockIndex, actualIndex);
verify(mockQueryService, times(1)).createIndex(eq("FunctionalIndex"), eq("purchaseDate"), eq("/Orders"));
verify(mockQueryService, never()).defineIndex(anyString(), anyString(), anyString());
}
@Test
public void createFunctionalIndexWithImports() throws Exception {
Index mockIndex = mock(Index.class, "testCreateFunctionalIndexWithImports.MockIndex");
QueryService mockQueryService = mock(QueryService.class, "testCreateFunctionalIndexWithImports.MockQueryService");
when(mockQueryService.createIndex(eq("FunctionalIndexWithImports"), eq("purchaseDate"), eq("/Orders"),
eq("org.example.Order"))).thenReturn(mockIndex);
Index actualIndex = indexFactoryBean.createFunctionalIndex(mockQueryService, "FunctionalIndexWithImports",
"purchaseDate", "/Orders", "org.example.Order");
assertSame(mockIndex, actualIndex);
verify(mockQueryService, times(1)).createIndex(eq("FunctionalIndexWithImports"), eq("purchaseDate"),
eq("/Orders"), eq("org.example.Order"));
verify(mockQueryService, never()).defineIndex(anyString(), anyString(), anyString(), anyString());
}
@Test
public void defineFunctionalIndex() throws Exception {
QueryService mockQueryService = mock(QueryService.class, "testDefineFunctionalIndex.MockQueryService");
doAnswer(new Answer<Void>() {
@Override public Void answer(final InvocationOnMock invocation) throws Throwable {
return null;
}
}).when(mockQueryService).defineIndex(eq("FunctionalIndex"), eq("purchaseDate"), eq("/Orders"));
indexFactoryBean.setDefine(true);
Index actualIndex = indexFactoryBean.createFunctionalIndex(mockQueryService, "FunctionalIndex",
"purchaseDate", "/Orders", null);
assertTrue(actualIndex instanceof IndexFactoryBean.IndexWrapper);
assertSame(mockQueryService, ((IndexFactoryBean.IndexWrapper) actualIndex).getQueryService());
assertEquals("FunctionalIndex", ((IndexFactoryBean.IndexWrapper) actualIndex).getIndexName());
verify(mockQueryService, never()).createIndex(anyString(), anyString(), anyString());
verify(mockQueryService, times(1)).defineIndex(eq("FunctionalIndex"), eq("purchaseDate"), eq("/Orders"));
}
@Test
public void defineFunctionalIndexWithImports() throws Exception {
QueryService mockQueryService = mock(QueryService.class, "testDefineFunctionalIndexWithImports.MockQueryService");
doAnswer(new Answer<Void>() {
@Override public Void answer(final InvocationOnMock invocation) throws Throwable {
return null;
}
}).when(mockQueryService).defineIndex(eq("FunctionalIndex"), eq("purchaseDate"), eq("/Orders"),
eq("org.example.Order"));
indexFactoryBean.setDefine(true);
Index actualIndex = indexFactoryBean.createFunctionalIndex(mockQueryService, "FunctionalIndexWithImports",
"purchaseDate", "/Orders", "org.example.Order");
assertTrue(actualIndex instanceof IndexFactoryBean.IndexWrapper);
assertSame(mockQueryService, ((IndexFactoryBean.IndexWrapper) actualIndex).getQueryService());
assertEquals("FunctionalIndexWithImports", ((IndexFactoryBean.IndexWrapper) actualIndex).getIndexName());
verify(mockQueryService, never()).createIndex(anyString(), anyString(), anyString(), anyString());
verify(mockQueryService, times(1)).defineIndex(eq("FunctionalIndexWithImports"), eq("purchaseDate"),
eq("/Orders"), eq("org.example.Order"));
}
@Test
public void createHashIndex() throws Exception {
Index mockIndex = mock(Index.class, "testCreateHashIndex.MockIndex");
QueryService mockQueryService = mock(QueryService.class, "testCreateHashIndex.MockQueryService");
when(mockQueryService.createHashIndex(eq("HashIndex"), eq("name"), eq("/People"))).thenReturn(mockIndex);
Index actualIndex = indexFactoryBean.createHashIndex(mockQueryService, "HashIndex", "name", "/People", " ");
assertSame(mockIndex, actualIndex);
verify(mockQueryService, times(1)).createHashIndex(eq("HashIndex"), eq("name"), eq("/People"));
verify(mockQueryService, never()).defineHashIndex(anyString(), anyString(), anyString());
}
@Test
public void createHashIndexWithImports() throws Exception {
Index mockIndex = mock(Index.class, "testCreateHashIndexWithImports.MockIndex");
QueryService mockQueryService = mock(QueryService.class, "testCreateHashIndexWithImports.MockQueryService");
when(mockQueryService.createHashIndex(eq("HashIndexWithImports"), eq("name"), eq("/People"),
eq("org.example.Person"))).thenReturn(mockIndex);
Index actualIndex = indexFactoryBean.createHashIndex(mockQueryService, "HashIndexWithImports",
"name", "/People", "org.example.Person");
assertSame(mockIndex, actualIndex);
verify(mockQueryService, times(1)).createHashIndex(eq("HashIndexWithImports"), eq("name"), eq("/People"),
eq("org.example.Person"));
verify(mockQueryService, never()).defineHashIndex(anyString(), anyString(), anyString(), anyString());
}
@Test
public void defineHashIndex() throws Exception {
QueryService mockQueryService = mock(QueryService.class, "testDefineHashIndex.MockQueryService");
doAnswer(new Answer<Void>() {
@Override public Void answer(final InvocationOnMock invocation) throws Throwable {
return null;
}
}).when(mockQueryService).defineHashIndex(eq("HashIndex"), eq("name"), eq("/People"));
indexFactoryBean.setDefine(true);
Index actualIndex = indexFactoryBean.createHashIndex(mockQueryService, "HashIndex",
"name", "/People", " ");
assertTrue(actualIndex instanceof IndexFactoryBean.IndexWrapper);
assertSame(mockQueryService, ((IndexFactoryBean.IndexWrapper) actualIndex).getQueryService());
assertEquals("HashIndex", ((IndexFactoryBean.IndexWrapper) actualIndex).getIndexName());
verify(mockQueryService, never()).createHashIndex(anyString(), anyString(), anyString());
verify(mockQueryService, times(1)).defineHashIndex(eq("HashIndex"), eq("name"), eq("/People"));
}
@Test
public void defineHashIndexWithImports() throws Exception {
QueryService mockQueryService = mock(QueryService.class, "testDefineHashIndexWithImports.MockQueryService");
doAnswer(new Answer<Void>() {
@Override public Void answer(final InvocationOnMock invocation) throws Throwable {
return null;
}
}).when(mockQueryService).defineHashIndex(eq("HashIndexWithImports"), eq("name"), eq("/People"),
eq("org.example.Person"));
indexFactoryBean.setDefine(true);
Index actualIndex = indexFactoryBean.createHashIndex(mockQueryService, "HashIndexWithImports",
"name", "/People", "org.example.Person");
assertTrue(actualIndex instanceof IndexFactoryBean.IndexWrapper);
assertSame(mockQueryService, ((IndexFactoryBean.IndexWrapper) actualIndex).getQueryService());
assertEquals("HashIndexWithImports", ((IndexFactoryBean.IndexWrapper) actualIndex).getIndexName());
verify(mockQueryService, never()).createHashIndex(anyString(), anyString(), anyString(), anyString());
verify(mockQueryService, times(1)).defineHashIndex(eq("HashIndexWithImports"), eq("name"), eq("/People"),
eq("org.example.Person"));
}
@Test
public void createKeyIndex() throws Exception {
QueryService mockQueryService = mock(QueryService.class, "testCreateKeyIndex.MockQueryService");
Index mockIndex = mock(Index.class, "testCreateKeyIndex.MockKeyIndex");
when(mockQueryService.createKeyIndex(eq("KeyIndex"), eq("id"), eq("/Example"))).thenReturn(mockIndex);
indexFactoryBean.setDefine(false);
Index actualIndex = indexFactoryBean.createKeyIndex(mockQueryService, "KeyIndex", "id", "/Example");
assertSame(mockIndex, actualIndex);
verify(mockQueryService, times(1)).createKeyIndex(eq("KeyIndex"), eq("id"), eq("/Example"));
verify(mockQueryService, never()).defineKeyIndex(anyString(), anyString(), anyString());
}
@Test
public void defineKeyIndex() throws Exception {
QueryService mockQueryService = mock(QueryService.class, "testDefineKeyIndex.MockQueryService");
indexFactoryBean.setDefine(true);
Index actualIndex = indexFactoryBean.createKeyIndex(mockQueryService, "KeyIndex", "id", "/Example");
assertTrue(actualIndex instanceof IndexFactoryBean.IndexWrapper);
IndexFactoryBean.IndexWrapper indexWrapper = (IndexFactoryBean.IndexWrapper) actualIndex;
assertSame(mockQueryService, indexWrapper.getQueryService());
assertEquals("KeyIndex", indexWrapper.getIndexName());
verify(mockQueryService, never()).createKeyIndex(anyString(), anyString(), anyString());
verify(mockQueryService, times(1)).defineKeyIndex(eq("KeyIndex"), eq("id"), eq("/Example"));
}
@Test
public void getExistingIndex() {
Index mockIndexOne = mock(Index.class, "testGetExistingIndex.MockIndex.One");
Index mockIndexTwo = mock(Index.class, "testGetExistingIndex.MockIndex.Two");
Index mockIndexThree = mock(Index.class, "testGetExistingIndex.MockIndex.Two");
QueryService mockQueryService = mock(QueryService.class, "testGetExistingIndex.MockQueryService");
when(mockIndexOne.getName()).thenReturn("PrimaryIndex");
when(mockIndexTwo.getName()).thenReturn("SecondaryIndex");
when(mockIndexThree.getName()).thenReturn("TernaryIndex");
when(mockQueryService.getIndexes()).thenReturn(Arrays.asList(mockIndexOne, mockIndexTwo, mockIndexThree));
assertNull(indexFactoryBean.getExistingIndex(mockQueryService, null));
assertNull(indexFactoryBean.getExistingIndex(mockQueryService, ""));
assertNull(indexFactoryBean.getExistingIndex(mockQueryService, " "));
assertNull(indexFactoryBean.getExistingIndex(mockQueryService, "Primary Index"));
assertNull(indexFactoryBean.getExistingIndex(mockQueryService, "Secondary_Index"));
assertNull(indexFactoryBean.getExistingIndex(mockQueryService, "QuadIndex"));
assertSame(mockIndexOne, indexFactoryBean.getExistingIndex(mockQueryService, "PRIMARYINDEX"));
assertSame(mockIndexTwo, indexFactoryBean.getExistingIndex(mockQueryService, "SecondaryIndex"));
assertSame(mockIndexThree, indexFactoryBean.getExistingIndex(mockQueryService, "ternaryindex"));
}
@Test
public void getObjectLooksUpIndex() throws Exception {
QueryService mockQueryService = mock(QueryService.class, "testGetObjectLooksUpIndex.MockQueryService");
when(mockQueryService.getIndexes()).then(new Answer<Collection<Index>>() {
private final AtomicInteger counter = new AtomicInteger(1);
@Override public Collection<Index> answer(final InvocationOnMock invocation) throws Throwable {
Index mockIndex = mock(Index.class, "getObjectLooksUpIndex.MockIndex");
when(mockIndex.getName()).thenReturn(String.format("MockIndex%1$s", counter.getAndIncrement()));
return Collections.singletonList(mockIndex);
}
});
IndexFactoryBean indexFactoryBean = new IndexFactoryBean();
indexFactoryBean.setQueryService(mockQueryService);
indexFactoryBean.setName("MockIndex1");
ReflectionUtils.setField(IndexFactoryBean.class.getDeclaredField("indexName"), indexFactoryBean, "MockIndex1");
Index actualIndex = indexFactoryBean.getObject();
assertNotNull(actualIndex);
assertEquals("MockIndex1", actualIndex.getName());
Index sameIndex = indexFactoryBean.getObject();
assertSame(actualIndex, sameIndex);
}
@Test
public void indexFactoryBeanCreatesSingleIndex() {
assertTrue(indexFactoryBean.isSingleton());
}
@Test
public void defineMultipleIndexesWithSeparateIndexFactoryBeansSameSpringContext() throws Exception {
ConfigurableBeanFactory mockBeanFactory = mock(ConfigurableBeanFactory.class,
"testDefineMultipleIndexesWithSeparateIndexFactoryBeansSameSpringContext.MockBeanFactory");
Cache mockCacheOne = mock(Cache.class, "testDefineMultipleIndexesWithSeparateIndexFactoryBeansSameSpringContext.MockCacheOne");
Cache mockCacheTwo = mock(Cache.class, "testDefineMultipleIndexesWithSeparateIndexFactoryBeansSameSpringContext.MockCacheTwo");
QueryService mockQueryServiceOne = mock(QueryService.class,
"testDefineMultipleIndexesWithSeparateIndexFactoryBeansSameSpringContext.MockQueryServiceOne");
QueryService mockQueryServiceTwo = mock(QueryService.class,
"testDefineMultipleIndexesWithSeparateIndexFactoryBeansSameSpringContext.MockQueryServiceTwo");
final AtomicReference<QueryService> queryServiceReference = new AtomicReference<QueryService>(null);
doAnswer(new Answer<Boolean>() {
@Override public Boolean answer(final InvocationOnMock invocation) throws Throwable {
return (queryServiceReference.get() != null);
}
}).when(mockBeanFactory).containsBean(eq(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE));
doAnswer(new Answer<QueryService>() {
@Override public QueryService answer(final InvocationOnMock invocation) throws Throwable {
return queryServiceReference.get();
}
}).when(mockBeanFactory).getBean(eq(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE),
eq(QueryService.class));
doAnswer(new Answer<Void>() {
@Override public Void answer(final InvocationOnMock invocation) throws Throwable {
assertEquals(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE,
invocation.getArgument(0));
queryServiceReference.compareAndSet(null, invocation.getArgument(1));
return null;
}
}).when(mockBeanFactory).registerSingleton(eq(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE),
any(QueryService.class));
when(mockCacheOne.getQueryService()).thenReturn(mockQueryServiceOne);
when(mockCacheTwo.getQueryService()).thenReturn(mockQueryServiceTwo);
IndexFactoryBean indexFactoryBeanOne = new IndexFactoryBean();
indexFactoryBeanOne.setBeanFactory(mockBeanFactory);
indexFactoryBeanOne.setCache(mockCacheOne);
indexFactoryBeanOne.setDefine(true);
indexFactoryBeanOne.setExpression("id");
indexFactoryBeanOne.setFrom("/People");
indexFactoryBeanOne.setName("PersonIdIndex");
indexFactoryBeanOne.setType("Key");
indexFactoryBeanOne.afterPropertiesSet();
IndexFactoryBean indexFactoryBeanTwo = new IndexFactoryBean();
indexFactoryBeanTwo.setBeanFactory(mockBeanFactory);
indexFactoryBeanTwo.setCache(mockCacheTwo);
indexFactoryBeanTwo.setDefine(true);
indexFactoryBeanTwo.setExpression("purchaseDate");
indexFactoryBeanTwo.setFrom("/Orders");
indexFactoryBeanTwo.setImports("org.example.Order");
indexFactoryBeanTwo.setName("PurchaseDateIndex");
indexFactoryBeanTwo.setType("HASH");
indexFactoryBeanTwo.afterPropertiesSet();
verify(mockBeanFactory, times(2)).containsBean(eq(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE));
verify(mockBeanFactory, times(1)).getBean(eq(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE),
eq(QueryService.class));
verify(mockBeanFactory, times(1)).registerSingleton(eq(GemfireConstants.DEFAULT_GEMFIRE_INDEX_DEFINITION_QUERY_SERVICE),
same(mockQueryServiceOne));
verify(mockCacheOne, times(1)).getQueryService();
verify(mockCacheTwo, never()).getQueryService();
verify(mockQueryServiceOne, times(1)).defineKeyIndex(eq("PersonIdIndex"), eq("id"), eq("/People"));
verify(mockQueryServiceOne, times(1)).defineHashIndex(eq("PurchaseDateIndex"), eq("purchaseDate"), eq("/Orders"),
eq("org.example.Order"));
verify(mockQueryServiceTwo, never()).defineHashIndex(anyString(), anyString(), anyString());
verify(mockQueryServiceTwo, never()).defineHashIndex(anyString(), anyString(), anyString());
verify(mockQueryServiceTwo, never()).defineIndex(anyString(), anyString(), anyString());
verify(mockQueryServiceTwo, never()).defineIndex(anyString(), anyString(), anyString(), anyString());
verify(mockQueryServiceTwo, never()).defineKeyIndex(anyString(), anyString(), anyString());
}
@Test
@SuppressWarnings("deprecation")
public void indexWrapperDelegation() {
Index mockIndex = mock(Index.class, "indexWrapperDelegation.MockIndex");
IndexStatistics mockIndexStats = mock(IndexStatistics.class, "indexWrapperDelegation.MockIndexStats");
QueryService mockQueryService = mock(QueryService.class, "indexWrapperDelegation.MockQueryService");
when(mockIndex.getCanonicalizedFromClause()).thenReturn("/Example");
when(mockIndex.getCanonicalizedIndexedExpression()).thenReturn("ID");
when(mockIndex.getCanonicalizedProjectionAttributes()).thenReturn("identifier");
when(mockIndex.getFromClause()).thenReturn("Example");
when(mockIndex.getIndexedExpression()).thenReturn("id");
when(mockIndex.getName()).thenReturn("MockIndex");
when(mockIndex.getProjectionAttributes()).thenReturn("id");
when(mockIndex.getStatistics()).thenReturn(mockIndexStats);
when(mockIndex.getType()).thenReturn(org.apache.geode.cache.query.IndexType.HASH);
when(mockQueryService.getIndexes()).thenReturn(Collections.singletonList(mockIndex));
IndexFactoryBean.IndexWrapper indexWrapper = new IndexFactoryBean.IndexWrapper(mockQueryService, "MockIndex");
assertNotNull(indexWrapper);
assertEquals("MockIndex", indexWrapper.getIndexName());
assertSame(mockQueryService, indexWrapper.getQueryService());
Index actualIndex = indexWrapper.getIndex();
assertSame(mockIndex, actualIndex);
assertEquals("/Example", indexWrapper.getCanonicalizedFromClause());
assertEquals("ID", indexWrapper.getCanonicalizedIndexedExpression());
assertEquals("identifier", indexWrapper.getCanonicalizedProjectionAttributes());
assertEquals("Example", indexWrapper.getFromClause());
assertEquals("id", indexWrapper.getIndexedExpression());
assertEquals("MockIndex", indexWrapper.getName());
assertEquals("id", indexWrapper.getProjectionAttributes());
assertSame(mockIndexStats, indexWrapper.getStatistics());
assertEquals(org.apache.geode.cache.query.IndexType.HASH, indexWrapper.getType());
Index sameIndex = indexWrapper.getIndex();
assertSame(actualIndex, sameIndex);
}
@Test(expected = IllegalArgumentException.class)
public void createIndexWrapperWithNullQueryService() {
try {
new IndexFactoryBean.IndexWrapper(null, "TestIndex");
}
catch (IllegalArgumentException expected) {
assertEquals("QueryService must not be null", expected.getMessage());
throw expected;
}
}
@Test(expected = IllegalArgumentException.class)
public void createIndexWrapperWithUnspecifiedIndexName() {
try {
new IndexFactoryBean.IndexWrapper(mock(QueryService.class), " ");
}
catch (IllegalArgumentException expected) {
assertEquals("The name of the Index must be specified!", expected.getMessage());
throw expected;
}
}
@Test(expected = GemfireIndexException.class)
public void indexWrapperGetIndexWhenIndexNotFound() {
QueryService mockQueryService = mock(QueryService.class, "indexWrapperGetIndexWhenIndexNotFound.MockQueryService");
when(mockQueryService.getIndexes()).thenReturn(Collections.<Index>emptyList());
IndexFactoryBean.IndexWrapper indexWrapper = new IndexFactoryBean.IndexWrapper(mockQueryService, "NonExistingIndex");
assertNotNull(indexWrapper);
assertEquals("NonExistingIndex", indexWrapper.getIndexName());
assertSame(mockQueryService, indexWrapper.getQueryService());
try {
indexWrapper.getIndex();
}
catch (GemfireIndexException expected) {
assertThat(expected.getMessage(), startsWith("index with name (NonExistingIndex) was not found"));
assertTrue(expected.getCause() instanceof IndexInvalidException);
throw expected;
}
}
}