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:
John Blum
2015-08-07 01:36:59 -07:00
parent 677d46c1df
commit cd4a2497b7
16 changed files with 1005 additions and 152 deletions

View File

@@ -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"));
}
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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));
}
}

View File

@@ -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();
}