Commit fd6024eb authored by Phillip Webb's avatar Phillip Webb

Move and refactor Redis test server @Rule

Move the Redis JUnit @Rule so that it can be used with
SessionAutoConfigurationTests. Also refactored the internals a little.
parent 9ebe1523
...@@ -23,6 +23,7 @@ import org.junit.Test; ...@@ -23,6 +23,7 @@ import org.junit.Test;
import org.springframework.boot.actuate.metrics.Iterables; import org.springframework.boot.actuate.metrics.Iterables;
import org.springframework.boot.actuate.metrics.Metric; import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.boot.actuate.metrics.writer.Delta; import org.springframework.boot.actuate.metrics.writer.Delta;
import org.springframework.boot.redis.RedisTestServer;
import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
...@@ -30,29 +31,34 @@ import static org.junit.Assert.assertNotNull; ...@@ -30,29 +31,34 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
/** /**
* Tests for {@link RedisMetricRepository}.
*
* @author Dave Syer * @author Dave Syer
*/ */
public class RedisMetricRepositoryTests { public class RedisMetricRepositoryTests {
@Rule @Rule
public RedisServer redis = RedisServer.running(); public RedisTestServer redis = new RedisTestServer();
private RedisMetricRepository repository; private RedisMetricRepository repository;
private String prefix; private String prefix;
@Before @Before
public void init() { public void init() {
this.prefix = "spring.test." + System.currentTimeMillis(); this.prefix = "spring.test." + System.currentTimeMillis();
this.repository = new RedisMetricRepository(this.redis.getResource(), this.prefix); this.repository = new RedisMetricRepository(this.redis.getConnectionFactory(),
this.prefix);
} }
@After @After
public void clear() { public void clear() {
assertNotNull(new StringRedisTemplate(this.redis.getResource()).opsForValue() assertNotNull(new StringRedisTemplate(this.redis.getConnectionFactory())
.get(this.prefix + ".foo")); .opsForValue().get(this.prefix + ".foo"));
this.repository.reset("foo"); this.repository.reset("foo");
this.repository.reset("bar"); this.repository.reset("bar");
assertNull(new StringRedisTemplate(this.redis.getResource()).opsForValue().get( assertNull(new StringRedisTemplate(this.redis.getConnectionFactory())
this.prefix + ".foo")); .opsForValue().get(this.prefix + ".foo"));
} }
@Test @Test
......
...@@ -33,6 +33,7 @@ import org.junit.runners.Parameterized.Parameters; ...@@ -33,6 +33,7 @@ import org.junit.runners.Parameterized.Parameters;
import org.springframework.boot.actuate.metrics.Iterables; import org.springframework.boot.actuate.metrics.Iterables;
import org.springframework.boot.actuate.metrics.Metric; import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.boot.actuate.metrics.writer.Delta; import org.springframework.boot.actuate.metrics.writer.Delta;
import org.springframework.boot.redis.RedisTestServer;
import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
...@@ -48,8 +49,10 @@ import static org.junit.Assert.assertTrue; ...@@ -48,8 +49,10 @@ import static org.junit.Assert.assertTrue;
public class RedisMultiMetricRepositoryTests { public class RedisMultiMetricRepositoryTests {
@Rule @Rule
public RedisServer redis = RedisServer.running(); public RedisTestServer redis = new RedisTestServer();
private RedisMultiMetricRepository repository; private RedisMultiMetricRepository repository;
@Parameter(0) @Parameter(0)
public String prefix; public String prefix;
...@@ -62,24 +65,25 @@ public class RedisMultiMetricRepositoryTests { ...@@ -62,24 +65,25 @@ public class RedisMultiMetricRepositoryTests {
public void init() { public void init() {
if (this.prefix == null) { if (this.prefix == null) {
this.prefix = "spring.groups"; this.prefix = "spring.groups";
this.repository = new RedisMultiMetricRepository(this.redis.getResource()); this.repository = new RedisMultiMetricRepository(
this.redis.getConnectionFactory());
} }
else { else {
this.repository = new RedisMultiMetricRepository(this.redis.getResource(), this.repository = new RedisMultiMetricRepository(
this.prefix); this.redis.getConnectionFactory(), this.prefix);
} }
} }
@After @After
public void clear() { public void clear() {
assertTrue(new StringRedisTemplate(this.redis.getResource()).opsForZSet().size( assertTrue(new StringRedisTemplate(this.redis.getConnectionFactory())
"keys." + this.prefix) > 0); .opsForZSet().size("keys." + this.prefix) > 0);
this.repository.reset("foo"); this.repository.reset("foo");
this.repository.reset("bar"); this.repository.reset("bar");
assertNull(new StringRedisTemplate(this.redis.getResource()).opsForValue().get( assertNull(new StringRedisTemplate(this.redis.getConnectionFactory())
this.prefix + ".foo")); .opsForValue().get(this.prefix + ".foo"));
assertNull(new StringRedisTemplate(this.redis.getResource()).opsForValue().get( assertNull(new StringRedisTemplate(this.redis.getConnectionFactory())
this.prefix + ".bar")); .opsForValue().get(this.prefix + ".bar"));
} }
@Test @Test
...@@ -136,4 +140,5 @@ public class RedisMultiMetricRepositoryTests { ...@@ -136,4 +140,5 @@ public class RedisMultiMetricRepositoryTests {
assertTrue("Wrong names: " + names, names.contains("foo.bar")); assertTrue("Wrong names: " + names, names.contains("foo.bar"));
assertEquals(3d, bar.getValue()); assertEquals(3d, bar.getValue());
} }
} }
...@@ -95,7 +95,6 @@ public class RedisAutoConfigurationTests { ...@@ -95,7 +95,6 @@ public class RedisAutoConfigurationTests {
@Test @Test
public void testRedisConfigurationWithSentinel() throws Exception { public void testRedisConfigurationWithSentinel() throws Exception {
List<String> sentinels = Arrays.asList("127.0.0.1:26379", "127.0.0.1:26380"); List<String> sentinels = Arrays.asList("127.0.0.1:26379", "127.0.0.1:26380");
if (isAtLeastOneSentinelAvailable(sentinels)) { if (isAtLeastOneSentinelAvailable(sentinels)) {
load("spring.redis.sentinel.master:mymaster", "spring.redis.sentinel.nodes:" load("spring.redis.sentinel.master:mymaster", "spring.redis.sentinel.nodes:"
+ StringUtils.collectionToCommaDelimitedString(sentinels)); + StringUtils.collectionToCommaDelimitedString(sentinels));
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
package org.springframework.boot.autoconfigure.session; package org.springframework.boot.autoconfigure.session;
import org.junit.After; import org.junit.After;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration; import org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration;
...@@ -25,6 +26,7 @@ import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfigurat ...@@ -25,6 +26,7 @@ import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfigurat
import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext; import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.MockEmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.MockEmbeddedServletContainerFactory;
import org.springframework.boot.redis.RedisTestServer;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -39,6 +41,9 @@ import static org.junit.Assert.assertNotNull; ...@@ -39,6 +41,9 @@ import static org.junit.Assert.assertNotNull;
*/ */
public class SessionAutoConfigurationTests { public class SessionAutoConfigurationTests {
@Rule
public RedisTestServer redis = new RedisTestServer();
private AnnotationConfigEmbeddedWebApplicationContext context; private AnnotationConfigEmbeddedWebApplicationContext context;
@After @After
......
...@@ -246,6 +246,11 @@ ...@@ -246,6 +246,11 @@
<artifactId>spring-context-support</artifactId> <artifactId>spring-context-support</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.actuate.metrics.repository.redis; package org.springframework.boot.redis;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
...@@ -25,122 +25,86 @@ import org.junit.runners.model.Statement; ...@@ -25,122 +25,86 @@ import org.junit.runners.model.Statement;
import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import static org.junit.Assert.fail;
/** /**
* {@link TestRule} for working with an optional Redis server.
*
* @author Eric Bottard * @author Eric Bottard
* @author Gary Russell * @author Gary Russell
* @author Dave Syer * @author Dave Syer
* @author Phillip Webb
*/ */
public class RedisServer implements TestRule { public class RedisTestServer implements TestRule {
private static final String EXTERNAL_SERVERS_REQUIRED = "EXTERNAL_SERVERS_REQUIRED";
protected JedisConnectionFactory resource; private static final Log logger = LogFactory.getLog(RedisTestServer.class);
private final String resourceDescription = "Redis ConnectionFactory"; private JedisConnectionFactory connectionFactory;
private static final Log logger = LogFactory.getLog(RedisServer.class);
public static RedisServer running() {
return new RedisServer();
}
private RedisServer() {
}
@Override @Override
public Statement apply(final Statement base, Description description) { public Statement apply(final Statement base, Description description) {
try { try {
this.resource = obtainResource(); this.connectionFactory = createConnectionFactory();
return new RedisStatement(base, this.connectionFactory);
} }
catch (Exception ex) { catch (Exception ex) {
maybeCleanup(); logger.error("No Redis server availble", ex);
return failOrSkip(ex); return new SkipStatement();
} }
}
return new Statement() { private JedisConnectionFactory createConnectionFactory() {
JedisConnectionFactory connectionFactory = new JedisConnectionFactory();
connectionFactory.afterPropertiesSet();
testConnection(connectionFactory);
return connectionFactory;
}
@Override private void testConnection(JedisConnectionFactory connectionFactory) {
public void evaluate() throws Throwable { connectionFactory.getConnection().close();
try { }
base.evaluate();
}
finally {
try {
cleanupResource();
}
catch (Exception ignored) {
RedisServer.logger.warn(
"Exception while trying to cleanup proper resource",
ignored);
}
}
}
}; /**
* @return the connection factory if any
*/
public RedisConnectionFactory getConnectionFactory() {
return this.connectionFactory;
} }
private Statement failOrSkip(Exception exception) { private static class RedisStatement extends Statement {
String serversRequired = System.getenv(EXTERNAL_SERVERS_REQUIRED);
if ("true".equalsIgnoreCase(serversRequired)) { private final Statement base;
logger.error(this.resourceDescription + " IS REQUIRED BUT NOT AVAILABLE",
exception); private final JedisConnectionFactory connectionFactory;
fail(this.resourceDescription + " IS NOT AVAILABLE");
// Never reached, here to satisfy method signature public RedisStatement(Statement base, JedisConnectionFactory connectionFactory) {
return null; this.base = base;
} this.connectionFactory = connectionFactory;
else {
logger.error(this.resourceDescription + " IS NOT AVAILABLE, SKIPPING TESTS",
exception);
return new Statement() {
@Override
public void evaluate() throws Throwable {
Assume.assumeTrue("Skipping test due to "
+ RedisServer.this.resourceDescription
+ " not being available", false);
}
};
} }
}
private void maybeCleanup() { @Override
if (this.resource != null) { public void evaluate() throws Throwable {
try { try {
cleanupResource(); this.base.evaluate();
} }
catch (Exception ignored) { finally {
logger.warn("Exception while trying to cleanup failed resource", ignored); try {
this.connectionFactory.destroy();
}
catch (Exception ex) {
logger.warn("Exception while trying to cleanup redis resource", ex);
}
} }
} }
}
public RedisConnectionFactory getResource() {
return this.resource;
} }
/** private static class SkipStatement extends Statement {
* Perform cleanup of the {@link #resource} field, which is guaranteed to be non null.
* @Override
* @throws Exception any exception thrown by this method will be logged and swallowed public void evaluate() throws Throwable {
*/ Assume.assumeTrue("Skipping test due to " + "Redis ConnectionFactory"
protected void cleanupResource() throws Exception { + " not being available", false);
this.resource.destroy(); }
}
/**
* Try to obtain and validate a resource. Implementors should either set the
* {@link #resource} field with a valid resource and return normally, or throw an
* exception.
* @return the jedis connection factory
* @throws Exception if the factory cannot be obtained
*/
protected JedisConnectionFactory obtainResource() throws Exception {
JedisConnectionFactory resource = new JedisConnectionFactory();
resource.afterPropertiesSet();
resource.getConnection().close();
return resource;
} }
} }
/*
* Copyright 2012-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.
* 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.
*/
/**
* @author pwebb
*/
package org.springframework.boot.redis;
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment