1start_server {tags {"zset"}} { 2 proc create_zset {key items} { 3 r del $key 4 foreach {score entry} $items { 5 r zadd $key $score $entry 6 } 7 } 8 9 proc basics {encoding} { 10 if {$encoding == "ziplist"} { 11 r config set zset-max-ziplist-entries 128 12 r config set zset-max-ziplist-value 64 13 } elseif {$encoding == "skiplist"} { 14 r config set zset-max-ziplist-entries 0 15 r config set zset-max-ziplist-value 0 16 } else { 17 puts "Unknown sorted set encoding" 18 exit 19 } 20 21 test "Check encoding - $encoding" { 22 r del ztmp 23 r zadd ztmp 10 x 24 assert_encoding $encoding ztmp 25 } 26 27 test "ZSET basic ZADD and score update - $encoding" { 28 r del ztmp 29 r zadd ztmp 10 x 30 r zadd ztmp 20 y 31 r zadd ztmp 30 z 32 assert_equal {x y z} [r zrange ztmp 0 -1] 33 34 r zadd ztmp 1 y 35 assert_equal {y x z} [r zrange ztmp 0 -1] 36 } 37 38 test "ZSET element can't be set to NaN with ZADD - $encoding" { 39 assert_error "*not*float*" {r zadd myzset nan abc} 40 } 41 42 test "ZSET element can't be set to NaN with ZINCRBY" { 43 assert_error "*not*float*" {r zadd myzset nan abc} 44 } 45 46 test "ZADD with options syntax error with incomplete pair" { 47 r del ztmp 48 catch {r zadd ztmp xx 10 x 20} err 49 set err 50 } {ERR*} 51 52 test "ZADD XX option without key - $encoding" { 53 r del ztmp 54 assert {[r zadd ztmp xx 10 x] == 0} 55 assert {[r type ztmp] eq {none}} 56 } 57 58 test "ZADD XX existing key - $encoding" { 59 r del ztmp 60 r zadd ztmp 10 x 61 assert {[r zadd ztmp xx 20 y] == 0} 62 assert {[r zcard ztmp] == 1} 63 } 64 65 test "ZADD XX returns the number of elements actually added" { 66 r del ztmp 67 r zadd ztmp 10 x 68 set retval [r zadd ztmp 10 x 20 y 30 z] 69 assert {$retval == 2} 70 } 71 72 test "ZADD XX updates existing elements score" { 73 r del ztmp 74 r zadd ztmp 10 x 20 y 30 z 75 r zadd ztmp xx 5 foo 11 x 21 y 40 zap 76 assert {[r zcard ztmp] == 3} 77 assert {[r zscore ztmp x] == 11} 78 assert {[r zscore ztmp y] == 21} 79 } 80 81 test "ZADD XX and NX are not compatible" { 82 r del ztmp 83 catch {r zadd ztmp xx nx 10 x} err 84 set err 85 } {ERR*} 86 87 test "ZADD NX with non exisitng key" { 88 r del ztmp 89 r zadd ztmp nx 10 x 20 y 30 z 90 assert {[r zcard ztmp] == 3} 91 } 92 93 test "ZADD NX only add new elements without updating old ones" { 94 r del ztmp 95 r zadd ztmp 10 x 20 y 30 z 96 assert {[r zadd ztmp nx 11 x 21 y 100 a 200 b] == 2} 97 assert {[r zscore ztmp x] == 10} 98 assert {[r zscore ztmp y] == 20} 99 assert {[r zscore ztmp a] == 100} 100 assert {[r zscore ztmp b] == 200} 101 } 102 103 test "ZADD INCR works like ZINCRBY" { 104 r del ztmp 105 r zadd ztmp 10 x 20 y 30 z 106 r zadd ztmp INCR 15 x 107 assert {[r zscore ztmp x] == 25} 108 } 109 110 test "ZADD INCR works with a single score-elemenet pair" { 111 r del ztmp 112 r zadd ztmp 10 x 20 y 30 z 113 catch {r zadd ztmp INCR 15 x 10 y} err 114 set err 115 } {ERR*} 116 117 test "ZADD CH option changes return value to all changed elements" { 118 r del ztmp 119 r zadd ztmp 10 x 20 y 30 z 120 assert {[r zadd ztmp 11 x 21 y 30 z] == 0} 121 assert {[r zadd ztmp ch 12 x 22 y 30 z] == 2} 122 } 123 124 test "ZINCRBY calls leading to NaN result in error" { 125 r zincrby myzset +inf abc 126 assert_error "*NaN*" {r zincrby myzset -inf abc} 127 } 128 129 test {ZADD - Variadic version base case} { 130 r del myzset 131 list [r zadd myzset 10 a 20 b 30 c] [r zrange myzset 0 -1 withscores] 132 } {3 {a 10 b 20 c 30}} 133 134 test {ZADD - Return value is the number of actually added items} { 135 list [r zadd myzset 5 x 20 b 30 c] [r zrange myzset 0 -1 withscores] 136 } {1 {x 5 a 10 b 20 c 30}} 137 138 test {ZADD - Variadic version does not add nothing on single parsing err} { 139 r del myzset 140 catch {r zadd myzset 10 a 20 b 30.badscore c} e 141 assert_match {*ERR*not*float*} $e 142 r exists myzset 143 } {0} 144 145 test {ZADD - Variadic version will raise error on missing arg} { 146 r del myzset 147 catch {r zadd myzset 10 a 20 b 30 c 40} e 148 assert_match {*ERR*syntax*} $e 149 } 150 151 test {ZINCRBY does not work variadic even if shares ZADD implementation} { 152 r del myzset 153 catch {r zincrby myzset 10 a 20 b 30 c} e 154 assert_match {*ERR*wrong*number*arg*} $e 155 } 156 157 test "ZCARD basics - $encoding" { 158 r del ztmp 159 r zadd ztmp 10 a 20 b 30 c 160 assert_equal 3 [r zcard ztmp] 161 assert_equal 0 [r zcard zdoesntexist] 162 } 163 164 test "ZREM removes key after last element is removed" { 165 r del ztmp 166 r zadd ztmp 10 x 167 r zadd ztmp 20 y 168 169 assert_equal 1 [r exists ztmp] 170 assert_equal 0 [r zrem ztmp z] 171 assert_equal 1 [r zrem ztmp y] 172 assert_equal 1 [r zrem ztmp x] 173 assert_equal 0 [r exists ztmp] 174 } 175 176 test "ZREM variadic version" { 177 r del ztmp 178 r zadd ztmp 10 a 20 b 30 c 179 assert_equal 2 [r zrem ztmp x y a b k] 180 assert_equal 0 [r zrem ztmp foo bar] 181 assert_equal 1 [r zrem ztmp c] 182 r exists ztmp 183 } {0} 184 185 test "ZREM variadic version -- remove elements after key deletion" { 186 r del ztmp 187 r zadd ztmp 10 a 20 b 30 c 188 r zrem ztmp a b c d e f g 189 } {3} 190 191 test "ZRANGE basics - $encoding" { 192 r del ztmp 193 r zadd ztmp 1 a 194 r zadd ztmp 2 b 195 r zadd ztmp 3 c 196 r zadd ztmp 4 d 197 198 assert_equal {a b c d} [r zrange ztmp 0 -1] 199 assert_equal {a b c} [r zrange ztmp 0 -2] 200 assert_equal {b c d} [r zrange ztmp 1 -1] 201 assert_equal {b c} [r zrange ztmp 1 -2] 202 assert_equal {c d} [r zrange ztmp -2 -1] 203 assert_equal {c} [r zrange ztmp -2 -2] 204 205 # out of range start index 206 assert_equal {a b c} [r zrange ztmp -5 2] 207 assert_equal {a b} [r zrange ztmp -5 1] 208 assert_equal {} [r zrange ztmp 5 -1] 209 assert_equal {} [r zrange ztmp 5 -2] 210 211 # out of range end index 212 assert_equal {a b c d} [r zrange ztmp 0 5] 213 assert_equal {b c d} [r zrange ztmp 1 5] 214 assert_equal {} [r zrange ztmp 0 -5] 215 assert_equal {} [r zrange ztmp 1 -5] 216 217 # withscores 218 assert_equal {a 1 b 2 c 3 d 4} [r zrange ztmp 0 -1 withscores] 219 } 220 221 test "ZREVRANGE basics - $encoding" { 222 r del ztmp 223 r zadd ztmp 1 a 224 r zadd ztmp 2 b 225 r zadd ztmp 3 c 226 r zadd ztmp 4 d 227 228 assert_equal {d c b a} [r zrevrange ztmp 0 -1] 229 assert_equal {d c b} [r zrevrange ztmp 0 -2] 230 assert_equal {c b a} [r zrevrange ztmp 1 -1] 231 assert_equal {c b} [r zrevrange ztmp 1 -2] 232 assert_equal {b a} [r zrevrange ztmp -2 -1] 233 assert_equal {b} [r zrevrange ztmp -2 -2] 234 235 # out of range start index 236 assert_equal {d c b} [r zrevrange ztmp -5 2] 237 assert_equal {d c} [r zrevrange ztmp -5 1] 238 assert_equal {} [r zrevrange ztmp 5 -1] 239 assert_equal {} [r zrevrange ztmp 5 -2] 240 241 # out of range end index 242 assert_equal {d c b a} [r zrevrange ztmp 0 5] 243 assert_equal {c b a} [r zrevrange ztmp 1 5] 244 assert_equal {} [r zrevrange ztmp 0 -5] 245 assert_equal {} [r zrevrange ztmp 1 -5] 246 247 # withscores 248 assert_equal {d 4 c 3 b 2 a 1} [r zrevrange ztmp 0 -1 withscores] 249 } 250 251 test "ZRANK/ZREVRANK basics - $encoding" { 252 r del zranktmp 253 r zadd zranktmp 10 x 254 r zadd zranktmp 20 y 255 r zadd zranktmp 30 z 256 assert_equal 0 [r zrank zranktmp x] 257 assert_equal 1 [r zrank zranktmp y] 258 assert_equal 2 [r zrank zranktmp z] 259 assert_equal "" [r zrank zranktmp foo] 260 assert_equal 2 [r zrevrank zranktmp x] 261 assert_equal 1 [r zrevrank zranktmp y] 262 assert_equal 0 [r zrevrank zranktmp z] 263 assert_equal "" [r zrevrank zranktmp foo] 264 } 265 266 test "ZRANK - after deletion - $encoding" { 267 r zrem zranktmp y 268 assert_equal 0 [r zrank zranktmp x] 269 assert_equal 1 [r zrank zranktmp z] 270 } 271 272 test "ZINCRBY - can create a new sorted set - $encoding" { 273 r del zset 274 r zincrby zset 1 foo 275 assert_equal {foo} [r zrange zset 0 -1] 276 assert_equal 1 [r zscore zset foo] 277 } 278 279 test "ZINCRBY - increment and decrement - $encoding" { 280 r zincrby zset 2 foo 281 r zincrby zset 1 bar 282 assert_equal {bar foo} [r zrange zset 0 -1] 283 284 r zincrby zset 10 bar 285 r zincrby zset -5 foo 286 r zincrby zset -5 bar 287 assert_equal {foo bar} [r zrange zset 0 -1] 288 289 assert_equal -2 [r zscore zset foo] 290 assert_equal 6 [r zscore zset bar] 291 } 292 293 test "ZINCRBY return value" { 294 r del ztmp 295 set retval [r zincrby ztmp 1.0 x] 296 assert {$retval == 1.0} 297 } 298 299 proc create_default_zset {} { 300 create_zset zset {-inf a 1 b 2 c 3 d 4 e 5 f +inf g} 301 } 302 303 test "ZRANGEBYSCORE/ZREVRANGEBYSCORE/ZCOUNT basics" { 304 create_default_zset 305 306 # inclusive range 307 assert_equal {a b c} [r zrangebyscore zset -inf 2] 308 assert_equal {b c d} [r zrangebyscore zset 0 3] 309 assert_equal {d e f} [r zrangebyscore zset 3 6] 310 assert_equal {e f g} [r zrangebyscore zset 4 +inf] 311 assert_equal {c b a} [r zrevrangebyscore zset 2 -inf] 312 assert_equal {d c b} [r zrevrangebyscore zset 3 0] 313 assert_equal {f e d} [r zrevrangebyscore zset 6 3] 314 assert_equal {g f e} [r zrevrangebyscore zset +inf 4] 315 assert_equal 3 [r zcount zset 0 3] 316 317 # exclusive range 318 assert_equal {b} [r zrangebyscore zset (-inf (2] 319 assert_equal {b c} [r zrangebyscore zset (0 (3] 320 assert_equal {e f} [r zrangebyscore zset (3 (6] 321 assert_equal {f} [r zrangebyscore zset (4 (+inf] 322 assert_equal {b} [r zrevrangebyscore zset (2 (-inf] 323 assert_equal {c b} [r zrevrangebyscore zset (3 (0] 324 assert_equal {f e} [r zrevrangebyscore zset (6 (3] 325 assert_equal {f} [r zrevrangebyscore zset (+inf (4] 326 assert_equal 2 [r zcount zset (0 (3] 327 328 # test empty ranges 329 r zrem zset a 330 r zrem zset g 331 332 # inclusive 333 assert_equal {} [r zrangebyscore zset 4 2] 334 assert_equal {} [r zrangebyscore zset 6 +inf] 335 assert_equal {} [r zrangebyscore zset -inf -6] 336 assert_equal {} [r zrevrangebyscore zset +inf 6] 337 assert_equal {} [r zrevrangebyscore zset -6 -inf] 338 339 # exclusive 340 assert_equal {} [r zrangebyscore zset (4 (2] 341 assert_equal {} [r zrangebyscore zset 2 (2] 342 assert_equal {} [r zrangebyscore zset (2 2] 343 assert_equal {} [r zrangebyscore zset (6 (+inf] 344 assert_equal {} [r zrangebyscore zset (-inf (-6] 345 assert_equal {} [r zrevrangebyscore zset (+inf (6] 346 assert_equal {} [r zrevrangebyscore zset (-6 (-inf] 347 348 # empty inner range 349 assert_equal {} [r zrangebyscore zset 2.4 2.6] 350 assert_equal {} [r zrangebyscore zset (2.4 2.6] 351 assert_equal {} [r zrangebyscore zset 2.4 (2.6] 352 assert_equal {} [r zrangebyscore zset (2.4 (2.6] 353 } 354 355 test "ZRANGEBYSCORE with WITHSCORES" { 356 create_default_zset 357 assert_equal {b 1 c 2 d 3} [r zrangebyscore zset 0 3 withscores] 358 assert_equal {d 3 c 2 b 1} [r zrevrangebyscore zset 3 0 withscores] 359 } 360 361 test "ZRANGEBYSCORE with LIMIT" { 362 create_default_zset 363 assert_equal {b c} [r zrangebyscore zset 0 10 LIMIT 0 2] 364 assert_equal {d e f} [r zrangebyscore zset 0 10 LIMIT 2 3] 365 assert_equal {d e f} [r zrangebyscore zset 0 10 LIMIT 2 10] 366 assert_equal {} [r zrangebyscore zset 0 10 LIMIT 20 10] 367 assert_equal {f e} [r zrevrangebyscore zset 10 0 LIMIT 0 2] 368 assert_equal {d c b} [r zrevrangebyscore zset 10 0 LIMIT 2 3] 369 assert_equal {d c b} [r zrevrangebyscore zset 10 0 LIMIT 2 10] 370 assert_equal {} [r zrevrangebyscore zset 10 0 LIMIT 20 10] 371 } 372 373 test "ZRANGEBYSCORE with LIMIT and WITHSCORES" { 374 create_default_zset 375 assert_equal {e 4 f 5} [r zrangebyscore zset 2 5 LIMIT 2 3 WITHSCORES] 376 assert_equal {d 3 c 2} [r zrevrangebyscore zset 5 2 LIMIT 2 3 WITHSCORES] 377 } 378 379 test "ZRANGEBYSCORE with non-value min or max" { 380 assert_error "*not*float*" {r zrangebyscore fooz str 1} 381 assert_error "*not*float*" {r zrangebyscore fooz 1 str} 382 assert_error "*not*float*" {r zrangebyscore fooz 1 NaN} 383 } 384 385 proc create_default_lex_zset {} { 386 create_zset zset {0 alpha 0 bar 0 cool 0 down 387 0 elephant 0 foo 0 great 0 hill 388 0 omega} 389 } 390 391 test "ZRANGEBYLEX/ZREVRANGEBYLEX/ZCOUNT basics" { 392 create_default_lex_zset 393 394 # inclusive range 395 assert_equal {alpha bar cool} [r zrangebylex zset - \[cool] 396 assert_equal {bar cool down} [r zrangebylex zset \[bar \[down] 397 assert_equal {great hill omega} [r zrangebylex zset \[g +] 398 assert_equal {cool bar alpha} [r zrevrangebylex zset \[cool -] 399 assert_equal {down cool bar} [r zrevrangebylex zset \[down \[bar] 400 assert_equal {omega hill great foo elephant down} [r zrevrangebylex zset + \[d] 401 assert_equal 3 [r zlexcount zset \[ele \[h] 402 403 # exclusive range 404 assert_equal {alpha bar} [r zrangebylex zset - (cool] 405 assert_equal {cool} [r zrangebylex zset (bar (down] 406 assert_equal {hill omega} [r zrangebylex zset (great +] 407 assert_equal {bar alpha} [r zrevrangebylex zset (cool -] 408 assert_equal {cool} [r zrevrangebylex zset (down (bar] 409 assert_equal {omega hill} [r zrevrangebylex zset + (great] 410 assert_equal 2 [r zlexcount zset (ele (great] 411 412 # inclusive and exclusive 413 assert_equal {} [r zrangebylex zset (az (b] 414 assert_equal {} [r zrangebylex zset (z +] 415 assert_equal {} [r zrangebylex zset - \[aaaa] 416 assert_equal {} [r zrevrangebylex zset \[elez \[elex] 417 assert_equal {} [r zrevrangebylex zset (hill (omega] 418 } 419 420 test "ZRANGEBYSLEX with LIMIT" { 421 create_default_lex_zset 422 assert_equal {alpha bar} [r zrangebylex zset - \[cool LIMIT 0 2] 423 assert_equal {bar cool} [r zrangebylex zset - \[cool LIMIT 1 2] 424 assert_equal {} [r zrangebylex zset \[bar \[down LIMIT 0 0] 425 assert_equal {} [r zrangebylex zset \[bar \[down LIMIT 2 0] 426 assert_equal {bar} [r zrangebylex zset \[bar \[down LIMIT 0 1] 427 assert_equal {cool} [r zrangebylex zset \[bar \[down LIMIT 1 1] 428 assert_equal {bar cool down} [r zrangebylex zset \[bar \[down LIMIT 0 100] 429 assert_equal {omega hill great foo elephant} [r zrevrangebylex zset + \[d LIMIT 0 5] 430 assert_equal {omega hill great foo} [r zrevrangebylex zset + \[d LIMIT 0 4] 431 } 432 433 test "ZRANGEBYLEX with invalid lex range specifiers" { 434 assert_error "*not*string*" {r zrangebylex fooz foo bar} 435 assert_error "*not*string*" {r zrangebylex fooz \[foo bar} 436 assert_error "*not*string*" {r zrangebylex fooz foo \[bar} 437 assert_error "*not*string*" {r zrangebylex fooz +x \[bar} 438 assert_error "*not*string*" {r zrangebylex fooz -x \[bar} 439 } 440 441 test "ZREMRANGEBYSCORE basics" { 442 proc remrangebyscore {min max} { 443 create_zset zset {1 a 2 b 3 c 4 d 5 e} 444 assert_equal 1 [r exists zset] 445 r zremrangebyscore zset $min $max 446 } 447 448 # inner range 449 assert_equal 3 [remrangebyscore 2 4] 450 assert_equal {a e} [r zrange zset 0 -1] 451 452 # start underflow 453 assert_equal 1 [remrangebyscore -10 1] 454 assert_equal {b c d e} [r zrange zset 0 -1] 455 456 # end overflow 457 assert_equal 1 [remrangebyscore 5 10] 458 assert_equal {a b c d} [r zrange zset 0 -1] 459 460 # switch min and max 461 assert_equal 0 [remrangebyscore 4 2] 462 assert_equal {a b c d e} [r zrange zset 0 -1] 463 464 # -inf to mid 465 assert_equal 3 [remrangebyscore -inf 3] 466 assert_equal {d e} [r zrange zset 0 -1] 467 468 # mid to +inf 469 assert_equal 3 [remrangebyscore 3 +inf] 470 assert_equal {a b} [r zrange zset 0 -1] 471 472 # -inf to +inf 473 assert_equal 5 [remrangebyscore -inf +inf] 474 assert_equal {} [r zrange zset 0 -1] 475 476 # exclusive min 477 assert_equal 4 [remrangebyscore (1 5] 478 assert_equal {a} [r zrange zset 0 -1] 479 assert_equal 3 [remrangebyscore (2 5] 480 assert_equal {a b} [r zrange zset 0 -1] 481 482 # exclusive max 483 assert_equal 4 [remrangebyscore 1 (5] 484 assert_equal {e} [r zrange zset 0 -1] 485 assert_equal 3 [remrangebyscore 1 (4] 486 assert_equal {d e} [r zrange zset 0 -1] 487 488 # exclusive min and max 489 assert_equal 3 [remrangebyscore (1 (5] 490 assert_equal {a e} [r zrange zset 0 -1] 491 492 # destroy when empty 493 assert_equal 5 [remrangebyscore 1 5] 494 assert_equal 0 [r exists zset] 495 } 496 497 test "ZREMRANGEBYSCORE with non-value min or max" { 498 assert_error "*not*float*" {r zremrangebyscore fooz str 1} 499 assert_error "*not*float*" {r zremrangebyscore fooz 1 str} 500 assert_error "*not*float*" {r zremrangebyscore fooz 1 NaN} 501 } 502 503 test "ZREMRANGEBYRANK basics" { 504 proc remrangebyrank {min max} { 505 create_zset zset {1 a 2 b 3 c 4 d 5 e} 506 assert_equal 1 [r exists zset] 507 r zremrangebyrank zset $min $max 508 } 509 510 # inner range 511 assert_equal 3 [remrangebyrank 1 3] 512 assert_equal {a e} [r zrange zset 0 -1] 513 514 # start underflow 515 assert_equal 1 [remrangebyrank -10 0] 516 assert_equal {b c d e} [r zrange zset 0 -1] 517 518 # start overflow 519 assert_equal 0 [remrangebyrank 10 -1] 520 assert_equal {a b c d e} [r zrange zset 0 -1] 521 522 # end underflow 523 assert_equal 0 [remrangebyrank 0 -10] 524 assert_equal {a b c d e} [r zrange zset 0 -1] 525 526 # end overflow 527 assert_equal 5 [remrangebyrank 0 10] 528 assert_equal {} [r zrange zset 0 -1] 529 530 # destroy when empty 531 assert_equal 5 [remrangebyrank 0 4] 532 assert_equal 0 [r exists zset] 533 } 534 535 test "ZUNIONSTORE against non-existing key doesn't set destination - $encoding" { 536 r del zseta 537 assert_equal 0 [r zunionstore dst_key 1 zseta] 538 assert_equal 0 [r exists dst_key] 539 } 540 541 test "ZUNIONSTORE with empty set - $encoding" { 542 r del zseta zsetb 543 r zadd zseta 1 a 544 r zadd zseta 2 b 545 r zunionstore zsetc 2 zseta zsetb 546 r zrange zsetc 0 -1 withscores 547 } {a 1 b 2} 548 549 test "ZUNIONSTORE basics - $encoding" { 550 r del zseta zsetb zsetc 551 r zadd zseta 1 a 552 r zadd zseta 2 b 553 r zadd zseta 3 c 554 r zadd zsetb 1 b 555 r zadd zsetb 2 c 556 r zadd zsetb 3 d 557 558 assert_equal 4 [r zunionstore zsetc 2 zseta zsetb] 559 assert_equal {a 1 b 3 d 3 c 5} [r zrange zsetc 0 -1 withscores] 560 } 561 562 test "ZUNIONSTORE with weights - $encoding" { 563 assert_equal 4 [r zunionstore zsetc 2 zseta zsetb weights 2 3] 564 assert_equal {a 2 b 7 d 9 c 12} [r zrange zsetc 0 -1 withscores] 565 } 566 567 test "ZUNIONSTORE with a regular set and weights - $encoding" { 568 r del seta 569 r sadd seta a 570 r sadd seta b 571 r sadd seta c 572 573 assert_equal 4 [r zunionstore zsetc 2 seta zsetb weights 2 3] 574 assert_equal {a 2 b 5 c 8 d 9} [r zrange zsetc 0 -1 withscores] 575 } 576 577 test "ZUNIONSTORE with AGGREGATE MIN - $encoding" { 578 assert_equal 4 [r zunionstore zsetc 2 zseta zsetb aggregate min] 579 assert_equal {a 1 b 1 c 2 d 3} [r zrange zsetc 0 -1 withscores] 580 } 581 582 test "ZUNIONSTORE with AGGREGATE MAX - $encoding" { 583 assert_equal 4 [r zunionstore zsetc 2 zseta zsetb aggregate max] 584 assert_equal {a 1 b 2 c 3 d 3} [r zrange zsetc 0 -1 withscores] 585 } 586 587 test "ZINTERSTORE basics - $encoding" { 588 assert_equal 2 [r zinterstore zsetc 2 zseta zsetb] 589 assert_equal {b 3 c 5} [r zrange zsetc 0 -1 withscores] 590 } 591 592 test "ZINTERSTORE with weights - $encoding" { 593 assert_equal 2 [r zinterstore zsetc 2 zseta zsetb weights 2 3] 594 assert_equal {b 7 c 12} [r zrange zsetc 0 -1 withscores] 595 } 596 597 test "ZINTERSTORE with a regular set and weights - $encoding" { 598 r del seta 599 r sadd seta a 600 r sadd seta b 601 r sadd seta c 602 assert_equal 2 [r zinterstore zsetc 2 seta zsetb weights 2 3] 603 assert_equal {b 5 c 8} [r zrange zsetc 0 -1 withscores] 604 } 605 606 test "ZINTERSTORE with AGGREGATE MIN - $encoding" { 607 assert_equal 2 [r zinterstore zsetc 2 zseta zsetb aggregate min] 608 assert_equal {b 1 c 2} [r zrange zsetc 0 -1 withscores] 609 } 610 611 test "ZINTERSTORE with AGGREGATE MAX - $encoding" { 612 assert_equal 2 [r zinterstore zsetc 2 zseta zsetb aggregate max] 613 assert_equal {b 2 c 3} [r zrange zsetc 0 -1 withscores] 614 } 615 616 foreach cmd {ZUNIONSTORE ZINTERSTORE} { 617 test "$cmd with +inf/-inf scores - $encoding" { 618 r del zsetinf1 zsetinf2 619 620 r zadd zsetinf1 +inf key 621 r zadd zsetinf2 +inf key 622 r $cmd zsetinf3 2 zsetinf1 zsetinf2 623 assert_equal inf [r zscore zsetinf3 key] 624 625 r zadd zsetinf1 -inf key 626 r zadd zsetinf2 +inf key 627 r $cmd zsetinf3 2 zsetinf1 zsetinf2 628 assert_equal 0 [r zscore zsetinf3 key] 629 630 r zadd zsetinf1 +inf key 631 r zadd zsetinf2 -inf key 632 r $cmd zsetinf3 2 zsetinf1 zsetinf2 633 assert_equal 0 [r zscore zsetinf3 key] 634 635 r zadd zsetinf1 -inf key 636 r zadd zsetinf2 -inf key 637 r $cmd zsetinf3 2 zsetinf1 zsetinf2 638 assert_equal -inf [r zscore zsetinf3 key] 639 } 640 641 test "$cmd with NaN weights $encoding" { 642 r del zsetinf1 zsetinf2 643 644 r zadd zsetinf1 1.0 key 645 r zadd zsetinf2 1.0 key 646 assert_error "*weight*not*float*" { 647 r $cmd zsetinf3 2 zsetinf1 zsetinf2 weights nan nan 648 } 649 } 650 } 651 } 652 653 basics ziplist 654 basics skiplist 655 656 test {ZINTERSTORE regression with two sets, intset+hashtable} { 657 r del seta setb setc 658 r sadd set1 a 659 r sadd set2 10 660 r zinterstore set3 2 set1 set2 661 } {0} 662 663 test {ZUNIONSTORE regression, should not create NaN in scores} { 664 r zadd z -inf neginf 665 r zunionstore out 1 z weights 0 666 r zrange out 0 -1 withscores 667 } {neginf 0} 668 669 test {ZINTERSTORE #516 regression, mixed sets and ziplist zsets} { 670 r sadd one 100 101 102 103 671 r sadd two 100 200 201 202 672 r zadd three 1 500 1 501 1 502 1 503 1 100 673 r zinterstore to_here 3 one two three WEIGHTS 0 0 1 674 r zrange to_here 0 -1 675 } {100} 676 677 test {ZUNIONSTORE result is sorted} { 678 # Create two sets with common and not common elements, perform 679 # the UNION, check that elements are still sorted. 680 r del one two dest 681 set cmd1 [list r zadd one] 682 set cmd2 [list r zadd two] 683 for {set j 0} {$j < 1000} {incr j} { 684 lappend cmd1 [expr rand()] [randomInt 1000] 685 lappend cmd2 [expr rand()] [randomInt 1000] 686 } 687 {*}$cmd1 688 {*}$cmd2 689 assert {[r zcard one] > 100} 690 assert {[r zcard two] > 100} 691 r zunionstore dest 2 one two 692 set oldscore 0 693 foreach {ele score} [r zrange dest 0 -1 withscores] { 694 assert {$score >= $oldscore} 695 set oldscore $score 696 } 697 } 698 699 proc stressers {encoding} { 700 if {$encoding == "ziplist"} { 701 # Little extra to allow proper fuzzing in the sorting stresser 702 r config set zset-max-ziplist-entries 256 703 r config set zset-max-ziplist-value 64 704 set elements 128 705 } elseif {$encoding == "skiplist"} { 706 r config set zset-max-ziplist-entries 0 707 r config set zset-max-ziplist-value 0 708 if {$::accurate} {set elements 1000} else {set elements 100} 709 } else { 710 puts "Unknown sorted set encoding" 711 exit 712 } 713 714 test "ZSCORE - $encoding" { 715 r del zscoretest 716 set aux {} 717 for {set i 0} {$i < $elements} {incr i} { 718 set score [expr rand()] 719 lappend aux $score 720 r zadd zscoretest $score $i 721 } 722 723 assert_encoding $encoding zscoretest 724 for {set i 0} {$i < $elements} {incr i} { 725 assert_equal [lindex $aux $i] [r zscore zscoretest $i] 726 } 727 } 728 729 test "ZSCORE after a DEBUG RELOAD - $encoding" { 730 r del zscoretest 731 set aux {} 732 for {set i 0} {$i < $elements} {incr i} { 733 set score [expr rand()] 734 lappend aux $score 735 r zadd zscoretest $score $i 736 } 737 738 r debug reload 739 assert_encoding $encoding zscoretest 740 for {set i 0} {$i < $elements} {incr i} { 741 assert_equal [lindex $aux $i] [r zscore zscoretest $i] 742 } 743 } 744 745 test "ZSET sorting stresser - $encoding" { 746 set delta 0 747 for {set test 0} {$test < 2} {incr test} { 748 unset -nocomplain auxarray 749 array set auxarray {} 750 set auxlist {} 751 r del myzset 752 for {set i 0} {$i < $elements} {incr i} { 753 if {$test == 0} { 754 set score [expr rand()] 755 } else { 756 set score [expr int(rand()*10)] 757 } 758 set auxarray($i) $score 759 r zadd myzset $score $i 760 # Random update 761 if {[expr rand()] < .2} { 762 set j [expr int(rand()*1000)] 763 if {$test == 0} { 764 set score [expr rand()] 765 } else { 766 set score [expr int(rand()*10)] 767 } 768 set auxarray($j) $score 769 r zadd myzset $score $j 770 } 771 } 772 foreach {item score} [array get auxarray] { 773 lappend auxlist [list $score $item] 774 } 775 set sorted [lsort -command zlistAlikeSort $auxlist] 776 set auxlist {} 777 foreach x $sorted { 778 lappend auxlist [lindex $x 1] 779 } 780 781 assert_encoding $encoding myzset 782 set fromredis [r zrange myzset 0 -1] 783 set delta 0 784 for {set i 0} {$i < [llength $fromredis]} {incr i} { 785 if {[lindex $fromredis $i] != [lindex $auxlist $i]} { 786 incr delta 787 } 788 } 789 } 790 assert_equal 0 $delta 791 } 792 793 test "ZRANGEBYSCORE fuzzy test, 100 ranges in $elements element sorted set - $encoding" { 794 set err {} 795 r del zset 796 for {set i 0} {$i < $elements} {incr i} { 797 r zadd zset [expr rand()] $i 798 } 799 800 assert_encoding $encoding zset 801 for {set i 0} {$i < 100} {incr i} { 802 set min [expr rand()] 803 set max [expr rand()] 804 if {$min > $max} { 805 set aux $min 806 set min $max 807 set max $aux 808 } 809 set low [r zrangebyscore zset -inf $min] 810 set ok [r zrangebyscore zset $min $max] 811 set high [r zrangebyscore zset $max +inf] 812 set lowx [r zrangebyscore zset -inf ($min] 813 set okx [r zrangebyscore zset ($min ($max] 814 set highx [r zrangebyscore zset ($max +inf] 815 816 if {[r zcount zset -inf $min] != [llength $low]} { 817 append err "Error, len does not match zcount\n" 818 } 819 if {[r zcount zset $min $max] != [llength $ok]} { 820 append err "Error, len does not match zcount\n" 821 } 822 if {[r zcount zset $max +inf] != [llength $high]} { 823 append err "Error, len does not match zcount\n" 824 } 825 if {[r zcount zset -inf ($min] != [llength $lowx]} { 826 append err "Error, len does not match zcount\n" 827 } 828 if {[r zcount zset ($min ($max] != [llength $okx]} { 829 append err "Error, len does not match zcount\n" 830 } 831 if {[r zcount zset ($max +inf] != [llength $highx]} { 832 append err "Error, len does not match zcount\n" 833 } 834 835 foreach x $low { 836 set score [r zscore zset $x] 837 if {$score > $min} { 838 append err "Error, score for $x is $score > $min\n" 839 } 840 } 841 foreach x $lowx { 842 set score [r zscore zset $x] 843 if {$score >= $min} { 844 append err "Error, score for $x is $score >= $min\n" 845 } 846 } 847 foreach x $ok { 848 set score [r zscore zset $x] 849 if {$score < $min || $score > $max} { 850 append err "Error, score for $x is $score outside $min-$max range\n" 851 } 852 } 853 foreach x $okx { 854 set score [r zscore zset $x] 855 if {$score <= $min || $score >= $max} { 856 append err "Error, score for $x is $score outside $min-$max open range\n" 857 } 858 } 859 foreach x $high { 860 set score [r zscore zset $x] 861 if {$score < $max} { 862 append err "Error, score for $x is $score < $max\n" 863 } 864 } 865 foreach x $highx { 866 set score [r zscore zset $x] 867 if {$score <= $max} { 868 append err "Error, score for $x is $score <= $max\n" 869 } 870 } 871 } 872 assert_equal {} $err 873 } 874 875 test "ZRANGEBYLEX fuzzy test, 100 ranges in $elements element sorted set - $encoding" { 876 set lexset {} 877 r del zset 878 for {set j 0} {$j < $elements} {incr j} { 879 set e [randstring 0 30 alpha] 880 lappend lexset $e 881 r zadd zset 0 $e 882 } 883 set lexset [lsort -unique $lexset] 884 for {set j 0} {$j < 100} {incr j} { 885 set min [randstring 0 30 alpha] 886 set max [randstring 0 30 alpha] 887 set mininc [randomInt 2] 888 set maxinc [randomInt 2] 889 if {$mininc} {set cmin "\[$min"} else {set cmin "($min"} 890 if {$maxinc} {set cmax "\[$max"} else {set cmax "($max"} 891 set rev [randomInt 2] 892 if {$rev} { 893 set cmd zrevrangebylex 894 } else { 895 set cmd zrangebylex 896 } 897 898 # Make sure data is the same in both sides 899 assert {[r zrange zset 0 -1] eq $lexset} 900 901 # Get the Redis output 902 set output [r $cmd zset $cmin $cmax] 903 if {$rev} { 904 set outlen [r zlexcount zset $cmax $cmin] 905 } else { 906 set outlen [r zlexcount zset $cmin $cmax] 907 } 908 909 # Compute the same output via Tcl 910 set o {} 911 set copy $lexset 912 if {(!$rev && [string compare $min $max] > 0) || 913 ($rev && [string compare $max $min] > 0)} { 914 # Empty output when ranges are inverted. 915 } else { 916 if {$rev} { 917 # Invert the Tcl array using Redis itself. 918 set copy [r zrevrange zset 0 -1] 919 # Invert min / max as well 920 lassign [list $min $max $mininc $maxinc] \ 921 max min maxinc mininc 922 } 923 foreach e $copy { 924 set mincmp [string compare $e $min] 925 set maxcmp [string compare $e $max] 926 if { 927 ($mininc && $mincmp >= 0 || !$mininc && $mincmp > 0) 928 && 929 ($maxinc && $maxcmp <= 0 || !$maxinc && $maxcmp < 0) 930 } { 931 lappend o $e 932 } 933 } 934 } 935 assert {$o eq $output} 936 assert {$outlen eq [llength $output]} 937 } 938 } 939 940 test "ZREMRANGEBYLEX fuzzy test, 100 ranges in $elements element sorted set - $encoding" { 941 set lexset {} 942 r del zset zsetcopy 943 for {set j 0} {$j < $elements} {incr j} { 944 set e [randstring 0 30 alpha] 945 lappend lexset $e 946 r zadd zset 0 $e 947 } 948 set lexset [lsort -unique $lexset] 949 for {set j 0} {$j < 100} {incr j} { 950 # Copy... 951 r zunionstore zsetcopy 1 zset 952 set lexsetcopy $lexset 953 954 set min [randstring 0 30 alpha] 955 set max [randstring 0 30 alpha] 956 set mininc [randomInt 2] 957 set maxinc [randomInt 2] 958 if {$mininc} {set cmin "\[$min"} else {set cmin "($min"} 959 if {$maxinc} {set cmax "\[$max"} else {set cmax "($max"} 960 961 # Make sure data is the same in both sides 962 assert {[r zrange zset 0 -1] eq $lexset} 963 964 # Get the range we are going to remove 965 set torem [r zrangebylex zset $cmin $cmax] 966 set toremlen [r zlexcount zset $cmin $cmax] 967 r zremrangebylex zsetcopy $cmin $cmax 968 set output [r zrange zsetcopy 0 -1] 969 970 # Remove the range with Tcl from the original list 971 if {$toremlen} { 972 set first [lsearch -exact $lexsetcopy [lindex $torem 0]] 973 set last [expr {$first+$toremlen-1}] 974 set lexsetcopy [lreplace $lexsetcopy $first $last] 975 } 976 assert {$lexsetcopy eq $output} 977 } 978 } 979 980 test "ZSETs skiplist implementation backlink consistency test - $encoding" { 981 set diff 0 982 for {set j 0} {$j < $elements} {incr j} { 983 r zadd myzset [expr rand()] "Element-$j" 984 r zrem myzset "Element-[expr int(rand()*$elements)]" 985 } 986 987 assert_encoding $encoding myzset 988 set l1 [r zrange myzset 0 -1] 989 set l2 [r zrevrange myzset 0 -1] 990 for {set j 0} {$j < [llength $l1]} {incr j} { 991 if {[lindex $l1 $j] ne [lindex $l2 end-$j]} { 992 incr diff 993 } 994 } 995 assert_equal 0 $diff 996 } 997 998 test "ZSETs ZRANK augmented skip list stress testing - $encoding" { 999 set err {} 1000 r del myzset 1001 for {set k 0} {$k < 2000} {incr k} { 1002 set i [expr {$k % $elements}] 1003 if {[expr rand()] < .2} { 1004 r zrem myzset $i 1005 } else { 1006 set score [expr rand()] 1007 r zadd myzset $score $i 1008 assert_encoding $encoding myzset 1009 } 1010 1011 set card [r zcard myzset] 1012 if {$card > 0} { 1013 set index [randomInt $card] 1014 set ele [lindex [r zrange myzset $index $index] 0] 1015 set rank [r zrank myzset $ele] 1016 if {$rank != $index} { 1017 set err "$ele RANK is wrong! ($rank != $index)" 1018 break 1019 } 1020 } 1021 } 1022 assert_equal {} $err 1023 } 1024 } 1025 1026 tags {"slow"} { 1027 stressers ziplist 1028 stressers skiplist 1029 } 1030} 1031