diff --git a/pom.xml b/pom.xml index f50aae9fff..c1f1ef6628 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-redis - 1.7.0.BUILD-SNAPSHOT + 1.7.0.DATAREDIS-469-SNAPSHOT Spring Data Redis diff --git a/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicDouble.java b/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicDouble.java index 992cd1eeb6..d47c758094 100644 --- a/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicDouble.java +++ b/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicDouble.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 the original author or authors. + * Copyright 2013-2016 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. @@ -20,6 +20,7 @@ import java.util.Date; import java.util.concurrent.TimeUnit; +import org.springframework.dao.DataRetrievalFailureException; import org.springframework.data.redis.connection.DataType; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.BoundKeyOperations; @@ -35,9 +36,11 @@ /** * Atomic double backed by Redis. Uses Redis atomic increment/decrement and watch/multi/exec operations for CAS * operations. - * + * * @author Jennifer Hickey * @author Thomas Darimont + * @author Christoph Strobl + * @author Mark Paluch */ public class RedisAtomicDouble extends Number implements Serializable, BoundKeyOperations { @@ -49,7 +52,7 @@ public class RedisAtomicDouble extends Number implements Serializable, BoundKeyO /** * Constructs a new RedisAtomicDouble instance. Uses the value existing in Redis or 0 if none is found. - * + * * @param redisCounter redis counter * @param factory connection factory */ @@ -59,7 +62,7 @@ public RedisAtomicDouble(String redisCounter, RedisConnectionFactory factory) { /** * Constructs a new RedisAtomicDouble instance. - * + * * @param redisCounter * @param factory * @param initialValue @@ -94,7 +97,7 @@ private RedisAtomicDouble(String redisCounter, RedisConnectionFactory factory, D /** * Constructs a new RedisAtomicDouble instance. Uses the value existing in Redis or 0 if none is found. - * + * * @param redisCounter the redis counter * @param template the template * @see #RedisAtomicDouble(String, RedisConnectionFactory, double) @@ -108,7 +111,7 @@ public RedisAtomicDouble(String redisCounter, RedisOperations te * with appropriate {@link RedisSerializer} for the key and value. As an alternative one could use the * {@link #RedisAtomicDouble(String, RedisConnectionFactory, Double)} constructor which uses appropriate default * serializers. - * + * * @param redisCounter the redis counter * @param template the template * @param initialValue the initial value @@ -139,16 +142,22 @@ private RedisAtomicDouble(String redisCounter, RedisOperations t /** * Gets the current value. - * + * * @return the current value */ public double get() { - return operations.get(key); + + Double value = operations.get(key); + if (value != null) { + return value.doubleValue(); + } + + throw new DataRetrievalFailureException(String.format("The key '%s' seems to no longer exist.", key)); } /** * Sets to the given value. - * + * * @param newValue the new value */ public void set(double newValue) { @@ -157,17 +166,23 @@ public void set(double newValue) { /** * Atomically sets to the given value and returns the old value. - * + * * @param newValue the new value * @return the previous value */ public double getAndSet(double newValue) { - return operations.getAndSet(key, newValue); + + Double value = operations.getAndSet(key, newValue); + if (value != null) { + return value.doubleValue(); + } + + return 0; } /** * Atomically sets the value to the given updated value if the current value {@code ==} the expected value. - * + * * @param expect the expected value * @param update the new value * @return true if successful. False return indicates that the actual value was not equal to the expected value. @@ -196,7 +211,7 @@ public Boolean execute(RedisOperations operations) { /** * Atomically increments by one the current value. - * + * * @return the previous value */ public double getAndIncrement() { @@ -205,7 +220,7 @@ public double getAndIncrement() { /** * Atomically decrements by one the current value. - * + * * @return the previous value */ public double getAndDecrement() { @@ -214,7 +229,7 @@ public double getAndDecrement() { /** * Atomically adds the given value to the current value. - * + * * @param delta the value to add * @return the previous value */ @@ -224,7 +239,7 @@ public double getAndAdd(final double delta) { /** * Atomically increments by one the current value. - * + * * @return the updated value */ public double incrementAndGet() { @@ -233,7 +248,7 @@ public double incrementAndGet() { /** * Atomically decrements by one the current value. - * + * * @return the updated value */ public double decrementAndGet() { @@ -242,7 +257,7 @@ public double decrementAndGet() { /** * Atomically adds the given value to the current value. - * + * * @param delta the value to add * @return the updated value */ @@ -252,7 +267,7 @@ public double addAndGet(double delta) { /** * Returns the String representation of the current value. - * + * * @return the String representation of the current value. */ public String toString() { diff --git a/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicInteger.java b/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicInteger.java index 224460aace..a2e44270f6 100644 --- a/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicInteger.java +++ b/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicInteger.java @@ -1,12 +1,12 @@ /* - * Copyright 2011-2014 the original author or authors. - * + * Copyright 2011-2016 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. @@ -20,6 +20,7 @@ import java.util.Date; import java.util.concurrent.TimeUnit; +import org.springframework.dao.DataRetrievalFailureException; import org.springframework.data.redis.connection.DataType; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.BoundKeyOperations; @@ -35,10 +36,12 @@ /** * Atomic integer backed by Redis. Uses Redis atomic increment/decrement and watch/multi/exec operations for CAS * operations. - * + * * @see java.util.concurrent.atomic.AtomicInteger * @author Costin Leau * @author Thomas Darimont + * @author Christoph Strobl + * @author Mark Paluch */ public class RedisAtomicInteger extends Number implements Serializable, BoundKeyOperations { @@ -50,7 +53,7 @@ public class RedisAtomicInteger extends Number implements Serializable, BoundKey /** * Constructs a new RedisAtomicInteger instance. Uses the value existing in Redis or 0 if none is found. - * + * * @param redisCounter redis counter * @param factory connection factory */ @@ -60,7 +63,7 @@ public RedisAtomicInteger(String redisCounter, RedisConnectionFactory factory) { /** * Constructs a new RedisAtomicInteger instance. - * + * * @param redisCounter the redis counter * @param factory the factory * @param initialValue the initial value @@ -71,7 +74,7 @@ public RedisAtomicInteger(String redisCounter, RedisConnectionFactory factory, i /** * Constructs a new RedisAtomicInteger instance. Uses the value existing in Redis or 0 if none is found. - * + * * @param redisCounter the redis counter * @param template the template * @see #RedisAtomicInteger(String, RedisConnectionFactory, int) @@ -85,7 +88,7 @@ public RedisAtomicInteger(String redisCounter, RedisOperations * with appropriate {@link RedisSerializer} for the key and value. As an alternative one could use the * {@link #RedisAtomicInteger(String, RedisConnectionFactory, Integer)} constructor which uses appropriate default * serializers. - * + * * @param redisCounter the redis counter * @param template the template * @param initialValue the initial value @@ -137,16 +140,22 @@ private RedisAtomicInteger(String redisCounter, RedisOperations /** * Get the current value. - * + * * @return the current value */ public int get() { - return Integer.valueOf(operations.get(key)); + + Integer value = operations.get(key); + if (value != null) { + return value.intValue(); + } + + throw new DataRetrievalFailureException(String.format("The key '%s' seems to no longer exist.", key)); } /** * Set to the given value. - * + * * @param newValue the new value */ public void set(int newValue) { @@ -155,17 +164,23 @@ public void set(int newValue) { /** * Set to the give value and return the old value. - * + * * @param newValue the new value * @return the previous value */ public int getAndSet(int newValue) { - return operations.getAndSet(key, newValue); + + Integer value = operations.getAndSet(key, newValue); + if (value != null) { + return value.intValue(); + } + + return 0; } /** * Atomically set the value to the given updated value if the current value == the expected value. - * + * * @param expect the expected value * @param update the new value * @return true if successful. False return indicates that the actual value was not equal to the expected value. @@ -194,7 +209,7 @@ public Boolean execute(RedisOperations operations) { /** * Atomically increment by one the current value. - * + * * @return the previous value */ public int getAndIncrement() { @@ -203,7 +218,7 @@ public int getAndIncrement() { /** * Atomically decrement by one the current value. - * + * * @return the previous value */ public int getAndDecrement() { @@ -212,7 +227,7 @@ public int getAndDecrement() { /** * Atomically add the given value to current value. - * + * * @param delta the value to add * @return the previous value */ @@ -222,7 +237,7 @@ public int getAndAdd(final int delta) { /** * Atomically increment by one the current value. - * + * * @return the updated value */ public int incrementAndGet() { @@ -231,7 +246,7 @@ public int incrementAndGet() { /** * Atomically decrement by one the current value. - * + * * @return the updated value */ public int decrementAndGet() { @@ -240,7 +255,7 @@ public int decrementAndGet() { /** * Atomically add the given value to current value. - * + * * @param delta the value to add * @return the updated value */ @@ -250,7 +265,7 @@ public int addAndGet(int delta) { /** * Returns the String representation of the current value. - * + * * @return the String representation of the current value. */ public String toString() { diff --git a/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicLong.java b/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicLong.java index a2e738f361..2f78d25a15 100644 --- a/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicLong.java +++ b/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicLong.java @@ -1,12 +1,12 @@ /* - * Copyright 2011-2014 the original author or authors. - * + * Copyright 2011-2016 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. @@ -20,6 +20,7 @@ import java.util.Date; import java.util.concurrent.TimeUnit; +import org.springframework.dao.DataRetrievalFailureException; import org.springframework.data.redis.connection.DataType; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.BoundKeyOperations; @@ -35,10 +36,12 @@ /** * Atomic long backed by Redis. Uses Redis atomic increment/decrement and watch/multi/exec operations for CAS * operations. - * + * * @see java.util.concurrent.atomic.AtomicLong * @author Costin Leau * @author Thomas Darimont + * @author Christoph Strobl + * @author Mark Paluch */ public class RedisAtomicLong extends Number implements Serializable, BoundKeyOperations { @@ -50,7 +53,7 @@ public class RedisAtomicLong extends Number implements Serializable, BoundKeyOpe /** * Constructs a new RedisAtomicLong instance. Uses the value existing in Redis or 0 if none is found. - * + * * @param redisCounter redis counter * @param factory connection factory */ @@ -60,7 +63,7 @@ public RedisAtomicLong(String redisCounter, RedisConnectionFactory factory) { /** * Constructs a new RedisAtomicLong instance. - * + * * @param redisCounter * @param factory * @param initialValue @@ -95,7 +98,7 @@ private RedisAtomicLong(String redisCounter, RedisConnectionFactory factory, Lon /** * Constructs a new RedisAtomicLong instance. Uses the value existing in Redis or 0 if none is found. - * + * * @param redisCounter the redis counter * @param template the template * @see #RedisAtomicLong(String, RedisConnectionFactory, long) @@ -114,7 +117,7 @@ public RedisAtomicLong(String redisCounter, RedisOperations templa * As an alternative one could use the {@link #RedisAtomicLong(String, RedisConnectionFactory, Long)} constructor * which uses appropriate default serializers, in this case {@link StringRedisSerializer} for the key and * {@link GenericToStringSerializer} for the value. - * + * * @param redisCounter the redis counter * @param template the template * @param initialValue the initial value @@ -145,16 +148,22 @@ private RedisAtomicLong(String redisCounter, RedisOperations templ /** * Gets the current value. - * + * * @return the current value */ public long get() { - return operations.get(key); + + Long value = operations.get(key); + if (value != null) { + return value.longValue(); + } + + throw new DataRetrievalFailureException(String.format("The key '%s' seems to no longer exist.", key)); } /** * Sets to the given value. - * + * * @param newValue the new value */ public void set(long newValue) { @@ -163,17 +172,23 @@ public void set(long newValue) { /** * Atomically sets to the given value and returns the old value. - * + * * @param newValue the new value * @return the previous value */ public long getAndSet(long newValue) { - return operations.getAndSet(key, newValue); + + Long value = operations.getAndSet(key, newValue); + if (value != null) { + return value.longValue(); + } + + return 0; } /** * Atomically sets the value to the given updated value if the current value {@code ==} the expected value. - * + * * @param expect the expected value * @param update the new value * @return true if successful. False return indicates that the actual value was not equal to the expected value. @@ -202,7 +217,7 @@ public Boolean execute(RedisOperations operations) { /** * Atomically increments by one the current value. - * + * * @return the previous value */ public long getAndIncrement() { @@ -211,7 +226,7 @@ public long getAndIncrement() { /** * Atomically decrements by one the current value. - * + * * @return the previous value */ public long getAndDecrement() { @@ -220,7 +235,7 @@ public long getAndDecrement() { /** * Atomically adds the given value to the current value. - * + * * @param delta the value to add * @return the previous value */ @@ -230,7 +245,7 @@ public long getAndAdd(final long delta) { /** * Atomically increments by one the current value. - * + * * @return the updated value */ public long incrementAndGet() { @@ -239,7 +254,7 @@ public long incrementAndGet() { /** * Atomically decrements by one the current value. - * + * * @return the updated value */ public long decrementAndGet() { @@ -248,7 +263,7 @@ public long decrementAndGet() { /** * Atomically adds the given value to the current value. - * + * * @param delta the value to add * @return the updated value */ @@ -258,7 +273,7 @@ public long addAndGet(long delta) { /** * Returns the String representation of the current value. - * + * * @return the String representation of the current value. */ public String toString() { diff --git a/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicDoubleTests.java b/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicDoubleTests.java index 09d1bf7cae..b62e8d7eb8 100644 --- a/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicDoubleTests.java +++ b/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicDoubleTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 the original author or authors. + * Copyright 2013-2016 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. @@ -30,6 +30,7 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; +import org.springframework.dao.DataRetrievalFailureException; import org.springframework.data.redis.ConnectionFactoryTracker; import org.springframework.data.redis.RedisTestProfileValueSource; import org.springframework.data.redis.connection.ConnectionUtils; @@ -41,20 +42,30 @@ /** * Integration test of {@link RedisAtomicDouble} - * + * * @author Jennifer Hickey * @author Thomas Darimont + * @author Christoph Strobl + * @author Mark Paluch */ @RunWith(Parameterized.class) public class RedisAtomicDoubleTests extends AbstractRedisAtomicsTests { private RedisAtomicDouble doubleCounter; - private RedisConnectionFactory factory; + private RedisTemplate template; public RedisAtomicDoubleTests(RedisConnectionFactory factory) { - doubleCounter = new RedisAtomicDouble(getClass().getSimpleName() + ":double", factory); + + this.doubleCounter = new RedisAtomicDouble(getClass().getSimpleName() + ":double", factory); this.factory = factory; + + this.template = new RedisTemplate(); + this.template.setConnectionFactory(factory); + this.template.setKeySerializer(new StringRedisSerializer()); + this.template.setValueSerializer(new GenericToStringSerializer(Double.class)); + this.template.afterPropertiesSet(); + ConnectionFactoryTracker.add(factory); } @@ -199,15 +210,42 @@ public void testShouldThrowExceptionIfRedisAtomicDoubleIsUsedWithRedisTemplateAn @Test public void testShouldBeAbleToUseRedisAtomicDoubleWithProperlyConfiguredRedisTemplate() { - RedisTemplate template = new RedisTemplate(); - template.setConnectionFactory(factory); - template.setKeySerializer(new StringRedisSerializer()); - template.setValueSerializer(new GenericToStringSerializer(Double.class)); - template.afterPropertiesSet(); - RedisAtomicDouble ral = new RedisAtomicDouble("DATAREDIS-317.atomicDouble", template); ral.set(32.23); assertThat(ral.get(), is(32.23)); } + + /** + * @see DATAREDIS-469 + */ + @Test + public void getThrowsExceptionWhenKeyHasBeenRemoved() { + + expectedException.expect(DataRetrievalFailureException.class); + expectedException.expectMessage("'test' seems to no longer exist"); + + // setup double + RedisAtomicDouble test = new RedisAtomicDouble("test", factory, 1); + assertThat(test.get(), equalTo(1D)); // this passes + + template.delete("test"); + + test.get(); + } + + /** + * @see DATAREDIS-469 + */ + @Test + public void getAndSetReturnsZeroWhenKeyHasBeenRemoved() { + + // setup double + RedisAtomicDouble test = new RedisAtomicDouble("test", factory, 1); + assertThat(test.get(), equalTo(1D)); // this passes + + template.delete("test"); + + assertThat(test.getAndSet(2), is(0D)); + } } diff --git a/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicIntegerTests.java b/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicIntegerTests.java index bd28071ebf..1f7e3cff7d 100644 --- a/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicIntegerTests.java +++ b/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicIntegerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 the original author or authors. + * Copyright 2013-2016 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. @@ -30,6 +30,7 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; +import org.springframework.dao.DataRetrievalFailureException; import org.springframework.data.redis.ConnectionFactoryTracker; import org.springframework.data.redis.connection.ConnectionUtils; import org.springframework.data.redis.connection.RedisConnection; @@ -40,20 +41,31 @@ /** * Integration test of {@link RedisAtomicInteger} - * + * * @author Costin Leau * @author Jennifer Hickey * @author Thomas Darimont + * @author Christoph Strobl + * @author Mark Paluch */ @RunWith(Parameterized.class) public class RedisAtomicIntegerTests extends AbstractRedisAtomicsTests { private RedisAtomicInteger intCounter; private RedisConnectionFactory factory; + private RedisTemplate template; public RedisAtomicIntegerTests(RedisConnectionFactory factory) { - intCounter = new RedisAtomicInteger(getClass().getSimpleName() + ":int", factory); + + this.intCounter = new RedisAtomicInteger(getClass().getSimpleName() + ":int", factory); this.factory = factory; + + this.template = new RedisTemplate(); + this.template.setConnectionFactory(factory); + this.template.setKeySerializer(new StringRedisSerializer()); + this.template.setValueSerializer(new GenericToStringSerializer(Integer.class)); + this.template.afterPropertiesSet(); + ConnectionFactoryTracker.add(factory); } @@ -75,7 +87,7 @@ public static Collection testParams() { } @Test - public void testCheckAndSet() throws Exception { + public void testCheckAndSet() { // Txs not supported in Jredis assumeTrue(!ConnectionUtils.isJredis(factory)); intCounter.set(0); @@ -85,7 +97,7 @@ public void testCheckAndSet() throws Exception { } @Test - public void testIncrementAndGet() throws Exception { + public void testIncrementAndGet() { intCounter.set(0); assertEquals(1, intCounter.incrementAndGet()); } @@ -98,11 +110,55 @@ public void testAddAndGet() throws Exception { } @Test - public void testDecrementAndGet() throws Exception { + public void testDecrementAndGet() { intCounter.set(1); assertEquals(0, intCounter.decrementAndGet()); } + /** + * @see DATAREDIS-469 + */ + @Test + public void testGetAndIncrement() { + + intCounter.set(1); + assertEquals(1, intCounter.getAndIncrement()); + assertEquals(2, intCounter.get()); + } + + /** + * @see DATAREDIS-469 + */ + @Test + public void testGetAndAdd() { + + intCounter.set(1); + assertEquals(1, intCounter.getAndAdd(5)); + assertEquals(6, intCounter.get()); + } + + /** + * @see DATAREDIS-469 + */ + @Test + public void testGetAndDecrement() { + + intCounter.set(1); + assertEquals(1, intCounter.getAndDecrement()); + assertEquals(0, intCounter.get()); + } + + /** + * @see DATAREDIS-469 + */ + @Test + public void testGetAndSet() { + + intCounter.set(1); + assertEquals(1, intCounter.getAndSet(5)); + assertEquals(5, intCounter.get()); + } + @Test @Ignore("DATAREDIS-108 Test is intermittently failing") public void testCompareSet() throws Exception { @@ -169,15 +225,42 @@ public void testShouldThrowExceptionIfRedisAtomicIntegerIsUsedWithRedisTemplateA @Test public void testShouldBeAbleToUseRedisAtomicIntegerWithProperlyConfiguredRedisTemplate() { - RedisTemplate template = new RedisTemplate(); - template.setConnectionFactory(factory); - template.setKeySerializer(new StringRedisSerializer()); - template.setValueSerializer(new GenericToStringSerializer(Integer.class)); - template.afterPropertiesSet(); - RedisAtomicInteger ral = new RedisAtomicInteger("DATAREDIS-317.atomicInteger", template); ral.set(32); assertThat(ral.get(), is(32)); } + + /** + * @see DATAREDIS-469 + */ + @Test + public void getThrowsExceptionWhenKeyHasBeenRemoved() { + + expectedException.expect(DataRetrievalFailureException.class); + expectedException.expectMessage("'test' seems to no longer exist"); + + // setup integer + RedisAtomicInteger test = new RedisAtomicInteger("test", factory, 1); + assertThat(test.get(), equalTo(1)); // this passes + + template.delete("test"); + + test.get(); + } + + /** + * @see DATAREDIS-469 + */ + @Test + public void getAndSetReturnsZeroWhenKeyHasBeenRemoved() { + + // setup integer + RedisAtomicInteger test = new RedisAtomicInteger("test", factory, 1); + assertThat(test.get(), equalTo(1)); // this passes + + template.delete("test"); + + assertThat(test.getAndSet(2), is(0)); + } } diff --git a/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicLongTests.java b/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicLongTests.java index aeee29e86d..685011b16a 100644 --- a/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicLongTests.java +++ b/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicLongTests.java @@ -27,6 +27,7 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; +import org.springframework.dao.DataRetrievalFailureException; import org.springframework.data.redis.ConnectionFactoryTracker; import org.springframework.data.redis.connection.ConnectionUtils; import org.springframework.data.redis.connection.RedisConnection; @@ -37,20 +38,30 @@ /** * Integration test of {@link RedisAtomicLong} - * + * * @author Costin Leau * @author Jennifer Hickey * @author Thomas Darimont + * @author Christoph Strobl */ @RunWith(Parameterized.class) public class RedisAtomicLongTests extends AbstractRedisAtomicsTests { private RedisAtomicLong longCounter; private RedisConnectionFactory factory; + private RedisTemplate template; public RedisAtomicLongTests(RedisConnectionFactory factory) { - longCounter = new RedisAtomicLong(getClass().getSimpleName() + ":long", factory); + + this.longCounter = new RedisAtomicLong(getClass().getSimpleName() + ":long", factory); this.factory = factory; + + this.template = new RedisTemplate(); + this.template.setConnectionFactory(factory); + this.template.setKeySerializer(new StringRedisSerializer()); + this.template.setValueSerializer(new GenericToStringSerializer(Long.class)); + this.template.afterPropertiesSet(); + ConnectionFactoryTracker.add(factory); } @@ -100,8 +111,53 @@ public void testDecrementAndGet() throws Exception { assertEquals(0, longCounter.decrementAndGet()); } + /** + * @see DATAREDIS-469 + */ + @Test + public void testGetAndIncrement() { + + longCounter.set(1); + assertEquals(1, longCounter.getAndIncrement()); + assertEquals(2, longCounter.get()); + } + + /** + * @see DATAREDIS-469 + */ + @Test + public void testGetAndAdd() { + + longCounter.set(1); + assertEquals(1, longCounter.getAndAdd(5)); + assertEquals(6, longCounter.get()); + } + + /** + * @see DATAREDIS-469 + */ + @Test + public void testGetAndDecrement() { + + longCounter.set(1); + assertEquals(1, longCounter.getAndDecrement()); + assertEquals(0, longCounter.get()); + } + + /** + * @see DATAREDIS-469 + */ + @Test + public void testGetAndSet() { + + longCounter.set(1); + assertEquals(1, longCounter.getAndSet(5)); + assertEquals(5, longCounter.get()); + } + @Test public void testGetExistingValue() throws Exception { + longCounter.set(5); RedisAtomicLong keyCopy = new RedisAtomicLong(longCounter.getKey(), factory); assertEquals(longCounter.get(), keyCopy.get()); @@ -151,4 +207,37 @@ public void testShouldBeAbleToUseRedisAtomicLongWithProperlyConfiguredRedisTempl assertThat(ral.get(), is(32L)); } + + /** + * @see DATAREDIS-469 + */ + @Test + public void getThrowsExceptionWhenKeyHasBeenRemoved() { + + expectedException.expect(DataRetrievalFailureException.class); + expectedException.expectMessage("'test' seems to no longer exist"); + + // setup long + RedisAtomicLong test = new RedisAtomicLong("test", factory, 1); + assertThat(test.get(), equalTo(1L)); // this passes + + template.delete("test"); + + test.get(); + } + + /** + * @see DATAREDIS-469 + */ + @Test + public void getAndSetReturnsZeroWhenKeyHasBeenRemoved() { + + // setup long + RedisAtomicLong test = new RedisAtomicLong("test", factory, 1); + assertThat(test.get(), equalTo(1L)); // this passes + + template.delete("test"); + + assertThat(test.getAndSet(2), is(0L)); + } }