From 794d3221d0c773028422174a7ad405225ea4f265 Mon Sep 17 00:00:00 2001 From: AlteredCoder <64792091+AlteredCoder@users.noreply.github.com> Date: Tue, 28 Jul 2020 15:38:48 +0200 Subject: [PATCH] add tests in pkg/csconfig and improve pkg/exprhelpers tests (#150) * add tests for csconfig & improve exprhelpers tests --- cmd/crowdsec-cli/main.go | 2 +- cmd/crowdsec/main.go | 2 +- pkg/csconfig/config.go | 13 +- pkg/csconfig/config_test.go | 411 ++++++++++++++++++ pkg/csconfig/tests/bad_config.yaml | 19 + pkg/csconfig/tests/bad_config_simulation.yaml | 18 + .../tests/bad_config_simulation_1.yaml | 18 + pkg/csconfig/tests/bad_simulation.yaml | 1 + pkg/csconfig/tests/config.yaml | 18 + pkg/csconfig/tests/simulation.yaml | 4 + pkg/exprhelpers/expr_test.go | 135 ------ pkg/exprhelpers/exprlib_test.go | 206 +++++++++ pkg/exprhelpers/jsonextract_test.go | 49 +++ 13 files changed, 752 insertions(+), 144 deletions(-) create mode 100644 pkg/csconfig/config_test.go create mode 100644 pkg/csconfig/tests/bad_config.yaml create mode 100644 pkg/csconfig/tests/bad_config_simulation.yaml create mode 100644 pkg/csconfig/tests/bad_config_simulation_1.yaml create mode 100644 pkg/csconfig/tests/bad_simulation.yaml create mode 100644 pkg/csconfig/tests/config.yaml create mode 100644 pkg/csconfig/tests/simulation.yaml delete mode 100644 pkg/exprhelpers/expr_test.go create mode 100644 pkg/exprhelpers/exprlib_test.go create mode 100644 pkg/exprhelpers/jsonextract_test.go diff --git a/cmd/crowdsec-cli/main.go b/cmd/crowdsec-cli/main.go index 5d2885d45..b62509544 100644 --- a/cmd/crowdsec-cli/main.go +++ b/cmd/crowdsec-cli/main.go @@ -37,7 +37,7 @@ func initConfig() { } csConfig := csconfig.NewCrowdSecConfig() - if err := csConfig.GetCliConfig(&config.ConfigFilePath); err != nil { + if err := csConfig.LoadConfigurationFile(&config.ConfigFilePath); err != nil { log.Fatalf(err.Error()) } config.configFolder = filepath.Clean(csConfig.CsCliFolder) diff --git a/cmd/crowdsec/main.go b/cmd/crowdsec/main.go index c4ae8eb70..c755242c4 100644 --- a/cmd/crowdsec/main.go +++ b/cmd/crowdsec/main.go @@ -244,7 +244,7 @@ func main() { cConfig = csconfig.NewCrowdSecConfig() // Handle command line arguments - if err := cConfig.GetOPT(); err != nil { + if err := cConfig.LoadConfig(); err != nil { log.Fatalf(err.Error()) } // Configure logging diff --git a/pkg/csconfig/config.go b/pkg/csconfig/config.go index 4f92a3061..697daae7a 100644 --- a/pkg/csconfig/config.go +++ b/pkg/csconfig/config.go @@ -81,7 +81,7 @@ func (c *CrowdSec) LoadSimulation() error { return nil } -func (c *CrowdSec) GetCliConfig(configFile *string) error { +func (c *CrowdSec) LoadConfigurationFile(configFile *string) error { /*overriden by cfg file*/ if *configFile != "" { rcfg, err := ioutil.ReadFile(*configFile) @@ -101,9 +101,8 @@ func (c *CrowdSec) GetCliConfig(configFile *string) error { return nil } -// GetOPT return flags parsed from command line -func (c *CrowdSec) GetOPT() error { - +// LoadConfig return configuration parsed from command line and configuration file +func (c *CrowdSec) LoadConfig() error { AcquisitionFile := flag.String("acquis", "", "path to acquis.yaml") configFile := flag.String("c", "", "configuration file") printTrace := flag.Bool("trace", false, "VERY verbose") @@ -129,14 +128,14 @@ func (c *CrowdSec) GetOPT() error { if *catFile != "" { if *catFileType == "" { - log.Fatalf("-file requires -type") + return fmt.Errorf("-file requires -type") } c.SingleFile = *catFile c.SingleFileLabel = *catFileType } - if err := c.GetCliConfig(configFile); err != nil { - log.Fatalf("Error while loading configuration : %s", err) + if err := c.LoadConfigurationFile(configFile); err != nil { + return fmt.Errorf("Error while loading configuration : %s", err) } if *AcquisitionFile != "" { diff --git a/pkg/csconfig/config_test.go b/pkg/csconfig/config_test.go new file mode 100644 index 000000000..130afb1e0 --- /dev/null +++ b/pkg/csconfig/config_test.go @@ -0,0 +1,411 @@ +package csconfig + +import ( + "flag" + "os" + "testing" + + "github.com/crowdsecurity/crowdsec/pkg/outputs" + log "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" +) + +func TestNewCrowdSecConfig(t *testing.T) { + tests := []struct { + name string + expectedResult *CrowdSec + err string + }{ + { + name: "new configuration: basic", + expectedResult: &CrowdSec{ + LogLevel: log.InfoLevel, + Daemonize: false, + Profiling: false, + WorkingFolder: "/tmp/", + DataFolder: "/var/lib/crowdsec/data/", + ConfigFolder: "/etc/crowdsec/config/", + PIDFolder: "/var/run/", + LogFolder: "/var/log/", + LogMode: "stdout", + APIMode: false, + NbParsers: 1, + Prometheus: false, + HTTPListen: "127.0.0.1:6060", + }, + err: "", + }, + } + for _, test := range tests { + result := NewCrowdSecConfig() + isOk := assert.Equal(t, test.expectedResult, result) + if !isOk { + t.Fatalf("test '%s' failed", test.name) + } + log.Infof("test '%s' : OK", test.name) + } + +} + +func TestLoadConfig(t *testing.T) { + tests := []struct { + name string + expectedResult *CrowdSec + Args []string + err string + }{ + { + name: "load configuration: basic", + expectedResult: &CrowdSec{ + LogLevel: log.InfoLevel, + Daemonize: true, + Profiling: true, + WorkingFolder: "./tests/", + DataFolder: "./tests/", + ConfigFolder: "./tests/", + PIDFolder: "./tests/", + LogFolder: "./tests/", + LogMode: "stdout", + APIMode: true, + NbParsers: 1, + Prometheus: true, + HTTPListen: "127.0.0.1:6060", + AcquisitionFile: "tests/acquis.yaml", + CsCliFolder: "./tests/cscli/", + SimulationCfg: &SimulationConfig{ + Simulation: false, + Exclusions: nil, + }, + SimulationCfgPath: "./tests/simulation.yaml", + OutputConfig: &outputs.OutputFactory{ + BackendFolder: "./tests/plugins/backend", + MaxRecords: "", + MaxRecordsAge: "720h", + Flush: false, + Debug: false, + }, + }, + Args: []string{ + "crowdsec", + "-c", + "./tests/config.yaml", + }, + err: "", + }, + { + name: "load configuration: with -file", + expectedResult: &CrowdSec{ + LogLevel: log.InfoLevel, + SingleFile: "./tests/test.file", + SingleFileLabel: "test", + Daemonize: true, + Profiling: true, + WorkingFolder: "./tests/", + DataFolder: "./tests/", + ConfigFolder: "./tests/", + PIDFolder: "./tests/", + LogFolder: "./tests/", + LogMode: "stdout", + APIMode: true, + NbParsers: 1, + Prometheus: true, + HTTPListen: "127.0.0.1:6060", + AcquisitionFile: "tests/acquis.yaml", + CsCliFolder: "./tests/cscli/", + SimulationCfg: &SimulationConfig{ + Simulation: false, + Exclusions: nil, + }, + SimulationCfgPath: "./tests/simulation.yaml", + OutputConfig: &outputs.OutputFactory{ + BackendFolder: "./tests/plugins/backend", + MaxRecords: "", + MaxRecordsAge: "720h", + Flush: false, + Debug: false, + }, + }, + Args: []string{ + "crowdsec", + "-c", + "./tests/config.yaml", + "-file", + "./tests/test.file", + "-type", + "test", + }, + err: "", + }, + { + name: "load configuration: with -file without -type", + expectedResult: &CrowdSec{ + LogLevel: log.InfoLevel, + Daemonize: false, + Profiling: false, + WorkingFolder: "/tmp/", + DataFolder: "/var/lib/crowdsec/data/", + ConfigFolder: "/etc/crowdsec/config/", + PIDFolder: "/var/run/", + LogFolder: "/var/log/", + LogMode: "stdout", + APIMode: false, + NbParsers: 1, + Prometheus: false, + HTTPListen: "127.0.0.1:6060", + }, + Args: []string{ + "crowdsec", + "-c", + "./tests/config.yaml", + "-file", + "./tests/test.file", + }, + err: "-file requires -type", + }, + { + name: "load configuration: all flags set", + expectedResult: &CrowdSec{ + LogLevel: log.TraceLevel, + Daemonize: true, + Profiling: true, + WorkingFolder: "./tests/", + DataFolder: "./tests/", + ConfigFolder: "./tests/", + PIDFolder: "./tests/", + LogFolder: "./tests/", + LogMode: "stdout", + APIMode: true, + Linter: true, + NbParsers: 1, + Prometheus: true, + HTTPListen: "127.0.0.1:6060", + AcquisitionFile: "./tests/acquis.yaml", + CsCliFolder: "./tests/cscli/", + SimulationCfg: &SimulationConfig{ + Simulation: false, + Exclusions: nil, + }, + SimulationCfgPath: "./tests/simulation.yaml", + OutputConfig: &outputs.OutputFactory{ + BackendFolder: "./tests/plugins/backend", + MaxRecords: "", + MaxRecordsAge: "720h", + Flush: false, + Debug: false, + }, + RestoreMode: "./tests/states.json", + DumpBuckets: true, + }, + Args: []string{ + "crowdsec", + "-c", + "./tests/config.yaml", + "-acquis", + "./tests/acquis.yaml", + "-dump-state", + "-prometheus-metrics", + "-t", + "-daemon", + "-profile", + "-debug", + "-trace", + "-info", + "-restore-state", + "./tests/states.json", + "-api", + }, + err: "", + }, + { + name: "load configuration: bad config file", + expectedResult: &CrowdSec{ + LogLevel: log.InfoLevel, + Daemonize: true, + Profiling: true, + WorkingFolder: "./tests/", + DataFolder: "./tests/", + ConfigFolder: "./tests/", + PIDFolder: "./tests/", + LogFolder: "./tests/", + LogMode: "stdout", + APIMode: true, + Linter: false, + NbParsers: 1, + Prometheus: true, + HTTPListen: "127.0.0.1:6060", + CsCliFolder: "./tests/cscli/", + SimulationCfgPath: "./tests/simulation.yaml", + OutputConfig: &outputs.OutputFactory{ + BackendFolder: "./tests/plugins/backend", + MaxRecords: "", + MaxRecordsAge: "720h", + Flush: false, + Debug: false, + }, + }, + Args: []string{ + "crowdsec", + "-c", + "./tests/bad_config.yaml", + }, + err: "Error while loading configuration : parse './tests/bad_config.yaml' : yaml: unmarshal errors:\n line 1: field non_existing_field not found in type csconfig.CrowdSec", + }, + { + name: "load configuration: bad simulation file", + expectedResult: &CrowdSec{ + LogLevel: log.InfoLevel, + Daemonize: true, + Profiling: true, + WorkingFolder: "./tests/", + DataFolder: "./tests/", + ConfigFolder: "./tests/", + PIDFolder: "./tests/", + LogFolder: "./tests/", + LogMode: "stdout", + APIMode: true, + Linter: false, + NbParsers: 1, + Prometheus: true, + AcquisitionFile: "tests/acquis.yaml", + HTTPListen: "127.0.0.1:6060", + CsCliFolder: "./tests/cscli/", + SimulationCfgPath: "./tests/bad_simulation.yaml", + OutputConfig: &outputs.OutputFactory{ + BackendFolder: "./tests/plugins/backend", + MaxRecords: "", + MaxRecordsAge: "720h", + Flush: false, + Debug: false, + }, + }, + Args: []string{ + "crowdsec", + "-c", + "./tests/bad_config_simulation.yaml", + }, + err: `Error while loading configuration : loading simulation config : while parsing './tests/bad_simulation.yaml' : yaml: unmarshal errors: + line 1: field test not found in type csconfig.SimulationConfig`, + }, + { + name: "load configuration: bad config file", + expectedResult: &CrowdSec{ + LogLevel: log.InfoLevel, + Daemonize: true, + Profiling: true, + WorkingFolder: "./tests/", + DataFolder: "./tests/", + ConfigFolder: "./tests/", + PIDFolder: "./tests/", + LogFolder: "./tests/", + LogMode: "stdout", + APIMode: true, + Linter: false, + NbParsers: 1, + Prometheus: true, + HTTPListen: "127.0.0.1:6060", + CsCliFolder: "./tests/cscli/", + SimulationCfgPath: "./tests/simulation.yaml", + OutputConfig: &outputs.OutputFactory{ + BackendFolder: "./tests/plugins/backend", + MaxRecords: "", + MaxRecordsAge: "720h", + Flush: false, + Debug: false, + }, + }, + Args: []string{ + "crowdsec", + "-c", + "./tests/bad_config.yaml", + }, + err: "Error while loading configuration : parse './tests/bad_config.yaml' : yaml: unmarshal errors:\n line 1: field non_existing_field not found in type csconfig.CrowdSec", + }, + { + name: "load configuration: non exist simulation file", + expectedResult: &CrowdSec{ + LogLevel: log.InfoLevel, + Daemonize: true, + Profiling: true, + WorkingFolder: "./tests/", + DataFolder: "./tests/", + ConfigFolder: "./tests/", + PIDFolder: "./tests/", + LogFolder: "./tests/", + LogMode: "stdout", + APIMode: true, + Linter: false, + NbParsers: 1, + Prometheus: true, + AcquisitionFile: "tests/acquis.yaml", + HTTPListen: "127.0.0.1:6060", + CsCliFolder: "./tests/cscli/", + SimulationCfgPath: "./tests/non_exist.yaml", + OutputConfig: &outputs.OutputFactory{ + BackendFolder: "./tests/plugins/backend", + MaxRecords: "", + MaxRecordsAge: "720h", + Flush: false, + Debug: false, + }, + }, + Args: []string{ + "crowdsec", + "-c", + "./tests/bad_config_simulation_1.yaml", + }, + err: "Error while loading configuration : loading simulation config : while reading './tests/non_exist.yaml' : open ./tests/non_exist.yaml: no such file or directory", + }, + { + name: "load configuration: non existent configuration file", + expectedResult: &CrowdSec{ + LogLevel: log.InfoLevel, + Daemonize: false, + Profiling: false, + WorkingFolder: "/tmp/", + DataFolder: "/var/lib/crowdsec/data/", + ConfigFolder: "/etc/crowdsec/config/", + PIDFolder: "/var/run/", + LogFolder: "/var/log/", + LogMode: "stdout", + APIMode: false, + NbParsers: 1, + Prometheus: false, + HTTPListen: "127.0.0.1:6060", + }, + Args: []string{ + "crowdsec", + "-c", + "./tests/non_exist.yaml", + }, + err: "Error while loading configuration : read './tests/non_exist.yaml' : open ./tests/non_exist.yaml: no such file or directory", + }, + } + + oldArgs := os.Args + defer func() { os.Args = oldArgs }() + for _, test := range tests { + log.Printf("testing '%s'", test.name) + flag.CommandLine = flag.NewFlagSet(test.Args[0], flag.ExitOnError) + result := NewCrowdSecConfig() + os.Args = test.Args + err := result.LoadConfig() + + if test.err != "" { + if err == nil { + t.Fatalf("test '%s' should returned an error", test.name) + } + isOk := assert.EqualErrorf(t, err, test.err, "") + if !isOk { + t.Fatalf("test '%s' failed", test.name) + } + } + if test.err == "" && err != nil { + t.Fatalf("test '%s' return an error : %s", test.name, err) + } + isOk := assert.Equal(t, test.expectedResult, result) + if !isOk { + t.Fatalf("test '%s' failed", test.name) + } + log.Infof("test '%s' : OK", test.name) + } +} diff --git a/pkg/csconfig/tests/bad_config.yaml b/pkg/csconfig/tests/bad_config.yaml new file mode 100644 index 000000000..bda935b58 --- /dev/null +++ b/pkg/csconfig/tests/bad_config.yaml @@ -0,0 +1,19 @@ +non_existing_field: "" +working_dir: ./tests/ +data_dir: ./tests/ +config_dir: ./tests/ +pid_dir: ./tests/ +log_dir: ./tests/ +cscli_dir: ./tests/cscli/ +simulation_path: ./tests/simulation.yaml +log_mode: stdout +log_level: info +profiling: true +apimode: true +daemon: true +prometheus: true +#for prometheus agent / golang debugging +http_listen: 127.0.0.1:6060 +plugin: + backend: "./tests/plugins/backend" + max_records_age: 720h diff --git a/pkg/csconfig/tests/bad_config_simulation.yaml b/pkg/csconfig/tests/bad_config_simulation.yaml new file mode 100644 index 000000000..58685f896 --- /dev/null +++ b/pkg/csconfig/tests/bad_config_simulation.yaml @@ -0,0 +1,18 @@ +working_dir: ./tests/ +data_dir: ./tests/ +config_dir: ./tests/ +pid_dir: ./tests/ +log_dir: ./tests/ +cscli_dir: ./tests/cscli/ +simulation_path: ./tests/bad_simulation.yaml +log_mode: stdout +log_level: info +profiling: true +apimode: true +daemon: true +prometheus: true +#for prometheus agent / golang debugging +http_listen: 127.0.0.1:6060 +plugin: + backend: "./tests/plugins/backend" + max_records_age: 720h diff --git a/pkg/csconfig/tests/bad_config_simulation_1.yaml b/pkg/csconfig/tests/bad_config_simulation_1.yaml new file mode 100644 index 000000000..b34d8153e --- /dev/null +++ b/pkg/csconfig/tests/bad_config_simulation_1.yaml @@ -0,0 +1,18 @@ +working_dir: ./tests/ +data_dir: ./tests/ +config_dir: ./tests/ +pid_dir: ./tests/ +log_dir: ./tests/ +cscli_dir: ./tests/cscli/ +simulation_path: ./tests/non_exist.yaml +log_mode: stdout +log_level: info +profiling: true +apimode: true +daemon: true +prometheus: true +#for prometheus agent / golang debugging +http_listen: 127.0.0.1:6060 +plugin: + backend: "./tests/plugins/backend" + max_records_age: 720h diff --git a/pkg/csconfig/tests/bad_simulation.yaml b/pkg/csconfig/tests/bad_simulation.yaml new file mode 100644 index 000000000..128e78a31 --- /dev/null +++ b/pkg/csconfig/tests/bad_simulation.yaml @@ -0,0 +1 @@ +test: "" \ No newline at end of file diff --git a/pkg/csconfig/tests/config.yaml b/pkg/csconfig/tests/config.yaml new file mode 100644 index 000000000..4c762313d --- /dev/null +++ b/pkg/csconfig/tests/config.yaml @@ -0,0 +1,18 @@ +working_dir: ./tests/ +data_dir: ./tests/ +config_dir: ./tests/ +pid_dir: ./tests/ +log_dir: ./tests/ +cscli_dir: ./tests/cscli/ +simulation_path: ./tests/simulation.yaml +log_mode: stdout +log_level: info +profiling: true +apimode: true +daemon: true +prometheus: true +#for prometheus agent / golang debugging +http_listen: 127.0.0.1:6060 +plugin: + backend: "./tests/plugins/backend" + max_records_age: 720h diff --git a/pkg/csconfig/tests/simulation.yaml b/pkg/csconfig/tests/simulation.yaml new file mode 100644 index 000000000..e9c689993 --- /dev/null +++ b/pkg/csconfig/tests/simulation.yaml @@ -0,0 +1,4 @@ +simulation: off +# exclusions: +# - crowdsecurity/ssh-bf + \ No newline at end of file diff --git a/pkg/exprhelpers/expr_test.go b/pkg/exprhelpers/expr_test.go deleted file mode 100644 index b44fbd919..000000000 --- a/pkg/exprhelpers/expr_test.go +++ /dev/null @@ -1,135 +0,0 @@ -package exprhelpers - -import ( - "log" - "testing" - - "github.com/antonmedv/expr" - "github.com/stretchr/testify/require" - "gotest.tools/assert" -) - -var ( - TestFolder = "tests" -) - -func TestRegexpInFile(t *testing.T) { - if err := Init(); err != nil { - log.Fatalf(err.Error()) - } - - err := FileInit(TestFolder, "test_data_re.txt", "regex") - if err != nil { - log.Fatalf(err.Error()) - } - - tests := []struct { - filter string - result bool - err error - }{ - { - filter: "RegexpInFile('crowdsec', 'test_data_re.txt')", - result: false, - err: nil, - }, - { - filter: "RegexpInFile('Crowdsec', 'test_data_re.txt')", - result: true, - err: nil, - }, - { - filter: "RegexpInFile('test Crowdsec', 'test_data_re.txt')", - result: true, - err: nil, - }, - { - filter: "RegexpInFile('test CrowdSec', 'test_data_re.txt')", - result: true, - err: nil, - }, - } - - for _, test := range tests { - compiledFilter, err := expr.Compile(test.filter, expr.Env(GetExprEnv(map[string]interface{}{}))) - if err != nil { - log.Fatalf(err.Error()) - } - log.Printf("Running filter : %s", test.filter) - result, err := expr.Run(compiledFilter, GetExprEnv(map[string]interface{}{})) - if err != nil { - log.Fatalf(err.Error()) - } - assert.Equal(t, test.result, result) - } -} - -func TestFile(t *testing.T) { - if err := Init(); err != nil { - log.Fatalf(err.Error()) - } - - err := FileInit(TestFolder, "test_data.txt", "") - if err != nil { - log.Fatalf(err.Error()) - } - - tests := []struct { - filter string - result bool - err error - }{ - { - filter: "'Crowdsec' in File('test_data.txt')", - result: true, - err: nil, - }, - { - filter: "'CrowdSecurity' in File('test_data.txt')", - result: false, - err: nil, - }, - { - filter: "'Crowdsecurity' in File('test_data.txt')", - result: true, - err: nil, - }, - { - filter: "'test' in File('test_data.txt')", - result: false, - err: nil, - }, - } - - for _, test := range tests { - compiledFilter, err := expr.Compile(test.filter, expr.Env(GetExprEnv(map[string]interface{}{}))) - if err != nil { - log.Fatalf(err.Error()) - } - log.Printf("Running filter : %s", test.filter) - result, err := expr.Run(compiledFilter, GetExprEnv(map[string]interface{}{})) - if err != nil { - log.Fatalf(err.Error()) - } - assert.Equal(t, test.result, result) - } -} - -func TestIpInRange(t *testing.T) { - env := map[string]interface{}{ - "ip": "192.168.0.1", - "ipRange": "192.168.0.0/24", - "IpInRange": IpInRange, - } - code := "IpInRange(ip, ipRange)" - log.Printf("Running filter : %s", code) - - program, err := expr.Compile(code, expr.Env(env)) - require.NoError(t, err) - - output, err := expr.Run(program, env) - require.NoError(t, err) - - require.Equal(t, true, output) - -} diff --git a/pkg/exprhelpers/exprlib_test.go b/pkg/exprhelpers/exprlib_test.go new file mode 100644 index 000000000..32a288673 --- /dev/null +++ b/pkg/exprhelpers/exprlib_test.go @@ -0,0 +1,206 @@ +package exprhelpers + +import ( + "log" + "testing" + + "github.com/antonmedv/expr" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var ( + TestFolder = "tests" +) + +func TestRegexpInFile(t *testing.T) { + if err := Init(); err != nil { + log.Fatalf(err.Error()) + } + + err := FileInit(TestFolder, "test_data_re.txt", "regex") + if err != nil { + log.Fatalf(err.Error()) + } + + tests := []struct { + name string + filter string + result bool + err error + }{ + { + name: "RegexpInFile() test: lower case word in data file", + filter: "RegexpInFile('crowdsec', 'test_data_re.txt')", + result: false, + err: nil, + }, + { + name: "RegexpInFile() test: Match exactly", + filter: "RegexpInFile('Crowdsec', 'test_data_re.txt')", + result: true, + err: nil, + }, + { + name: "RegexpInFile() test: match with word before", + filter: "RegexpInFile('test Crowdsec', 'test_data_re.txt')", + result: true, + err: nil, + }, + { + name: "RegexpInFile() test: match with word before and other case", + filter: "RegexpInFile('test CrowdSec', 'test_data_re.txt')", + result: true, + err: nil, + }, + } + + for _, test := range tests { + compiledFilter, err := expr.Compile(test.filter, expr.Env(GetExprEnv(map[string]interface{}{}))) + if err != nil { + log.Fatalf(err.Error()) + } + result, err := expr.Run(compiledFilter, GetExprEnv(map[string]interface{}{})) + if err != nil { + log.Fatalf(err.Error()) + } + if isOk := assert.Equal(t, test.result, result); !isOk { + t.Fatalf("test '%s' : NOK", test.name) + } + } +} + +func TestFile(t *testing.T) { + if err := Init(); err != nil { + log.Fatalf(err.Error()) + } + + err := FileInit(TestFolder, "test_data.txt", "") + if err != nil { + log.Fatalf(err.Error()) + } + + tests := []struct { + name string + filter string + result bool + err error + }{ + { + name: "File() test: word in file", + filter: "'Crowdsec' in File('test_data.txt')", + result: true, + err: nil, + }, + { + name: "File() test: word in file but different case", + filter: "'CrowdSecurity' in File('test_data.txt')", + result: false, + err: nil, + }, + { + name: "File() test: word not in file", + filter: "'test' in File('test_data.txt')", + result: false, + err: nil, + }, + { + name: "File() test: filepath provided doesn't exist", + filter: "'test' in File('non_existing_data.txt')", + result: false, + err: nil, + }, + } + + for _, test := range tests { + compiledFilter, err := expr.Compile(test.filter, expr.Env(GetExprEnv(map[string]interface{}{}))) + if err != nil { + log.Fatalf(err.Error()) + } + result, err := expr.Run(compiledFilter, GetExprEnv(map[string]interface{}{})) + if err != nil { + log.Fatalf(err.Error()) + } + if isOk := assert.Equal(t, test.result, result); !isOk { + t.Fatalf("test '%s' : NOK", test.name) + } + log.Printf("test '%s' : OK", test.name) + + } +} + +func TestIpInRange(t *testing.T) { + tests := []struct { + name string + env map[string]interface{} + code string + result bool + err string + }{ + { + name: "IpInRange() test: basic test", + env: map[string]interface{}{ + "ip": "192.168.0.1", + "ipRange": "192.168.0.0/24", + "IpInRange": IpInRange, + }, + code: "IpInRange(ip, ipRange)", + result: true, + err: "", + }, + { + name: "IpInRange() test: malformed IP", + env: map[string]interface{}{ + "ip": "192.168.0", + "ipRange": "192.168.0.0/24", + "IpInRange": IpInRange, + }, + code: "IpInRange(ip, ipRange)", + result: false, + err: "", + }, + { + name: "IpInRange() test: malformed IP range", + env: map[string]interface{}{ + "ip": "192.168.0.0/255", + "ipRange": "192.168.0.0/24", + "IpInRange": IpInRange, + }, + code: "IpInRange(ip, ipRange)", + result: false, + err: "", + }, + } + + for _, test := range tests { + program, err := expr.Compile(test.code, expr.Env(test.env)) + require.NoError(t, err) + output, err := expr.Run(program, test.env) + require.NoError(t, err) + require.Equal(t, test.result, output) + log.Printf("test '%s' : OK", test.name) + } + +} + +func TestAtof(t *testing.T) { + testFloat := "1.5" + expectedFloat := 1.5 + + if Atof(testFloat) != expectedFloat { + t.Fatalf("Atof should returned 1.5 as a float") + } + + log.Printf("test 'Atof()' : OK") +} + +func TestUpper(t *testing.T) { + testStr := "test" + expectedStr := "TEST" + + if Upper(testStr) != expectedStr { + t.Fatalf("Upper() should returned 1.5 as a float") + } + + log.Printf("test 'Upper()' : OK") +} diff --git a/pkg/exprhelpers/jsonextract_test.go b/pkg/exprhelpers/jsonextract_test.go new file mode 100644 index 000000000..6694dc1b1 --- /dev/null +++ b/pkg/exprhelpers/jsonextract_test.go @@ -0,0 +1,49 @@ +package exprhelpers + +import ( + "log" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestJsonExtract(t *testing.T) { + if err := Init(); err != nil { + log.Fatalf(err.Error()) + } + + err := FileInit(TestFolder, "test_data_re.txt", "regex") + if err != nil { + log.Fatalf(err.Error()) + } + + tests := []struct { + name string + jsonBlob string + targetField string + expectResult string + }{ + { + name: "basic json extract", + jsonBlob: `{"test" : "1234"}`, + targetField: "test", + expectResult: "1234", + }, + { + name: "basic json extract with non existing field", + jsonBlob: `{"test" : "1234"}`, + targetField: "non_existing_field", + expectResult: "", + }, + } + + for _, test := range tests { + result := JsonExtract(test.jsonBlob, test.targetField) + isOk := assert.Equal(t, test.expectResult, result) + if !isOk { + t.Fatalf("test '%s' failed", test.name) + } + log.Printf("test '%s' : OK", test.name) + } + +}