Преглед на файлове

add tests in pkg/csconfig and improve pkg/exprhelpers tests (#150)

* add tests for csconfig & improve exprhelpers tests
AlteredCoder преди 5 години
родител
ревизия
794d3221d0

+ 1 - 1
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)

+ 1 - 1
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

+ 6 - 7
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 != "" {

+ 411 - 0
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)
+	}
+}

+ 19 - 0
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

+ 18 - 0
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

+ 18 - 0
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

+ 1 - 0
pkg/csconfig/tests/bad_simulation.yaml

@@ -0,0 +1 @@
+test: ""

+ 18 - 0
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

+ 4 - 0
pkg/csconfig/tests/simulation.yaml

@@ -0,0 +1,4 @@
+simulation: off
+# exclusions:
+#  - crowdsecurity/ssh-bf
+ 

+ 0 - 135
pkg/exprhelpers/expr_test.go

@@ -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)
-
-}

+ 206 - 0
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")
+}

+ 49 - 0
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)
+	}
+
+}