]> git.saurik.com Git - redis.git/blobdiff - tests/unit/basic.tcl
Disable negative offsets for SETRANGE
[redis.git] / tests / unit / basic.tcl
index b14ac6ed28d4e371a35e988bdf678e0ec2b71481..a9b25fcece90345133f0d565d7b2d108763902b2 100644 (file)
@@ -1,4 +1,4 @@
-start_server default.conf {} {
+start_server {tags {"basic"}} {
     test {DEL all keys to start with a clean DB} {
         foreach key [r keys *] {r del $key}
         r dbsize
@@ -52,46 +52,48 @@ start_server default.conf {} {
         r get foo
     } [string repeat "abcd" 1000000]
 
-    test {Very big payload random access} {
-        set err {}
-        array set payload {}
-        for {set j 0} {$j < 100} {incr j} {
-            set size [expr 1+[randomInt 100000]]
-            set buf [string repeat "pl-$j" $size]
-            set payload($j) $buf
-            r set bigpayload_$j $buf
-        }
-        for {set j 0} {$j < 1000} {incr j} {
-            set index [randomInt 100]
-            set buf [r get bigpayload_$index]
-            if {$buf != $payload($index)} {
-                set err "Values differ: I set '$payload($index)' but I read back '$buf'"
-                break
+    tags {"slow"} {
+        test {Very big payload random access} {
+            set err {}
+            array set payload {}
+            for {set j 0} {$j < 100} {incr j} {
+                set size [expr 1+[randomInt 100000]]
+                set buf [string repeat "pl-$j" $size]
+                set payload($j) $buf
+                r set bigpayload_$j $buf
             }
-        }
-        unset payload
-        set _ $err
-    } {}
-
-    test {SET 10000 numeric keys and access all them in reverse order} {
-        set err {}
-        for {set x 0} {$x < 10000} {incr x} {
-            r set $x $x
-        }
-        set sum 0
-        for {set x 9999} {$x >= 0} {incr x -1} {
-            set val [r get $x]
-            if {$val ne $x} {
-                set err "Eleemnt at position $x is $val instead of $x"
-                break
+            for {set j 0} {$j < 1000} {incr j} {
+                set index [randomInt 100]
+                set buf [r get bigpayload_$index]
+                if {$buf != $payload($index)} {
+                    set err "Values differ: I set '$payload($index)' but I read back '$buf'"
+                    break
+                }
             }
-        }
-        set _ $err
-    } {}
+            unset payload
+            set _ $err
+        } {}
+
+        test {SET 10000 numeric keys and access all them in reverse order} {
+            set err {}
+            for {set x 0} {$x < 10000} {incr x} {
+                r set $x $x
+            }
+            set sum 0
+            for {set x 9999} {$x >= 0} {incr x -1} {
+                set val [r get $x]
+                if {$val ne $x} {
+                    set err "Eleemnt at position $x is $val instead of $x"
+                    break
+                }
+            }
+            set _ $err
+        } {}
 
-    test {DBSIZE should be 10101 now} {
-        r dbsize
-    } {10101}
+        test {DBSIZE should be 10101 now} {
+            r dbsize
+        } {10101}
+    }
 
     test {INCR against non existing key} {
         set res {}
@@ -146,12 +148,11 @@ start_server default.conf {} {
         r get novar2
     } {foobared}
 
-    test {SETNX will overwrite EXPIREing key} {
+    test {SETNX against volatile key} {
         r set x 10
         r expire x 10000
-        r setnx x 20
-        r get x
-    } {20}
+        list [r setnx x 20] [r get x]
+    } {0 10}
 
     test {EXISTS} {
         set res {}
@@ -171,7 +172,7 @@ start_server default.conf {} {
 
     test {Commands pipelining} {
         set fd [r channel]
-        puts -nonewline $fd "SET k1 4\r\nxyzk\r\nGET k1\r\nPING\r\n"
+        puts -nonewline $fd "SET k1 xyzk\r\nGET k1\r\nPING\r\n"
         flush $fd
         set res {}
         append res [string match OK* [::redis::redis_read_reply $fd]]
@@ -360,10 +361,229 @@ start_server default.conf {} {
         list [r msetnx x1 xxx y2 yyy] [r get x1] [r get y2]
     } {1 xxx yyy}
 
-    test {MSETNX should remove all the volatile keys even on failure} {
-        r mset x 1 y 2 z 3
-        r expire y 10000
-        r expire z 10000
-        list [r msetnx x A y B z C] [r mget x y z]
-    } {0 {1 {} {}}}
+    test {STRLEN against non existing key} {
+        r strlen notakey
+    } {0}
+
+    test {STRLEN against integer} {
+        r set myinteger -555
+        r strlen myinteger
+    } {4}
+
+    test {STRLEN against plain string} {
+        r set mystring "foozzz0123456789 baz"
+        r strlen mystring
+    }
+
+    test "SETBIT against non-existing key" {
+        r del mykey
+        assert_equal 0 [r setbit mykey 1 1]
+        assert_equal [binary format B* 01000000] [r get mykey]
+    }
+
+    test "SETBIT against string-encoded key" {
+        # Ascii "@" is integer 64 = 01 00 00 00
+        r set mykey "@"
+
+        assert_equal 0 [r setbit mykey 2 1]
+        assert_equal [binary format B* 01100000] [r get mykey]
+        assert_equal 1 [r setbit mykey 1 0]
+        assert_equal [binary format B* 00100000] [r get mykey]
+    }
+
+    test "SETBIT against integer-encoded key" {
+        # Ascii "1" is integer 49 = 00 11 00 01
+        r set mykey 1
+        assert_encoding int mykey
+
+        assert_equal 0 [r setbit mykey 6 1]
+        assert_equal [binary format B* 00110011] [r get mykey]
+        assert_equal 1 [r setbit mykey 2 0]
+        assert_equal [binary format B* 00010011] [r get mykey]
+    }
+
+    test "SETBIT against key with wrong type" {
+        r del mykey
+        r lpush mykey "foo"
+        assert_error "*wrong kind*" {r setbit mykey 0 1}
+    }
+
+    test "SETBIT with out of range bit offset" {
+        r del mykey
+        assert_error "*out of range*" {r setbit mykey [expr 4*1024*1024*1024] 1}
+        assert_error "*out of range*" {r setbit mykey -1 1}
+    }
+
+    test "SETBIT with non-bit argument" {
+        r del mykey
+        assert_error "*out of range*" {r setbit mykey 0 -1}
+        assert_error "*out of range*" {r setbit mykey 0  2}
+        assert_error "*out of range*" {r setbit mykey 0 10}
+        assert_error "*out of range*" {r setbit mykey 0 20}
+    }
+
+    test "SETBIT fuzzing" {
+        set str ""
+        set len [expr 256*8]
+        r del mykey
+
+        for {set i 0} {$i < 2000} {incr i} {
+            set bitnum [randomInt $len]
+            set bitval [randomInt 2]
+            set fmt [format "%%-%ds%%d%%-s" $bitnum]
+            set head [string range $str 0 $bitnum-1]
+            set tail [string range $str $bitnum+1 end]
+            set str [string map {" " 0} [format $fmt $head $bitval $tail]]
+
+            r setbit mykey $bitnum $bitval
+            assert_equal [binary format B* $str] [r get mykey]
+        }
+    }
+
+    test "GETBIT against non-existing key" {
+        r del mykey
+        assert_equal 0 [r getbit mykey 0]
+    }
+
+    test "GETBIT against string-encoded key" {
+        # Single byte with 2nd and 3rd bit set
+        r set mykey "`"
+
+        # In-range
+        assert_equal 0 [r getbit mykey 0]
+        assert_equal 1 [r getbit mykey 1]
+        assert_equal 1 [r getbit mykey 2]
+        assert_equal 0 [r getbit mykey 3]
+
+        # Out-range
+        assert_equal 0 [r getbit mykey 8]
+        assert_equal 0 [r getbit mykey 100]
+        assert_equal 0 [r getbit mykey 10000]
+    }
+
+    test "GETBIT against integer-encoded key" {
+        r set mykey 1
+        assert_encoding int mykey
+
+        # Ascii "1" is integer 49 = 00 11 00 01
+        assert_equal 0 [r getbit mykey 0]
+        assert_equal 0 [r getbit mykey 1]
+        assert_equal 1 [r getbit mykey 2]
+        assert_equal 1 [r getbit mykey 3]
+
+        # Out-range
+        assert_equal 0 [r getbit mykey 8]
+        assert_equal 0 [r getbit mykey 100]
+        assert_equal 0 [r getbit mykey 10000]
+    }
+
+    test "SETRANGE against non-existing key" {
+        r del mykey
+        assert_equal 3 [r setrange mykey 0 foo]
+        assert_equal "foo" [r get mykey]
+
+        r del mykey
+        assert_equal 0 [r setrange mykey 0 ""]
+        assert_equal 0 [r exists mykey]
+
+        r del mykey
+        assert_equal 4 [r setrange mykey 1 foo]
+        assert_equal "\000foo" [r get mykey]
+    }
+
+    test "SETRANGE against string-encoded key" {
+        r set mykey "foo"
+        assert_equal 3 [r setrange mykey 0 b]
+        assert_equal "boo" [r get mykey]
+
+        r set mykey "foo"
+        assert_equal 3 [r setrange mykey 0 ""]
+        assert_equal "foo" [r get mykey]
+
+        r set mykey "foo"
+        assert_equal 3 [r setrange mykey 1 b]
+        assert_equal "fbo" [r get mykey]
+
+        r set mykey "foo"
+        assert_equal 7 [r setrange mykey 4 bar]
+        assert_equal "foo\000bar" [r get mykey]
+    }
+
+    test "SETRANGE against integer-encoded key" {
+        r set mykey 1234
+        assert_encoding int mykey
+        assert_equal 4 [r setrange mykey 0 2]
+        assert_encoding raw mykey
+        assert_equal 2234 [r get mykey]
+
+        # Shouldn't change encoding when nothing is set
+        r set mykey 1234
+        assert_encoding int mykey
+        assert_equal 4 [r setrange mykey 0 ""]
+        assert_encoding int mykey
+        assert_equal 1234 [r get mykey]
+
+        r set mykey 1234
+        assert_encoding int mykey
+        assert_equal 4 [r setrange mykey 1 3]
+        assert_encoding raw mykey
+        assert_equal 1334 [r get mykey]
+
+        r set mykey 1234
+        assert_encoding int mykey
+        assert_equal 6 [r setrange mykey 5 2]
+        assert_encoding raw mykey
+        assert_equal "1234\0002" [r get mykey]
+    }
+
+    test "SETRANGE against key with wrong type" {
+        r del mykey
+        r lpush mykey "foo"
+        assert_error "*wrong kind*" {r setrange mykey 0 bar}
+    }
+
+    test "SETRANGE with out of range offset" {
+        r del mykey
+        assert_error "*maximum allowed size*" {r setrange mykey [expr 512*1024*1024-4] world}
+
+        r set mykey "hello"
+        assert_error "*out of range*" {r setrange mykey -1 world}
+        assert_error "*maximum allowed size*" {r setrange mykey [expr 512*1024*1024-4] world}
+    }
+
+    test "GETRANGE against non-existing key" {
+        r del mykey
+        assert_equal "" [r getrange mykey 0 -1]
+    }
+
+    test "GETRANGE against string value" {
+        r set mykey "Hello World"
+        assert_equal "Hell" [r getrange mykey 0 3]
+        assert_equal "Hello World" [r getrange mykey 0 -1]
+        assert_equal "orld" [r getrange mykey -4 -1]
+        assert_equal "" [r getrange mykey 5 3]
+        assert_equal " World" [r getrange mykey 5 5000]
+        assert_equal "Hello World" [r getrange mykey -5000 10000]
+    }
+
+    test "GETRANGE against integer-encoded value" {
+        r set mykey 1234
+        assert_equal "123" [r getrange mykey 0 2]
+        assert_equal "1234" [r getrange mykey 0 -1]
+        assert_equal "234" [r getrange mykey -3 -1]
+        assert_equal "" [r getrange mykey 5 3]
+        assert_equal "4" [r getrange mykey 3 5000]
+        assert_equal "1234" [r getrange mykey -5000 10000]
+    }
+
+    test "GETRANGE fuzzing" {
+        for {set i 0} {$i < 1000} {incr i} {
+            r set bin [set bin [randstring 0 1024 binary]]
+            set _start [set start [randomInt 1500]]
+            set _end [set end [randomInt 1500]]
+            if {$_start < 0} {set _start "end-[abs($_start)-1]"}
+            if {$_end < 0} {set _end "end-[abs($_end)-1]"}
+            assert_equal [string range $bin $_start $_end] [r getrange bin $start $end]
+        }
+    }
 }