123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509 |
- /*
- * ECAL
- *
- * Copyright 2020 Matthias Ladkau. All rights reserved.
- *
- * This Source Code Form is subject to the terms of the MIT
- * License, If a copy of the MIT License was not distributed with this
- * file, You can obtain one at https://opensource.org/licenses/MIT.
- */
- package engine
- import (
- "fmt"
- "regexp"
- "sort"
- "testing"
- )
- func TestRuleIndexSimple(t *testing.T) {
- ruleindexidcounter = 0
- defer func() {
- ruleindexidcounter = 0
- }()
- // Store a simple rule
- rule := &Rule{
- "TestRule", // Name
- "", // Description
- []string{"core.main.tester", "core.tmp.*"}, // Kind match
- []string{"data.read", "data.test"}, // Match on event cascade scope
- nil,
- 0, // Priority of the rule
- []string{"TestRule66"}, // List of suppressed rules by this rule
- func(p Processor, m Monitor, e *Event) error { // Action of the rule
- return nil
- },
- }
- index := NewRuleIndex()
- index.AddRule(rule)
- // Check error cases
- err := index.AddRule(&Rule{
- "TestRuleError", // Name
- "", // Description
- []string{"core.main.tester"}, // Kind match
- nil,
- nil,
- 0, // Priority of the rule
- []string{"TestRule66"}, // List of suppressed rules by this rule
- func(p Processor, m Monitor, e *Event) error { // Action of the rule
- return nil
- },
- })
- if err.Error() != "Cannot add rule without a scope match: TestRuleError" {
- t.Error("Unexpected result:", err)
- return
- }
- err = index.AddRule(&Rule{
- "TestRuleError2", // Name
- "", // Description
- nil, // Kind match
- []string{"data.read", "data.test"}, // Match on event cascade scope
- nil,
- 0, // Priority of the rule
- []string{"TestRule66"}, // List of suppressed rules by this rule
- func(p Processor, m Monitor, e *Event) error { // Action of the rule
- return nil
- },
- })
- if err.Error() != "Cannot add rule without a kind match: TestRuleError2" {
- t.Error("Unexpected result:", err)
- return
- }
- // Check index layout
- if res := index.String(); res != `
- core - RuleIndexKind (0)
- main - RuleIndexKind (1)
- tester - RuleIndexKind (2)
- RuleIndexAll (3)
- Rule:TestRule [] (Priority:0 Kind:[core.main.tester core.tmp.*] Scope:[data.read data.test] StateMatch:null Suppress:[TestRule66])
- tmp - RuleIndexKind (1)
- * - RuleIndexKind (4)
- RuleIndexAll (5)
- Rule:TestRule [] (Priority:0 Kind:[core.main.tester core.tmp.*] Scope:[data.read data.test] StateMatch:null Suppress:[TestRule66])
- `[1:] {
- t.Error("Unexpected index layout:", res)
- return
- }
- // Check trigger queries
- if !index.IsTriggering(&Event{
- "bla",
- []string{"core", "tmp", "bla"},
- nil,
- }) {
- t.Error("Unexpected result")
- return
- }
- if index.IsTriggering(&Event{
- "bla",
- []string{"core", "tmp"},
- nil,
- }) {
- t.Error("Unexpected result")
- return
- }
- if index.IsTriggering(&Event{
- "bla",
- []string{"core", "tmpp", "bla"},
- nil,
- }) {
- t.Error("Unexpected result")
- return
- }
- if !index.IsTriggering(&Event{
- "bla",
- []string{"core", "main", "tester"},
- nil,
- }) {
- t.Error("Unexpected result")
- return
- }
- if index.IsTriggering(&Event{
- "bla",
- []string{"core", "main", "tester", "bla"},
- nil,
- }) {
- t.Error("Unexpected result")
- return
- }
- if index.IsTriggering(&Event{
- "bla",
- []string{"core", "main", "teste"},
- nil,
- }) {
- t.Error("Unexpected result")
- return
- }
- if index.IsTriggering(&Event{
- "bla",
- []string{"core", "main"},
- nil,
- }) {
- t.Error("Unexpected result")
- return
- }
- // Event matching
- if res := index.Match(&Event{
- "bla",
- []string{"core", "main", "tester"},
- nil,
- }); printRules(res) != "[TestRule]" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := index.Match(&Event{
- "bla",
- []string{"core", "tmp", "x"},
- nil,
- }); printRules(res) != "[TestRule]" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := index.Match(&Event{
- "bla",
- []string{"core", "tmp"},
- nil,
- }); printRules(res) != "[]" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := index.Match(&Event{
- "bla",
- []string{"core", "tmp", "x", "y"},
- nil,
- }); printRules(res) != "[]" {
- t.Error("Unexpected result:", res)
- return
- }
- }
- func TestRuleIndexStateMatch(t *testing.T) {
- ruleindexidcounter = 0
- defer func() {
- ruleindexidcounter = 0
- }()
- rule1 := &Rule{
- "TestRule1", // Name
- "", // Description
- []string{"core.main.tester", "core.tmp.*"}, // Kind match
- []string{"data.read", "data.test"}, // Match on event cascade scope
- map[string]interface{}{ // Match on event state
- "name": nil,
- "test": "val1",
- },
- 0, // Priority of the rule
- []string{"TestRule66"}, // List of suppressed rules by this rule
- func(p Processor, m Monitor, e *Event) error { // Action of the rule
- return nil
- },
- }
- rule2 := &Rule{
- "TestRule2", // Name
- "", // Description
- []string{"core.main.tester"}, // Kind match
- []string{"data.read"}, // Match on event cascade scope
- map[string]interface{}{ // Match on event state
- "name": nil,
- "test": "val2",
- "test2": 42,
- },
- 0, // Priority of the rule
- []string{"TestRule66"}, // List of suppressed rules by this rule
- func(p Processor, m Monitor, e *Event) error { // Action of the rule
- return nil
- },
- }
- rule3 := &Rule{
- "TestRule3", // Name
- "", // Description
- []string{"core.main.tester"}, // Kind match
- []string{"data.read"}, // Match on event cascade scope
- map[string]interface{}{ // Match on event state
- "name": nil,
- "test": "val2",
- "test2": 42,
- "test3": 15,
- },
- 0, // Priority of the rule
- []string{"TestRule66"}, // List of suppressed rules by this rule
- func(p Processor, m Monitor, e *Event) error { // Action of the rule
- return nil
- },
- }
- index := NewRuleIndex()
- index.AddRule(rule1)
- index.AddRule(rule2)
- index.AddRule(rule3)
- if err := index.AddRule(rule3); err.Error() != "Cannot add rule TestRule3 twice" {
- t.Error("Unexpected result:", err)
- return
- }
- if len(index.Rules()) != 3 {
- t.Error("Unexpected number of rules:", len(index.Rules()))
- }
- // Check index layout
- if res := index.String(); res != `
- core - RuleIndexKind (0)
- main - RuleIndexKind (1)
- tester - RuleIndexKind (2)
- RuleIndexState (3) [TestRule1 TestRule2 TestRule3 ]
- name - 00000007 *:00000007 [] []
- test - 00000007 *:00000000 [val1:00000001 val2:00000006 ] []
- test2 - 00000006 *:00000000 [42:00000006 ] []
- test3 - 00000004 *:00000000 [15:00000004 ] []
- tmp - RuleIndexKind (1)
- * - RuleIndexKind (4)
- RuleIndexState (5) [TestRule1 ]
- name - 00000001 *:00000001 [] []
- test - 00000001 *:00000000 [val1:00000001 ] []
- `[1:] {
- t.Error("Unexpected index layout:", res)
- return
- }
- // Make sure events without state do not match
- if res := index.Match(&Event{
- "bla",
- []string{"core", "tmp", "x"},
- nil,
- }); printRules(res) != "[]" {
- t.Error("Unexpected result:", res)
- return
- }
- // Single rule match
- if res := index.Match(&Event{
- "bla",
- []string{"core", "tmp", "x"},
- map[interface{}]interface{}{ // Match on event state
- "name": nil,
- "test": "val1",
- },
- }); printRules(res) != "[TestRule1]" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := index.Match(&Event{
- "bla",
- []string{"core", "main", "tester"},
- map[interface{}]interface{}{ // Match on event state
- "name": nil,
- "test": "val1",
- },
- }); printRules(res) != "[TestRule1]" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := index.Match(&Event{
- "bla",
- []string{"core", "main", "tester"},
- map[interface{}]interface{}{ // Match on event state
- "name": "foobar",
- "test": "val2",
- "test2": 42,
- },
- }); printRules(res) != "[TestRule2]" {
- t.Error("Unexpected result:", res)
- return
- }
- // Test multiple rule match
- if res := index.Match(&Event{
- "bla",
- []string{"core", "main", "tester"},
- map[interface{}]interface{}{ // Match on event state
- "name": nil,
- "test": "val2",
- "test2": 42,
- "test3": 15,
- },
- }); printRules(res) != "[TestRule2 TestRule3]" {
- t.Error("Unexpected result:", res)
- return
- }
- }
- func TestRuleIndexStateRegexMatch(t *testing.T) {
- ruleindexidcounter = 0
- defer func() {
- ruleindexidcounter = 0
- }()
- rule1 := &Rule{
- "TestRule1", // Name
- "", // Description
- []string{"core.main.tester", "core.tmp.*"}, // Kind match
- []string{"data.read", "data.test"}, // Match on event cascade scope
- map[string]interface{}{ // Match on event state
- "name": nil,
- "test": regexp.MustCompile("val.*"),
- },
- 0, // Priority of the rule
- []string{"TestRule66"}, // List of suppressed rules by this rule
- func(p Processor, m Monitor, e *Event) error { // Action of the rule
- return nil
- },
- }
- rule2 := &Rule{
- "TestRule2", // Name
- "", // Description
- []string{"core.main.tester"}, // Kind match
- []string{"data.read"}, // Match on event cascade scope
- map[string]interface{}{ // Match on event state
- "name": nil,
- "test": regexp.MustCompile("va..*"),
- },
- 0, // Priority of the rule
- []string{"TestRule66"}, // List of suppressed rules by this rule
- func(p Processor, m Monitor, e *Event) error { // Action of the rule
- return nil
- },
- }
- index := NewRuleIndex()
- index.AddRule(rule1)
- index.AddRule(rule2)
- // Check index layout
- if res := index.String(); res != `
- core - RuleIndexKind (0)
- main - RuleIndexKind (1)
- tester - RuleIndexKind (2)
- RuleIndexState (3) [TestRule1 TestRule2 ]
- name - 00000003 *:00000003 [] []
- test - 00000003 *:00000003 [] [00000001:val.* 00000002:va..* ]
- tmp - RuleIndexKind (1)
- * - RuleIndexKind (4)
- RuleIndexState (5) [TestRule1 ]
- name - 00000001 *:00000001 [] []
- test - 00000001 *:00000001 [] [00000001:val.* ]
- `[1:] {
- t.Error("Unexpected index layout:", res)
- return
- }
- if res := index.Match(&Event{
- "bla",
- []string{"core", "tmp", "x"},
- map[interface{}]interface{}{ // Match on event state
- "name": "boo",
- "test": "val1",
- },
- }); printRules(res) != "[TestRule1]" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := index.Match(&Event{
- "bla",
- []string{"core", "tmp", "x"},
- map[interface{}]interface{}{ // Match on event state
- "name": "boo",
- "test": "val",
- },
- }); printRules(res) != "[TestRule1]" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := index.Match(&Event{
- "bla",
- []string{"core", "main", "tester"},
- map[interface{}]interface{}{ // Match on event state
- "name": "boo",
- "test": "var",
- },
- }); printRules(res) != "[TestRule2]" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := index.Match(&Event{
- "bla",
- []string{"core", "main", "tester"},
- map[interface{}]interface{}{ // Match on event state
- "name": "boo",
- "test": "val",
- },
- }); printRules(res) != "[TestRule1 TestRule2]" {
- t.Error("Unexpected result:", res)
- return
- }
- // Test error cases
- if res := index.IsTriggering(&Event{
- "bla",
- []string{"core", "main", "tester", "a"},
- map[interface{}]interface{}{ // Match on event state
- "name": "boo",
- "test": "val",
- },
- }); res {
- t.Error("Unexpected result:", res)
- return
- }
- if res := index.Match(&Event{
- "bla",
- []string{"core", "main", "tester", "a"},
- map[interface{}]interface{}{ // Match on event state
- "name": "boo",
- "test": "val",
- },
- }); printRules(res) != "[]" {
- t.Error("Unexpected result:", res)
- return
- }
- }
- func printRules(rules []*Rule) string {
- var ret []string
- for _, r := range rules {
- ret = append(ret, r.Name)
- }
- sort.Strings(ret)
- return fmt.Sprint(ret)
- }
|