From f7699b19420bc2171c35359ba975e2a211e1a728 Mon Sep 17 00:00:00 2001 From: Gabriel Erzse Date: Wed, 13 Mar 2024 16:04:07 +0200 Subject: [PATCH] Add pipelined tests for sorted sets (#3771) Co-authored-by: Gabriel Erzse --- .../SortedSetPipelineCommandsTest.java | 1891 +++++++++++++++++ 1 file changed, 1891 insertions(+) create mode 100644 src/test/java/redis/clients/jedis/commands/unified/pipeline/SortedSetPipelineCommandsTest.java diff --git a/src/test/java/redis/clients/jedis/commands/unified/pipeline/SortedSetPipelineCommandsTest.java b/src/test/java/redis/clients/jedis/commands/unified/pipeline/SortedSetPipelineCommandsTest.java new file mode 100644 index 0000000000..12a2282e27 --- /dev/null +++ b/src/test/java/redis/clients/jedis/commands/unified/pipeline/SortedSetPipelineCommandsTest.java @@ -0,0 +1,1891 @@ +package redis.clients.jedis.commands.unified.pipeline; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.closeTo; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.in; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertEquals; +import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START; +import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START_BINARY; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import redis.clients.jedis.Response; +import redis.clients.jedis.args.SortedSetOption; +import redis.clients.jedis.commands.unified.pooled.PooledCommandsTestHelper; +import redis.clients.jedis.params.ScanParams; +import redis.clients.jedis.params.ZAddParams; +import redis.clients.jedis.params.ZIncrByParams; +import redis.clients.jedis.params.ZParams; +import redis.clients.jedis.params.ZRangeParams; +import redis.clients.jedis.resps.ScanResult; +import redis.clients.jedis.resps.Tuple; +import redis.clients.jedis.util.AssertUtil; +import redis.clients.jedis.util.KeyValue; +import redis.clients.jedis.util.SafeEncoder; + +public class SortedSetPipelineCommandsTest extends PipelineCommandsTestBase { + final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 }; + final byte[] bbar = { 0x05, 0x06, 0x07, 0x08 }; + final byte[] bcar = { 0x09, 0x0A, 0x0B, 0x0C }; + final byte[] ba = { 0x0A }; + final byte[] bb = { 0x0B }; + final byte[] bc = { 0x0C }; + final byte[] bInclusiveB = { 0x5B, 0x0B }; + final byte[] bExclusiveC = { 0x28, 0x0C }; + final byte[] bLexMinusInf = { 0x2D }; + final byte[] bLexPlusInf = { 0x2B }; + + final byte[] bbar1 = { 0x05, 0x06, 0x07, 0x08, 0x0A }; + final byte[] bbar2 = { 0x05, 0x06, 0x07, 0x08, 0x0B }; + final byte[] bbar3 = { 0x05, 0x06, 0x07, 0x08, 0x0C }; + final byte[] bbarstar = { 0x05, 0x06, 0x07, 0x08, '*' }; + + @BeforeClass + public static void prepare() throws InterruptedException { + jedis = PooledCommandsTestHelper.getPooled(); + } + + @AfterClass + public static void cleanUp() { + jedis.close(); + } + + @Test + public void zadd() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 10d, "b"); + pipe.zadd("foo", 0.1d, "c"); + pipe.zadd("foo", 2d, "a"); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + assertThat(pipe.syncAndReturnAll(), contains( + 1L, + 1L, + 1L, + 0L, + 1L, + 1L, + 1L, + 0L + )); + } + + @Test + public void zaddWithParams() { + pipe.del("foo"); + + // xx: never add new member + pipe.zadd("foo", 1d, "a", ZAddParams.zAddParams().xx()); + + pipe.zadd("foo", 1d, "a"); + + // nx: never update current member + pipe.zadd("foo", 2d, "a", ZAddParams.zAddParams().nx()); + pipe.zscore("foo", "a"); + + Map scoreMembers = new HashMap(); + scoreMembers.put("a", 2d); + scoreMembers.put("b", 1d); + // ch: return count of members not only added, but also updated + pipe.zadd("foo", scoreMembers, ZAddParams.zAddParams().ch()); + + assertThat(pipe.syncAndReturnAll(), contains( + 0L, + 0L, + 1L, + 0L, + 1d, + 2L + )); + + // lt: only update existing elements if the new score is less than the current score. + pipe.zadd("foo", 3d, "a", ZAddParams.zAddParams().lt()); + pipe.zscore("foo", "a"); + pipe.zadd("foo", 1d, "a", ZAddParams.zAddParams().lt()); + pipe.zscore("foo", "a"); + + assertThat(pipe.syncAndReturnAll(), contains( + 0L, + 2d, + 0L, + 1d + )); + + // gt: only update existing elements if the new score is greater than the current score. + pipe.zadd("foo", 0d, "b", ZAddParams.zAddParams().gt()); + pipe.zscore("foo", "b"); + pipe.zadd("foo", 2d, "b", ZAddParams.zAddParams().gt()); + pipe.zscore("foo", "b"); + + assertThat(pipe.syncAndReturnAll(), contains( + 0L, + 1d, + 0L, + 2d + )); + + // incr: don't update already existing elements. + pipe.zaddIncr("foo", 1d, "b", ZAddParams.zAddParams().nx()); + pipe.zscore("foo", "b"); + // incr: update elements that already exist. + pipe.zaddIncr("foo", 1d, "b", ZAddParams.zAddParams().xx()); + pipe.zscore("foo", "b"); + + assertThat(pipe.syncAndReturnAll(), contains( + nullValue(), + equalTo(2d), + equalTo(3d), + equalTo(3d) + )); + + // binary + pipe.del(bfoo); + + // xx: never add new member + pipe.zadd(bfoo, 1d, ba, ZAddParams.zAddParams().xx()); + + pipe.zadd(bfoo, 1d, ba); + + // nx: never update current member + pipe.zadd(bfoo, 2d, ba, ZAddParams.zAddParams().nx()); + pipe.zscore(bfoo, ba); + + Map binaryScoreMembers = new HashMap<>(); + binaryScoreMembers.put(ba, 2d); + binaryScoreMembers.put(bb, 1d); + // ch: return count of members not only added, but also updated + pipe.zadd(bfoo, binaryScoreMembers, ZAddParams.zAddParams().ch()); + + assertThat(pipe.syncAndReturnAll(), contains( + 0L, + 0L, + 1L, + 0L, + 1d, + 2L + )); + + // lt: only update existing elements if the new score is less than the current score. + pipe.zadd(bfoo, 3d, ba, ZAddParams.zAddParams().lt()); + pipe.zscore(bfoo, ba); + pipe.zadd(bfoo, 1d, ba, ZAddParams.zAddParams().lt()); + pipe.zscore(bfoo, ba); + + assertThat(pipe.syncAndReturnAll(), contains( + 0L, + 2d, + 0L, + 1d + )); + + // gt: only update existing elements if the new score is greater than the current score. + pipe.zadd(bfoo, 0d, bb, ZAddParams.zAddParams().gt()); + pipe.zscore(bfoo, bb); + pipe.zadd(bfoo, 2d, bb, ZAddParams.zAddParams().gt()); + pipe.zscore(bfoo, bb); + + assertThat(pipe.syncAndReturnAll(), contains( + 0L, + 1d, + 0L, + 2d + )); + + // incr: don't update already existing elements. + pipe.zaddIncr(bfoo, 1d, bb, ZAddParams.zAddParams().nx()); + pipe.zscore(bfoo, bb); + // incr: update elements that already exist. + pipe.zaddIncr(bfoo, 1d, bb, ZAddParams.zAddParams().xx()); + pipe.zscore(bfoo, bb); + + assertThat(pipe.syncAndReturnAll(), contains( + nullValue(), + equalTo(2d), + equalTo(3d), + equalTo(3d) + )); + } + + @Test + public void zrange() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 10d, "b"); + pipe.zadd("foo", 0.1d, "c"); + pipe.zadd("foo", 2d, "a"); + + Response> range1 = pipe.zrange("foo", 0, 1); + Response> range2 = pipe.zrange("foo", 0, 100); + + pipe.sync(); + + assertThat(range1.get(), contains("c", "a")); + assertThat(range2.get(), contains("c", "a", "b")); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + Response> brange1 = pipe.zrange(bfoo, 0, 1); + Response> brange2 = pipe.zrange(bfoo, 0, 100); + + pipe.sync(); + + assertThat(brange1.get(), contains(bc, ba)); + assertThat(brange2.get(), contains(bc, ba, bb)); + } + + @Test + public void zrangeByLex() { + pipe.zadd("foo", 1, "aa"); + pipe.zadd("foo", 1, "c"); + pipe.zadd("foo", 1, "bb"); + pipe.zadd("foo", 1, "d"); + + // exclusive aa ~ inclusive c + Response> range1 = pipe.zrangeByLex("foo", "(aa", "[c"); + + // with LIMIT + Response> range2 = pipe.zrangeByLex("foo", "-", "+", 1, 2); + + pipe.sync(); + + assertThat(range1.get(), contains("bb", "c")); + assertThat(range2.get(), contains("bb", "c")); + } + + @Test + public void zrangeByLexBinary() { + pipe.zadd(bfoo, 1, ba); + pipe.zadd(bfoo, 1, bc); + pipe.zadd(bfoo, 1, bb); + + Response> brange1 = pipe.zrangeByLex(bfoo, bInclusiveB, bExclusiveC); + + // with LIMIT + Response> brange2 = pipe.zrangeByLex(bfoo, bLexMinusInf, bLexPlusInf, 0, 2); + + pipe.sync(); + + assertThat(brange1.get(), contains(bb)); + assertThat(brange2.get(), contains(ba, bb)); + } + + @Test + public void zrevrangeByLex() { + pipe.zadd("foo", 1, "aa"); + pipe.zadd("foo", 1, "c"); + pipe.zadd("foo", 1, "bb"); + pipe.zadd("foo", 1, "d"); + + // exclusive aa ~ inclusive c + Response> range1 = pipe.zrevrangeByLex("foo", "[c", "(aa"); + + // with LIMIT + Response> range2 = pipe.zrevrangeByLex("foo", "+", "-", 1, 2); + + pipe.sync(); + + assertThat(range1.get(), contains("c", "bb")); + assertThat(range2.get(), contains("c", "bb")); + } + + @Test + public void zrevrangeByLexBinary() { + // binary + pipe.zadd(bfoo, 1, ba); + pipe.zadd(bfoo, 1, bc); + pipe.zadd(bfoo, 1, bb); + + Response> brange1 = pipe.zrevrangeByLex(bfoo, bExclusiveC, bInclusiveB); + + // with LIMIT + Response> brange2 = pipe.zrevrangeByLex(bfoo, bLexPlusInf, bLexMinusInf, 0, 2); + + pipe.sync(); + + assertThat(brange1.get(), contains(bb)); + assertThat(brange2.get(), contains(bc, bb)); + } + + @Test + public void zrevrange() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 10d, "b"); + pipe.zadd("foo", 0.1d, "c"); + pipe.zadd("foo", 2d, "a"); + + Response> range1 = pipe.zrevrange("foo", 0, 1); + Response> range2 = pipe.zrevrange("foo", 0, 100); + + pipe.sync(); + + assertThat(range1.get(), contains("b", "a")); + assertThat(range2.get(), contains("b", "a", "c")); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + Response> brange1 = pipe.zrevrange(bfoo, 0, 1); + Response> brange2 = pipe.zrevrange(bfoo, 0, 100); + + pipe.sync(); + + assertThat(brange1.get(), contains(bb, ba)); + assertThat(brange2.get(), contains(bb, ba, bc)); + } + + @Test + public void zrangeParams() { + pipe.zadd("foo", 1, "aa"); + pipe.zadd("foo", 1, "c"); + pipe.zadd("foo", 1, "bb"); + pipe.zadd("foo", 1, "d"); + + Response> range1 = pipe.zrange("foo", ZRangeParams.zrangeByLexParams("[c", "(aa").rev()); + Response> range2 = pipe.zrangeWithScores("foo", ZRangeParams.zrangeByScoreParams(0, 1)); + + pipe.sync(); + + assertThat(range1.get(), contains("c", "bb")); + assertThat(range2.get().stream().map(Tuple::getElement).collect(Collectors.toList()), contains("aa", "bb", "c", "d")); + + // Binary + pipe.zadd(bfoo, 1, ba); + pipe.zadd(bfoo, 1, bc); + pipe.zadd(bfoo, 1, bb); + + Response> brange1 = pipe.zrange(bfoo, ZRangeParams.zrangeByLexParams(bExclusiveC, bInclusiveB).rev()); + Response> brange2 = pipe.zrangeWithScores(bfoo, ZRangeParams.zrangeByScoreParams(0, 1).limit(0, 3)); + + pipe.sync(); + + assertThat(brange1.get(), contains(bb)); + assertThat(brange2.get().stream().map(Tuple::getBinaryElement).collect(Collectors.toList()), contains(ba, bb, bc)); + } + + @Test + public void zrangestore() { + pipe.zadd("foo", 1, "aa"); + pipe.zadd("foo", 2, "c"); + pipe.zadd("foo", 3, "bb"); + + Response stored = pipe.zrangestore("bar", "foo", ZRangeParams.zrangeByScoreParams(1, 2)); + Response> range = pipe.zrange("bar", 0, -1); + + pipe.sync(); + + assertThat(stored.get(), equalTo(2L)); + assertThat(range.get(), contains("aa", "c")); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + Response bstored = pipe.zrangestore(bbar, bfoo, ZRangeParams.zrangeParams(0, 1).rev()); + Response> brange = pipe.zrevrange(bbar, 0, 1); + + pipe.sync(); + + assertThat(bstored.get(), equalTo(2L)); + assertThat(brange.get(), contains(bb, ba)); + } + + @Test + public void zrem() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 2d, "b"); + + Response result1 = pipe.zrem("foo", "a"); + Response> range = pipe.zrange("foo", 0, 100); + Response result2 = pipe.zrem("foo", "bar"); + + pipe.sync(); + + assertThat(result1.get(), equalTo(1L)); + assertThat(range.get(), contains("b")); + assertThat(result2.get(), equalTo(0L)); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 2d, bb); + + Response bresult1 = pipe.zrem(bfoo, ba); + Response> brange = pipe.zrange(bfoo, 0, 100); + Response bresult2 = pipe.zrem(bfoo, bbar); + + pipe.sync(); + + assertThat(bresult1.get(), equalTo(1L)); + assertThat(brange.get(), contains(bb)); + assertThat(bresult2.get(), equalTo(0L)); + } + + @Test + public void zincrby() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 2d, "b"); + + Response result = pipe.zincrby("foo", 2d, "a"); + Response> range = pipe.zrange("foo", 0, 100); + + pipe.sync(); + + assertThat(result.get(), closeTo(3d, 0.001)); + assertThat(range.get(), contains("b", "a")); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 2d, bb); + + Response bresult = pipe.zincrby(bfoo, 2d, ba); + Response> brange = pipe.zrange(bfoo, 0, 100); + + pipe.sync(); + + assertThat(bresult.get(), closeTo(3d, 0.001)); + assertThat(brange.get(), contains(bb, ba)); + } + + @Test + public void zincrbyWithParams() { + pipe.del("foo"); + + // xx: never add new member + Response result1 = pipe.zincrby("foo", 2d, "a", ZIncrByParams.zIncrByParams().xx()); + + pipe.zadd("foo", 2d, "a"); + + // nx: never update current member + Response result2 = pipe.zincrby("foo", 1d, "a", ZIncrByParams.zIncrByParams().nx()); + Response result3 = pipe.zscore("foo", "a"); + + pipe.sync(); + + assertThat(result1.get(), nullValue()); + assertThat(result2.get(), nullValue()); + assertThat(result3.get(), closeTo(2d, 0.001)); + + // Binary + + pipe.del(bfoo); + + // xx: never add new member + Response bresult1 = pipe.zincrby(bfoo, 2d, ba, ZIncrByParams.zIncrByParams().xx()); + + pipe.zadd(bfoo, 2d, ba); + + // nx: never update current member + Response bresult2 = pipe.zincrby(bfoo, 1d, ba, ZIncrByParams.zIncrByParams().nx()); + Response bresult3 = pipe.zscore(bfoo, ba); + + pipe.sync(); + + assertThat(bresult1.get(), nullValue()); + assertThat(bresult2.get(), nullValue()); + assertThat(bresult3.get(), closeTo(2d, 0.001)); + } + + @Test + public void zrank() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 2d, "b"); + + pipe.zrank("foo", "a"); + pipe.zrank("foo", "b"); + pipe.zrank("car", "b"); + + assertThat(pipe.syncAndReturnAll(), contains( + equalTo(1L), + equalTo(1L), + equalTo(0L), + equalTo(1L), + nullValue() + )); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 2d, bb); + + pipe.zrank(bfoo, ba); + pipe.zrank(bfoo, bb); + pipe.zrank(bcar, bb); + + assertThat(pipe.syncAndReturnAll(), contains( + equalTo(1L), + equalTo(1L), + equalTo(0L), + equalTo(1L), + nullValue() + )); + } + + @Test + public void zrankWithScore() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 2d, "b"); + + Response> keyValue1 = pipe.zrankWithScore("foo", "a"); + Response> keyValue2 = pipe.zrankWithScore("foo", "b"); + Response> keyValue3 = pipe.zrankWithScore("car", "b"); + + pipe.sync(); + + assertThat(keyValue1.get(), equalTo(new KeyValue<>(0L, 1d))); + assertThat(keyValue2.get(), equalTo(new KeyValue<>(1L, 2d))); + assertThat(keyValue3.get(), nullValue()); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 2d, bb); + + Response> bKeyValue1 = pipe.zrankWithScore(bfoo, ba); + Response> bKeyValue2 = pipe.zrankWithScore(bfoo, bb); + Response> bKeyValue3 = pipe.zrankWithScore(bcar, bb); + + pipe.sync(); + + assertThat(bKeyValue1.get(), equalTo(new KeyValue<>(0L, 1d))); + assertThat(bKeyValue2.get(), equalTo(new KeyValue<>(1L, 2d))); + assertThat(bKeyValue3.get(), nullValue()); + } + + @Test + public void zrevrank() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 2d, "b"); + + pipe.zrevrank("foo", "a"); + pipe.zrevrank("foo", "b"); + + assertThat(pipe.syncAndReturnAll(), contains( + equalTo(1L), + equalTo(1L), + equalTo(1L), + equalTo(0L) + )); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 2d, bb); + pipe.zrevrank(bfoo, ba); + pipe.zrevrank(bfoo, bb); + + assertThat(pipe.syncAndReturnAll(), contains( + equalTo(1L), + equalTo(1L), + equalTo(1L), + equalTo(0L) + )); + } + + @Test + public void zrangeWithScores() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 10d, "b"); + pipe.zadd("foo", 0.1d, "c"); + pipe.zadd("foo", 2d, "a"); + + Response> range1 = pipe.zrangeWithScores("foo", 0, 1); + Response> range2 = pipe.zrangeWithScores("foo", 0, 100); + + pipe.sync(); + + assertThat(range1.get(), contains( + new Tuple("c", 0.1d), + new Tuple("a", 2d) + )); + assertThat(range2.get(), contains( + new Tuple("c", 0.1d), + new Tuple("a", 2d), + new Tuple("b", 10d) + )); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + Response> brange1 = pipe.zrangeWithScores(bfoo, 0, 1); + Response> brange2 = pipe.zrangeWithScores(bfoo, 0, 100); + + pipe.sync(); + + assertThat(brange1.get(), contains( + new Tuple(bc, 0.1d), + new Tuple(ba, 2d) + )); + assertThat(brange2.get(), contains( + new Tuple(bc, 0.1d), + new Tuple(ba, 2d), + new Tuple(bb, 10d) + )); + } + + @Test + public void zrevrangeWithScores() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 10d, "b"); + pipe.zadd("foo", 0.1d, "c"); + pipe.zadd("foo", 2d, "a"); + + Response> range1 = pipe.zrevrangeWithScores("foo", 0, 1); + Response> range2 = pipe.zrevrangeWithScores("foo", 0, 100); + + pipe.sync(); + + assertThat(range1.get(), contains( + new Tuple("b", 10d), + new Tuple("a", 2d) + )); + assertThat(range2.get(), contains( + new Tuple("b", 10d), + new Tuple("a", 2d), + new Tuple("c", 0.1d) + )); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + Response> brange1 = pipe.zrevrangeWithScores(bfoo, 0, 1); + Response> brange2 = pipe.zrevrangeWithScores(bfoo, 0, 100); + + pipe.sync(); + + assertThat(brange1.get(), contains( + new Tuple(bb, 10d), + new Tuple(ba, 2d) + )); + assertThat(brange2.get(), contains( + new Tuple(bb, 10d), + new Tuple(ba, 2d), + new Tuple(bc, 0.1d) + )); + } + + @Test + public void zcard() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 10d, "b"); + pipe.zadd("foo", 0.1d, "c"); + pipe.zadd("foo", 2d, "a"); + + Response result = pipe.zcard("foo"); + + pipe.sync(); + + assertThat(result.get(), equalTo(3L)); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + Response bresult = pipe.zcard(bfoo); + + pipe.sync(); + + assertThat(bresult.get(), equalTo(3L)); + } + + @Test + public void zscore() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 10d, "b"); + pipe.zadd("foo", 0.1d, "c"); + pipe.zadd("foo", 2d, "a"); + + Response result1 = pipe.zscore("foo", "b"); + Response result2 = pipe.zscore("foo", "c"); + Response result3 = pipe.zscore("foo", "s"); + + pipe.sync(); + + assertThat(result1.get(), closeTo(10d, 0.001)); + assertThat(result2.get(), closeTo(0.1d, 0.001)); + assertThat(result3.get(), nullValue()); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + Response bresult1 = pipe.zscore(bfoo, bb); + Response bresult2 = pipe.zscore(bfoo, bc); + Response bresult3 = pipe.zscore(bfoo, SafeEncoder.encode("s")); + + pipe.sync(); + + assertThat(bresult1.get(), closeTo(10d, 0.001)); + assertThat(bresult2.get(), closeTo(0.1d, 0.001)); + assertThat(bresult3.get(), nullValue()); + } + + @Test + public void zmscore() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 10d, "b"); + pipe.zadd("foo", 0.1d, "c"); + pipe.zadd("foo", 2d, "a"); + + Response> score = pipe.zmscore("foo", "b", "c", "s"); + + pipe.sync(); + + assertThat(score.get(), contains(10d, 0.1d, null)); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + Response> bscore = pipe.zmscore(bfoo, bb, bc, SafeEncoder.encode("s")); + + pipe.sync(); + + assertThat(bscore.get(), contains(10d, 0.1d, null)); + } + + @Test + public void zpopmax() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 10d, "b"); + pipe.zadd("foo", 0.1d, "c"); + pipe.zadd("foo", 2d, "d"); + + pipe.sync(); + + pipe.zpopmax("foo"); + pipe.zpopmax("foo"); + pipe.zpopmax("foo"); + pipe.zpopmax("foo"); + pipe.zpopmax("foo"); + + assertThat(pipe.syncAndReturnAll(), contains( + equalTo(new Tuple("b", 10d)), + equalTo(new Tuple("d", 2d)), + equalTo(new Tuple("a", 1d)), + equalTo(new Tuple("c", 0.1d)), + nullValue() + )); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + pipe.sync(); + + pipe.zpopmax(bfoo); + pipe.zpopmax(bfoo); + pipe.zpopmax(bfoo); + pipe.zpopmax(bfoo); + + assertThat(pipe.syncAndReturnAll(), contains( + equalTo(new Tuple(bb, 10d)), + equalTo(new Tuple(ba, 2d)), + equalTo(new Tuple(bc, 0.1d)), + nullValue() + )); + } + + @Test + public void zpopmaxWithCount() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 10d, "b"); + pipe.zadd("foo", 0.1d, "c"); + pipe.zadd("foo", 2d, "d"); + pipe.zadd("foo", 0.03, "e"); + + Response> actual1 = pipe.zpopmax("foo", 2); + Response> actual2 = pipe.zpopmax("foo", 3); + Response> actual3 = pipe.zpopmax("foo", 1); + + pipe.sync(); + + assertThat(actual1.get(), contains( + new Tuple("b", 10d), + new Tuple("d", 2d) + )); + + assertThat(actual2.get(), contains( + new Tuple("a", 1d), + new Tuple("c", 0.1d), + new Tuple("e", 0.03d) + )); + + assertThat(actual3.get(), empty()); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + Response> bactual1 = pipe.zpopmax(bfoo, 1); + Response> bactual2 = pipe.zpopmax(bfoo, 1); + Response> bactual3 = pipe.zpopmax(bfoo, 1); + Response> bactual4 = pipe.zpopmax(bfoo, 1); + + pipe.sync(); + + assertThat(bactual1.get(), contains( + new Tuple(bb, 10d) + )); + + assertThat(bactual2.get(), contains( + new Tuple(ba, 2d) + )); + + assertThat(bactual3.get(), contains( + new Tuple(bc, 0.1d) + )); + + assertThat(bactual4.get(), empty()); + } + + @Test + public void zpopmin() { + pipe.zadd("foo", 1d, "a", ZAddParams.zAddParams().nx()); + pipe.zadd("foo", 10d, "b", ZAddParams.zAddParams().nx()); + pipe.zadd("foo", 0.1d, "c", ZAddParams.zAddParams().nx()); + pipe.zadd("foo", 2d, "a", ZAddParams.zAddParams().nx()); + + Response> range = pipe.zpopmin("foo", 2); + Response item = pipe.zpopmin("foo"); + + pipe.sync(); + + assertThat(range.get(), contains( + new Tuple("c", 0.1d), + new Tuple("a", 1d) + )); + + assertThat(item.get(), equalTo(new Tuple("b", 10d))); + + // Binary + + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + Response> brange = pipe.zpopmin(bfoo, 2); + Response bitem = pipe.zpopmin(bfoo); + + pipe.sync(); + + assertThat(brange.get(), contains( + new Tuple(bc, 0.1d), + new Tuple(ba, 2d) + )); + + assertThat(bitem.get(), equalTo(new Tuple(bb, 10d))); + } + + @Test + public void zcount() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 10d, "b"); + pipe.zadd("foo", 0.1d, "c"); + pipe.zadd("foo", 2d, "a"); + + pipe.sync(); + + pipe.zcount("foo", 0.01d, 2.1d); + pipe.zcount("foo", "(0.01", "+inf"); + + assertThat(pipe.syncAndReturnAll(), contains( + 2L, + 3L + )); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + pipe.sync(); + + pipe.zcount(bfoo, 0.01d, 2.1d); + pipe.zcount(bfoo, SafeEncoder.encode("(0.01"), SafeEncoder.encode("+inf")); + + assertThat(pipe.syncAndReturnAll(), contains( + 2L, + 3L + )); + } + + @Test + public void zlexcount() { + pipe.zadd("foo", 1, "a"); + pipe.zadd("foo", 1, "b"); + pipe.zadd("foo", 1, "c"); + pipe.zadd("foo", 1, "aa"); + + pipe.sync(); + + pipe.zlexcount("foo", "[aa", "(c"); + pipe.zlexcount("foo", "-", "+"); + pipe.zlexcount("foo", "-", "(c"); + pipe.zlexcount("foo", "[aa", "+"); + + assertThat(pipe.syncAndReturnAll(), contains( + 2L, + 4L, + 3L, + 3L + )); + } + + @Test + public void zlexcountBinary() { + // Binary + pipe.zadd(bfoo, 1, ba); + pipe.zadd(bfoo, 1, bc); + pipe.zadd(bfoo, 1, bb); + + pipe.sync(); + + pipe.zlexcount(bfoo, bInclusiveB, bExclusiveC); + pipe.zlexcount(bfoo, bLexMinusInf, bLexPlusInf); + + assertThat(pipe.syncAndReturnAll(), contains( + 1L, + 3L + )); + } + + @Test + public void zrangebyscore() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 10d, "b"); + pipe.zadd("foo", 0.1d, "c"); + pipe.zadd("foo", 2d, "a"); + + Response> range1 = pipe.zrangeByScore("foo", 0d, 2d); + Response> range2 = pipe.zrangeByScore("foo", 0d, 2d, 0, 1); + Response> range3 = pipe.zrangeByScore("foo", 0d, 2d, 1, 1); + Response> range4 = pipe.zrangeByScore("foo", "-inf", "(2"); + + pipe.sync(); + + assertThat(range1.get(), contains("c", "a")); + assertThat(range2.get(), contains("c")); + assertThat(range3.get(), contains("a")); + assertThat(range4.get(), contains("c")); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + Response> brange1 = pipe.zrangeByScore(bfoo, 0d, 2d); + Response> brange2 = pipe.zrangeByScore(bfoo, 0d, 2d, 0, 1); + Response> brange3 = pipe.zrangeByScore(bfoo, 0d, 2d, 1, 1); + Response> brange4 = pipe.zrangeByScore(bfoo, SafeEncoder.encode("-inf"), SafeEncoder.encode("(2")); + + pipe.sync(); + + assertThat(brange1.get(), contains(bc, ba)); + assertThat(brange2.get(), contains(bc)); + assertThat(brange3.get(), contains(ba)); + assertThat(brange4.get(), contains(bc)); + } + + @Test + public void zrevrangebyscore() { + pipe.zadd("foo", 1.0d, "a"); + pipe.zadd("foo", 2.0d, "b"); + pipe.zadd("foo", 3.0d, "c"); + pipe.zadd("foo", 4.0d, "d"); + pipe.zadd("foo", 5.0d, "e"); + + Response> range1 = pipe.zrevrangeByScore("foo", 3d, Double.NEGATIVE_INFINITY, 0, 1); + Response> range2 = pipe.zrevrangeByScore("foo", 3.5d, Double.NEGATIVE_INFINITY, 0, 2); + Response> range3 = pipe.zrevrangeByScore("foo", 3.5d, Double.NEGATIVE_INFINITY, 1, 1); + Response> range4 = pipe.zrevrangeByScore("foo", 4d, 2d); + Response> range5 = pipe.zrevrangeByScore("foo", "4", "2", 0, 2); + Response> range6 = pipe.zrevrangeByScore("foo", "+inf", "(4"); + + pipe.sync(); + + assertThat(range1.get(), contains("c")); + assertThat(range2.get(), contains("c", "b")); + assertThat(range3.get(), contains("b")); + assertThat(range4.get(), contains("d", "c", "b")); + assertThat(range5.get(), contains("d", "c")); + assertThat(range6.get(), contains("e")); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + Response> brange1 = pipe.zrevrangeByScore(bfoo, 2d, 0d); + Response> brange2 = pipe.zrevrangeByScore(bfoo, 2d, 0d, 0, 1); + Response> brange3 = pipe.zrevrangeByScore(bfoo, SafeEncoder.encode("+inf"), SafeEncoder.encode("(2")); + Response> brange4 = pipe.zrevrangeByScore(bfoo, 2d, 0d, 1, 1); + + pipe.sync(); + + assertThat(brange1.get(), contains(ba, bc)); + assertThat(brange2.get(), contains(ba)); + assertThat(brange3.get(), contains(bb)); + assertThat(brange4.get(), contains(bc)); + } + + @Test + public void zrangebyscoreWithScores() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 10d, "b"); + pipe.zadd("foo", 0.1d, "c"); + pipe.zadd("foo", 2d, "a"); + + Response> range1 = pipe.zrangeByScoreWithScores("foo", 0d, 2d); + Response> range2 = pipe.zrangeByScoreWithScores("foo", 0d, 2d, 0, 1); + Response> range3 = pipe.zrangeByScoreWithScores("foo", 0d, 2d, 1, 1); + + pipe.sync(); + + assertThat(range1.get(), contains( + new Tuple("c", 0.1d), + new Tuple("a", 2d) + )); + + assertThat(range2.get(), contains( + new Tuple("c", 0.1d) + )); + + assertThat(range3.get(), contains( + new Tuple("a", 2d) + )); + + // Binary + + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + Response> brange1 = pipe.zrangeByScoreWithScores(bfoo, 0d, 2d); + Response> brange2 = pipe.zrangeByScoreWithScores(bfoo, 0d, 2d, 0, 1); + Response> brange3 = pipe.zrangeByScoreWithScores(bfoo, 0d, 2d, 1, 1); + + pipe.sync(); + + assertThat(brange1.get(), contains( + new Tuple(bc, 0.1d), + new Tuple(ba, 2d) + )); + + assertThat(brange2.get(), contains( + new Tuple(bc, 0.1d) + )); + + assertThat(brange3.get(), contains( + new Tuple(ba, 2d) + )); + } + + @Test + public void zrevrangebyscoreWithScores() { + pipe.zadd("foo", 1.0d, "a"); + pipe.zadd("foo", 2.0d, "b"); + pipe.zadd("foo", 3.0d, "c"); + pipe.zadd("foo", 4.0d, "d"); + pipe.zadd("foo", 5.0d, "e"); + + Response> range1 = pipe.zrevrangeByScoreWithScores("foo", 3d, Double.NEGATIVE_INFINITY, 0, 1); + Response> range2 = pipe.zrevrangeByScoreWithScores("foo", 3.5d, Double.NEGATIVE_INFINITY, 0, 2); + Response> range3 = pipe.zrevrangeByScoreWithScores("foo", 3.5d, Double.NEGATIVE_INFINITY, 1, 1); + Response> range4 = pipe.zrevrangeByScoreWithScores("foo", 4d, 2d); + + pipe.sync(); + + assertThat(range1.get(), contains( + new Tuple("c", 3.0d) + )); + + assertThat(range2.get(), contains( + new Tuple("c", 3.0d), + new Tuple("b", 2.0d) + )); + + assertThat(range3.get(), contains( + new Tuple("b", 2.0d) + )); + + assertThat(range4.get(), contains( + new Tuple("d", 4.0d), + new Tuple("c", 3.0d), + new Tuple("b", 2.0d) + )); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + Response> brange1 = pipe.zrevrangeByScoreWithScores(bfoo, 2d, 0d); + Response> brange2 = pipe.zrevrangeByScoreWithScores(bfoo, 2d, 0d, 0, 1); + Response> brange3 = pipe.zrevrangeByScoreWithScores(bfoo, 2d, 0d, 1, 1); + + pipe.sync(); + + assertThat(brange1.get(), contains( + new Tuple(ba, 2d), + new Tuple(bc, 0.1d) + )); + + assertThat(brange2.get(), contains( + new Tuple(ba, 2d) + )); + + assertThat(brange3.get(), contains( + new Tuple(bc, 0.1d) + )); + } + + @Test + public void zremrangeByRank() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 10d, "b"); + pipe.zadd("foo", 0.1d, "c"); + pipe.zadd("foo", 2d, "a"); + + Response result = pipe.zremrangeByRank("foo", 0, 0); + Response> items = pipe.zrange("foo", 0, 100); + + pipe.sync(); + + assertThat(result.get(), equalTo(1L)); + assertThat(items.get(), contains("a", "b")); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + Response bresult = pipe.zremrangeByRank(bfoo, 0, 0); + Response> bitems = pipe.zrange(bfoo, 0, 100); + + pipe.sync(); + + assertThat(bresult.get(), equalTo(1L)); + assertThat(bitems.get(), contains(ba, bb)); + } + + @Test + public void zremrangeByScore() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 10d, "b"); + pipe.zadd("foo", 0.1d, "c"); + pipe.zadd("foo", 2d, "a"); + + Response result = pipe.zremrangeByScore("foo", 0, 2); + Response> items = pipe.zrange("foo", 0, 100); + + pipe.sync(); + + assertThat(result.get(), equalTo(2L)); + assertThat(items.get(), contains("b")); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bfoo, 0.1d, bc); + pipe.zadd(bfoo, 2d, ba); + + Response bresult = pipe.zremrangeByScore(bfoo, 0, 2); + Response> bitems = pipe.zrange(bfoo, 0, 100); + + pipe.sync(); + + assertThat(bresult.get(), equalTo(2L)); + assertThat(bitems.get(), contains(bb)); + } + + @Test + public void zremrangeByScoreExclusive() { + pipe.zadd("foo", 1d, "a"); + pipe.zadd("foo", 0d, "c"); + pipe.zadd("foo", 2d, "b"); + + Response result = pipe.zremrangeByScore("foo", "(0", "(2"); + + pipe.sync(); + + assertThat(result.get(), equalTo(1L)); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 0d, bc); + pipe.zadd(bfoo, 2d, bb); + + Response bresult = pipe.zremrangeByScore(bfoo, "(0".getBytes(), "(2".getBytes()); + + pipe.sync(); + + assertThat(bresult.get(), equalTo(1L)); + } + + @Test + public void zremrangeByLex() { + pipe.zadd("foo", 1, "a"); + pipe.zadd("foo", 1, "b"); + pipe.zadd("foo", 1, "c"); + pipe.zadd("foo", 1, "aa"); + + Response result = pipe.zremrangeByLex("foo", "[aa", "(c"); + Response> items = pipe.zrangeByLex("foo", "-", "+"); + + pipe.sync(); + + assertThat(result.get(), equalTo(2L)); + assertThat(items.get(), contains("a", "c")); + } + + @Test + public void zremrangeByLexBinary() { + pipe.zadd(bfoo, 1, ba); + pipe.zadd(bfoo, 1, bc); + pipe.zadd(bfoo, 1, bb); + + Response bresult = pipe.zremrangeByLex(bfoo, bInclusiveB, bExclusiveC); + Response> bitems = pipe.zrangeByLex(bfoo, bLexMinusInf, bLexPlusInf); + + pipe.sync(); + + assertThat(bresult.get(), equalTo(1L)); + assertThat(bitems.get(), contains(ba, bc)); + } + + @Test + public void zunion() { + pipe.zadd("foo", 1, "a"); + pipe.zadd("foo", 2, "b"); + pipe.zadd("bar", 2, "a"); + pipe.zadd("bar", 2, "b"); + + ZParams params = new ZParams(); + params.weights(2, 2.5); + params.aggregate(ZParams.Aggregate.SUM); + + Response> union1 = pipe.zunion(params, "foo", "bar"); + Response> union2 = pipe.zunionWithScores(params, "foo", "bar"); + + pipe.sync(); + + assertThat(union1.get(), contains("a", "b")); + assertThat(union2.get(), contains( + new Tuple("a", new Double(7)), + new Tuple("b", new Double(9)) + )); + + // Binary + pipe.zadd(bfoo, 1, ba); + pipe.zadd(bfoo, 2, bb); + pipe.zadd(bbar, 2, ba); + pipe.zadd(bbar, 2, bb); + + Response> bunion1 = pipe.zunion(params, bfoo, bbar); + Response> bunion2 = pipe.zunionWithScores(params, bfoo, bbar); + + pipe.sync(); + + assertThat(bunion1.get(), contains(ba, bb)); + assertThat(bunion2.get(), contains( + new Tuple(ba, new Double(7)), + new Tuple(bb, new Double(9)) + )); + } + + @Test + public void zunionstore() { + pipe.zadd("foo", 1, "a"); + pipe.zadd("foo", 2, "b"); + pipe.zadd("bar", 2, "a"); + pipe.zadd("bar", 2, "b"); + + Response result = pipe.zunionstore("dst", "foo", "bar"); + Response> items = pipe.zrangeWithScores("dst", 0, 100); + + pipe.sync(); + + assertThat(result.get(), equalTo(2L)); + assertThat(items.get(), contains( + new Tuple("a", new Double(3)), + new Tuple("b", new Double(4)) + )); + + // Binary + pipe.zadd(bfoo, 1, ba); + pipe.zadd(bfoo, 2, bb); + pipe.zadd(bbar, 2, ba); + pipe.zadd(bbar, 2, bb); + + Response bresult = pipe.zunionstore(SafeEncoder.encode("dst"), bfoo, bbar); + Response> bitems = pipe.zrangeWithScores(SafeEncoder.encode("dst"), 0, 100); + + pipe.sync(); + + assertThat(bresult.get(), equalTo(2L)); + assertThat(bitems.get(), contains( + new Tuple(ba, new Double(3)), + new Tuple(bb, new Double(4)) + )); + } + + @Test + public void zunionstoreParams() { + pipe.zadd("foo", 1, "a"); + pipe.zadd("foo", 2, "b"); + pipe.zadd("bar", 2, "a"); + pipe.zadd("bar", 2, "b"); + + ZParams params = new ZParams(); + params.weights(2, 2.5); + params.aggregate(ZParams.Aggregate.SUM); + + Response result = pipe.zunionstore("dst", params, "foo", "bar"); + Response> items = pipe.zrangeWithScores("dst", 0, 100); + + pipe.sync(); + + assertThat(result.get(), equalTo(2L)); + assertThat(items.get(), contains( + new Tuple("a", new Double(7)), + new Tuple("b", new Double(9)) + )); + + // Binary + pipe.zadd(bfoo, 1, ba); + pipe.zadd(bfoo, 2, bb); + pipe.zadd(bbar, 2, ba); + pipe.zadd(bbar, 2, bb); + + ZParams bparams = new ZParams(); + bparams.weights(2, 2.5); + bparams.aggregate(ZParams.Aggregate.SUM); + + Response bresult = pipe.zunionstore(SafeEncoder.encode("dst"), bparams, bfoo, bbar); + Response> bitems = pipe.zrangeWithScores(SafeEncoder.encode("dst"), 0, 100); + + pipe.sync(); + + assertThat(bresult.get(), equalTo(2L)); + assertThat(bitems.get(), contains( + new Tuple(ba, new Double(7)), + new Tuple(bb, new Double(9)) + )); + } + + @Test + public void zinter() { + pipe.zadd("foo", 1, "a"); + pipe.zadd("foo", 2, "b"); + pipe.zadd("bar", 2, "a"); + + ZParams params = new ZParams(); + params.weights(2, 2.5); + params.aggregate(ZParams.Aggregate.SUM); + Response> inter1 = pipe.zinter(params, "foo", "bar"); + + Response> inter2 = pipe.zinterWithScores(params, "foo", "bar"); + + pipe.sync(); + + assertThat(inter1.get(), contains("a")); + assertThat(inter2.get(), contains(new Tuple("a", new Double(7)))); + + // Binary + pipe.zadd(bfoo, 1, ba); + pipe.zadd(bfoo, 2, bb); + pipe.zadd(bbar, 2, ba); + + ZParams bparams = new ZParams(); + bparams.weights(2, 2.5); + bparams.aggregate(ZParams.Aggregate.SUM); + Response> binter1 = pipe.zinter(params, bfoo, bbar); + + Response> binter2 = pipe.zinterWithScores(bparams, bfoo, bbar); + + pipe.sync(); + + assertThat(binter1.get(), contains(ba)); + assertThat(binter2.get(), contains(new Tuple(ba, new Double(7)))); + } + + @Test + public void zinterstore() { + pipe.zadd("foo", 1, "a"); + pipe.zadd("foo", 2, "b"); + pipe.zadd("bar", 2, "a"); + + Response result1 = pipe.zinterstore("dst", "foo", "bar"); + Response> items1 = pipe.zrangeWithScores("dst", 0, 100); + + pipe.sync(); + + assertThat(result1.get(), equalTo(1L)); + assertThat(items1.get(), contains(new Tuple("a", new Double(3)))); + + // Binary + pipe.zadd(bfoo, 1, ba); + pipe.zadd(bfoo, 2, bb); + pipe.zadd(bbar, 2, ba); + + Response bresult1 = pipe.zinterstore(SafeEncoder.encode("dst"), bfoo, bbar); + Response> bitems1 = pipe.zrangeWithScores(SafeEncoder.encode("dst"), 0, 100); + + pipe.sync(); + + assertThat(bresult1.get(), equalTo(1L)); + assertThat(bitems1.get(), contains(new Tuple(ba, new Double(3)))); + } + + @Test + public void zintertoreParams() { + pipe.zadd("foo", 1, "a"); + pipe.zadd("foo", 2, "b"); + pipe.zadd("bar", 2, "a"); + + ZParams params = new ZParams(); + params.weights(2, 2.5); + params.aggregate(ZParams.Aggregate.SUM); + Response result1 = pipe.zinterstore("dst", params, "foo", "bar"); + + Response> items1 = pipe.zrangeWithScores("dst", 0, 100); + + pipe.sync(); + + assertThat(result1.get(), equalTo(1L)); + assertThat(items1.get(), contains(new Tuple("a", new Double(7)))); + + // Binary + pipe.zadd(bfoo, 1, ba); + pipe.zadd(bfoo, 2, bb); + pipe.zadd(bbar, 2, ba); + + ZParams bparams = new ZParams(); + bparams.weights(2, 2.5); + bparams.aggregate(ZParams.Aggregate.SUM); + Response bresult1 = pipe.zinterstore(SafeEncoder.encode("dst"), bparams, bfoo, bbar); + + Response> bitems1 = pipe.zrangeWithScores(SafeEncoder.encode("dst"), 0, 100); + + pipe.sync(); + + assertThat(bresult1.get(), equalTo(1L)); + assertThat(bitems1.get(), contains(new Tuple(ba, new Double(7)))); + } + + @Test + public void zintercard() { + pipe.zadd("foo", 1, "a"); + pipe.zadd("foo", 2, "b"); + pipe.zadd("bar", 2, "a"); + pipe.zadd("bar", 1, "b"); + + Response result1 = pipe.zintercard("foo", "bar"); + Response result2 = pipe.zintercard(1, "foo", "bar"); + + pipe.sync(); + + assertThat(result1.get(), equalTo(2L)); + assertThat(result2.get(), equalTo(1L)); + + // Binary + pipe.zadd(bfoo, 1, ba); + pipe.zadd(bfoo, 2, bb); + pipe.zadd(bbar, 2, ba); + pipe.zadd(bbar, 2, bb); + + Response bresult1 = pipe.zintercard(bfoo, bbar); + Response bresult2 = pipe.zintercard(1, bfoo, bbar); + + pipe.sync(); + + assertThat(bresult1.get(), equalTo(2L)); + assertThat(bresult2.get(), equalTo(1L)); + } + + @Test + public void zscan() { + pipe.zadd("foo", 1, "a"); + pipe.zadd("foo", 2, "b"); + + Response> result = pipe.zscan("foo", SCAN_POINTER_START); + + pipe.sync(); + + assertThat(result.get().getCursor(), equalTo(SCAN_POINTER_START)); + assertThat(result.get().getResult().stream().map(Tuple::getElement).collect(Collectors.toList()), + containsInAnyOrder("a", "b")); + + // binary + pipe.zadd(bfoo, 1, ba); + pipe.zadd(bfoo, 1, bb); + + Response> bResult = pipe.zscan(bfoo, SCAN_POINTER_START_BINARY); + + pipe.sync(); + + assertThat(bResult.get().getCursor(), equalTo(SCAN_POINTER_START)); + assertThat(bResult.get().getResult().stream().map(Tuple::getBinaryElement).collect(Collectors.toList()), + containsInAnyOrder(ba, bb)); + } + + @Test + public void zscanMatch() { + ScanParams params = new ScanParams(); + params.match("a*"); + + pipe.zadd("foo", 2, "b"); + pipe.zadd("foo", 1, "a"); + pipe.zadd("foo", 11, "aa"); + Response> result = pipe.zscan("foo", SCAN_POINTER_START, params); + + pipe.sync(); + + assertThat(result.get().getCursor(), equalTo(SCAN_POINTER_START)); + assertThat(result.get().getResult().stream().map(Tuple::getElement).collect(Collectors.toList()), + containsInAnyOrder("a", "aa")); + + // binary + params = new ScanParams(); + params.match(bbarstar); + + pipe.zadd(bfoo, 2, bbar1); + pipe.zadd(bfoo, 1, bbar2); + pipe.zadd(bfoo, 11, bbar3); + Response> bResult = pipe.zscan(bfoo, SCAN_POINTER_START_BINARY, params); + + pipe.sync(); + + assertThat(bResult.get().getCursor(), equalTo(SCAN_POINTER_START)); + assertThat(bResult.get().getResult().stream().map(Tuple::getBinaryElement).collect(Collectors.toList()), + containsInAnyOrder(bbar1, bbar2, bbar3)); + } + + @Test + public void zscanCount() { + ScanParams params = new ScanParams(); + params.count(2); + + pipe.zadd("foo", 1, "a1"); + pipe.zadd("foo", 2, "a2"); + pipe.zadd("foo", 3, "a3"); + pipe.zadd("foo", 4, "a4"); + pipe.zadd("foo", 5, "a5"); + + Response> result = pipe.zscan("foo", SCAN_POINTER_START, params); + + pipe.sync(); + + assertThat(result.get().getResult(), not(empty())); + + // binary + params = new ScanParams(); + params.count(2); + + pipe.zadd(bfoo, 2, bbar1); + pipe.zadd(bfoo, 1, bbar2); + pipe.zadd(bfoo, 11, bbar3); + + Response> bResult = pipe.zscan(bfoo, SCAN_POINTER_START_BINARY, params); + + pipe.sync(); + + assertThat(bResult.get().getResult(), not(empty())); + } + + @Test + public void infinity() { + pipe.zadd("key", Double.POSITIVE_INFINITY, "pos"); + + Response score1 = pipe.zscore("key", "pos"); + + pipe.zadd("key", Double.NEGATIVE_INFINITY, "neg"); + + Response score2 = pipe.zscore("key", "neg"); + + pipe.zadd("key", 0d, "zero"); + + Response> set = pipe.zrangeWithScores("key", 0, -1); + + pipe.sync(); + + assertThat(score1.get(), equalTo(Double.POSITIVE_INFINITY)); + assertThat(score2.get(), equalTo(Double.NEGATIVE_INFINITY)); + assertThat(set.get().stream().map(Tuple::getScore).collect(Collectors.toList()), + contains(Double.NEGATIVE_INFINITY, 0d, Double.POSITIVE_INFINITY)); + } + + @Test + public void bzpopmax() { + pipe.zadd("foo", 1d, "a", ZAddParams.zAddParams().nx()); + pipe.zadd("foo", 10d, "b", ZAddParams.zAddParams().nx()); + pipe.zadd("bar", 0.1d, "c", ZAddParams.zAddParams().nx()); + + Response> item1 = pipe.bzpopmax(0, "foo", "bar"); + + pipe.sync(); + + assertThat(item1.get().getKey(), equalTo("foo")); + assertThat(item1.get().getValue(), equalTo(new Tuple("b", 10d))); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bbar, 0.1d, bc); + + Response> bitem1 = pipe.bzpopmax(0, bfoo, bbar); + + pipe.sync(); + + assertThat(bitem1.get().getKey(), equalTo(bfoo)); + assertThat(bitem1.get().getValue(), equalTo(new Tuple(bb, 10d))); + } + + @Test + public void bzpopmin() { + pipe.zadd("foo", 1d, "a", ZAddParams.zAddParams().nx()); + pipe.zadd("foo", 10d, "b", ZAddParams.zAddParams().nx()); + pipe.zadd("bar", 0.1d, "c", ZAddParams.zAddParams().nx()); + + Response> item1 = pipe.bzpopmin(0, "bar", "foo"); + + pipe.sync(); + + assertThat(item1.get(), equalTo(new KeyValue<>("bar", new Tuple("c", 0.1)))); + + // Binary + pipe.zadd(bfoo, 1d, ba); + pipe.zadd(bfoo, 10d, bb); + pipe.zadd(bbar, 0.1d, bc); + + Response> bitem1 = pipe.bzpopmin(0, bbar, bfoo); + + pipe.sync(); + + assertThat(bitem1.get().getKey(), equalTo(bbar)); + assertThat(bitem1.get().getValue(), equalTo(new Tuple(bc, 0.1))); + } + + @Test + public void zdiff() { + pipe.zadd("foo", 1.0, "a"); + pipe.zadd("foo", 2.0, "b"); + pipe.zadd("bar", 1.0, "a"); + + Response> diff1 = pipe.zdiff("bar1", "bar2"); + Response> diff2 = pipe.zdiff("foo", "bar"); + Response> diff3 = pipe.zdiffWithScores("foo", "bar"); + + pipe.sync(); + + assertThat(diff1.get(), empty()); + assertThat(diff2.get(), contains("b")); + assertThat(diff3.get(), contains(new Tuple("b", 2.0d))); + + // binary + pipe.zadd(bfoo, 1.0, ba); + pipe.zadd(bfoo, 2.0, bb); + pipe.zadd(bbar, 1.0, ba); + + Response> bdiff1 = pipe.zdiff(bbar1, bbar2); + Response> bdiff2 = pipe.zdiff(bfoo, bbar); + Response> bdiff3 = pipe.zdiffWithScores(bfoo, bbar); + + pipe.sync(); + + assertThat(bdiff1.get(), empty()); + assertThat(bdiff2.get(), contains(bb)); + assertThat(bdiff3.get(), contains(new Tuple(bb, 2.0d))); + } + + @Test + public void zdiffstore() { + pipe.zadd("foo", 1.0, "a"); + pipe.zadd("foo", 2.0, "b"); + pipe.zadd("bar", 1.0, "a"); + + Response result1 = pipe.zdiffstore("bar3", "bar1", "bar2"); + Response result2 = pipe.zdiffstore("bar3", "foo", "bar"); + Response> items = pipe.zrange("bar3", 0, -1); + + pipe.sync(); + + assertThat(result1.get(), equalTo(0L)); + assertThat(result2.get(), equalTo(1L)); + assertThat(items.get(), contains("b")); + + // binary + pipe.zadd(bfoo, 1.0, ba); + pipe.zadd(bfoo, 2.0, bb); + pipe.zadd(bbar, 1.0, ba); + + Response bresult1 = pipe.zdiffstore(bbar3, bbar1, bbar2); + Response bresult2 = pipe.zdiffstore(bbar3, bfoo, bbar); + Response> bitems = pipe.zrange(bbar3, 0, -1); + + pipe.sync(); + + assertThat(bresult1.get(), equalTo(0L)); + assertThat(bresult2.get(), equalTo(1L)); + assertThat(bitems.get(), contains(bb)); + } + + @Test + public void zrandmember() { + Response item1 = pipe.zrandmember("foo"); + Response> items1 = pipe.zrandmember("foo", 1); + Response> items2 = pipe.zrandmemberWithScores("foo", 1); + + pipe.sync(); + + assertThat(item1.get(), nullValue()); + assertThat(items1.get(), empty()); + assertThat(items2.get(), empty()); + + Map hash = new HashMap<>(); + hash.put("bar1", 1d); + hash.put("bar2", 10d); + hash.put("bar3", 0.1d); + pipe.zadd("foo", hash); + + Response item2 = pipe.zrandmember("foo"); + Response> items3 = pipe.zrandmember("foo", 2); + Response> items4 = pipe.zrandmemberWithScores("foo", 2); + + pipe.sync(); + + assertThat(item2.get(), in(hash.keySet())); + assertThat(items3.get(), hasSize(2)); + assertThat(items4.get(), hasSize(2)); + items4.get().forEach(t -> assertEquals(hash.get(t.getElement()), t.getScore(), 0d)); + + // Binary + Response bitem1 = pipe.zrandmember(bfoo); + Response> bitems1 = pipe.zrandmember(bfoo, 1); + Response> bitems2 = pipe.zrandmemberWithScores(bfoo, 1); + + pipe.sync(); + + assertThat(bitem1.get(), nullValue()); + assertThat(bitems1.get(), empty()); + assertThat(bitems2.get(), empty()); + + Map bhash = new HashMap<>(); + bhash.put(bbar1, 1d); + bhash.put(bbar2, 10d); + bhash.put(bbar3, 0.1d); + pipe.zadd(bfoo, bhash); + + Response bitem2 = pipe.zrandmember(bfoo); + Response> bitems3 = pipe.zrandmember(bfoo, 2); + Response> bitems4 = pipe.zrandmemberWithScores(bfoo, 2); + + pipe.sync(); + + AssertUtil.assertByteArrayCollectionContains(bhash.keySet(), bitem2.get()); + assertThat(bitems3.get(), hasSize(2)); + assertThat(bitems4.get(), hasSize(2)); + bitems4.get().forEach(t -> assertEquals(getScoreFromByteMap(bhash, t.getBinaryElement()), t.getScore(), 0d)); + } + + private Double getScoreFromByteMap(Map bhash, byte[] key) { + for (Map.Entry en : bhash.entrySet()) { + if (Arrays.equals(en.getKey(), key)) { + return en.getValue(); + } + } + return null; + } + + @Test + public void zmpop() { + pipe.zadd("foo", 1d, "a", ZAddParams.zAddParams().nx()); + pipe.zadd("foo", 10d, "b", ZAddParams.zAddParams().nx()); + pipe.zadd("foo", 0.1d, "c", ZAddParams.zAddParams().nx()); + pipe.zadd("foo", 2d, "a", ZAddParams.zAddParams().nx()); + + Response>> single = pipe.zmpop(SortedSetOption.MAX, "foo"); + Response>> range = pipe.zmpop(SortedSetOption.MIN, 2, "foo"); + Response>> nullRange = pipe.zmpop(SortedSetOption.MAX, "foo"); + + pipe.sync(); + + assertThat(single.get().getValue(), contains(new Tuple("b", 10d))); + + assertThat(range.get().getValue(), contains( + new Tuple("c", 0.1d), + new Tuple("a", 1d) + )); + + assertThat(nullRange.get(), nullValue()); + } + + @Test + public void bzmpopSimple() { + pipe.zadd("foo", 1d, "a", ZAddParams.zAddParams().nx()); + pipe.zadd("foo", 10d, "b", ZAddParams.zAddParams().nx()); + pipe.zadd("foo", 0.1d, "c", ZAddParams.zAddParams().nx()); + pipe.zadd("foo", 2d, "a", ZAddParams.zAddParams().nx()); + + Response>> single = pipe.bzmpop(1L, SortedSetOption.MAX, "foo"); + Response>> range = pipe.bzmpop(1L, SortedSetOption.MIN, 2, "foo"); + Response>> nullRange = pipe.bzmpop(1L, SortedSetOption.MAX, "foo"); + + pipe.sync(); + + assertThat(single.get().getValue(), contains(new Tuple("b", 10d))); + + assertThat(range.get().getValue(), contains( + new Tuple("c", 0.1d), + new Tuple("a", 1d) + )); + + assertThat(nullRange.get(), nullValue()); + } +}