From d9e28bcf00a1e52c5e0c8cbc5f2c8c8cb7d7027f Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Thu, 29 Jul 2010 21:31:58 +0200 Subject: [PATCH] Fix ZUNIONSTORE/ZINTERSTORE to never store a NaN score. When +inf and -inf are added, the result is NaN. We don't want NaN scores in a sorted set, so agreed on the result of this operation being zero. --- src/t_zset.c | 4 ++++ tests/unit/type/zset.tcl | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/t_zset.c b/src/t_zset.c index 8efe3c2a..a85a9dc1 100644 --- a/src/t_zset.c +++ b/src/t_zset.c @@ -541,6 +541,10 @@ int qsortCompareZsetopsrcByCardinality(const void *s1, const void *s2) { inline static void zunionInterAggregate(double *target, double val, int aggregate) { if (aggregate == REDIS_AGGR_SUM) { *target = *target + val; + /* The result of adding two doubles is NaN when one variable + * is +inf and the other is -inf. When these numbers are added, + * we maintain the convention of the result being 0.0. */ + if (isnan(*target)) *target = 0.0; } else if (aggregate == REDIS_AGGR_MIN) { *target = val < *target ? val : *target; } else if (aggregate == REDIS_AGGR_MAX) { diff --git a/tests/unit/type/zset.tcl b/tests/unit/type/zset.tcl index da264845..a289d883 100644 --- a/tests/unit/type/zset.tcl +++ b/tests/unit/type/zset.tcl @@ -433,6 +433,30 @@ start_server {tags {"zset"}} { list [r zinterstore zsetc 2 zseta zsetb aggregate max] [r zrange zsetc 0 -1 withscores] } {2 {b 2 c 3}} + foreach cmd {ZUNIONSTORE ZINTERSTORE} { + test "$cmd with +inf/-inf scores" { + r zadd zsetinf1 +inf key + r zadd zsetinf2 +inf key + r $cmd zsetinf3 2 zsetinf1 zsetinf2 + assert_equal inf [r zscore zsetinf3 key] + + r zadd zsetinf1 -inf key + r zadd zsetinf2 +inf key + r $cmd zsetinf3 2 zsetinf1 zsetinf2 + assert_equal 0 [r zscore zsetinf3 key] + + r zadd zsetinf1 +inf key + r zadd zsetinf2 -inf key + r $cmd zsetinf3 2 zsetinf1 zsetinf2 + assert_equal 0 [r zscore zsetinf3 key] + + r zadd zsetinf1 -inf key + r zadd zsetinf2 -inf key + r $cmd zsetinf3 2 zsetinf1 zsetinf2 + assert_equal -inf [r zscore zsetinf3 key] + } + } + tags {"slow"} { test {ZSETs skiplist implementation backlink consistency test} { set diff 0