/* * Copyright 2011-2017 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. */ package org.springframework.data.redis.support.collections; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import static org.junit.Assume.*; import static org.springframework.data.redis.matcher.RedisTestMatchers.*; import java.io.IOException; import java.util.Arrays; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Set; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.springframework.data.redis.DoubleAsStringObjectFactory; import org.springframework.data.redis.DoubleObjectFactory; import org.springframework.data.redis.LongAsStringObjectFactory; import org.springframework.data.redis.LongObjectFactory; import org.springframework.data.redis.ObjectFactory; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisZSetCommands; import org.springframework.data.redis.core.BoundZSetOperations; import org.springframework.data.redis.core.Cursor; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ZSetOperations.TypedTuple; import org.springframework.data.redis.test.util.MinimumRedisVersionRule; import org.springframework.data.redis.test.util.RedisClientRule; import org.springframework.data.redis.test.util.RedisDriver; import org.springframework.data.redis.test.util.WithRedisDriver; import org.springframework.test.annotation.IfProfileValue; /** * Integration test for Redis ZSet. * * @author Costin Leau * @author Jennifer Hickey * @author Thomas Darimont * @author Mark Paluch */ public abstract class AbstractRedisZSetTest<T> extends AbstractRedisCollectionTests<T> { public @Rule RedisClientRule clientRule = new RedisClientRule() { public RedisConnectionFactory getConnectionFactory() { return template.getConnectionFactory(); } }; public @Rule MinimumRedisVersionRule versionRule = new MinimumRedisVersionRule(); protected RedisZSet<T> zSet; /** * Constructs a new <code>AbstractRedisZSetTest</code> instance. * * @param factory * @param template */ @SuppressWarnings("rawtypes") public AbstractRedisZSetTest(ObjectFactory<T> factory, RedisTemplate template) { super(factory, template); } @SuppressWarnings("unchecked") @Before public void setUp() throws Exception { super.setUp(); zSet = (RedisZSet<T>) collection; } @Test public void testAddWithScore() { T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 3); zSet.add(t2, 4); zSet.add(t3, 5); Iterator<T> iterator = zSet.iterator(); assertThat(iterator.next(), isEqual(t1)); assertThat(iterator.next(), isEqual(t2)); assertThat(iterator.next(), isEqual(t3)); assertFalse(iterator.hasNext()); } @Test public void testAdd() { T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1); zSet.add(t2); zSet.add(t3); Double d = new Double("1"); assertEquals(d, zSet.score(t1)); assertEquals(d, zSet.score(t2)); assertEquals(d, zSet.score(t3)); } @Test public void testFirst() { T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 3); zSet.add(t2, 4); zSet.add(t3, 5); assertEquals(3, zSet.size()); assertThat(zSet.first(), isEqual(t1)); } @Test(expected = NoSuchElementException.class) public void testFirstException() throws Exception { zSet.first(); } @Test public void testLast() { T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 3); zSet.add(t2, 4); zSet.add(t3, 5); assertEquals(3, zSet.size()); assertThat(zSet.last(), isEqual(t3)); } @Test(expected = NoSuchElementException.class) public void testLastException() throws Exception { zSet.last(); } @Test public void testRank() { T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 3); zSet.add(t2, 4); zSet.add(t3, 5); assertEquals(Long.valueOf(0), zSet.rank(t1)); assertEquals(Long.valueOf(1), zSet.rank(t2)); assertEquals(Long.valueOf(2), zSet.rank(t3)); assertNull(zSet.rank(getT())); // assertNull(); } @Test public void testReverseRank() { T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 3); zSet.add(t2, 4); zSet.add(t3, 5); assertEquals(Long.valueOf(0), zSet.reverseRank(t3)); assertEquals(Long.valueOf(1), zSet.reverseRank(t2)); assertEquals(Long.valueOf(2), zSet.reverseRank(t1)); assertNull(zSet.rank(getT())); } @Test public void testScore() { T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 3); zSet.add(t2, 4); zSet.add(t3, 5); assertNull(zSet.score(getT())); assertEquals(Double.valueOf(3), zSet.score(t1)); assertEquals(Double.valueOf(4), zSet.score(t2)); assertEquals(Double.valueOf(5), zSet.score(t3)); } @Test public void testDefaultScore() { assertEquals(1, zSet.getDefaultScore(), 0); } @SuppressWarnings("unchecked") private RedisZSet<T> createZSetFor(String key) { return new DefaultRedisZSet<T>((BoundZSetOperations<String, T>) zSet.getOperations().boundZSetOps(key)); } @SuppressWarnings("unchecked") @Test public void testIntersectAndStore() { RedisZSet<T> interSet1 = createZSetFor("test:zset:inter1"); RedisZSet<T> interSet2 = createZSetFor("test:zset:inter"); T t1 = getT(); T t2 = getT(); T t3 = getT(); T t4 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); interSet1.add(t2, 2); interSet1.add(t4, 3); interSet2.add(t2, 2); interSet2.add(t3, 3); String resultName = "test:zset:inter:result:1"; RedisZSet<T> inter = zSet.intersectAndStore(Arrays.asList(interSet1, interSet2), resultName); assertEquals(1, inter.size()); assertThat(inter, hasItem(t2)); assertEquals(Double.valueOf(6), inter.score(t2)); assertEquals(resultName, inter.getKey()); } @Test public void testRange() { T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); Set<T> range = zSet.range(1, 2); assertEquals(2, range.size()); Iterator<T> iterator = range.iterator(); assertThat(iterator.next(), isEqual(t2)); assertThat(iterator.next(), isEqual(t3)); } @Test public void testRangeWithScores() { T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); Set<TypedTuple<T>> range = zSet.rangeWithScores(1, 2); assertEquals(2, range.size()); Iterator<TypedTuple<T>> iterator = range.iterator(); TypedTuple<T> tuple1 = iterator.next(); assertThat(tuple1.getValue(), isEqual(t2)); assertThat(tuple1.getScore(), isEqual(Double.valueOf(2))); TypedTuple<T> tuple2 = iterator.next(); assertThat(tuple2.getValue(), isEqual(t3)); assertThat(tuple2.getScore(), isEqual(Double.valueOf(3))); } @Test public void testReverseRange() { T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); Set<T> range = zSet.reverseRange(1, 2); assertEquals(2, range.size()); Iterator<T> iterator = range.iterator(); assertThat(iterator.next(), isEqual(t2)); assertThat(iterator.next(), isEqual(t1)); } @Test public void testReverseRangeWithScores() { T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); Set<TypedTuple<T>> range = zSet.reverseRangeWithScores(1, 2); assertEquals(2, range.size()); Iterator<TypedTuple<T>> iterator = range.iterator(); TypedTuple<T> tuple1 = iterator.next(); assertThat(tuple1.getValue(), isEqual(t2)); assertThat(tuple1.getScore(), isEqual(Double.valueOf(2))); TypedTuple<T> tuple2 = iterator.next(); assertThat(tuple2.getValue(), isEqual(t1)); assertThat(tuple2.getScore(), isEqual(Double.valueOf(1))); } @Test // DATAREDIS-407 public void testRangeByLexUnbounded() { assumeThat(factory, anyOf(instanceOf(DoubleObjectFactory.class), instanceOf(DoubleAsStringObjectFactory.class), instanceOf(LongAsStringObjectFactory.class), instanceOf(LongObjectFactory.class))); T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); Set<T> tuples = zSet.rangeByLex(RedisZSetCommands.Range.unbounded()); assertEquals(3, tuples.size()); T tuple = tuples.iterator().next(); assertThat(tuple, isEqual(t1)); } @Test // DATAREDIS-407 public void testRangeByLexBounded() { assumeThat(factory, anyOf(instanceOf(DoubleObjectFactory.class), instanceOf(DoubleAsStringObjectFactory.class), instanceOf(LongAsStringObjectFactory.class), instanceOf(LongObjectFactory.class))); T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); Set<T> tuples = zSet.rangeByLex(RedisZSetCommands.Range.range().gt(t1).lt(t3)); assertEquals(1, tuples.size()); T tuple = tuples.iterator().next(); assertThat(tuple, isEqual(t2)); } @Test // DATAREDIS-407 public void testRangeByLexUnboundedWithLimit() { assumeThat(factory, anyOf(instanceOf(DoubleObjectFactory.class), instanceOf(DoubleAsStringObjectFactory.class), instanceOf(LongAsStringObjectFactory.class), instanceOf(LongObjectFactory.class))); T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); Set<T> tuples = zSet.rangeByLex(RedisZSetCommands.Range.unbounded(), RedisZSetCommands.Limit.limit().count(1).offset(1)); assertEquals(1, tuples.size()); T tuple = tuples.iterator().next(); assertThat(tuple, isEqual(t2)); } @Test // DATAREDIS-407 public void testRangeByLexBoundedWithLimit() { assumeThat(factory, anyOf(instanceOf(DoubleObjectFactory.class), instanceOf(DoubleAsStringObjectFactory.class), instanceOf(LongAsStringObjectFactory.class), instanceOf(LongObjectFactory.class))); T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); Set<T> tuples = zSet.rangeByLex(RedisZSetCommands.Range.range().gte(t1), RedisZSetCommands.Limit.limit().count(1).offset(1)); assertEquals(1, tuples.size()); T tuple = tuples.iterator().next(); assertThat(tuple, isEqual(t2)); } @Test public void testReverseRangeByScore() { T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); Set<T> range = zSet.reverseRangeByScore(1.5, 3.5); assertEquals(2, range.size()); Iterator<T> iterator = range.iterator(); assertThat(iterator.next(), isEqual(t3)); assertThat(iterator.next(), isEqual(t2)); } @Test public void testReverseRangeByScoreWithScores() { T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); Set<TypedTuple<T>> range = zSet.reverseRangeByScoreWithScores(1.5, 3.5); assertEquals(2, range.size()); Iterator<TypedTuple<T>> iterator = range.iterator(); TypedTuple<T> tuple1 = iterator.next(); assertThat(tuple1.getValue(), isEqual(t3)); assertThat(tuple1.getScore(), isEqual(Double.valueOf(3))); TypedTuple<T> tuple2 = iterator.next(); assertThat(tuple2.getValue(), isEqual(t2)); assertThat(tuple2.getScore(), isEqual(Double.valueOf(2))); } @SuppressWarnings("unchecked") @Test public void testRangeByScore() { T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); Set<T> range = zSet.rangeByScore(1.5, 3.5); assertEquals(2, range.size()); assertThat(range, hasItems(t2, t3)); Iterator<T> iterator = range.iterator(); assertThat(iterator.next(), isEqual(t2)); assertThat(iterator.next(), isEqual(t3)); } @Test public void testRangeByScoreWithScores() { T t1 = getT(); T t2 = getT(); T t3 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); Set<TypedTuple<T>> range = zSet.rangeByScoreWithScores(1.5, 3.5); assertEquals(2, range.size()); Iterator<TypedTuple<T>> iterator = range.iterator(); TypedTuple<T> tuple1 = iterator.next(); assertThat(tuple1.getValue(), isEqual(t2)); assertThat(tuple1.getScore(), isEqual(Double.valueOf(2))); TypedTuple<T> tuple2 = iterator.next(); assertThat(tuple2.getValue(), isEqual(t3)); assertThat(tuple2.getScore(), isEqual(Double.valueOf(3))); } @Test public void testRemove() { T t1 = getT(); T t2 = getT(); T t3 = getT(); T t4 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); zSet.add(t4, 4); zSet.remove(1, 2); assertEquals(2, zSet.size()); Iterator<T> iterator = zSet.iterator(); assertThat(iterator.next(), isEqual(t1)); assertThat(iterator.next(), isEqual(t4)); } @Test public void testRemoveByScore() { T t1 = getT(); T t2 = getT(); T t3 = getT(); T t4 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); zSet.add(t4, 4); zSet.removeByScore(1.5, 2.5); assertEquals(3, zSet.size()); Iterator<T> iterator = zSet.iterator(); assertThat(iterator.next(), isEqual(t1)); assertThat(iterator.next(), isEqual(t3)); assertThat(iterator.next(), isEqual(t4)); } @SuppressWarnings("unchecked") @Test public void testUnionAndStore() { RedisZSet<T> unionSet1 = createZSetFor("test:zset:union1"); RedisZSet<T> unionSet2 = createZSetFor("test:zset:union2"); T t1 = getT(); T t2 = getT(); T t3 = getT(); T t4 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); unionSet1.add(t2, 2); unionSet1.add(t4, 5); unionSet2.add(t3, 6); String resultName = "test:zset:union:result:1"; RedisZSet<T> union = zSet.unionAndStore(Arrays.asList(unionSet1, unionSet2), resultName); assertEquals(4, union.size()); assertThat(union, hasItems(t1, t2, t3, t4)); assertEquals(resultName, union.getKey()); assertEquals(Double.valueOf(1), union.score(t1)); assertEquals(Double.valueOf(4), union.score(t2)); assertEquals(Double.valueOf(6), union.score(t3)); assertEquals(Double.valueOf(5), union.score(t4)); } @Test public void testIterator() { T t1 = getT(); T t2 = getT(); T t3 = getT(); T t4 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); zSet.add(t4, 4); Iterator<T> iterator = collection.iterator(); assertThat(iterator.next(), isEqual(t1)); assertThat(iterator.next(), isEqual(t2)); assertThat(iterator.next(), isEqual(t3)); assertThat(iterator.next(), isEqual(t4)); assertFalse(iterator.hasNext()); } @Test public void testToArray() { T t1 = getT(); T t2 = getT(); T t3 = getT(); T t4 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); zSet.add(t4, 4); Object[] array = collection.toArray(); assertArrayEquals(new Object[] { t1, t2, t3, t4 }, array); } @Test public void testToArrayWithGenerics() { T t1 = getT(); T t2 = getT(); T t3 = getT(); T t4 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); zSet.add(t4, 4); Object[] array = collection.toArray(new Object[zSet.size()]); assertArrayEquals(new Object[] { t1, t2, t3, t4 }, array); } @IfProfileValue(name = "redisVersion", value = "2.8+") @Test // DATAREDIS-314 @WithRedisDriver({ RedisDriver.JEDIS, RedisDriver.LETTUCE }) public void testScanWorksCorrectly() throws IOException { T t1 = getT(); T t2 = getT(); T t3 = getT(); T t4 = getT(); zSet.add(t1, 1); zSet.add(t2, 2); zSet.add(t3, 3); zSet.add(t4, 4); Cursor<T> cursor = (Cursor<T>) zSet.scan(); while (cursor.hasNext()) { assertThat(cursor.next(), anyOf(equalTo(t1), equalTo(t2), equalTo(t3), equalTo(t4))); } cursor.close(); } }