summaryrefslogtreecommitdiffstats
path: root/tests/unit/keyspace.tcl
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tests/unit/keyspace.tcl498
1 files changed, 498 insertions, 0 deletions
diff --git a/tests/unit/keyspace.tcl b/tests/unit/keyspace.tcl
new file mode 100644
index 0000000..437f71f
--- /dev/null
+++ b/tests/unit/keyspace.tcl
@@ -0,0 +1,498 @@
+start_server {tags {"keyspace"}} {
+ test {DEL against a single item} {
+ r set x foo
+ assert {[r get x] eq "foo"}
+ r del x
+ r get x
+ } {}
+
+ test {Vararg DEL} {
+ r set foo1{t} a
+ r set foo2{t} b
+ r set foo3{t} c
+ list [r del foo1{t} foo2{t} foo3{t} foo4{t}] [r mget foo1{t} foo2{t} foo3{t}]
+ } {3 {{} {} {}}}
+
+ test {Untagged multi-key commands} {
+ r mset foo1 a foo2 b foo3 c
+ assert_equal {a b c {}} [r mget foo1 foo2 foo3 foo4]
+ r del foo1 foo2 foo3 foo4
+ } {3} {cluster:skip}
+
+ test {KEYS with pattern} {
+ foreach key {key_x key_y key_z foo_a foo_b foo_c} {
+ r set $key hello
+ }
+ lsort [r keys foo*]
+ } {foo_a foo_b foo_c}
+
+ test {KEYS to get all keys} {
+ lsort [r keys *]
+ } {foo_a foo_b foo_c key_x key_y key_z}
+
+ test {DBSIZE} {
+ r dbsize
+ } {6}
+
+ test {DEL all keys} {
+ foreach key [r keys *] {r del $key}
+ r dbsize
+ } {0}
+
+ test "DEL against expired key" {
+ r debug set-active-expire 0
+ r setex keyExpire 1 valExpire
+ after 1100
+ assert_equal 0 [r del keyExpire]
+ r debug set-active-expire 1
+ } {OK} {needs:debug}
+
+ test {EXISTS} {
+ set res {}
+ r set newkey test
+ append res [r exists newkey]
+ r del newkey
+ append res [r exists newkey]
+ } {10}
+
+ test {Zero length value in key. SET/GET/EXISTS} {
+ r set emptykey {}
+ set res [r get emptykey]
+ append res [r exists emptykey]
+ r del emptykey
+ append res [r exists emptykey]
+ } {10}
+
+ test {Commands pipelining} {
+ set fd [r channel]
+ puts -nonewline $fd "SET k1 xyzk\r\nGET k1\r\nPING\r\n"
+ flush $fd
+ set res {}
+ append res [string match OK* [r read]]
+ append res [r read]
+ append res [string match PONG* [r read]]
+ format $res
+ } {1xyzk1}
+
+ test {Non existing command} {
+ catch {r foobaredcommand} err
+ string match ERR* $err
+ } {1}
+
+ test {RENAME basic usage} {
+ r set mykey{t} hello
+ r rename mykey{t} mykey1{t}
+ r rename mykey1{t} mykey2{t}
+ r get mykey2{t}
+ } {hello}
+
+ test {RENAME source key should no longer exist} {
+ r exists mykey
+ } {0}
+
+ test {RENAME against already existing key} {
+ r set mykey{t} a
+ r set mykey2{t} b
+ r rename mykey2{t} mykey{t}
+ set res [r get mykey{t}]
+ append res [r exists mykey2{t}]
+ } {b0}
+
+ test {RENAMENX basic usage} {
+ r del mykey{t}
+ r del mykey2{t}
+ r set mykey{t} foobar
+ r renamenx mykey{t} mykey2{t}
+ set res [r get mykey2{t}]
+ append res [r exists mykey{t}]
+ } {foobar0}
+
+ test {RENAMENX against already existing key} {
+ r set mykey{t} foo
+ r set mykey2{t} bar
+ r renamenx mykey{t} mykey2{t}
+ } {0}
+
+ test {RENAMENX against already existing key (2)} {
+ set res [r get mykey{t}]
+ append res [r get mykey2{t}]
+ } {foobar}
+
+ test {RENAME against non existing source key} {
+ catch {r rename nokey{t} foobar{t}} err
+ format $err
+ } {ERR*}
+
+ test {RENAME where source and dest key are the same (existing)} {
+ r set mykey foo
+ r rename mykey mykey
+ } {OK}
+
+ test {RENAMENX where source and dest key are the same (existing)} {
+ r set mykey foo
+ r renamenx mykey mykey
+ } {0}
+
+ test {RENAME where source and dest key are the same (non existing)} {
+ r del mykey
+ catch {r rename mykey mykey} err
+ format $err
+ } {ERR*}
+
+ test {RENAME with volatile key, should move the TTL as well} {
+ r del mykey{t} mykey2{t}
+ r set mykey{t} foo
+ r expire mykey{t} 100
+ assert {[r ttl mykey{t}] > 95 && [r ttl mykey{t}] <= 100}
+ r rename mykey{t} mykey2{t}
+ assert {[r ttl mykey2{t}] > 95 && [r ttl mykey2{t}] <= 100}
+ }
+
+ test {RENAME with volatile key, should not inherit TTL of target key} {
+ r del mykey{t} mykey2{t}
+ r set mykey{t} foo
+ r set mykey2{t} bar
+ r expire mykey2{t} 100
+ assert {[r ttl mykey{t}] == -1 && [r ttl mykey2{t}] > 0}
+ r rename mykey{t} mykey2{t}
+ r ttl mykey2{t}
+ } {-1}
+
+ test {DEL all keys again (DB 0)} {
+ foreach key [r keys *] {
+ r del $key
+ }
+ r dbsize
+ } {0}
+
+ test {DEL all keys again (DB 1)} {
+ r select 10
+ foreach key [r keys *] {
+ r del $key
+ }
+ set res [r dbsize]
+ r select 9
+ format $res
+ } {0} {singledb:skip}
+
+ test {COPY basic usage for string} {
+ r set mykey{t} foobar
+ set res {}
+ r copy mykey{t} mynewkey{t}
+ lappend res [r get mynewkey{t}]
+ lappend res [r dbsize]
+ if {$::singledb} {
+ assert_equal [list foobar 2] [format $res]
+ } else {
+ r copy mykey{t} mynewkey{t} DB 10
+ r select 10
+ lappend res [r get mynewkey{t}]
+ lappend res [r dbsize]
+ r select 9
+ assert_equal [list foobar 2 foobar 1] [format $res]
+ }
+ }
+
+ test {COPY for string does not replace an existing key without REPLACE option} {
+ r set mykey2{t} hello
+ catch {r copy mykey2{t} mynewkey{t} DB 10} e
+ set e
+ } {0} {singledb:skip}
+
+ test {COPY for string can replace an existing key with REPLACE option} {
+ r copy mykey2{t} mynewkey{t} DB 10 REPLACE
+ r select 10
+ r get mynewkey{t}
+ } {hello} {singledb:skip}
+
+ test {COPY for string ensures that copied data is independent of copying data} {
+ r flushdb
+ r select 9
+ r set mykey{t} foobar
+ set res {}
+ r copy mykey{t} mynewkey{t} DB 10
+ r select 10
+ lappend res [r get mynewkey{t}]
+ r set mynewkey{t} hoge
+ lappend res [r get mynewkey{t}]
+ r select 9
+ lappend res [r get mykey{t}]
+ r select 10
+ r flushdb
+ r select 9
+ format $res
+ } [list foobar hoge foobar] {singledb:skip}
+
+ test {COPY for string does not copy data to no-integer DB} {
+ r set mykey{t} foobar
+ catch {r copy mykey{t} mynewkey{t} DB notanumber} e
+ set e
+ } {ERR value is not an integer or out of range}
+
+ test {COPY can copy key expire metadata as well} {
+ r set mykey{t} foobar ex 100
+ r copy mykey{t} mynewkey{t} REPLACE
+ assert {[r ttl mynewkey{t}] > 0 && [r ttl mynewkey{t}] <= 100}
+ assert {[r get mynewkey{t}] eq "foobar"}
+ }
+
+ test {COPY does not create an expire if it does not exist} {
+ r set mykey{t} foobar
+ assert {[r ttl mykey{t}] == -1}
+ r copy mykey{t} mynewkey{t} REPLACE
+ assert {[r ttl mynewkey{t}] == -1}
+ assert {[r get mynewkey{t}] eq "foobar"}
+ }
+
+ test {COPY basic usage for list} {
+ r del mylist{t} mynewlist{t}
+ r lpush mylist{t} a b c d
+ r copy mylist{t} mynewlist{t}
+ set digest [debug_digest_value mylist{t}]
+ assert_equal $digest [debug_digest_value mynewlist{t}]
+ assert_refcount 1 mylist{t}
+ assert_refcount 1 mynewlist{t}
+ r del mylist{t}
+ assert_equal $digest [debug_digest_value mynewlist{t}]
+ }
+
+ test {COPY basic usage for intset set} {
+ r del set1{t} newset1{t}
+ r sadd set1{t} 1 2 3
+ assert_encoding intset set1{t}
+ r copy set1{t} newset1{t}
+ set digest [debug_digest_value set1{t}]
+ assert_equal $digest [debug_digest_value newset1{t}]
+ assert_refcount 1 set1{t}
+ assert_refcount 1 newset1{t}
+ r del set1{t}
+ assert_equal $digest [debug_digest_value newset1{t}]
+ }
+
+ test {COPY basic usage for hashtable set} {
+ r del set2{t} newset2{t}
+ r sadd set2{t} 1 2 3 a
+ assert_encoding hashtable set2{t}
+ r copy set2{t} newset2{t}
+ set digest [debug_digest_value set2{t}]
+ assert_equal $digest [debug_digest_value newset2{t}]
+ assert_refcount 1 set2{t}
+ assert_refcount 1 newset2{t}
+ r del set2{t}
+ assert_equal $digest [debug_digest_value newset2{t}]
+ }
+
+ test {COPY basic usage for listpack sorted set} {
+ r del zset1{t} newzset1{t}
+ r zadd zset1{t} 123 foobar
+ assert_encoding listpack zset1{t}
+ r copy zset1{t} newzset1{t}
+ set digest [debug_digest_value zset1{t}]
+ assert_equal $digest [debug_digest_value newzset1{t}]
+ assert_refcount 1 zset1{t}
+ assert_refcount 1 newzset1{t}
+ r del zset1{t}
+ assert_equal $digest [debug_digest_value newzset1{t}]
+ }
+
+ test {COPY basic usage for skiplist sorted set} {
+ r del zset2{t} newzset2{t}
+ set original_max [lindex [r config get zset-max-ziplist-entries] 1]
+ r config set zset-max-ziplist-entries 0
+ for {set j 0} {$j < 130} {incr j} {
+ r zadd zset2{t} [randomInt 50] ele-[randomInt 10]
+ }
+ assert_encoding skiplist zset2{t}
+ r copy zset2{t} newzset2{t}
+ set digest [debug_digest_value zset2{t}]
+ assert_equal $digest [debug_digest_value newzset2{t}]
+ assert_refcount 1 zset2{t}
+ assert_refcount 1 newzset2{t}
+ r del zset2{t}
+ assert_equal $digest [debug_digest_value newzset2{t}]
+ r config set zset-max-ziplist-entries $original_max
+ }
+
+ test {COPY basic usage for listpack hash} {
+ r del hash1{t} newhash1{t}
+ r hset hash1{t} tmp 17179869184
+ assert_encoding listpack hash1{t}
+ r copy hash1{t} newhash1{t}
+ set digest [debug_digest_value hash1{t}]
+ assert_equal $digest [debug_digest_value newhash1{t}]
+ assert_refcount 1 hash1{t}
+ assert_refcount 1 newhash1{t}
+ r del hash1{t}
+ assert_equal $digest [debug_digest_value newhash1{t}]
+ }
+
+ test {COPY basic usage for hashtable hash} {
+ r del hash2{t} newhash2{t}
+ set original_max [lindex [r config get hash-max-ziplist-entries] 1]
+ r config set hash-max-ziplist-entries 0
+ for {set i 0} {$i < 64} {incr i} {
+ r hset hash2{t} [randomValue] [randomValue]
+ }
+ assert_encoding hashtable hash2{t}
+ r copy hash2{t} newhash2{t}
+ set digest [debug_digest_value hash2{t}]
+ assert_equal $digest [debug_digest_value newhash2{t}]
+ assert_refcount 1 hash2{t}
+ assert_refcount 1 newhash2{t}
+ r del hash2{t}
+ assert_equal $digest [debug_digest_value newhash2{t}]
+ r config set hash-max-ziplist-entries $original_max
+ }
+
+ test {COPY basic usage for stream} {
+ r del mystream{t} mynewstream{t}
+ for {set i 0} {$i < 1000} {incr i} {
+ r XADD mystream{t} * item 2 value b
+ }
+ r copy mystream{t} mynewstream{t}
+ set digest [debug_digest_value mystream{t}]
+ assert_equal $digest [debug_digest_value mynewstream{t}]
+ assert_refcount 1 mystream{t}
+ assert_refcount 1 mynewstream{t}
+ r del mystream{t}
+ assert_equal $digest [debug_digest_value mynewstream{t}]
+ }
+
+ test {COPY basic usage for stream-cgroups} {
+ r del x{t}
+ r XADD x{t} 100 a 1
+ set id [r XADD x{t} 101 b 1]
+ r XADD x{t} 102 c 1
+ r XADD x{t} 103 e 1
+ r XADD x{t} 104 f 1
+ r XADD x{t} 105 g 1
+ r XGROUP CREATE x{t} g1 0
+ r XGROUP CREATE x{t} g2 0
+ r XREADGROUP GROUP g1 Alice COUNT 1 STREAMS x{t} >
+ r XREADGROUP GROUP g1 Bob COUNT 1 STREAMS x{t} >
+ r XREADGROUP GROUP g1 Bob NOACK COUNT 1 STREAMS x{t} >
+ r XREADGROUP GROUP g2 Charlie COUNT 4 STREAMS x{t} >
+ r XGROUP SETID x{t} g1 $id
+ r XREADGROUP GROUP g1 Dave COUNT 3 STREAMS x{t} >
+ r XDEL x{t} 103
+
+ r copy x{t} newx{t}
+ set info [r xinfo stream x{t} full]
+ assert_equal $info [r xinfo stream newx{t} full]
+ assert_refcount 1 x{t}
+ assert_refcount 1 newx{t}
+ r del x{t}
+ assert_equal $info [r xinfo stream newx{t} full]
+ r flushdb
+ }
+
+ test {MOVE basic usage} {
+ r set mykey foobar
+ r move mykey 10
+ set res {}
+ lappend res [r exists mykey]
+ lappend res [r dbsize]
+ r select 10
+ lappend res [r get mykey]
+ lappend res [r dbsize]
+ r select 9
+ format $res
+ } [list 0 0 foobar 1] {singledb:skip}
+
+ test {MOVE against key existing in the target DB} {
+ r set mykey hello
+ r move mykey 10
+ } {0} {singledb:skip}
+
+ test {MOVE against non-integer DB (#1428)} {
+ r set mykey hello
+ catch {r move mykey notanumber} e
+ set e
+ } {ERR value is not an integer or out of range} {singledb:skip}
+
+ test {MOVE can move key expire metadata as well} {
+ r select 10
+ r flushdb
+ r select 9
+ r set mykey foo ex 100
+ r move mykey 10
+ assert {[r ttl mykey] == -2}
+ r select 10
+ assert {[r ttl mykey] > 0 && [r ttl mykey] <= 100}
+ assert {[r get mykey] eq "foo"}
+ r select 9
+ } {OK} {singledb:skip}
+
+ test {MOVE does not create an expire if it does not exist} {
+ r select 10
+ r flushdb
+ r select 9
+ r set mykey foo
+ r move mykey 10
+ assert {[r ttl mykey] == -2}
+ r select 10
+ assert {[r ttl mykey] == -1}
+ assert {[r get mykey] eq "foo"}
+ r select 9
+ } {OK} {singledb:skip}
+
+ test {SET/GET keys in different DBs} {
+ r set a hello
+ r set b world
+ r select 10
+ r set a foo
+ r set b bared
+ r select 9
+ set res {}
+ lappend res [r get a]
+ lappend res [r get b]
+ r select 10
+ lappend res [r get a]
+ lappend res [r get b]
+ r select 9
+ format $res
+ } {hello world foo bared} {singledb:skip}
+
+ test {RANDOMKEY} {
+ r flushdb
+ r set foo x
+ r set bar y
+ set foo_seen 0
+ set bar_seen 0
+ for {set i 0} {$i < 100} {incr i} {
+ set rkey [r randomkey]
+ if {$rkey eq {foo}} {
+ set foo_seen 1
+ }
+ if {$rkey eq {bar}} {
+ set bar_seen 1
+ }
+ }
+ list $foo_seen $bar_seen
+ } {1 1}
+
+ test {RANDOMKEY against empty DB} {
+ r flushdb
+ r randomkey
+ } {}
+
+ test {RANDOMKEY regression 1} {
+ r flushdb
+ r set x 10
+ r del x
+ r randomkey
+ } {}
+
+ test {KEYS * two times with long key, Github issue #1208} {
+ r flushdb
+ r set dlskeriewrioeuwqoirueioqwrueoqwrueqw test
+ r keys *
+ r keys *
+ } {dlskeriewrioeuwqoirueioqwrueoqwrueqw}
+
+ test {Regression for pattern matching long nested loops} {
+ r flushdb
+ r SET aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 1
+ r KEYS "a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*b"
+ } {}
+}