Fix RedisInboundChannelAdapterTests Race Condition

Instead of waiting for a hard 1 second, intelligently wait
until the container is subscribed by sending/receiving a test message.

Also reduces the test run time from 20s to 200ms locally.
This commit is contained in:
Gary Russell
2015-06-01 14:00:40 -04:00
parent 0fdc63007a
commit bc8b946a9e
2 changed files with 43 additions and 11 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2007-2014 the original author or authors
* Copyright 2007-2015 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.
@@ -16,8 +16,11 @@
package org.springframework.integration.redis.inbound;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import org.hamcrest.Matchers;
import org.junit.Test;
@@ -36,6 +39,7 @@ import org.springframework.messaging.Message;
/**
* @author Mark Fisher
* @author Artem Bilan
* @author Gary Russell
* @since 2.1
*/
public class RedisInboundChannelAdapterTests extends RedisAvailableTests {
@@ -62,11 +66,12 @@ public class RedisInboundChannelAdapterTests extends RedisAvailableTests {
adapter.afterPropertiesSet();
adapter.start();
this.awaitContainerSubscribed(TestUtils.getPropertyValue(adapter, "container",
RedisMessageListenerContainer.class));
StringRedisTemplate redisTemplate = new StringRedisTemplate(connectionFactory);
redisTemplate.afterPropertiesSet();
awaitFullySubscribed(TestUtils.getPropertyValue(adapter, "container", RedisMessageListenerContainer.class),
redisTemplate, redisChannelName, channel, "foo");
for (int i = 0; i < numToTest; i++) {
String message = "test-" + i + " iteration " + iteration;
redisTemplate.convertAndSend(redisChannelName, message);
@@ -91,14 +96,14 @@ public class RedisInboundChannelAdapterTests extends RedisAvailableTests {
adapter.afterPropertiesSet();
adapter.start();
this.awaitContainerSubscribed(TestUtils.getPropertyValue(adapter, "container",
RedisMessageListenerContainer.class));
RedisTemplate<?, ?> template = new RedisTemplate<Object, Object>();
template.setConnectionFactory(connectionFactory);
template.setEnableDefaultSerializer(false);
template.afterPropertiesSet();
awaitFullySubscribed(TestUtils.getPropertyValue(adapter, "container", RedisMessageListenerContainer.class),
template, redisChannelName, channel, "foo".getBytes());
for (int i = 0; i < numToTest; i++) {
String message = "test-" + i + " iteration " + iteration;
template.convertAndSend(redisChannelName, message.getBytes());

View File

@@ -25,9 +25,12 @@ import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.BoundZSetOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
/**
* @author Oleg Zhurakousky
@@ -52,6 +55,12 @@ public class RedisAvailableTests {
}
protected void awaitContainerSubscribed(RedisMessageListenerContainer container) throws Exception {
awaitContainerSubscribedNoWait(container);
// wait another second because of race condition
Thread.sleep(1000);
}
private void awaitContainerSubscribedNoWait(RedisMessageListenerContainer container) throws InterruptedException {
RedisConnection connection = null;
int n = 0;
@@ -67,8 +76,6 @@ public class RedisAvailableTests {
Thread.sleep(100);
}
assertTrue("RedisMessageListenerContainer Failed to Subscribe", n < 100);
// wait another second because of race condition
Thread.sleep(1000);
}
protected void awaitContainerSubscribedWithPatterns(RedisMessageListenerContainer container) throws Exception {
@@ -85,6 +92,26 @@ public class RedisAvailableTests {
Thread.sleep(1000);
}
protected void awaitFullySubscribed(RedisMessageListenerContainer container, RedisTemplate<?, ?> redisTemplate,
String redisChannelName, QueueChannel channel, Object message) throws Exception {
awaitContainerSubscribedNoWait(container);
drain(channel);
long now = System.currentTimeMillis();
Message<?> received = null;
while (received == null && System.currentTimeMillis() - now < 10000) {
redisTemplate.convertAndSend(redisChannelName, message);
received = channel.receive(1000);
}
drain(channel);
assertNotNull("Container failed to fully start", received);
}
private void drain(QueueChannel channel) {
while (channel.receive(0) != null) {
;
}
}
protected void prepareList(RedisConnectionFactory connectionFactory){
StringRedisTemplate redisTemplate = createStringRedisTemplate(connectionFactory);