SGF-423 - Handle improper ClassCastException thrown from SDG's Function Execution interface and annotation-based support when a GemFire Function throws an Exception.
Additional refactoring and added serveral unit tests. (cherry picked from commit a806f1540e6fc995410671f34382d14389ace90a) Signed-off-by: John Blum <jblum@pivotal.io>
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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.function;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.isA;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.gemfire.fork.ServerProcess;
|
||||
import org.springframework.data.gemfire.function.annotation.GemfireFunction;
|
||||
import org.springframework.data.gemfire.function.sample.ExceptionThrowingFunctionExecution;
|
||||
import org.springframework.data.gemfire.process.ProcessExecutor;
|
||||
import org.springframework.data.gemfire.process.ProcessWrapper;
|
||||
import org.springframework.data.gemfire.test.support.FileSystemUtils;
|
||||
import org.springframework.data.gemfire.test.support.ThreadUtils;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.gemstone.gemfire.cache.execute.FunctionAdapter;
|
||||
import com.gemstone.gemfire.cache.execute.FunctionContext;
|
||||
import com.gemstone.gemfire.cache.execute.FunctionException;
|
||||
|
||||
/**
|
||||
* The ExceptionThrowingFunctionExecutionIntegrationTest class is a test suite of test cases testing the invocation
|
||||
* of a GemFire Function using Spring Data GemFire Function Execution Annotation support when that Function throws
|
||||
* an Exception.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Rule
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.springframework.data.gemfire.fork.ServerProcess
|
||||
* @see org.springframework.data.gemfire.function.annotation.GemfireFunction
|
||||
* @see org.springframework.data.gemfire.function.sample.ExceptionThrowingFunctionExecution
|
||||
* @see org.springframework.data.gemfire.process.ProcessExecutor
|
||||
* @see org.springframework.data.gemfire.process.ProcessWrapper
|
||||
* @see org.springframework.test.context.ContextConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
|
||||
* @since 1.7.0
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@SuppressWarnings("unused")
|
||||
public class ExceptionThrowingFunctionExecutionIntegrationTest {
|
||||
|
||||
private static ProcessWrapper serverProcess;
|
||||
|
||||
@Rule
|
||||
public ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
@Autowired
|
||||
private ExceptionThrowingFunctionExecution exceptionThrowingFunctionExecution;
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws IOException {
|
||||
String serverName = ExceptionThrowingFunctionExecutionIntegrationTest.class.getSimpleName().concat("Server");
|
||||
|
||||
File serverWorkingDirectory = new File(FileSystemUtils.WORKING_DIRECTORY, serverName.toLowerCase());
|
||||
|
||||
Assert.isTrue(serverWorkingDirectory.isDirectory() || serverWorkingDirectory.mkdirs());
|
||||
|
||||
List<String> arguments = new ArrayList<String>();
|
||||
|
||||
arguments.add("-Dgemfire.name=" + serverName);
|
||||
arguments.add(ExceptionThrowingFunctionExecutionIntegrationTest.class.getName().replaceAll("\\.",
|
||||
File.separator)
|
||||
.concat("-server-context.xml"));
|
||||
|
||||
serverProcess = ProcessExecutor.launch(serverWorkingDirectory, ServerProcess.class,
|
||||
arguments.toArray(new String[arguments.size()]));
|
||||
|
||||
waitForServerStart(TimeUnit.SECONDS.toMillis(20));
|
||||
|
||||
System.out.println("GemFire Cache Server Process for ClientCache Indexing should be running...");
|
||||
}
|
||||
|
||||
private static void waitForServerStart(final long milliseconds) {
|
||||
ThreadUtils.timedWait(milliseconds, TimeUnit.MILLISECONDS.toMillis(500), new ThreadUtils.WaitCondition() {
|
||||
private File serverPidControlFile = new File(serverProcess.getWorkingDirectory(),
|
||||
ServerProcess.getServerProcessControlFilename());
|
||||
|
||||
@Override public boolean waiting() {
|
||||
return !serverPidControlFile.isFile();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() {
|
||||
serverProcess.shutdown();
|
||||
|
||||
if (Boolean.valueOf(System.getProperty("spring.gemfire.fork.clean", Boolean.TRUE.toString()))) {
|
||||
org.springframework.util.FileSystemUtils.deleteRecursively(serverProcess.getWorkingDirectory());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exceptionThrowingFunctionExecutionRethrowsException() {
|
||||
expectedException.expect(FunctionException.class);
|
||||
expectedException.expectCause(isA(IllegalArgumentException.class));
|
||||
expectedException.expectMessage(containsString("Execution of Function with ID 'exceptionThrowingFunction' failed"));
|
||||
exceptionThrowingFunctionExecution.exceptionThrowingFunction();
|
||||
}
|
||||
|
||||
public static class ExceptionThrowingFunction extends FunctionAdapter {
|
||||
@Override
|
||||
public String getId() {
|
||||
return "exceptionThrowingFunction";
|
||||
}
|
||||
@Override
|
||||
public void execute(final FunctionContext context) {
|
||||
context.getResultSender().sendException(new IllegalArgumentException("TEST"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* 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.function.config;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
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.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.data.gemfire.config.GemfireConstants;
|
||||
|
||||
/**
|
||||
* The ServerBasedExecutionBeanDefinitionBuilderTest class is test suite of test cases testing the contract
|
||||
* and functionality of the ServerBasedExecutionBeanDefinitionBuilder class.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.springframework.data.gemfire.function.config.ServerBasedExecutionBeanDefinitionBuilder
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public class ServerBasedExecutionBeanDefinitionBuilderTest {
|
||||
|
||||
@Rule
|
||||
public ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void getGemfireFunctionOperationsBeanDefinitionBuilder() {
|
||||
FunctionExecutionConfiguration mockFunctionExecutionConfiguration =
|
||||
mock(FunctionExecutionConfiguration.class, "MockFunctionExecutionConfiguration");
|
||||
|
||||
when(mockFunctionExecutionConfiguration.getAttribute(eq("cache"))).thenReturn(null);
|
||||
when(mockFunctionExecutionConfiguration.getAttribute(eq("pool"))).thenReturn(" ");
|
||||
when(mockFunctionExecutionConfiguration.getFunctionExecutionInterface()).thenAnswer(new Answer<Class<?>>() {
|
||||
@Override public Class<?> answer(final InvocationOnMock invocation) throws Throwable {
|
||||
return Object.class;
|
||||
}
|
||||
});
|
||||
|
||||
ServerBasedExecutionBeanDefinitionBuilder builder = new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) {
|
||||
@Override protected Class<?> getGemfireFunctionOperationsClass() {
|
||||
return Object.class;
|
||||
}
|
||||
};
|
||||
|
||||
BeanDefinitionBuilder beanDefinitionBuilder = builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null);
|
||||
|
||||
assertThat(beanDefinitionBuilder, is(notNullValue()));
|
||||
|
||||
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
|
||||
|
||||
assertThat(beanDefinition, is(notNullValue()));
|
||||
assertThat((Class<Object>) beanDefinition.getBeanClass(), is(equalTo(Object.class)));
|
||||
assertThat(String.valueOf(beanDefinition.getConstructorArgumentValues()
|
||||
.getArgumentValue(0, RuntimeBeanReference.class).getValue()),
|
||||
containsString(GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME));
|
||||
|
||||
verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("cache"));
|
||||
verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("pool"));
|
||||
verify(mockFunctionExecutionConfiguration, times(1)).getFunctionExecutionInterface();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void getGemfireFunctionOperationsBeanDefinitionBuilderWithCache() {
|
||||
FunctionExecutionConfiguration mockFunctionExecutionConfiguration =
|
||||
mock(FunctionExecutionConfiguration.class, "MockFunctionExecutionConfiguration");
|
||||
|
||||
when(mockFunctionExecutionConfiguration.getAttribute(eq("cache"))).thenReturn("TestCache");
|
||||
when(mockFunctionExecutionConfiguration.getAttribute(eq("pool"))).thenReturn(" ");
|
||||
when(mockFunctionExecutionConfiguration.getFunctionExecutionInterface()).thenAnswer(new Answer<Class<?>>() {
|
||||
@Override public Class<?> answer(final InvocationOnMock invocation) throws Throwable {
|
||||
return Object.class;
|
||||
}
|
||||
});
|
||||
|
||||
ServerBasedExecutionBeanDefinitionBuilder builder = new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) {
|
||||
@Override protected Class<?> getGemfireFunctionOperationsClass() {
|
||||
return Object.class;
|
||||
}
|
||||
};
|
||||
|
||||
BeanDefinitionBuilder beanDefinitionBuilder = builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null);
|
||||
|
||||
assertThat(beanDefinitionBuilder, is(notNullValue()));
|
||||
|
||||
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
|
||||
|
||||
assertThat(beanDefinition, is(notNullValue()));
|
||||
assertThat((Class<Object>) beanDefinition.getBeanClass(), is(equalTo(Object.class)));
|
||||
assertThat(String.valueOf(beanDefinition.getConstructorArgumentValues()
|
||||
.getArgumentValue(0, RuntimeBeanReference.class).getValue()), containsString("TestCache"));
|
||||
|
||||
verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("cache"));
|
||||
verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("pool"));
|
||||
verify(mockFunctionExecutionConfiguration, times(1)).getFunctionExecutionInterface();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void getGemfireFunctionOperationsBeanDefinitionBuilderWithPool() {
|
||||
FunctionExecutionConfiguration mockFunctionExecutionConfiguration =
|
||||
mock(FunctionExecutionConfiguration.class, "MockFunctionExecutionConfiguration");
|
||||
|
||||
when(mockFunctionExecutionConfiguration.getAttribute(eq("cache"))).thenReturn(null);
|
||||
when(mockFunctionExecutionConfiguration.getAttribute(eq("pool"))).thenReturn("TestPool");
|
||||
when(mockFunctionExecutionConfiguration.getFunctionExecutionInterface()).thenAnswer(new Answer<Class<?>>() {
|
||||
@Override public Class<?> answer(final InvocationOnMock invocation) throws Throwable {
|
||||
return Object.class;
|
||||
}
|
||||
});
|
||||
|
||||
ServerBasedExecutionBeanDefinitionBuilder builder = new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) {
|
||||
@Override protected Class<?> getGemfireFunctionOperationsClass() {
|
||||
return Object.class;
|
||||
}
|
||||
};
|
||||
|
||||
BeanDefinitionBuilder beanDefinitionBuilder = builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null);
|
||||
|
||||
assertThat(beanDefinitionBuilder, is(notNullValue()));
|
||||
|
||||
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
|
||||
|
||||
assertThat(beanDefinition, is(notNullValue()));
|
||||
assertThat((Class<Object>) beanDefinition.getBeanClass(), is(equalTo(Object.class)));
|
||||
assertThat(String.valueOf(beanDefinition.getConstructorArgumentValues()
|
||||
.getArgumentValue(0, RuntimeBeanReference.class).getValue()), containsString("TestPool"));
|
||||
|
||||
verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("cache"));
|
||||
verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("pool"));
|
||||
verify(mockFunctionExecutionConfiguration, times(1)).getFunctionExecutionInterface();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void getGemfireFunctionOperationsBeanDefinitionBuilderWithCacheAndPool() {
|
||||
FunctionExecutionConfiguration mockFunctionExecutionConfiguration =
|
||||
mock(FunctionExecutionConfiguration.class, "MockFunctionExecutionConfiguration");
|
||||
|
||||
when(mockFunctionExecutionConfiguration.getAttribute(eq("cache"))).thenReturn("TestCache");
|
||||
when(mockFunctionExecutionConfiguration.getAttribute(eq("pool"))).thenReturn("TestPool");
|
||||
when(mockFunctionExecutionConfiguration.getFunctionExecutionInterface()).thenAnswer(new Answer<Class<?>>() {
|
||||
@Override public Class<?> answer(final InvocationOnMock invocation) throws Throwable {
|
||||
return Object.class;
|
||||
}
|
||||
});
|
||||
|
||||
ServerBasedExecutionBeanDefinitionBuilder builder = new ServerBasedExecutionBeanDefinitionBuilder(mockFunctionExecutionConfiguration) {
|
||||
@Override protected Class<?> getGemfireFunctionOperationsClass() {
|
||||
return Object.class;
|
||||
}
|
||||
};
|
||||
|
||||
expectedException.expect(IllegalStateException.class);
|
||||
expectedException.expectCause(is(nullValue(Throwable.class)));
|
||||
expectedException.expectMessage(is(equalTo("invalid configuration for interface java.lang.Object;"
|
||||
+ " cannot specify both 'pool' and 'cache'")));
|
||||
builder.getGemfireFunctionOperationsBeanDefinitionBuilder(null);
|
||||
|
||||
verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("cache"));
|
||||
verify(mockFunctionExecutionConfiguration, times(1)).getAttribute(eq("pool"));
|
||||
verify(mockFunctionExecutionConfiguration, times(1)).getFunctionExecutionInterface();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* 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.function.execution;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.isA;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import com.gemstone.gemfire.cache.execute.Execution;
|
||||
import com.gemstone.gemfire.cache.execute.Function;
|
||||
import com.gemstone.gemfire.cache.execute.FunctionException;
|
||||
import com.gemstone.gemfire.cache.execute.ResultCollector;
|
||||
|
||||
/**
|
||||
* The AbstractFunctionExecutionTest class is a test suite of test cases testing the contract and functionality
|
||||
* of the AbstractFunctionExecution class.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.runners.MockitoJUnitRunner
|
||||
* @see org.springframework.data.gemfire.function.execution.AbstractFunctionExecution
|
||||
* @see com.gemstone.gemfire.cache.execute.Execution
|
||||
* @since 1.7.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AbstractFunctionExecutionTest {
|
||||
|
||||
@Rule
|
||||
public ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
@Mock
|
||||
private Execution mockExecution;
|
||||
|
||||
// TODO add more tests!!!
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void executeWithResults() throws Exception {
|
||||
Object[] args = { "one", "two", "three" };
|
||||
List<Object> results = Arrays.asList(args);
|
||||
|
||||
Function mockFunction = mock(Function.class, "MockFunction");
|
||||
ResultCollector mockResultCollector = mock(ResultCollector.class, "MockResultCollector");
|
||||
|
||||
when(mockExecution.withArgs(eq(args))).thenReturn(mockExecution);
|
||||
when(mockExecution.execute(eq(mockFunction))).thenReturn(mockResultCollector);
|
||||
when(mockFunction.hasResult()).thenReturn(true);
|
||||
when(mockResultCollector.getResult(500, TimeUnit.MILLISECONDS)).thenReturn(results);
|
||||
|
||||
AbstractFunctionExecution functionExecution = new AbstractFunctionExecution() {
|
||||
@Override protected Execution getExecution() {
|
||||
return mockExecution;
|
||||
}
|
||||
};
|
||||
|
||||
Iterable<Object> actualResults = functionExecution.setFunction(mockFunction)
|
||||
.setArgs(args).setTimeout(500).execute();
|
||||
|
||||
assertThat(actualResults, is(notNullValue()));
|
||||
assertThat(actualResults, is(equalTo((Iterable<Object>) results)));
|
||||
|
||||
verify(mockExecution, times(1)).withArgs(eq(args));
|
||||
verify(mockExecution, never()).withCollector(any(ResultCollector.class));
|
||||
verify(mockExecution, never()).withFilter(any(Set.class));
|
||||
verify(mockExecution, times(1)).execute(eq(mockFunction));
|
||||
verify(mockExecution, never()).execute(any(String.class));
|
||||
verify(mockResultCollector, times(1)).getResult(500, TimeUnit.MILLISECONDS);
|
||||
verify(mockResultCollector, never()).getResult();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeAndExtractWithSingleResult() {
|
||||
final List<String> results = Collections.singletonList("test");
|
||||
|
||||
AbstractFunctionExecution functionExecution = new AbstractFunctionExecution() {
|
||||
@Override protected Execution getExecution() {
|
||||
return mockExecution;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override <T> Iterable<T> execute() {
|
||||
return (Iterable<T>) results;
|
||||
}
|
||||
};
|
||||
|
||||
assertThat(String.valueOf(functionExecution.executeAndExtract()), is(equalTo("test")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeAndExtractWithMultipleResults() {
|
||||
final List<String> results = Arrays.asList("one", "two", "three");
|
||||
|
||||
AbstractFunctionExecution functionExecution = new AbstractFunctionExecution() {
|
||||
@Override protected Execution getExecution() {
|
||||
return mockExecution;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override <T> Iterable<T> execute() {
|
||||
return (Iterable<T>) results;
|
||||
}
|
||||
};
|
||||
|
||||
assertThat(String.valueOf(functionExecution.executeAndExtract()), is(equalTo("one")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeAndExtractWithNullResults() {
|
||||
AbstractFunctionExecution functionExecution = new AbstractFunctionExecution() {
|
||||
@Override protected Execution getExecution() {
|
||||
return mockExecution;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override <T> Iterable<T> execute() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
assertThat(functionExecution.executeAndExtract(), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeAndExtractWithNoResults() {
|
||||
AbstractFunctionExecution functionExecution = new AbstractFunctionExecution() {
|
||||
@Override protected Execution getExecution() {
|
||||
return mockExecution;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override <T> Iterable<T> execute() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
};
|
||||
|
||||
assertThat(functionExecution.executeAndExtract(), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeAndExtractWithThrowsException() {
|
||||
AbstractFunctionExecution functionExecution = new AbstractFunctionExecution() {
|
||||
@Override protected Execution getExecution() {
|
||||
return mockExecution;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override <T> Iterable<T> execute() {
|
||||
return Collections.singletonList((T) new IllegalArgumentException("test"));
|
||||
}
|
||||
};
|
||||
|
||||
expectedException.expect(FunctionException.class);
|
||||
expectedException.expectCause(isA(IllegalArgumentException.class));
|
||||
expectedException.expectMessage(containsString("Execution of Function with ID 'TestFunction' failed"));
|
||||
|
||||
functionExecution.setFunctionId("TestFunction").executeAndExtract();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* 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.function.execution;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import com.gemstone.gemfire.cache.execute.Function;
|
||||
import com.gemstone.gemfire.cache.execute.ResultCollector;
|
||||
|
||||
/**
|
||||
* The AbstractFunctionTemplateTest class is a test suite of test cases testing the contract and functionality
|
||||
* of the AbstractFunctionTemplate class.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.springframework.data.gemfire.function.execution.AbstractFunctionExecution
|
||||
* @see org.springframework.data.gemfire.function.execution.AbstractFunctionTemplate
|
||||
* @see com.gemstone.gemfire.cache.execute.Function
|
||||
* @see com.gemstone.gemfire.cache.execute.ResultCollector
|
||||
* @since 1.7.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AbstractFunctionTemplateTest {
|
||||
|
||||
@Mock
|
||||
private AbstractFunctionExecution mockFunctionExecution;
|
||||
|
||||
@Mock
|
||||
Function mockFunction;
|
||||
|
||||
@Mock
|
||||
private ResultCollector mockResultCollector;
|
||||
|
||||
@Test
|
||||
public void executeWithFunctionAndArgs() {
|
||||
Object[] args = { "test", "testing", "tested" };
|
||||
List<Object> results = Arrays.asList(args);
|
||||
|
||||
when(mockFunctionExecution.setArgs(args)).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.setFunction(mockFunction)).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.setResultCollector(mockResultCollector)).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.setTimeout(500)).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.execute()).thenReturn(results);
|
||||
|
||||
AbstractFunctionTemplate functionTemplate = new AbstractFunctionTemplate() {
|
||||
@Override protected AbstractFunctionExecution getFunctionExecution() {
|
||||
return mockFunctionExecution;
|
||||
}
|
||||
};
|
||||
|
||||
functionTemplate.setResultCollector(mockResultCollector);
|
||||
functionTemplate.setTimeout(500);
|
||||
|
||||
Iterable<Object> actualResults = functionTemplate.execute(mockFunction, args);
|
||||
|
||||
assertThat(functionTemplate.getResultCollector(), is(equalTo(mockResultCollector)));
|
||||
assertThat(actualResults, is(notNullValue()));
|
||||
assertThat(actualResults, is(equalTo((Iterable<Object>) results)));
|
||||
|
||||
verify(mockFunctionExecution, times(1)).setArgs(args);
|
||||
verify(mockFunctionExecution, times(1)).setFunction(mockFunction);
|
||||
verify(mockFunctionExecution, times(1)).setResultCollector(eq(mockResultCollector));
|
||||
verify(mockFunctionExecution, times(1)).setTimeout(500);
|
||||
verify(mockFunctionExecution, times(1)).execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeAndExtractWithFunctionAndArgs() {
|
||||
Object[] args = { "test", "testing", "tested" };
|
||||
|
||||
when(mockFunctionExecution.setArgs(args)).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.setFunction(mockFunction)).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.setResultCollector(mockResultCollector)).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.setTimeout(500)).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.executeAndExtract()).thenReturn(args[0]);
|
||||
|
||||
AbstractFunctionTemplate functionTemplate = new AbstractFunctionTemplate() {
|
||||
@Override protected AbstractFunctionExecution getFunctionExecution() {
|
||||
return mockFunctionExecution;
|
||||
}
|
||||
};
|
||||
|
||||
functionTemplate.setResultCollector(mockResultCollector);
|
||||
functionTemplate.setTimeout(500);
|
||||
|
||||
String result = functionTemplate.executeAndExtract(mockFunction, args);
|
||||
|
||||
assertThat(functionTemplate.getResultCollector(), is(equalTo(mockResultCollector)));
|
||||
assertThat(result, is(notNullValue()));
|
||||
assertThat(result, is(equalTo("test")));
|
||||
|
||||
verify(mockFunctionExecution, times(1)).setArgs(args);
|
||||
verify(mockFunctionExecution, times(1)).setFunction(mockFunction);
|
||||
verify(mockFunctionExecution, times(1)).setResultCollector(eq(mockResultCollector));
|
||||
verify(mockFunctionExecution, times(1)).setTimeout(500);
|
||||
verify(mockFunctionExecution, times(1)).executeAndExtract();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeWithFunctionIdAndArgs() {
|
||||
Object[] args = { "test", "testing", "tested" };
|
||||
List<Object> results = Arrays.asList(args);
|
||||
|
||||
when(mockFunctionExecution.setArgs(args)).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.setFunctionId("TestFunction")).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.setResultCollector(mockResultCollector)).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.setTimeout(500)).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.execute()).thenReturn(results);
|
||||
|
||||
AbstractFunctionTemplate functionTemplate = new AbstractFunctionTemplate() {
|
||||
@Override protected AbstractFunctionExecution getFunctionExecution() {
|
||||
return mockFunctionExecution;
|
||||
}
|
||||
};
|
||||
|
||||
functionTemplate.setResultCollector(mockResultCollector);
|
||||
functionTemplate.setTimeout(500);
|
||||
|
||||
Iterable<Object> actualResults = functionTemplate.execute("TestFunction", args);
|
||||
|
||||
assertThat(functionTemplate.getResultCollector(), is(equalTo(mockResultCollector)));
|
||||
assertThat(actualResults, is(notNullValue()));
|
||||
assertThat(actualResults, is(equalTo((Iterable<Object>) results)));
|
||||
|
||||
verify(mockFunctionExecution, times(1)).setArgs(args);
|
||||
verify(mockFunctionExecution, times(1)).setFunctionId("TestFunction");
|
||||
verify(mockFunctionExecution, times(1)).setResultCollector(eq(mockResultCollector));
|
||||
verify(mockFunctionExecution, times(1)).setTimeout(500);
|
||||
verify(mockFunctionExecution, times(1)).execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeAndExtractWithFunctionIdAndArgs() {
|
||||
Object[] args = { "test", "testing", "tested" };
|
||||
|
||||
when(mockFunctionExecution.setArgs(args)).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.setFunctionId("TestFunction")).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.setResultCollector(mockResultCollector)).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.setTimeout(500)).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.executeAndExtract()).thenReturn(args[0]);
|
||||
|
||||
AbstractFunctionTemplate functionTemplate = new AbstractFunctionTemplate() {
|
||||
@Override protected AbstractFunctionExecution getFunctionExecution() {
|
||||
return mockFunctionExecution;
|
||||
}
|
||||
};
|
||||
|
||||
functionTemplate.setResultCollector(mockResultCollector);
|
||||
functionTemplate.setTimeout(500);
|
||||
|
||||
String result = functionTemplate.executeAndExtract("TestFunction", args);
|
||||
|
||||
assertThat(functionTemplate.getResultCollector(), is(equalTo(mockResultCollector)));
|
||||
assertThat(result, is(notNullValue()));
|
||||
assertThat(result, is(equalTo("test")));
|
||||
|
||||
verify(mockFunctionExecution, times(1)).setArgs(args);
|
||||
verify(mockFunctionExecution, times(1)).setFunctionId("TestFunction");
|
||||
verify(mockFunctionExecution, times(1)).setResultCollector(eq(mockResultCollector));
|
||||
verify(mockFunctionExecution, times(1)).setTimeout(500);
|
||||
verify(mockFunctionExecution, times(1)).executeAndExtract();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeWithNoResultWithFunctionIdAndArgs() {
|
||||
Object[] args = { "test", "testing", "tested" };
|
||||
|
||||
when(mockFunctionExecution.setArgs(args)).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.setFunctionId("TestFunction")).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.setResultCollector(mockResultCollector)).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.setTimeout(500)).thenReturn(mockFunctionExecution);
|
||||
when(mockFunctionExecution.execute(eq(false))).thenReturn(null);
|
||||
|
||||
AbstractFunctionTemplate functionTemplate = new AbstractFunctionTemplate() {
|
||||
@Override protected AbstractFunctionExecution getFunctionExecution() {
|
||||
return mockFunctionExecution;
|
||||
}
|
||||
};
|
||||
|
||||
functionTemplate.setResultCollector(mockResultCollector);
|
||||
functionTemplate.setTimeout(500);
|
||||
|
||||
functionTemplate.executeWithNoResult("TestFunction", args);
|
||||
|
||||
assertThat(functionTemplate.getResultCollector(), is(equalTo(mockResultCollector)));
|
||||
|
||||
verify(mockFunctionExecution, times(1)).setArgs(args);
|
||||
verify(mockFunctionExecution, times(1)).setFunctionId("TestFunction");
|
||||
verify(mockFunctionExecution, times(1)).setResultCollector(eq(mockResultCollector));
|
||||
verify(mockFunctionExecution, times(1)).setTimeout(500);
|
||||
verify(mockFunctionExecution, times(1)).execute(eq(false));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.function.sample;
|
||||
|
||||
import org.springframework.data.gemfire.function.annotation.OnServer;
|
||||
|
||||
/**
|
||||
* The ExceptionThrowingFunctionExecution interface defines a GemFire Function that throws a RuntimeException.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.function.annotation.OnServer
|
||||
* @since 1.7.0
|
||||
*/
|
||||
@OnServer
|
||||
@SuppressWarnings("unused")
|
||||
public interface ExceptionThrowingFunctionExecution {
|
||||
|
||||
Integer exceptionThrowingFunction();
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user