1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-31 03:45:17 +00:00

Written base for patterns using TDD

This commit is contained in:
Maxim Goncharenko 2019-05-27 14:45:54 +03:00 committed by belyshev.denis@apriorit.com
parent 4ae45d7e9f
commit ac736bbf84
2 changed files with 319 additions and 0 deletions

106
pkg/engine/pattern.go Normal file
View file

@ -0,0 +1,106 @@
package engine
import (
"log"
"math"
"strings"
)
// ValidateValueWithPattern validates value with operators and wildcards
func ValidateValueWithPattern(value, pattern interface{}) bool {
switch typedPattern := pattern.(type) {
case bool:
typedValue, ok := value.(bool)
if !ok {
log.Printf("Expected bool, found %T", value)
return false
}
return typedPattern == typedValue
case int:
return validateValueWithIntPattern(value, typedPattern)
case float64:
return validateValueWithFloatPattern(value, typedPattern)
case string:
return validateValueWithStringPattern(value, typedPattern)
case map[string]interface{}, []interface{}:
log.Println("Maps and arrays as patterns are not supported")
return false
case nil:
return validateValueWithNilPattern(value)
default:
log.Printf("Unknown type as pattern: %T\n", pattern)
return false
}
}
func validateValueWithIntPattern(value interface{}, pattern int) bool {
switch typedValue := value.(type) {
case int:
return typedValue == pattern
case float64:
// check that float has no fraction
if typedValue == math.Trunc(typedValue) {
return int(typedValue) == pattern
}
log.Printf("Expected int, found float: %f\n", typedValue)
return false
default:
log.Printf("Expected int, found: %T\n", value)
return false
}
}
func validateValueWithFloatPattern(value interface{}, pattern float64) bool {
switch typedValue := value.(type) {
case int:
// check that float has no fraction
if pattern == math.Trunc(pattern) {
return int(pattern) == value
}
log.Printf("Expected float, found int: %d\n", typedValue)
return false
case float64:
return typedValue == pattern
default:
log.Printf("Expected float, found: %T\n", value)
return false
}
}
func validateValueWithNilPattern(value interface{}) bool {
switch typed := value.(type) {
case float64:
return typed == 0.0
case int:
return typed == 0
case string:
return typed == ""
case bool:
return typed == false
case nil:
return true
case map[string]interface{}, []interface{}:
log.Println("Maps and arrays could not be checked with nil pattern")
return false
default:
log.Printf("Unknown type as value when checking for nil pattern: %T\n", value)
return false
}
}
func validateValueWithStringPattern(value interface{}, pattern string) bool {
statements := strings.Split(pattern, "|")
for statement := range statements {
if checkSingleStatement(value, statement) {
return true
}
}
return false
}
func checkSingleStatement(value, pattern interface{}) bool {
return true
}

213
pkg/engine/pattern_test.go Normal file
View file

