blob: 874104c1866fa5fb82e3158d1480e61582fd8bc8 [file] [log] [blame]
/*
* =========================================================================
* Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* more patents listed at http://www.pivotal.io/patents.
* ========================================================================
*/
package com.gemstone.gemfire.management.internal.cli.functions;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.execute.FunctionContext;
import com.gemstone.gemfire.cache.execute.ResultSender;
import com.gemstone.gemfire.cache.query.Index;
import com.gemstone.gemfire.cache.query.IndexStatistics;
import com.gemstone.gemfire.cache.query.IndexType;
import com.gemstone.gemfire.cache.query.QueryService;
import com.gemstone.gemfire.distributed.DistributedMember;
import com.gemstone.gemfire.distributed.DistributedSystem;
import com.gemstone.gemfire.internal.lang.Filter;
import com.gemstone.gemfire.internal.lang.ObjectUtils;
import com.gemstone.gemfire.internal.util.CollectionUtils;
import com.gemstone.gemfire.management.internal.cli.domain.IndexDetails;
import com.gemstone.gemfire.management.internal.cli.domain.IndexDetails.IndexStatisticsDetails;
import com.gemstone.gemfire.test.junit.categories.UnitTest;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
/**
* The ListIndexFunctionJUnitTest class is test suite of test cases testing the contract and functionality of the
* ListIndexFunction GemFire function.
* </p>
* </p>
* @author John Blum
* @see com.gemstone.gemfire.management.internal.cli.functions.ListIndexFunction
* @see org.jmock.Expectations
* @see org.jmock.Mockery
* @see org.jmock.lib.legacy.ClassImposteriser
* @see org.junit.Assert
* @see org.junit.Test
* @since 7.0
*/
@Category(UnitTest.class)
public class ListIndexFunctionJUnitTest {
private AtomicLong mockCounter = new AtomicLong(0l);
private Mockery mockContext;
@Before
public void setup() {
mockContext = new Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
}
@After
public void tearDown() {
mockContext.assertIsSatisfied();
mockContext = null;
}
protected void assertEquals(final IndexDetails expectedIndexDetails, final IndexDetails actualIndexDetails) {
Assert.assertEquals(expectedIndexDetails.getFromClause(), actualIndexDetails.getFromClause());
Assert.assertEquals(expectedIndexDetails.getIndexedExpression(), actualIndexDetails.getIndexedExpression());
Assert.assertEquals(expectedIndexDetails.getIndexName(), actualIndexDetails.getIndexName());
assertEquals(expectedIndexDetails.getIndexStatisticsDetails(), actualIndexDetails.getIndexStatisticsDetails());
Assert.assertEquals(expectedIndexDetails.getIndexType(), actualIndexDetails.getIndexType());
Assert.assertEquals(expectedIndexDetails.getMemberId(), actualIndexDetails.getMemberId());
Assert.assertEquals(expectedIndexDetails.getMemberName(), actualIndexDetails.getMemberName());
Assert.assertEquals(expectedIndexDetails.getProjectionAttributes(), actualIndexDetails.getProjectionAttributes());
Assert.assertEquals(expectedIndexDetails.getRegionName(), actualIndexDetails.getRegionName());
Assert.assertEquals(expectedIndexDetails.getRegionPath(), actualIndexDetails.getRegionPath());
}
protected void assertEquals(final IndexStatisticsDetails expectedIndexStatisticsDetails, final IndexStatisticsDetails actualIndexStatisticsDetails) {
if (expectedIndexStatisticsDetails != null) {
assertNotNull(actualIndexStatisticsDetails);
Assert.assertEquals(expectedIndexStatisticsDetails.getNumberOfKeys(), actualIndexStatisticsDetails
.getNumberOfKeys());
Assert.assertEquals(expectedIndexStatisticsDetails.getNumberOfUpdates(), actualIndexStatisticsDetails
.getNumberOfUpdates());
Assert.assertEquals(expectedIndexStatisticsDetails.getNumberOfValues(), actualIndexStatisticsDetails
.getNumberOfValues());
Assert.assertEquals(expectedIndexStatisticsDetails.getTotalUpdateTime(), actualIndexStatisticsDetails
.getTotalUpdateTime());
Assert.assertEquals(expectedIndexStatisticsDetails.getTotalUses(), actualIndexStatisticsDetails.getTotalUses());
}
else {
assertNull(actualIndexStatisticsDetails);
}
}
protected IndexDetails createIndexDetails(final String memberId,
final String regionPath,
final String indexName,
final IndexType indexType,
final String fromClause,
final String indexedExpression,
final String memberName,
final String projectionAttributes,
final String regionName)
{
final IndexDetails indexDetails = new IndexDetails(memberId, regionPath, indexName);
indexDetails.setFromClause(fromClause);
indexDetails.setIndexedExpression(indexedExpression);
indexDetails.setIndexType(indexType);
indexDetails.setMemberName(memberName);
indexDetails.setProjectionAttributes(projectionAttributes);
indexDetails.setRegionName(regionName);
return indexDetails;
}
protected IndexStatisticsDetails createIndexStatisticsDetails(final Long numberOfKeys,
final Long numberOfUpdates,
final Long numberOfValues,
final Long totalUpdateTime,
final Long totalUses)
{
final IndexStatisticsDetails indexStatisticsDetails = new IndexStatisticsDetails();
indexStatisticsDetails.setNumberOfKeys(numberOfKeys);
indexStatisticsDetails.setNumberOfUpdates(numberOfUpdates);
indexStatisticsDetails.setNumberOfValues(numberOfValues);
indexStatisticsDetails.setTotalUpdateTime(totalUpdateTime);
indexStatisticsDetails.setTotalUses(totalUses);
return indexStatisticsDetails;
}
protected ListIndexFunction createListIndexFunction(final Cache cache) {
return new TestListIndexFunction(cache);
}
protected Index createMockIndex(final IndexDetails indexDetails) {
final Index mockIndex = mockContext.mock(Index.class, "Index " + indexDetails.getIndexName() + " "
+ mockCounter.getAndIncrement());
final Region mockRegion = mockContext.mock(Region.class, "Region " + indexDetails.getRegionPath() + " "
+ mockCounter.getAndIncrement());
mockContext.checking(new Expectations() {{
oneOf(mockIndex).getFromClause();
will(returnValue(indexDetails.getFromClause()));
oneOf(mockIndex).getIndexedExpression();
will(returnValue(indexDetails.getIndexedExpression()));
oneOf(mockIndex).getName();
will(returnValue(indexDetails.getIndexName()));
oneOf(mockIndex).getProjectionAttributes();
will(returnValue(indexDetails.getProjectionAttributes()));
exactly(2).of(mockIndex).getRegion();
will(returnValue(mockRegion));
oneOf(mockIndex).getType();
will(returnValue(getIndexType(indexDetails.getIndexType())));
oneOf(mockRegion).getName();
will(returnValue(indexDetails.getRegionName()));
oneOf(mockRegion).getFullPath();
will(returnValue(indexDetails.getRegionPath()));
}});
if (indexDetails.getIndexStatisticsDetails() != null) {
final IndexStatistics mockIndexStatistics = mockContext.mock(IndexStatistics.class, "IndexStatistics "
+ indexDetails.getIndexName() + " " + mockCounter.getAndIncrement());
mockContext.checking(new Expectations() {{
exactly(2).of(mockIndex).getStatistics();
will(returnValue(mockIndexStatistics));
oneOf(mockIndexStatistics).getNumUpdates();
will(returnValue(indexDetails.getIndexStatisticsDetails().getNumberOfUpdates()));
oneOf(mockIndexStatistics).getNumberOfKeys();
will(returnValue(indexDetails.getIndexStatisticsDetails().getNumberOfKeys()));
oneOf(mockIndexStatistics).getNumberOfValues();
will(returnValue(indexDetails.getIndexStatisticsDetails().getNumberOfValues()));
oneOf(mockIndexStatistics).getTotalUpdateTime();
will(returnValue(indexDetails.getIndexStatisticsDetails().getTotalUpdateTime()));
oneOf(mockIndexStatistics).getTotalUses();
will(returnValue(indexDetails.getIndexStatisticsDetails().getTotalUses()));
}});
}
else {
mockContext.checking(new Expectations() {{
oneOf(mockIndex).getStatistics();
will(returnValue(null));
}});
}
return mockIndex;
}
protected IndexType getIndexType(final IndexDetails.IndexType type) {
switch (type) {
case FUNCTIONAL:
return IndexType.FUNCTIONAL;
case PRIMARY_KEY:
return IndexType.PRIMARY_KEY;
default:
return null;
}
}
@Test
@SuppressWarnings("unchecked")
public void testExecute() throws Throwable {
final String memberId = "mockMemberId";
final String memberName = "mockMemberName";
final Cache mockCache = mockContext.mock(Cache.class, "Cache");
final DistributedSystem mockDistributedSystem = mockContext.mock(DistributedSystem.class, "DistributedSystem");
final DistributedMember mockDistributedMember = mockContext.mock(DistributedMember.class, "DistributedMember");
final IndexDetails indexDetailsOne = createIndexDetails(memberId, "/Employees", "empIdIdx", IndexType.PRIMARY_KEY,
"/Employees", "id", memberName, "id, firstName, lastName", "Employees");
indexDetailsOne.setIndexStatisticsDetails(createIndexStatisticsDetails(10124l, 4096l, 10124l, 1284100l, 280120l));
final IndexDetails indexDetailsTwo = createIndexDetails(memberId, "/Employees", "empGivenNameIdx",
IndexType.FUNCTIONAL, "/Employees", "lastName", memberName, "id, firstName, lastName", "Employees");
final IndexDetails indexDetailsThree = createIndexDetails(memberId, "/Contractors", "empIdIdx",
IndexType.PRIMARY_KEY, "/Contrators", "id", memberName, "id, firstName, lastName", "Contractors");
indexDetailsThree.setIndexStatisticsDetails(createIndexStatisticsDetails(1024l, 256l, 20248l, 768001l, 24480l));
final IndexDetails indexDetailsFour = createIndexDetails(memberId, "/Employees", "empIdIdx", IndexType.FUNCTIONAL,
"/Employees", "emp_id", memberName, "id, surname, givenname", "Employees");
final Set<IndexDetails> expectedIndexDetailsSet = new HashSet<IndexDetails>(3);
expectedIndexDetailsSet.add(indexDetailsOne);
expectedIndexDetailsSet.add(indexDetailsTwo);
expectedIndexDetailsSet.add(indexDetailsThree);
final QueryService mockQueryService = mockContext.mock(QueryService.class, "QueryService");
final FunctionContext mockFunctionContext = mockContext.mock(FunctionContext.class, "FunctionContext");
final TestResultSender testResultSender = new TestResultSender();
mockContext.checking(new Expectations() {{
oneOf(mockCache).getDistributedSystem();
will(returnValue(mockDistributedSystem));
oneOf(mockCache).getQueryService();
will(returnValue(mockQueryService));
oneOf(mockDistributedSystem).getDistributedMember();
will(returnValue(mockDistributedMember));
exactly(4).of(mockDistributedMember).getId();
will(returnValue(memberId));
exactly(4).of(mockDistributedMember).getName();
will(returnValue(memberName));
oneOf(mockQueryService).getIndexes();
will(returnValue(Arrays.asList(createMockIndex(indexDetailsOne), createMockIndex(indexDetailsTwo),
createMockIndex(indexDetailsThree), createMockIndex(indexDetailsFour))));
oneOf(mockFunctionContext).getResultSender();
will(returnValue(testResultSender));
}});
final ListIndexFunction function = createListIndexFunction(mockCache);
function.execute(mockFunctionContext);
final List<?> results = testResultSender.getResults();
assertNotNull(results);
Assert.assertEquals(1, results.size());
final Set<IndexDetails> actualIndexDetailsSet = (Set<IndexDetails>) results.get(0);
assertNotNull(actualIndexDetailsSet);
Assert.assertEquals(expectedIndexDetailsSet.size(), actualIndexDetailsSet.size());
for (final IndexDetails expectedIndexDetails : expectedIndexDetailsSet) {
final IndexDetails actualIndexDetails = CollectionUtils.findBy(actualIndexDetailsSet, new Filter<IndexDetails>() {
@Override public boolean accept(final IndexDetails indexDetails) {
return ObjectUtils.equals(expectedIndexDetails, indexDetails);
}
});
assertNotNull(actualIndexDetails);
assertEquals(expectedIndexDetails, actualIndexDetails);
}
}
@Test
@SuppressWarnings("unchecked")
public void testExecuteWithNoIndexes() throws Throwable {
final Cache mockCache = mockContext.mock(Cache.class, "Cache");
final DistributedSystem mockDistributedSystem = mockContext.mock(DistributedSystem.class, "DistributedSystem");
final DistributedMember mockDistributedMember = mockContext.mock(DistributedMember.class, "DistributedMember");
final QueryService mockQueryService = mockContext.mock(QueryService.class, "QueryService");
final FunctionContext mockFunctionContext = mockContext.mock(FunctionContext.class, "FunctionContext");
final TestResultSender testResultSender = new TestResultSender();
mockContext.checking(new Expectations() {{
oneOf(mockCache).getDistributedSystem();
will(returnValue(mockDistributedSystem));
oneOf(mockCache).getQueryService();
will(returnValue(mockQueryService));
oneOf(mockDistributedSystem).getDistributedMember();
will(returnValue(mockDistributedMember));
oneOf(mockQueryService).getIndexes();
will(returnValue(Collections.emptyList()));
oneOf(mockFunctionContext).getResultSender();
will(returnValue(testResultSender));
}});
final ListIndexFunction function = createListIndexFunction(mockCache);
function.execute(mockFunctionContext);
final List<?> results = testResultSender.getResults();
assertNotNull(results);
Assert.assertEquals(1, results.size());
final Set<IndexDetails> actualIndexDetailsSet = (Set<IndexDetails>) results.get(0);
assertNotNull(actualIndexDetailsSet);
assertTrue(actualIndexDetailsSet.isEmpty());
}
@Test(expected = RuntimeException.class)
public void testExecuteThrowsException() throws Throwable {
final Cache mockCache = mockContext.mock(Cache.class, "Cache");
final DistributedSystem mockDistributedSystem = mockContext.mock(DistributedSystem.class, "DistributedSystem");
final DistributedMember mockDistributedMember = mockContext.mock(DistributedMember.class, "DistributedMember");
final QueryService mockQueryService = mockContext.mock(QueryService.class, "QueryService");
final FunctionContext mockFunctionContext = mockContext.mock(FunctionContext.class, "FunctionContext");
final TestResultSender testResultSender = new TestResultSender();
mockContext.checking(new Expectations() {{
oneOf(mockCache).getDistributedSystem();
will(returnValue(mockDistributedSystem));
oneOf(mockCache).getQueryService();
will(returnValue(mockQueryService));
oneOf(mockDistributedSystem).getDistributedMember();
will(returnValue(mockDistributedMember));
oneOf(mockQueryService).getIndexes();
will(throwException(new RuntimeException("expected")));
oneOf(mockFunctionContext).getResultSender();
will(returnValue(testResultSender));
}});
final ListIndexFunction function = createListIndexFunction(mockCache);
function.execute(mockFunctionContext);
try {
testResultSender.getResults();
}
catch (Throwable t) {
assertTrue(t instanceof RuntimeException);
Assert.assertEquals("expected", t.getMessage());
throw t;
}
}
protected static class TestListIndexFunction extends ListIndexFunction {
private final Cache cache;
protected TestListIndexFunction(final Cache cache) {
assert cache != null : "The Cache cannot be null!";
this.cache = cache;
}
@Override
protected Cache getCache() {
return this.cache;
}
}
protected static class TestResultSender implements ResultSender {
private final List<Object> results = new LinkedList<Object>();
private Throwable t;
protected List<Object> getResults() throws Throwable {
if (t != null) {
throw t;
}
return Collections.unmodifiableList(results);
}
public void lastResult(final Object lastResult) {
results.add(lastResult);
}
public void sendResult(final Object oneResult) {
results.add(oneResult);
}
public void sendException(final Throwable t) {
this.t = t;
}
}
}