parent
ee4453fb50
commit
b855b50339
14 changed files with 497 additions and 242 deletions
@ -1,125 +0,0 @@ |
||||
package command |
||||
|
||||
import ( |
||||
"testing" |
||||
) |
||||
|
||||
func Test_Get_Match_Keys_Mset_Cmd(t *testing.T) { |
||||
mset_cmd := redisCommands["mset"] |
||||
/*filterkey: x |
||||
*cmd: mset kk 1 |
||||
*/ |
||||
args := make([][]byte, 2) |
||||
args[0] = []byte("kk") |
||||
args[1] = []byte("1") |
||||
filterkey := make([]string, 1) |
||||
filterkey[0] = "x" |
||||
new_args, ret := GetMatchKeys(mset_cmd, args, filterkey) |
||||
|
||||
if len(new_args) != 0 || ret != false { |
||||
t.Error("mset test fail") |
||||
} |
||||
|
||||
/*filterkey: k |
||||
*cmd: mset kk 1 |
||||
*/ |
||||
args = make([][]byte, 2) |
||||
args[0] = []byte("kk") |
||||
args[1] = []byte("1") |
||||
filterkey = make([]string, 1) |
||||
filterkey[0] = "k" |
||||
new_args, ret = GetMatchKeys(mset_cmd, args, filterkey) |
||||
|
||||
if len(new_args) != 2 || ret != true { |
||||
t.Error("mset test fail") |
||||
} |
||||
|
||||
/*filterkey: k |
||||
*cmd: mset kk 1 gg ll zz nn k ll |
||||
*/ |
||||
args = make([][]byte, 8) |
||||
args[0] = []byte("kk") |
||||
args[1] = []byte("1") |
||||
args[2] = []byte("gg") |
||||
args[3] = []byte("ll") |
||||
args[4] = []byte("zz") |
||||
args[5] = []byte("nn") |
||||
args[6] = []byte("k") |
||||
args[7] = []byte("ll") |
||||
filterkey = make([]string, 1) |
||||
filterkey[0] = "k" |
||||
new_args, ret = GetMatchKeys(mset_cmd, args, filterkey) |
||||
|
||||
if len(new_args) != 4 || ret != true || |
||||
string(new_args[0]) != "kk" || string(new_args[1]) != "1" || |
||||
string(new_args[2]) != "k" || string(new_args[3]) != "ll" { |
||||
t.Error("mset test fail") |
||||
} |
||||
} |
||||
|
||||
func Test_Get_Match_Keys_SetXX_Cmd(t *testing.T) { |
||||
set_cmd := redisCommands["set"] |
||||
/*filterkey: x |
||||
*cmd: set kk 1 |
||||
*/ |
||||
args := make([][]byte, 2) |
||||
args[0] = []byte("kk") |
||||
args[1] = []byte("1") |
||||
filterkey := make([]string, 1) |
||||
filterkey[0] = "x" |
||||
new_args, ret := GetMatchKeys(set_cmd, args, filterkey) |
||||
|
||||
if ret != false { |
||||
t.Error("set test fail", ret, len(new_args)) |
||||
} |
||||
|
||||
/*filterkey: k |
||||
*cmd: set kk 1 |
||||
*/ |
||||
args = make([][]byte, 2) |
||||
args[0] = []byte("kk") |
||||
args[1] = []byte("1") |
||||
filterkey = make([]string, 1) |
||||
filterkey[0] = "k" |
||||
new_args, ret = GetMatchKeys(set_cmd, args, filterkey) |
||||
|
||||
if len(new_args) != 2 || ret != true { |
||||
t.Error("set test fail") |
||||
} |
||||
|
||||
/*filterkey: k |
||||
*cmd: setex kk 3000 lll |
||||
*/ |
||||
set_cmd = redisCommands["setex"] |
||||
args = make([][]byte, 3) |
||||
args[0] = []byte("kk") |
||||
args[1] = []byte("3000") |
||||
args[2] = []byte("lll") |
||||
filterkey = make([]string, 1) |
||||
filterkey[0] = "k" |
||||
new_args, ret = GetMatchKeys(set_cmd, args, filterkey) |
||||
|
||||
if len(new_args) != 3 || ret != true || |
||||
string(new_args[0]) != "kk" || string(new_args[1]) != "3000" || |
||||
string(new_args[2]) != "lll" { |
||||
t.Error("setex test fail") |
||||
} |
||||
|
||||
/*filterkey: k |
||||
*cmd: setrange kk 3000 lll |
||||
*/ |
||||
set_cmd = redisCommands["setrange"] |
||||
args = make([][]byte, 3) |
||||
args[0] = []byte("kk") |
||||
args[1] = []byte("3000") |
||||
args[2] = []byte("lll") |
||||
filterkey = make([]string, 1) |
||||
filterkey[0] = "k" |
||||
new_args, ret = GetMatchKeys(set_cmd, args, filterkey) |
||||
|
||||
if len(new_args) != 3 || ret != true || |
||||
string(new_args[0]) != "kk" || string(new_args[1]) != "3000" || |
||||
string(new_args[2]) != "lll" { |
||||
t.Error("setrange test fail") |
||||
} |
||||
} |
@ -1,17 +0,0 @@ |
||||
package utils |
||||
|
||||
import "strings" |
||||
|
||||
// return true means not pass
|
||||
func FilterCommands(cmd string, luaFilter bool) bool { |
||||
if strings.EqualFold(cmd, "opinfo") { |
||||
return true |
||||
} |
||||
|
||||
if luaFilter && (strings.EqualFold(cmd, "eval") || strings.EqualFold(cmd, "script") || |
||||
strings.EqualFold(cmd, "evalsha")) { |
||||
return true |
||||
} |
||||
|
||||
return false |
||||
} |
@ -0,0 +1,111 @@ |
||||
package filter |
||||
|
||||
import ( |
||||
"strings" |
||||
"redis-shake/configure" |
||||
"strconv" |
||||
) |
||||
|
||||
// return true means not pass
|
||||
func FilterCommands(cmd string) bool { |
||||
if strings.EqualFold(cmd, "opinfo") { |
||||
return true |
||||
} |
||||
|
||||
if conf.Options.FilterLua && (strings.EqualFold(cmd, "eval") || strings.EqualFold(cmd, "script") || |
||||
strings.EqualFold(cmd, "evalsha")) { |
||||
return true |
||||
} |
||||
|
||||
return false |
||||
} |
||||
|
||||
// return true means not pass
|
||||
func FilterKey(key string) bool { |
||||
if len(conf.Options.FilterKeyBlacklist) != 0 { |
||||
if hasAtLeastOnePrefix(key, conf.Options.FilterKeyBlacklist) { |
||||
return true |
||||
} |
||||
return false |
||||
} else if len(conf.Options.FilterKeyWhitelist) != 0 { |
||||
if hasAtLeastOnePrefix(key, conf.Options.FilterKeyWhitelist) { |
||||
return false |
||||
} |
||||
return true |
||||
} |
||||
return false |
||||
} |
||||
|
||||
// return true means not pass
|
||||
func FilterSlot(slot int) bool { |
||||
if len(conf.Options.FilterSlot) == 0 { |
||||
return false |
||||
} |
||||
|
||||
// the slot in FilterSlot need to be passed
|
||||
for _, ele := range conf.Options.FilterSlot { |
||||
slotInt, _ := strconv.Atoi(ele) |
||||
if slot == slotInt { |
||||
return false |
||||
} |
||||
} |
||||
return true |
||||
} |
||||
|
||||
// return true means not pass
|
||||
func FilterDB(db int) bool { |
||||
dbString := strconv.FormatInt(int64(db), 10) |
||||
if len(conf.Options.FilterDBBlacklist) != 0 { |
||||
if matchOne(dbString, conf.Options.FilterDBBlacklist) { |
||||
return true |
||||
} |
||||
return false |
||||
} else if len(conf.Options.FilterDBWhitelist) != 0 { |
||||
if matchOne(dbString, conf.Options.FilterDBWhitelist) { |
||||
return false |
||||
} |
||||
return true |
||||
} |
||||
return false |
||||
} |
||||
|
||||
/* |
||||
* judge whether the input command with key should be filter, |
||||
* @return: |
||||
* [][]byte: the new argv which may be modified after filter. |
||||
* bool: true means pass |
||||
*/ |
||||
func HandleFilterKeyWithCommand(scmd string, commandArgv [][]byte) ([][]byte, bool) { |
||||
if len(conf.Options.FilterKeyWhitelist) == 0 && len(conf.Options.FilterKeyBlacklist) == 0 { |
||||
// pass if no filter given
|
||||
return commandArgv, false |
||||
} |
||||
|
||||
cmdNode, ok := RedisCommands[scmd] |
||||
if !ok || len(commandArgv) == 0 { |
||||
// pass when command not found or length of argv == 0
|
||||
return commandArgv, false |
||||
} |
||||
|
||||
newArgs, pass := getMatchKeys(cmdNode, commandArgv) |
||||
return newArgs, !pass |
||||
} |
||||
|
||||
// hasAtLeastOnePrefix checks whether the key begins with at least one of prefixes.
|
||||
func hasAtLeastOnePrefix(key string, prefixes []string) bool { |
||||
for _, prefix := range prefixes { |
||||
if strings.HasPrefix(key, prefix) { |
||||
return true |
||||
} |
||||
} |
||||
return false |
||||
} |
||||
|
||||
func matchOne(input string, list []string) bool { |
||||
for _, ele := range list { |
||||
if ele == input { |
||||
return true |
||||
} |
||||
} |
||||
return false |
||||
} |
@ -0,0 +1,287 @@ |
||||
package filter |
||||
|
||||
import ( |
||||
"testing" |
||||
"fmt" |
||||
|
||||
"redis-shake/configure" |
||||
|
||||
"github.com/stretchr/testify/assert" |
||||
) |
||||
|
||||
func TestFilterCommands(t *testing.T) { |
||||
// test FilterCommands
|
||||
|
||||
var nr int |
||||
{ |
||||
fmt.Printf("TestFilterCommands case %d.\n", nr) |
||||
nr++ |
||||
|
||||
assert.Equal(t, false, FilterCommands("unknown-cmd"), "should be equal") |
||||
assert.Equal(t, true, FilterCommands("opinfo"), "should be equal") |
||||
assert.Equal(t, false, FilterCommands("eval"), "should be equal") |
||||
conf.Options.FilterLua = true |
||||
assert.Equal(t, false, FilterCommands("unknown-cmd"), "should be equal") |
||||
assert.Equal(t, true, FilterCommands("eval"), "should be equal") |
||||
assert.Equal(t, true, FilterCommands("evalsha"), "should be equal") |
||||
assert.Equal(t, true, FilterCommands("script"), "should be equal") |
||||
|
||||
} |
||||
} |
||||
|
||||
func TestFilterKey(t *testing.T) { |
||||
// test FilterKey
|
||||
|
||||
var nr int |
||||
{ |
||||
fmt.Printf("TestFilterKey case %d.\n", nr) |
||||
nr++ |
||||
|
||||
assert.Equal(t, false, FilterKey("unknown-key"), "should be equal") |
||||
} |
||||
|
||||
{ |
||||
fmt.Printf("TestFilterKey case %d.\n", nr) |
||||
nr++ |
||||
|
||||
conf.Options.FilterKeyBlacklist = []string{"abc", "xyz", "a"} |
||||
conf.Options.FilterKeyWhitelist = []string{} |
||||
assert.Equal(t, false, FilterKey("unknown-key"), "should be equal") |
||||
assert.Equal(t, true, FilterKey("abc"), "should be equal") |
||||
assert.Equal(t, true, FilterKey("abc111"), "should be equal") |
||||
assert.Equal(t, true, FilterKey("abcxyz"), "should be equal") |
||||
assert.Equal(t, true, FilterKey("xyz"), "should be equal") |
||||
assert.Equal(t, false, FilterKey("xy"), "should be equal") |
||||
assert.Equal(t, true, FilterKey("a"), "should be equal") |
||||
assert.Equal(t, true, FilterKey("ab"), "should be equal") |
||||
} |
||||
|
||||
{ |
||||
fmt.Printf("TestFilterKey case %d.\n", nr) |
||||
nr++ |
||||
|
||||
conf.Options.FilterKeyBlacklist = []string{} |
||||
conf.Options.FilterKeyWhitelist = []string{"abc", "xyz", "a"} |
||||
assert.Equal(t, true, FilterKey("unknown-key"), "should be equal") |
||||
assert.Equal(t, false, FilterKey("abc"), "should be equal") |
||||
assert.Equal(t, false, FilterKey("abc111"), "should be equal") |
||||
assert.Equal(t, false, FilterKey("abcxyz"), "should be equal") |
||||
assert.Equal(t, false, FilterKey("xyz"), "should be equal") |
||||
assert.Equal(t, true, FilterKey("xy"), "should be equal") |
||||
assert.Equal(t, false, FilterKey("a"), "should be equal") |
||||
assert.Equal(t, false, FilterKey("ab"), "should be equal") |
||||
} |
||||
} |
||||
|
||||
func TestFilterSlot(t *testing.T) { |
||||
// test FilterSlot
|
||||
|
||||
var nr int |
||||
{ |
||||
fmt.Printf("TestFilterSlot case %d.\n", nr) |
||||
nr++ |
||||
|
||||
conf.Options.FilterSlot = []string{} |
||||
assert.Equal(t, false, FilterSlot(2), "should be equal") |
||||
assert.Equal(t, false, FilterSlot(0), "should be equal") |
||||
} |
||||
|
||||
{ |
||||
fmt.Printf("TestFilterSlot case %d.\n", nr) |
||||
nr++ |
||||
|
||||
conf.Options.FilterSlot = []string{"1", "3", "5"} |
||||
assert.Equal(t, false, FilterSlot(1), "should be equal") |
||||
assert.Equal(t, true, FilterSlot(0), "should be equal") |
||||
assert.Equal(t, false, FilterSlot(5), "should be equal") |
||||
} |
||||
} |
||||
|
||||
func TestFilterDB(t *testing.T) { |
||||
// test FilterDB
|
||||
|
||||
var nr int |
||||
{ |
||||
fmt.Printf("TestFilterDB case %d.\n", nr) |
||||
nr++ |
||||
|
||||
conf.Options.FilterDBWhitelist = []string{} |
||||
conf.Options.FilterDBBlacklist = []string{} |
||||
assert.Equal(t, false, FilterDB(2), "should be equal") |
||||
assert.Equal(t, false, FilterDB(0), "should be equal") |
||||
} |
||||
|
||||
{ |
||||
fmt.Printf("TestFilterDB case %d.\n", nr) |
||||
nr++ |
||||
|
||||
conf.Options.FilterDBWhitelist = []string{"0", "1", "5"} |
||||
conf.Options.FilterDBBlacklist = []string{} |
||||
assert.Equal(t, true, FilterDB(2), "should be equal") |
||||
assert.Equal(t, false, FilterDB(0), "should be equal") |
||||
assert.Equal(t, false, FilterDB(5), "should be equal") |
||||
|
||||
} |
||||
|
||||
{ |
||||
fmt.Printf("TestFilterDB case %d.\n", nr) |
||||
nr++ |
||||
|
||||
conf.Options.FilterDBWhitelist = []string{} |
||||
conf.Options.FilterDBBlacklist = []string{"0", "1", "5"} |
||||
assert.Equal(t, false, FilterDB(2), "should be equal") |
||||
assert.Equal(t, true, FilterDB(0), "should be equal") |
||||
assert.Equal(t, true, FilterDB(5), "should be equal") |
||||
|
||||
} |
||||
} |
||||
|
||||
func TestHandleFilterKeyWithCommand(t *testing.T) { |
||||
// test HandleFilterKeyWithCommand
|
||||
|
||||
var nr int |
||||
var cmd string |
||||
var args, expectArgs, ret [][]byte |
||||
var filter bool |
||||
{ |
||||
fmt.Printf("TestHandleFilterKeyWithCommand case %d.\n", nr) |
||||
nr++ |
||||
|
||||
cmd = "set" |
||||
args = convertToByte("xyz", "1") |
||||
conf.Options.FilterKeyBlacklist = []string{} |
||||
conf.Options.FilterKeyWhitelist = []string{} |
||||
ret, filter = HandleFilterKeyWithCommand(cmd, args) |
||||
assert.Equal(t, false, filter, "should be equal") |
||||
assert.Equal(t, args, ret, "should be equal") |
||||
|
||||
conf.Options.FilterKeyBlacklist = []string{"x", "y"} |
||||
conf.Options.FilterKeyWhitelist = []string{} |
||||
ret, filter = HandleFilterKeyWithCommand(cmd, args) |
||||
assert.Equal(t, true, filter, "should be equal") |
||||
|
||||
conf.Options.FilterKeyBlacklist = []string{} |
||||
conf.Options.FilterKeyWhitelist = []string{"x"} |
||||
ret, filter = HandleFilterKeyWithCommand(cmd, args) |
||||
assert.Equal(t, false, filter, "should be equal") |
||||
assert.Equal(t, args, ret, "should be equal") |
||||
} |
||||
|
||||
{ |
||||
fmt.Printf("TestHandleFilterKeyWithCommand case %d.\n", nr) |
||||
nr++ |
||||
|
||||
cmd = "mset" |
||||
args = convertToByte("xyz", "1", "abc", "2", "ab", "3", "zzz", "1111111111111", "ffffffffff", "90") |
||||
conf.Options.FilterKeyBlacklist = []string{} |
||||
conf.Options.FilterKeyWhitelist = []string{} |
||||
ret, filter = HandleFilterKeyWithCommand(cmd, args) |
||||
assert.Equal(t, false, filter, "should be equal") |
||||
assert.Equal(t, args, ret, "should be equal") |
||||
|
||||
conf.Options.FilterKeyBlacklist = []string{"x"} |
||||
conf.Options.FilterKeyWhitelist = []string{} |
||||
ret, filter = HandleFilterKeyWithCommand(cmd, args) |
||||
expectArgs = convertToByte("abc", "2", "ab", "3", "zzz", "1111111111111", "ffffffffff", "90") |
||||
assert.Equal(t, false, filter, "should be equal") |
||||
assert.Equal(t, expectArgs, ret, "should be equal") |
||||
|
||||
conf.Options.FilterKeyBlacklist = []string{} |
||||
conf.Options.FilterKeyWhitelist = []string{"x"} |
||||
ret, filter = HandleFilterKeyWithCommand(cmd, args) |
||||
expectArgs = convertToByte("xyz", "1") |
||||
assert.Equal(t, false, filter, "should be equal") |
||||
assert.Equal(t, expectArgs, ret, "should be equal") |
||||
} |
||||
|
||||
{ |
||||
fmt.Printf("TestHandleFilterKeyWithCommand case %d.\n", nr) |
||||
nr++ |
||||
|
||||
cmd = "msetnx" |
||||
args = convertToByte("xyz", "1", "abc", "2", "ab", "3", "zzz", "1111111111111", "ffffffffff", "90") |
||||
conf.Options.FilterKeyBlacklist = []string{} |
||||
conf.Options.FilterKeyWhitelist = []string{} |
||||
ret, filter = HandleFilterKeyWithCommand(cmd, args) |
||||
assert.Equal(t, false, filter, "should be equal") |
||||
assert.Equal(t, args, ret, "should be equal") |
||||
|
||||
conf.Options.FilterKeyBlacklist = []string{"x"} |
||||
conf.Options.FilterKeyWhitelist = []string{} |
||||
ret, filter = HandleFilterKeyWithCommand(cmd, args) |
||||
expectArgs = convertToByte("abc", "2", "ab", "3", "zzz", "1111111111111", "ffffffffff", "90") |
||||
assert.Equal(t, false, filter, "should be equal") |
||||
assert.Equal(t, expectArgs, ret, "should be equal") |
||||
|
||||
conf.Options.FilterKeyBlacklist = []string{} |
||||
conf.Options.FilterKeyWhitelist = []string{"x"} |
||||
ret, filter = HandleFilterKeyWithCommand(cmd, args) |
||||
expectArgs = convertToByte("xyz", "1") |
||||
assert.Equal(t, false, filter, "should be equal") |
||||
assert.Equal(t, expectArgs, ret, "should be equal") |
||||
} |
||||
|
||||
// unknown command, should pass
|
||||
{ |
||||
fmt.Printf("TestHandleFilterKeyWithCommand case %d.\n", nr) |
||||
nr++ |
||||
|
||||
cmd = "unknownCmd" |
||||
args = convertToByte("xyz", "1") |
||||
conf.Options.FilterKeyBlacklist = []string{} |
||||
conf.Options.FilterKeyWhitelist = []string{} |
||||
ret, filter = HandleFilterKeyWithCommand(cmd, args) |
||||
assert.Equal(t, false, filter, "should be equal") |
||||
assert.Equal(t, args, ret, "should be equal") |
||||
} |
||||
|
||||
// length == 0
|
||||
{ |
||||
fmt.Printf("TestHandleFilterKeyWithCommand case %d.\n", nr) |
||||
nr++ |
||||
|
||||
cmd = "unknownCmd" |
||||
args = convertToByte("xyz") |
||||
conf.Options.FilterKeyBlacklist = []string{} |
||||
conf.Options.FilterKeyWhitelist = []string{} |
||||
ret, filter = HandleFilterKeyWithCommand(cmd, args) |
||||
assert.Equal(t, false, filter, "should be equal") |
||||
assert.Equal(t, args, ret, "should be equal") |
||||
} |
||||
|
||||
// del
|
||||
{ |
||||
fmt.Printf("TestHandleFilterKeyWithCommand case %d.\n", nr) |
||||
nr++ |
||||
|
||||
cmd = "del" |
||||
args = convertToByte("xyz", "abc", "ab", "zzz", "ffffffffff") |
||||
conf.Options.FilterKeyBlacklist = []string{} |
||||
conf.Options.FilterKeyWhitelist = []string{} |
||||
ret, filter = HandleFilterKeyWithCommand(cmd, args) |
||||
assert.Equal(t, false, filter, "should be equal") |
||||
assert.Equal(t, args, ret, "should be equal") |
||||
|
||||
conf.Options.FilterKeyBlacklist = []string{"x"} |
||||
conf.Options.FilterKeyWhitelist = []string{} |
||||
ret, filter = HandleFilterKeyWithCommand(cmd, args) |
||||
expectArgs = convertToByte("abc", "ab", "zzz", "ffffffffff") |
||||
assert.Equal(t, false, filter, "should be equal") |
||||
assert.Equal(t, expectArgs, ret, "should be equal") |
||||
|
||||
conf.Options.FilterKeyBlacklist = []string{} |
||||
conf.Options.FilterKeyWhitelist = []string{"x"} |
||||
ret, filter = HandleFilterKeyWithCommand(cmd, args) |
||||
expectArgs = convertToByte("xyz") |
||||
assert.Equal(t, false, filter, "should be equal") |
||||
assert.Equal(t, expectArgs, ret, "should be equal") |
||||
} |
||||
} |
||||
|
||||
func convertToByte(args... string) [][]byte { |
||||
ret := make([][]byte, 0) |
||||
for _, arg := range args { |
||||
ret = append(ret, []byte(arg)) |
||||
} |
||||
return ret |
||||
} |
Loading…
Reference in new issue