| 28 | ) |
| 29 | |
| 30 | func TestParseFunction(t *testing.T) { |
| 31 | var tests = []struct { |
| 32 | expr string |
| 33 | err error |
| 34 | }{ |
| 35 | {expr: "cidr_contains(net.dip)", err: errors.New("CIDR_CONTAINS function requires 2 argument(s) but 1 argument(s) given")}, |
| 36 | {expr: "cidr_contains(net.dip, 12)", err: errors.New("argument #2 (cidr) in function CIDR_CONTAINS should be one of: string")}, |
| 37 | {expr: "cidr_contains(net.dip, '172.17.12.4/24')"}, |
| 38 | {expr: "cidr_contains($e1.net.dip, '172.17.12.4/24')"}, |
| 39 | {expr: "md('172.17.12.4')", err: errors.New("md function is undefined")}, |
| 40 | {expr: "concat('hello ', 'world')"}, |
| 41 | {expr: "concat('hello')", err: errors.New("CONCAT function requires 2 argument(s) but 1 argument(s) given")}, |
| 42 | {expr: "ltrim('hello world', 'hello ')"}, |
| 43 | {expr: "replace('hello world', 'hello', 'hell', 'world')", err: errors.New("old/new replacements mismatch")}, |
| 44 | {expr: "replace('hello world', 'hello', 'hell', 'world', 'war', 'hello')", err: errors.New("old/new replacements mismatch")}, |
| 45 | {expr: "replace('hello world', 'hello', 'hell', 'world', 'war', 'hello', 'warld', 'old', 'new', 'one')", err: errors.New("old/new replacements mismatch")}, |
| 46 | {expr: "indexof('hello', 'h', 'frst')", err: errors.New("frst is not a valid index search order")}, |
| 47 | {expr: "base('C:\\\\Windows\\\\cmd.exe', false)"}, |
| 48 | {expr: "foreach(ps.modules, $n, $n = 'user32.dll')"}, |
| 49 | {expr: "foreach(ps._ancestors, $proc, $proc.name = 'svchost.exe')"}, |
| 50 | {expr: "foreach(ps._ancestors, $proc, $process.name = 'svchost.exe')", err: errors.New(`undeclared bound variable $process in predicate "$process.name = svchost.exe"`)}, |
| 51 | {expr: "foreach(ps._ancestors, $proc, $proc.pid = 4 or $process.name = 'svchost.exe')", err: errors.New(`undeclared bound variable $process in predicate "$proc.pid = 4 OR $process.name = svchost.exe"`)}, |
| 52 | {expr: "foreach(ps._ancestors, $ps, $ps.name = 'svchost.exe')", err: errors.New(`"$ps" is a reserved bound variable name`)}, |
| 53 | {expr: "foreach(pe._sections, $sec, $sec.protection = 'RWX')", err: errors.New(`unrecognized property "protection" accessing bound variable $sec. Allowed properties [name, size, entropy, md5]`)}, |
| 54 | {expr: "foreach(ps.modules, $n, $n.name = 'user32.dll')", err: errors.New(`unrecognized property "name" accessing bound variable $n. Allowed properties []`)}, |
| 55 | {expr: "foreach(ps._ancestors, $proc, ($proc.name = 'svchost.exe' and $proc.sessionid > 0) or $proc.sid = 'S-1-5-8')"}, |
| 56 | {expr: "foreach(ps._ancestors, $proc, $proc.name = 'svchost.exe' and ps.cwd imatches '?:\\\\Windows\\\\System32\\\\*', ps.cwd)"}, |
| 57 | {expr: "foreach(ps._ancestors, $proc, $proc.name = 'svchost.exe', ps.cwd)", err: errors.New(`one of captured field(s) (ps.cwd) not used in predicate "$proc.name = svchost.exe"`)}, |
| 58 | {expr: "foreach(ps._ancestors, $proc, $proc.name = 'svchost.exe' and ps.cwd != ' ')", err: errors.New(`field ps.cwd used in predicate "$proc.name = svchost.exe AND ps.cwd != " but not captured`)}, |
| 59 | {expr: "foreach(ps._ancestors, $proc, $proc.name = 'svchost.exe' and ps.cwd = '.' and ps.sid = 'S-1-5-18', ps.cwd, ps.sid)"}, |
| 60 | {expr: "foreach(ps._ancestors, $proc, $proc.name = 'svchost.exe' and ps.cwd = '.' and ps.sid = 'S-1-5-18', ps.cwd)", err: errors.New(`field ps.sid used in predicate "$proc.name = svchost.exe AND ps.cwd = . AND ps.sid = S-1-5-18" but not captured`)}, |
| 61 | } |
| 62 | |
| 63 | for i, tt := range tests { |
| 64 | p := NewParser(tt.expr) |
| 65 | _, err := p.ParseExpr() |
| 66 | if err == nil && tt.err != nil { |
| 67 | t.Errorf("%d. exp=%s expected error=%v", i, tt.expr, tt.err) |
| 68 | } else if err != nil && tt.err != nil { |
| 69 | assert.True(t, strings.Contains(err.Error(), tt.err.Error()), fmt.Sprintf("exp=%v got=%v", tt.err, err)) |
| 70 | } else if err != nil && tt.err == nil { |
| 71 | t.Errorf("%d. exp=%s got error=%v", i, tt.expr, err) |
| 72 | } |
| 73 | } |
| 74 | } |