From 27540605acf9e837b133fe7974734c48a635cca7 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Sat, 29 Apr 2017 12:49:24 +0200 Subject: [PATCH] Fix zset score parsing for infinite scores #528 Lettuce now parses positive and negative infinite scores correctly. Infinite scores are received as inf and -inf that require appropriate transformation instead of parsing the floating point value. Previously parsing caused NumberFormatException. --- .../com/lambdaworks/redis/LettuceStrings.java | 40 +++++++-- .../redis/output/ScoredValueListOutput.java | 10 ++- .../redis/output/ScoredValueScanOutput.java | 7 +- .../ScoredValueScanStreamingOutput.java | 7 +- .../output/ScoredValueStreamingOutput.java | 7 +- .../redis/commands/SortedSetCommandTest.java | 88 +++++++++++++------ 6 files changed, 112 insertions(+), 47 deletions(-) diff --git a/src/main/java/com/lambdaworks/redis/LettuceStrings.java b/src/main/java/com/lambdaworks/redis/LettuceStrings.java index 3ae78371c9..04ebdde1c7 100644 --- a/src/main/java/com/lambdaworks/redis/LettuceStrings.java +++ b/src/main/java/com/lambdaworks/redis/LettuceStrings.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * 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. @@ -23,7 +23,7 @@ /** * Helper for {@link String} checks. This class is part of the internal API and may change without further notice. - * + * * @author Mark Paluch * @since 3.0 */ @@ -38,7 +38,7 @@ private LettuceStrings() { /** * Checks if a CharSequence is empty ("") or null. - * + * * @param cs the char sequence * @return true if empty */ @@ -48,18 +48,19 @@ public static boolean isEmpty(final CharSequence cs) { /** * Checks if a CharSequence is not empty ("") and not null. - * + * * @param cs the char sequence * @return true if not empty - * + * */ public static boolean isNotEmpty(final CharSequence cs) { return !isEmpty(cs); } /** - * Convert double to string. If double is infinite, returns positive/negative infinity {@code +inf} and {@code -inf}. - * + * Convert {@code double} to {@link String}. If {@code n} is infinite, returns positive/negative infinity {@code +inf} and + * {@code -inf}. + * * @param n the double. * @return string representation of {@code n} */ @@ -70,9 +71,30 @@ public static String string(double n) { return Double.toString(n); } + /** + * Convert {@link String} to {@code double}. If {@code s} is {@literal +inf}/{@literal -inf}, returns positive/negative + * infinity. + * + * @param s string representation of the number + * @return the {@code double} value. + * @since 4.3.3 + */ + public static double toDouble(String s) { + + if ("+inf".equals(s) || "inf".equals(s)) { + return Double.POSITIVE_INFINITY; + } + + if ("-inf".equals(s)) { + return Double.NEGATIVE_INFINITY; + } + + return Double.parseDouble(s); + } + /** * Create SHA1 digest from Lua script. - * + * * @param script the script * @return the Base16 encoded SHA1 value */ @@ -82,7 +104,7 @@ public static String digest(byte[] script) { /** * Create SHA1 digest from Lua script. - * + * * @param script the script * @return the Base16 encoded SHA1 value */ diff --git a/src/main/java/com/lambdaworks/redis/output/ScoredValueListOutput.java b/src/main/java/com/lambdaworks/redis/output/ScoredValueListOutput.java index 2296dc25c7..2563b74694 100644 --- a/src/main/java/com/lambdaworks/redis/output/ScoredValueListOutput.java +++ b/src/main/java/com/lambdaworks/redis/output/ScoredValueListOutput.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * 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. @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; +import com.lambdaworks.redis.LettuceStrings; import com.lambdaworks.redis.ScoredValue; import com.lambdaworks.redis.codec.RedisCodec; import com.lambdaworks.redis.internal.LettuceAssert; @@ -30,8 +31,9 @@ * @param Value type. * @author Will Glozer */ -public class ScoredValueListOutput extends CommandOutput>> - implements StreamingOutput> { +public class ScoredValueListOutput extends CommandOutput>> implements + StreamingOutput> { + private V value; private Subscriber> subscriber; @@ -47,7 +49,7 @@ public void set(ByteBuffer bytes) { return; } - double score = Double.parseDouble(decodeAscii(bytes)); + double score = LettuceStrings.toDouble(decodeAscii(bytes)); subscriber.onNext(new ScoredValue<>(score, value)); value = null; } diff --git a/src/main/java/com/lambdaworks/redis/output/ScoredValueScanOutput.java b/src/main/java/com/lambdaworks/redis/output/ScoredValueScanOutput.java index efe6bdbe83..5c15fb4259 100644 --- a/src/main/java/com/lambdaworks/redis/output/ScoredValueScanOutput.java +++ b/src/main/java/com/lambdaworks/redis/output/ScoredValueScanOutput.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * 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. @@ -17,13 +17,14 @@ import java.nio.ByteBuffer; +import com.lambdaworks.redis.LettuceStrings; import com.lambdaworks.redis.ScoredValue; import com.lambdaworks.redis.ScoredValueScanCursor; import com.lambdaworks.redis.codec.RedisCodec; /** * {@link com.lambdaworks.redis.ScoredValueScanCursor} for scan cursor output. - * + * * @param Key type. * @param Value type. * @author Mark Paluch @@ -44,7 +45,7 @@ protected void setOutput(ByteBuffer bytes) { return; } - double score = Double.parseDouble(decodeAscii(bytes)); + double score = LettuceStrings.toDouble(decodeAscii(bytes)); output.getValues().add(new ScoredValue(score, value)); value = null; } diff --git a/src/main/java/com/lambdaworks/redis/output/ScoredValueScanStreamingOutput.java b/src/main/java/com/lambdaworks/redis/output/ScoredValueScanStreamingOutput.java index 386bb9ef42..aa0672c6b6 100644 --- a/src/main/java/com/lambdaworks/redis/output/ScoredValueScanStreamingOutput.java +++ b/src/main/java/com/lambdaworks/redis/output/ScoredValueScanStreamingOutput.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * 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. @@ -17,13 +17,14 @@ import java.nio.ByteBuffer; +import com.lambdaworks.redis.LettuceStrings; import com.lambdaworks.redis.ScoredValue; import com.lambdaworks.redis.StreamScanCursor; import com.lambdaworks.redis.codec.RedisCodec; /** * Streaming-Output of of values and their associated scores. Returns the count of all values (including null). - * + * * @param Key type. * @param Value type. * @author Mark Paluch @@ -45,7 +46,7 @@ protected void setOutput(ByteBuffer bytes) { return; } - double score = Double.parseDouble(decodeAscii(bytes)); + double score = LettuceStrings.toDouble(decodeAscii(bytes)); channel.onValue(new ScoredValue(score, value)); value = null; output.setCount(output.getCount() + 1); diff --git a/src/main/java/com/lambdaworks/redis/output/ScoredValueStreamingOutput.java b/src/main/java/com/lambdaworks/redis/output/ScoredValueStreamingOutput.java index ec3bbd552c..4cca653804 100644 --- a/src/main/java/com/lambdaworks/redis/output/ScoredValueStreamingOutput.java +++ b/src/main/java/com/lambdaworks/redis/output/ScoredValueStreamingOutput.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * 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. @@ -17,12 +17,13 @@ import java.nio.ByteBuffer; +import com.lambdaworks.redis.LettuceStrings; import com.lambdaworks.redis.ScoredValue; import com.lambdaworks.redis.codec.RedisCodec; /** * Streaming-Output of of values and their associated scores. Returns the count of all values (including null). - * + * * @author Mark Paluch * @param Key type. * @param Value type. @@ -44,7 +45,7 @@ public void set(ByteBuffer bytes) { return; } - double score = Double.parseDouble(decodeAscii(bytes)); + double score = LettuceStrings.toDouble(decodeAscii(bytes)); channel.onValue(new ScoredValue(score, value)); value = null; output = output.longValue() + 1; diff --git a/src/test/java/com/lambdaworks/redis/commands/SortedSetCommandTest.java b/src/test/java/com/lambdaworks/redis/commands/SortedSetCommandTest.java index e47208e16a..b65c2ab17a 100644 --- a/src/test/java/com/lambdaworks/redis/commands/SortedSetCommandTest.java +++ b/src/test/java/com/lambdaworks/redis/commands/SortedSetCommandTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * 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. @@ -15,6 +15,7 @@ */ package com.lambdaworks.redis.commands; +import static com.lambdaworks.redis.Range.Boundary.including; import static com.lambdaworks.redis.ZStoreArgs.Builder.max; import static com.lambdaworks.redis.ZStoreArgs.Builder.min; import static com.lambdaworks.redis.ZStoreArgs.Builder.sum; @@ -146,7 +147,7 @@ public void zcount() throws Exception { assertThat(redis.zcount(key, Range.create(1.0, 2.0))).isEqualTo(2); assertThat(redis.zcount(key, Range.create(NEGATIVE_INFINITY, POSITIVE_INFINITY))).isEqualTo(3); - assertThat(redis.zcount(key, Range.from(Boundary.excluding(1.0), Boundary.including(3.0)))).isEqualTo(2); + assertThat(redis.zcount(key, Range.from(Boundary.excluding(1.0), including(3.0)))).isEqualTo(2); assertThat(redis.zcount(key, Range.unbounded())).isEqualTo(3); } @@ -219,7 +220,8 @@ public void zrangebyscore() throws Exception { assertThat(redis.zrangebyscore(key, "-inf", "+inf", 2, 2)).isEqualTo(list("c", "d")); assertThat(redis.zrangebyscore(key, Range.create(2.0, 3.0))).isEqualTo(list("b", "c")); - assertThat(redis.zrangebyscore(key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo(list("b", "c")); + assertThat(redis.zrangebyscore(key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo( + list("b", "c")); assertThat(redis.zrangebyscore(key, Range.unbounded())).isEqualTo(list("a", "b", "c", "d")); assertThat(redis.zrangebyscore(key, Range.create(0.0, 4.0), Limit.create(1, 3))).isEqualTo(list("b", "c", "d")); assertThat(redis.zrangebyscore(key, Range.unbounded(), Limit.create(2, 2))).isEqualTo(list("c", "d")); @@ -239,7 +241,8 @@ public void zrangebyscoreStreaming() throws Exception { assertThat(redis.zrangebyscore(streamingAdapter, key, "-inf", "+inf", 2, 2)).isEqualTo(2); assertThat(redis.zrangebyscore(streamingAdapter, key, Range.create(2.0, 3.0))).isEqualTo(2); - assertThat(redis.zrangebyscore(streamingAdapter, key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo(2); + assertThat(redis.zrangebyscore(streamingAdapter, key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))) + .isEqualTo(2); assertThat(redis.zrangebyscore(streamingAdapter, key, Range.unbounded())).isEqualTo(4); assertThat(redis.zrangebyscore(streamingAdapter, key, Range.create(0.0, 4.0), Limit.create(1, 3))).isEqualTo(3); assertThat(redis.zrangebyscore(streamingAdapter, key, Range.unbounded(), Limit.create(2, 2))).isEqualTo(2); @@ -262,12 +265,30 @@ public void zrangebyscoreWithScores() throws Exception { assertThat(redis.zrangebyscoreWithScores(key, "-inf", "+inf", 2, 2)).isEqualTo(svlist(sv(3.0, "c"), sv(4.0, "d"))); assertThat(redis.zrangebyscoreWithScores(key, Range.create(2.0, 3.0))).isEqualTo(svlist(sv(2.0, "b"), sv(3.0, "c"))); - assertThat(redis.zrangebyscoreWithScores(key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo(svlist(sv(2.0, "b"), sv(3.0, "c"))); + assertThat(redis.zrangebyscoreWithScores(key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo( + svlist(sv(2.0, "b"), sv(3.0, "c"))); assertThat(redis.zrangebyscoreWithScores(key, Range.unbounded())).isEqualTo( svlist(sv(1.0, "a"), sv(2.0, "b"), sv(3.0, "c"), sv(4.0, "d"))); assertThat(redis.zrangebyscoreWithScores(key, Range.create(0.0, 4.0), Limit.create(1, 3))).isEqualTo( svlist(sv(2.0, "b"), sv(3.0, "c"), sv(4.0, "d"))); - assertThat(redis.zrangebyscoreWithScores(key, Range.unbounded(), Limit.create(2, 2))).isEqualTo(svlist(sv(3.0, "c"), sv(4.0, "d"))); + assertThat(redis.zrangebyscoreWithScores(key, Range.unbounded(), Limit.create(2, 2))).isEqualTo( + svlist(sv(3.0, "c"), sv(4.0, "d"))); + } + + @Test + @SuppressWarnings({ "unchecked" }) + public void zrangebyscoreWithScoresInfinity() throws Exception { + + redis.zadd(key, Double.POSITIVE_INFINITY, "a", Double.NEGATIVE_INFINITY, "b"); + + assertThat(redis.zrangebyscoreWithScores(key, "-inf", "+inf")).hasSize(2); + + ListStreamingAdapter streamingAdapter = new ListStreamingAdapter<>(); + + Range range = Range.from(including(Double.NEGATIVE_INFINITY), including(Double.POSITIVE_INFINITY)); + redis.zrangebyscoreWithScores(streamingAdapter, key, range); + + assertThat(streamingAdapter.getList()).hasSize(2); } @Test @@ -284,11 +305,14 @@ public void zrangebyscoreWithScoresStreaming() throws Exception { assertThat(redis.zrangebyscoreWithScores(streamingAdapter, key, 0.0, 4.0, 1, 3).longValue()).isEqualTo(3); assertThat(redis.zrangebyscoreWithScores(streamingAdapter, key, "-inf", "+inf", 2, 2).longValue()).isEqualTo(2); - assertThat(redis.zrangebyscoreWithScores(streamingAdapter,key, Range.create(2.0, 3.0))).isEqualTo(2); - assertThat(redis.zrangebyscoreWithScores(streamingAdapter,key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo(2); - assertThat(redis.zrangebyscoreWithScores(streamingAdapter,key, Range.unbounded())).isEqualTo(4); - assertThat(redis.zrangebyscoreWithScores(streamingAdapter,key, Range.create(0.0, 4.0), Limit.create(1, 3))).isEqualTo(3); - assertThat(redis.zrangebyscoreWithScores(streamingAdapter,key, Range.unbounded(), Limit.create(2, 2))).isEqualTo(2); + assertThat(redis.zrangebyscoreWithScores(streamingAdapter, key, Range.create(2.0, 3.0))).isEqualTo(2); + assertThat( + redis.zrangebyscoreWithScores(streamingAdapter, key, + Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo(2); + assertThat(redis.zrangebyscoreWithScores(streamingAdapter, key, Range.unbounded())).isEqualTo(4); + assertThat(redis.zrangebyscoreWithScores(streamingAdapter, key, Range.create(0.0, 4.0), Limit.create(1, 3))).isEqualTo( + 3); + assertThat(redis.zrangebyscoreWithScores(streamingAdapter, key, Range.unbounded(), Limit.create(2, 2))).isEqualTo(2); } @@ -380,8 +404,9 @@ public void zrevrangebylex() throws Exception { assertThat(redis.zrevrangebylex(key, Range.unbounded())).hasSize(100); assertThat(redis.zrevrangebylex(key, Range.create("value", "zzz"))).hasSize(100); - assertThat(redis.zrevrangebylex(key, Range.from(Boundary.including("value98"), Boundary.including("value99")))).containsSequence("value99", "value98"); - assertThat(redis.zrevrangebylex(key, Range.from(Boundary.including("value99"), Boundary.unbounded()))).hasSize(1); + assertThat(redis.zrevrangebylex(key, Range.from(including("value98"), including("value99")))).containsSequence( + "value99", "value98"); + assertThat(redis.zrevrangebylex(key, Range.from(including("value99"), Boundary.unbounded()))).hasSize(1); assertThat(redis.zrevrangebylex(key, Range.from(Boundary.excluding("value99"), Boundary.unbounded()))).hasSize(0); } @@ -398,7 +423,8 @@ public void zrevrangebyscore() throws Exception { assertThat(redis.zrevrangebyscore(key, "+inf", "-inf", 2, 2)).isEqualTo(list("b", "a")); assertThat(redis.zrevrangebyscore(key, Range.create(2.0, 3.0))).isEqualTo(list("c", "b")); - assertThat(redis.zrevrangebyscore(key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo(list("c", "b")); + assertThat(redis.zrevrangebyscore(key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo( + list("c", "b")); assertThat(redis.zrevrangebyscore(key, Range.unbounded())).isEqualTo(list("d", "c", "b", "a")); assertThat(redis.zrevrangebyscore(key, Range.create(0.0, 4.0), Limit.create(1, 3))).isEqualTo(list("c", "b", "a")); assertThat(redis.zrevrangebyscore(key, Range.unbounded(), Limit.create(2, 2))).isEqualTo(list("b", "a")); @@ -420,12 +446,14 @@ public void zrevrangebyscoreWithScores() throws Exception { assertThat(redis.zrevrangebyscoreWithScores(key, "+inf", "-inf", 2, 2)).isEqualTo(svlist(sv(2.0, "b"), sv(1.0, "a"))); assertThat(redis.zrevrangebyscoreWithScores(key, Range.create(2.0, 3.0))).isEqualTo(svlist(sv(3.0, "c"), sv(2.0, "b"))); - assertThat(redis.zrevrangebyscoreWithScores(key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo(svlist(sv(3.0, "c"), sv(2.0, "b"))); + assertThat(redis.zrevrangebyscoreWithScores(key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))) + .isEqualTo(svlist(sv(3.0, "c"), sv(2.0, "b"))); assertThat(redis.zrevrangebyscoreWithScores(key, Range.unbounded())).isEqualTo( svlist(sv(4.0, "d"), sv(3.0, "c"), sv(2.0, "b"), sv(1.0, "a"))); assertThat(redis.zrevrangebyscoreWithScores(key, Range.create(0.0, 4.0), Limit.create(1, 3))).isEqualTo( svlist(sv(3.0, "c"), sv(2.0, "b"), sv(1.0, "a"))); - assertThat(redis.zrevrangebyscoreWithScores(key, Range.unbounded(), Limit.create(2, 2))).isEqualTo(svlist(sv(2.0, "b"), sv(1.0, "a"))); + assertThat(redis.zrevrangebyscoreWithScores(key, Range.unbounded(), Limit.create(2, 2))).isEqualTo( + svlist(sv(2.0, "b"), sv(1.0, "a"))); } @Test @@ -442,10 +470,14 @@ public void zrevrangebyscoreStreaming() throws Exception { assertThat(redis.zrevrangebyscore(streamingAdapter, key, "+inf", "-inf", 2, 2).longValue()).isEqualTo(2); assertThat(redis.zrevrangebyscore(streamingAdapter, key, Range.create(2.0, 3.0)).longValue()).isEqualTo(2); - assertThat(redis.zrevrangebyscore(streamingAdapter, key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0))).longValue()).isEqualTo(2); + assertThat( + redis.zrevrangebyscore(streamingAdapter, key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0))) + .longValue()).isEqualTo(2); assertThat(redis.zrevrangebyscore(streamingAdapter, key, Range.unbounded()).longValue()).isEqualTo(4); - assertThat(redis.zrevrangebyscore(streamingAdapter, key, Range.create(0.0, 4.0), Limit.create(1, 3)).longValue()).isEqualTo(3); - assertThat(redis.zrevrangebyscore(streamingAdapter, key, Range.unbounded(), Limit.create(2, 2)).longValue()).isEqualTo(2); + assertThat(redis.zrevrangebyscore(streamingAdapter, key, Range.create(0.0, 4.0), Limit.create(1, 3)).longValue()) + .isEqualTo(3); + assertThat(redis.zrevrangebyscore(streamingAdapter, key, Range.unbounded(), Limit.create(2, 2)).longValue()).isEqualTo( + 2); } @Test @@ -463,10 +495,15 @@ public void zrevrangebyscoreWithScoresStreaming() throws Exception { assertThat(redis.zrevrangebyscoreWithScores(streamingAdapter, key, "+inf", "-inf", 2, 2)).isEqualTo(2); assertThat(redis.zrevrangebyscoreWithScores(streamingAdapter, key, Range.create(2.0, 3.0)).longValue()).isEqualTo(2); - assertThat(redis.zrevrangebyscoreWithScores(streamingAdapter, key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0))).longValue()).isEqualTo(2); + assertThat( + redis.zrevrangebyscoreWithScores(streamingAdapter, key, + Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0))).longValue()).isEqualTo(2); assertThat(redis.zrevrangebyscoreWithScores(streamingAdapter, key, Range.unbounded()).longValue()).isEqualTo(4); - assertThat(redis.zrevrangebyscoreWithScores(streamingAdapter, key, Range.create(0.0, 4.0), Limit.create(1, 3)).longValue()).isEqualTo(3); - assertThat(redis.zrevrangebyscoreWithScores(streamingAdapter, key, Range.unbounded(), Limit.create(2, 2)).longValue()).isEqualTo(2); + assertThat( + redis.zrevrangebyscoreWithScores(streamingAdapter, key, Range.create(0.0, 4.0), Limit.create(1, 3)).longValue()) + .isEqualTo(3); + assertThat(redis.zrevrangebyscoreWithScores(streamingAdapter, key, Range.unbounded(), Limit.create(2, 2)).longValue()) + .isEqualTo(2); } @Test @@ -656,7 +693,7 @@ public void zlexcount() throws Exception { assertThat(redis.zlexcount(key, Range.unbounded())).isEqualTo(100); assertThat(redis.zlexcount(key, Range.create("value", "zzz"))).isEqualTo(100); - assertThat(redis.zlexcount(key, Range.from(Boundary.including("value99"), Boundary.unbounded()))).isEqualTo(1); + assertThat(redis.zlexcount(key, Range.from(including("value99"), Boundary.unbounded()))).isEqualTo(1); assertThat(redis.zlexcount(key, Range.from(Boundary.excluding("value99"), Boundary.unbounded()))).isEqualTo(0); } @@ -669,8 +706,9 @@ public void zrangebylex() throws Exception { assertThat(redis.zrangebylex(key, Range.unbounded())).hasSize(100); assertThat(redis.zrangebylex(key, Range.create("value", "zzz"))).hasSize(100); - assertThat(redis.zrangebylex(key, Range.from(Boundary.including("value98"), Boundary.including("value99")))).containsSequence("value98", "value99"); - assertThat(redis.zrangebylex(key, Range.from(Boundary.including("value99"), Boundary.unbounded()))).hasSize(1); + assertThat(redis.zrangebylex(key, Range.from(including("value98"), including("value99")))).containsSequence("value98", + "value99"); + assertThat(redis.zrangebylex(key, Range.from(including("value99"), Boundary.unbounded()))).hasSize(1); assertThat(redis.zrangebylex(key, Range.from(Boundary.excluding("value99"), Boundary.unbounded()))).hasSize(0); }