diff --git a/tests/cluster/tests/15-cluster-slots.tcl b/tests/cluster/tests/15-cluster-slots.tcl index dc9938ef6..1b33c57bd 100644 --- a/tests/cluster/tests/15-cluster-slots.tcl +++ b/tests/cluster/tests/15-cluster-slots.tcl @@ -41,4 +41,10 @@ test "client do not break when cluster slot" { if { [catch {R 0 cluster slots}] } { fail "output overflow when cluster slots" } -} \ No newline at end of file +} + +test "client can handle keys with hash tag" { + set cluster [redis_cluster 127.0.0.1:[get_instance_attrib redis 0 port]] + $cluster set foo{tag} bar + $cluster close +} diff --git a/tests/support/cluster.tcl b/tests/support/cluster.tcl index 74587e1f7..64b079ff8 100644 --- a/tests/support/cluster.tcl +++ b/tests/support/cluster.tcl @@ -286,8 +286,29 @@ proc ::redis_cluster::crc16 {s} { # Hash a single key returning the slot it belongs to, Implemented hash # tags as described in the Redis Cluster specification. proc ::redis_cluster::hash {key} { - # TODO: Handle hash slots. - expr {[::redis_cluster::crc16 $key] & 16383} + set keylen [string length $key] + set s {} + set e {} + for {set s 0} {$s < $keylen} {incr s} { + if {[string index $key $s] eq "\{"} break + } + + if {[expr {$s == $keylen}]} { + set res [expr {[crc16 $key] & 16383}] + return $res + } + + for {set e [expr {$s+1}]} {$e < $keylen} {incr e} { + if {[string index $key $e] == "\}"} break + } + + if {$e == $keylen || $e == [expr {$s+1}]} { + set res [expr {[crc16 $key] & 16383}] + return $res + } + + set key_sub [string range $key [expr {$s+1}] [expr {$e-1}]] + return [expr {[crc16 $key_sub] & 16383}] } # Return the slot the specified keys hash to.