INT-3823: Fix EnableIntTests Race Condition

JIRA: https://jira.spring.io/browse/INT-3823

The test stops the endpoint.

The previous poller thread can 'steal' the `input` message, but since
it is interrupted, it can't send the message to the `publishedChannel`.

Add logic to wait until the previous poller has been interrupted in `receive()`.

Increase the endpoint `receiveTimeout` to ensure the thread will be interrupted.

Bump SF Version to 4.2.3

Remove `TRACE` logging from the `EnableIntegrationTests` since we have the fix already
Make some optimization around `@DirtiesContext`
This commit is contained in:
Gary Russell
2015-11-15 13:57:04 -05:00
committed by Artem Bilan
parent 0327666ca7
commit 9500d308a0
2 changed files with 50 additions and 9 deletions

View File

@@ -139,7 +139,7 @@ subprojects { subproject ->
springSecurityVersion = project.hasProperty('springSecurityVersion') ? project.springSecurityVersion : '4.0.2.RELEASE'
springSocialTwitterVersion = '1.1.1.RELEASE'
springRetryVersion = '1.1.2.RELEASE'
springVersion = project.hasProperty('springVersion') ? project.springVersion : '4.2.2.RELEASE'
springVersion = project.hasProperty('springVersion') ? project.springVersion : '4.2.3.RELEASE'
springWsVersion = '2.2.2.RELEASE'
xmlUnitVersion = '1.5'
xstreamVersion = '1.4.7'

View File

@@ -26,7 +26,10 @@ import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -46,7 +49,10 @@ import org.apache.commons.logging.LogFactory;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -129,13 +135,14 @@ import reactor.spring.context.config.EnableReactor;
/**
* @author Artem Bilan
* @author Gary Russell
* @since 4.0
*/
@ContextConfiguration(loader = AnnotationConfigContextLoader.class,
classes = {EnableIntegrationTests.ContextConfiguration.class, EnableIntegrationTests.ContextConfiguration2.class})
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class EnableIntegrationTests extends LogAdjustingTestSupport {
@DirtiesContext
public class EnableIntegrationTests {
@Autowired
private ApplicationContext context;
@@ -262,12 +269,15 @@ public class EnableIntegrationTests extends LogAdjustingTestSupport {
@Qualifier("enableIntegrationTests.ContextConfiguration2.sendAsyncHandler.serviceActivator")
private AbstractEndpoint sendAsyncHandler;
public EnableIntegrationTests() {
super("org.springframework.integration", "org.springframework");
}
@Autowired
private CountDownLatch inputReceiveLatch;
@Test
public void testAnnotatedServiceActivator() {
public void testAnnotatedServiceActivator() throws Exception {
this.serviceActivatorEndpoint.setReceiveTimeout(10000);
this.serviceActivatorEndpoint.start();
assertTrue(this.inputReceiveLatch.await(10, TimeUnit.SECONDS));
assertEquals(10L, TestUtils.getPropertyValue(this.serviceActivatorEndpoint, "maxMessagesPerPoll"));
Trigger trigger = TestUtils.getPropertyValue(this.serviceActivatorEndpoint, "trigger", Trigger.class);
@@ -276,8 +286,25 @@ public class EnableIntegrationTests extends LogAdjustingTestSupport {
assertFalse(TestUtils.getPropertyValue(trigger, "fixedRate", Boolean.class));
assertTrue(this.annotationTestService.isRunning());
Log logger = spy(TestUtils.getPropertyValue(this.serviceActivatorEndpoint, "logger", Log.class));
when(logger.isDebugEnabled()).thenReturn(true);
final CountDownLatch pollerInterruptedLatch = new CountDownLatch(1);
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
pollerInterruptedLatch.countDown();
invocation.callRealMethod();
return null;
}
}).when(logger).debug("Received no Message during the poll, returning 'false'");
new DirectFieldAccessor(this.serviceActivatorEndpoint).setPropertyValue("logger", logger);
this.serviceActivatorEndpoint.stop();
assertFalse(this.annotationTestService.isRunning());
// wait until the service activator's poller is interrupted.
assertTrue(pollerInterruptedLatch.await(10, TimeUnit.SECONDS));
this.serviceActivatorEndpoint.start();
assertTrue(this.annotationTestService.isRunning());
@@ -381,6 +408,7 @@ public class EnableIntegrationTests extends LogAdjustingTestSupport {
}
@Test
@DirtiesContext
public void testChangePatterns() {
try {
this.configurer.setComponentNamePatterns(new String[] {"*"});
@@ -603,6 +631,7 @@ public class EnableIntegrationTests extends LogAdjustingTestSupport {
}
@Test
@DirtiesContext
public void testRoles() {
this.roleController.stopLifecyclesInRole("foo");
@SuppressWarnings("unchecked")
@@ -625,9 +654,21 @@ public class EnableIntegrationTests extends LogAdjustingTestSupport {
@EnableMessageHistory({"input", "publishedChannel", "annotationTestService*"})
public static class ContextConfiguration {
@Bean
public CountDownLatch inputReceiveLatch() {
return new CountDownLatch(1);
}
@Bean
public QueueChannel input() {
return new QueueChannel();
return new QueueChannel() {
@Override
protected Message<?> doReceive(long timeout) {
inputReceiveLatch().countDown();
return super.doReceive(timeout);
}
};
}
@Bean
@@ -1060,7 +1101,7 @@ public class EnableIntegrationTests extends LogAdjustingTestSupport {
private boolean running;
@Override
@ServiceActivator(inputChannel = "input", outputChannel = "output",
@ServiceActivator(inputChannel = "input", outputChannel = "output", autoStartup = "false",
poller = @Poller(maxMessagesPerPoll = "${poller.maxMessagesPerPoll}", fixedDelay = "${poller.interval}"))
@Publisher
@Payload("#args[0].toLowerCase()")