@ -0,0 +1,213 @@
package engine
import (
"encoding/json"
"testing"
"gotest.tools/assert"
)
func TestValidateValueWithPattern_Bool(t *testing.T) {
assert.Assert(t, ValidateValueWithPattern(true, true))
assert.Assert(t, !ValidateValueWithPattern(true, false))
assert.Assert(t, !ValidateValueWithPattern(false, true))
assert.Assert(t, ValidateValueWithPattern(false, false))
}
func TestValidateValueWithPattern_BoolInJson(t *testing.T) {
rawPattern := []byte(`
{
"key": true
}
`)
rawValue := []byte(`
{
"key": true
}
`)
var pattern, value map[string]interface{}
err := json.Unmarshal(rawPattern, &pattern)
assert.Assert(t, err)
err = json.Unmarshal(rawValue, &value)
assert.Assert(t, err)
assert.Assert(t, ValidateValueWithPattern(value["key"], pattern["key"]))
}
func TestValidateValueWithPattern_NullPatternStringValue(t *testing.T) {
rawPattern := []byte(`
{
"key": null
}
`)
rawValue := []byte(`
{
"key": "value"
}
`)
var pattern, value map[string]interface{}
err := json.Unmarshal(rawPattern, &pattern)
assert.Assert(t, err)
err = json.Unmarshal(rawValue, &value)
assert.Assert(t, err)
assert.Assert(t, !ValidateValueWithPattern(value["key"], pattern["key"]))
}
func TestValidateValueWithPattern_NullPatternDefaultString(t *testing.T) {
rawPattern := []byte(`
{
"key": null
}
`)
rawValue := []byte(`
{
"key": ""
}
`)
var pattern, value map[string]interface{}
err := json.Unmarshal(rawPattern, &pattern)
assert.Assert(t, err)
err = json.Unmarshal(rawValue, &value)
assert.Assert(t, err)
assert.Assert(t, ValidateValueWithPattern(value["key"], pattern["key"]))
}
func TestValidateValueWithPattern_NullPatternDefaultFloat(t *testing.T) {
rawPattern := []byte(`
{
"key": null
}
`)
rawValue := []byte(`
{
"key": 0.0
}
`)
var pattern, value map[string]interface{}
err := json.Unmarshal(rawPattern, &pattern)
assert.Assert(t, err)
err = json.Unmarshal(rawValue, &value)
assert.Assert(t, err)
assert.Assert(t, ValidateValueWithPattern(value["key"], pattern["key"]))
}
func TestValidateValueWithPattern_NullPatternDefaultInt(t *testing.T) {
rawPattern := []byte(`
{
"key": null
}
`)
rawValue := []byte(`
{
"key": 0
}
`)
var pattern, value map[string]interface{}
err := json.Unmarshal(rawPattern, &pattern)
assert.Assert(t, err)
err = json.Unmarshal(rawValue, &value)
assert.Assert(t, err)
assert.Assert(t, ValidateValueWithPattern(value["key"], pattern["key"]))
}
func TestValidateValueWithPattern_NullPatternDefaultBool(t *testing.T) {
rawPattern := []byte(`
{
"key": null
}
`)
rawValue := []byte(`
{
"key": false
}
`)
var pattern, value map[string]interface{}
err := json.Unmarshal(rawPattern, &pattern)
assert.Assert(t, err)
err = json.Unmarshal(rawValue, &value)
assert.Assert(t, err)
assert.Assert(t, ValidateValueWithPattern(value["key"], pattern["key"]))
}
func TestValidateValueWithPattern_StringsLogicalOr(t *testing.T) {
pattern := "192.168.88.1 | 10.100.11.*"
value := "10.100.11.54"
assert.Assert(t, ValidateValueWithPattern(value, pattern))
}
func TestValidateValueWithNilPattern_NullPatternStringValue(t *testing.T) {
assert.Assert(t, !validateValueWithNilPattern("value"))
}
func TestValidateValueWithNilPattern_NullPatternDefaultString(t *testing.T) {
assert.Assert(t, validateValueWithNilPattern(""))
}
func TestValidateValueWithNilPattern_NullPatternDefaultFloat(t *testing.T) {
assert.Assert(t, validateValueWithNilPattern(0.0))
}
func TestValidateValueWithNilPattern_NullPatternFloat(t *testing.T) {
assert.Assert(t, !validateValueWithNilPattern(0.1))
}
func TestValidateValueWithNilPattern_NullPatternDefaultInt(t *testing.T) {
assert.Assert(t, validateValueWithNilPattern(0))
}
func TestValidateValueWithNilPattern_NullPatternInt(t *testing.T) {
assert.Assert(t, !validateValueWithNilPattern(1))
}
func TestValidateValueWithNilPattern_NullPatternDefaultBool(t *testing.T) {
assert.Assert(t, validateValueWithNilPattern(false))
}
func TestValidateValueWithNilPattern_NullPatternTrueBool(t *testing.T) {
assert.Assert(t, !validateValueWithNilPattern(true))
}
func TestValidateValueWithFloatPattern_FloatValue(t *testing.T) {
assert.Assert(t, validateValueWithFloatPattern(7.9914, 7.9914))
}
func TestValidateValueWithFloatPattern_FloatValueNotPass(t *testing.T) {
assert.Assert(t, !validateValueWithFloatPattern(7.9914, 7.99141))
}
func TestValidateValueWithFloatPattern_FloatPatternWithoutFractionIntValue(t *testing.T) {
assert.Assert(t, validateValueWithFloatPattern(7, 7.000000))
}
func TestValidateValueWithFloatPattern_FloatPatternWithoutFraction(t *testing.T) {
assert.Assert(t, validateValueWithFloatPattern(7.000000, 7.000000))
}
func TestValidateValueWithIntPattern_FloatValueWithoutFraction(t *testing.T) {
assert.Assert(t, validateValueWithFloatPattern(7.000000, 7))
}
func TestValidateValueWithIntPattern_FloatValueWitFraction(t *testing.T) {
assert.Assert(t, !validateValueWithFloatPattern(7.000001, 7))
}
func TestValidateValueWithIntPattern_NotPass(t *testing.T) {
assert.Assert(t, !validateValueWithFloatPattern(8, 7))
}