Fix Race Condition in TxSyncQueueChannelTests

https://build.spring.io/browse/INT-MASTER-653

The test-case uses only 1 second to wait for the message
in the `QueueChannel`.
That isn't enough on slow environment like CI causing failure for
the current test and unexpected value in the queue for the subsequent
tests

* Fix timeouts
* Get rid of `CountDownLatch` - the same is done by the wait on queues
* Purge queue in between tests.
This way we may not have failed subsequent test, thus failure analyze
will be much easier
* Rework `testRollback()` to wait for good result after one retry over
rollback
* Remove duplicate bean definition from XML config

**Cherry-pick to 4.3.x and 4.2.x**

Conflicts:
	spring-integration-core/src/test/java/org/springframework/integration/channel/TransactionSynchronizationQueueChannelTests.java
Resolved.
This commit is contained in:
Artem Bilan
2017-05-08 15:33:13 -04:00
committed by Gary Russell
parent 2c96f6a958
commit 194d710c3b
2 changed files with 28 additions and 36 deletions

View File

@@ -5,6 +5,11 @@
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="transactionManager" class="org.springframework.integration.transaction.PseudoTransactionManager" />
<bean id="service"
class="org.springframework.integration.channel.TransactionSynchronizationQueueChannelTests$Service"/>
<int:channel id="queueChannel">
<int:queue />
</int:channel>
@@ -15,7 +20,6 @@
</int:poller>
</int:service-activator>
<bean id="service" class="org.springframework.integration.channel.TransactionSynchronizationQueueChannelTests$Service"/>
<int:transaction-synchronization-factory id="txSyncFactory">
<int:after-commit channel="good" />
@@ -26,8 +30,6 @@
<int:queue />
</int:channel>
<bean id="transactionManager" class="org.springframework.integration.transaction.PseudoTransactionManager" />
<int:channel id="queueChannel2">
<int:queue />
</int:channel>
@@ -43,8 +45,4 @@
channel="good" />
</int:transaction-synchronization-factory>
<int:channel id="good">
<int:queue />
</int:channel>
</beans>

View File

@@ -18,20 +18,17 @@ package org.springframework.integration.channel;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -42,27 +39,30 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class TransactionSynchronizationQueueChannelTests {
@Autowired
private PollableChannel queueChannel;
private QueueChannel queueChannel;
@Autowired
private PollableChannel good;
private QueueChannel good;
@Autowired
private Service service;
private QueueChannel queueChannel2;
@Autowired
private PollableChannel queueChannel2;
@Before
public void setup() {
this.good.purge(null);
this.queueChannel.purge(null);
this.queueChannel2.purge(null);
}
@Test
public void testCommit() throws Exception {
service.latch = new CountDownLatch(1);
GenericMessage<String> sentMessage = new GenericMessage<String>("hello");
queueChannel.send(sentMessage);
assertTrue(service.latch.await(10, TimeUnit.SECONDS));
Message<?> message = good.receive(1000);
GenericMessage<String> sentMessage = new GenericMessage<>("hello");
this.queueChannel.send(sentMessage);
Message<?> message = this.good.receive(10000);
assertNotNull(message);
assertEquals("hello", message.getPayload());
assertSame(message, sentMessage);
@@ -70,38 +70,32 @@ public class TransactionSynchronizationQueueChannelTests {
@Test
public void testRollback() throws Exception {
service.latch = new CountDownLatch(1);
queueChannel.send(new GenericMessage<String>("fail"));
assertTrue(service.latch.await(10, TimeUnit.SECONDS));
Message<?> message = queueChannel.receive(1000);
this.queueChannel.send(new GenericMessage<>("fail"));
Message<?> message = this.good.receive(10000);
assertNotNull(message);
assertEquals("retry:fail", message.getPayload());
assertNull(good.receive(0));
}
@Test
public void testIncludeChannelName() throws Exception {
service.latch = new CountDownLatch(1);
Message<String> sentMessage = MessageBuilder.withPayload("hello")
.setHeader("foo", "bar").build();
queueChannel2.send(sentMessage);
assertTrue(service.latch.await(10, TimeUnit.SECONDS));
Message<?> message = good.receive(1000);
Message<?> message = good.receive(10000);
assertNotNull(message);
assertEquals("hello processed ok from queueChannel2", message.getPayload());
assertNotNull(message.getHeaders().get("foo"));
assertEquals("bar", message.getHeaders().get("foo"));
}
}
public static class Service {
private CountDownLatch latch;
public void handle(String foo) {
latch.countDown();
if (foo.startsWith("fail")) {
throw new RuntimeException("planned failure");
}
}
}
}