From 70b46058839259da76c8a2838db2a381272eab5f Mon Sep 17 00:00:00 2001 From: Owen Rumney Date: Thu, 6 Oct 2022 09:10:07 +0100 Subject: [PATCH] feat: add comparison functions (#990) Signed-off-by: Owen Rumney --- pkg/scanners/azure/functions/coalesce.go | 10 ++ pkg/scanners/azure/functions/coalesce_test.go | 56 +++++++++ pkg/scanners/azure/functions/equals.go | 25 ++++ pkg/scanners/azure/functions/equals_test.go | 111 ++++++++++++++++ pkg/scanners/azure/functions/functions.go | 6 + pkg/scanners/azure/functions/greater.go | 47 +++++++ pkg/scanners/azure/functions/greater_test.go | 119 ++++++++++++++++++ pkg/scanners/azure/functions/less.go | 47 +++++++ pkg/scanners/azure/functions/less_test.go | 119 ++++++++++++++++++ 9 files changed, 540 insertions(+) create mode 100644 pkg/scanners/azure/functions/coalesce.go create mode 100644 pkg/scanners/azure/functions/coalesce_test.go create mode 100644 pkg/scanners/azure/functions/equals.go create mode 100644 pkg/scanners/azure/functions/equals_test.go create mode 100644 pkg/scanners/azure/functions/greater.go create mode 100644 pkg/scanners/azure/functions/greater_test.go create mode 100644 pkg/scanners/azure/functions/less.go create mode 100644 pkg/scanners/azure/functions/less_test.go diff --git a/pkg/scanners/azure/functions/coalesce.go b/pkg/scanners/azure/functions/coalesce.go new file mode 100644 index 000000000..b7ec26145 --- /dev/null +++ b/pkg/scanners/azure/functions/coalesce.go @@ -0,0 +1,10 @@ +package functions + +func Coalesce(args ...interface{}) interface{} { + for _, arg := range args { + if arg != nil { + return arg + } + } + return nil +} diff --git a/pkg/scanners/azure/functions/coalesce_test.go b/pkg/scanners/azure/functions/coalesce_test.go new file mode 100644 index 000000000..361914df6 --- /dev/null +++ b/pkg/scanners/azure/functions/coalesce_test.go @@ -0,0 +1,56 @@ +package functions + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_Coalesce(t *testing.T) { + tests := []struct { + name string + args []interface{} + expected interface{} + }{ + { + name: "coalesce with nil", + args: []interface{}{ + nil, + }, + expected: nil, + }, + { + name: "coalesce with nil and string", + args: []interface{}{ + nil, + "test", + }, + expected: "test", + }, + { + name: "coalesce with nil and string and int", + args: []interface{}{ + nil, + "test", + 1, + }, + expected: "test", + }, + { + name: "coalesce with nil and nil and array", + args: []interface{}{ + nil, + nil, + []interface{}{"a", "b", "c"}, + }, + expected: []interface{}{"a", "b", "c"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := Coalesce(tt.args...) + assert.Equal(t, tt.expected, actual) + }) + } +} diff --git a/pkg/scanners/azure/functions/equals.go b/pkg/scanners/azure/functions/equals.go new file mode 100644 index 000000000..ca5174144 --- /dev/null +++ b/pkg/scanners/azure/functions/equals.go @@ -0,0 +1,25 @@ +package functions + +func Equals(args ...interface{}) interface{} { + if len(args) != 2 { + return false + } + + slice1, ok := args[0].([]interface{}) + if ok { + slice2, ok := args[1].([]interface{}) + if ok { + if len(slice1) != len(slice2) { + return false + } + for i := 0; i < len(slice1); i++ { + if slice1[i] != slice2[i] { + return false + } + } + return true + } + } + + return args[0] == args[1] +} diff --git a/pkg/scanners/azure/functions/equals_test.go b/pkg/scanners/azure/functions/equals_test.go new file mode 100644 index 000000000..e9ad7f03f --- /dev/null +++ b/pkg/scanners/azure/functions/equals_test.go @@ -0,0 +1,111 @@ +package functions + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_Equals(t *testing.T) { + tests := []struct { + name string + args []interface{} + expected interface{} + }{ + { + name: "equals with nil", + args: []interface{}{ + nil, + }, + expected: false, + }, + { + name: "equals with nil and string", + args: []interface{}{ + nil, + "test", + }, + expected: false, + }, + { + name: "equals with nil and string and int", + args: []interface{}{ + nil, + "test", + 1, + }, + expected: false, + }, + { + name: "equals with nil and nil and array", + args: []interface{}{ + nil, + nil, + []interface{}{"a", "b", "c"}, + }, + expected: false, + }, + { + name: "equals with nil and nil", + args: []interface{}{ + nil, + nil, + }, + expected: true, + }, + { + name: "equals with string and string", + args: []interface{}{ + "test", + "test", + }, + expected: true, + }, + { + name: "equals with string and string", + args: []interface{}{ + "test", + "test1", + }, + expected: false, + }, + { + name: "equals with int and int", + args: []interface{}{ + 1, + 1, + }, + expected: true, + }, + { + name: "equals with int and int", + args: []interface{}{ + 1, + 2, + }, + expected: false, + }, + { + name: "equals with array and array", + args: []interface{}{ + []interface{}{"a", "b", "c"}, + []interface{}{"a", "b", "c"}, + }, + expected: true, + }, + { + name: "equals with array and array", + args: []interface{}{ + []interface{}{"a", "b", "c"}, + []interface{}{"a", "b", "d"}, + }, + expected: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := Equals(tt.args...) + assert.Equal(t, tt.expected, actual) + }) + } +} diff --git a/pkg/scanners/azure/functions/functions.go b/pkg/scanners/azure/functions/functions.go index 81df40e5c..032b9db7d 100644 --- a/pkg/scanners/azure/functions/functions.go +++ b/pkg/scanners/azure/functions/functions.go @@ -43,6 +43,12 @@ var generalFuncs = map[string]func(...interface{}) interface{}{ "union:": Union, "uniqueString": UniqueString, "uri": Uri, + "coalesce": Coalesce, + "equals": Equals, + "greater": Greater, + "greaterOrEquals": GreaterOrEquals, + "less": Less, + "lessOrEquals": LessOrEquals, } func Evaluate(deploymentProvider DeploymentData, name string, args ...interface{}) interface{} { diff --git a/pkg/scanners/azure/functions/greater.go b/pkg/scanners/azure/functions/greater.go new file mode 100644 index 000000000..24bf79834 --- /dev/null +++ b/pkg/scanners/azure/functions/greater.go @@ -0,0 +1,47 @@ +package functions + +func Greater(args ...interface{}) interface{} { + + if len(args) != 2 { + return false + } + + switch arg0 := args[0].(type) { + case int: + arg1, ok := args[1].(int) + if ok { + return arg0 > arg1 + } + case string: + arg1, ok := args[1].(string) + if ok { + return arg0 > arg1 + } + } + + return false +} + +func GreaterOrEquals(args ...interface{}) interface{} { + + if len(args) != 2 { + return false + } + + switch arg0 := args[0].(type) { + case nil: + return args[1] == nil + case int: + arg1, ok := args[1].(int) + if ok { + return arg0 >= arg1 + } + case string: + arg1, ok := args[1].(string) + if ok { + return arg0 >= arg1 + } + } + + return false +} diff --git a/pkg/scanners/azure/functions/greater_test.go b/pkg/scanners/azure/functions/greater_test.go new file mode 100644 index 000000000..8d3e1b21b --- /dev/null +++ b/pkg/scanners/azure/functions/greater_test.go @@ -0,0 +1,119 @@ +package functions + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_Greater(t *testing.T) { + tests := []struct { + name string + args []interface{} + expected interface{} + }{ + + { + name: "greater with nil and string", + args: []interface{}{ + nil, + "test", + }, + expected: false, + }, + { + name: "greater with nil and nil", + args: []interface{}{ + nil, + nil, + }, + expected: false, + }, + { + name: "greater with string and string", + args: []interface{}{ + "test", + "test", + }, + expected: false, + }, + { + name: "greater with string and int", + args: []interface{}{ + "test", + 1, + }, + expected: false, + }, + { + name: "greater with int and int", + args: []interface{}{ + 1, + 1, + }, + expected: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := Greater(tt.args...) + assert.Equal(t, tt.expected, actual) + }) + } +} + +func Test_GreaterThanOrEqual(t *testing.T) { + tests := []struct { + name string + args []interface{} + expected interface{} + }{ + + { + name: "greater with nil and string", + args: []interface{}{ + nil, + "test", + }, + expected: false, + }, + { + name: "greater with nil and nil", + args: []interface{}{ + nil, + nil, + }, + expected: true, + }, + { + name: "greater with string and string", + args: []interface{}{ + "test", + "test", + }, + expected: true, + }, + { + name: "greater with string and int", + args: []interface{}{ + "test", + 1, + }, + expected: false, + }, + { + name: "greater with int and int", + args: []interface{}{ + 1, + 1, + }, + expected: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := GreaterOrEquals(tt.args...) + assert.Equal(t, tt.expected, actual) + }) + } +} diff --git a/pkg/scanners/azure/functions/less.go b/pkg/scanners/azure/functions/less.go new file mode 100644 index 000000000..e25b3662c --- /dev/null +++ b/pkg/scanners/azure/functions/less.go @@ -0,0 +1,47 @@ +package functions + +func Less(args ...interface{}) interface{} { + + if len(args) != 2 { + return false + } + + switch arg0 := args[0].(type) { + case int: + arg1, ok := args[1].(int) + if ok { + return arg0 < arg1 + } + case string: + arg1, ok := args[1].(string) + if ok { + return arg0 < arg1 + } + } + + return false +} + +func LessOrEquals(args ...interface{}) interface{} { + + if len(args) != 2 { + return false + } + + switch arg0 := args[0].(type) { + case nil: + return args[1] == nil + case int: + arg1, ok := args[1].(int) + if ok { + return arg0 <= arg1 + } + case string: + arg1, ok := args[1].(string) + if ok { + return arg0 <= arg1 + } + } + + return false +} diff --git a/pkg/scanners/azure/functions/less_test.go b/pkg/scanners/azure/functions/less_test.go new file mode 100644 index 000000000..706ee89db --- /dev/null +++ b/pkg/scanners/azure/functions/less_test.go @@ -0,0 +1,119 @@ +package functions + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_Less(t *testing.T) { + tests := []struct { + name string + args []interface{} + expected interface{} + }{ + + { + name: "less with nil and string", + args: []interface{}{ + nil, + "test", + }, + expected: false, + }, + { + name: "less with nil and nil", + args: []interface{}{ + nil, + nil, + }, + expected: false, + }, + { + name: "less with string and string", + args: []interface{}{ + "test", + "test", + }, + expected: false, + }, + { + name: "less with string and int", + args: []interface{}{ + "test", + 1, + }, + expected: false, + }, + { + name: "less with int and int", + args: []interface{}{ + 1, + 1, + }, + expected: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := Less(tt.args...) + assert.Equal(t, tt.expected, actual) + }) + } +} + +func Test_LessThanOrEqual(t *testing.T) { + tests := []struct { + name string + args []interface{} + expected interface{} + }{ + + { + name: "less with nil and string", + args: []interface{}{ + nil, + "test", + }, + expected: false, + }, + { + name: "less with nil and nil", + args: []interface{}{ + nil, + nil, + }, + expected: true, + }, + { + name: "less with string and string", + args: []interface{}{ + "test", + "test", + }, + expected: true, + }, + { + name: "less with string and int", + args: []interface{}{ + "test", + 1, + }, + expected: false, + }, + { + name: "less with int and int", + args: []interface{}{ + 1, + 1, + }, + expected: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := LessOrEquals(tt.args...) + assert.Equal(t, tt.expected, actual) + }) + } +}