1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-30 19:35:06 +00:00

[Feature] The ability to sum quantities (#6552)

* implemented array sum functionality

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

* provided tests and fixed some bugs

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

* added sum functionality

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

* fixed sonatype liftbot issue

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

* restructured the code implementation

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

* added helper errors

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

* removed commented codes

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

* modified error message

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

* applied requested changes

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

* removed some more comments

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

* added more tests

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

* fixed linter issues

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

---------

Signed-off-by: Ved Ratan <vedratan8@gmail.com>
Co-authored-by: shuting <shuting@nirmata.com>
This commit is contained in:
Ved Ratan 2023-03-23 14:29:05 +05:30 committed by GitHub
parent 2ad5ba3584
commit 893c22b96b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 176 additions and 0 deletions

View file

@ -106,6 +106,152 @@ func Test_Add(t *testing.T) {
}
}
func Test_Sum(t *testing.T) {
testCases := []struct {
name string
test string
expectedResult interface{}
err bool
retFloat bool
}{
// Scalar
{
name: "sum([]) -> error",
test: "sum([])",
err: true,
},
{
name: "sum(Scalar[]) -> Scalar",
test: "sum([`12`])",
expectedResult: 12.0,
retFloat: true,
},
{
name: "sum(Scalar[]) -> Scalar",
test: "sum([`12`, `13`, `1`, `4`])",
expectedResult: 30.0,
retFloat: true,
},
{
name: "sum(Scalar[]) -> Scalar",
test: "sum([`12`, `13`])",
expectedResult: 25.0,
retFloat: true,
},
{
name: "sum(Scalar[Scalar, Duration, ..]) -> error",
test: "sum(['12', '13s'])",
err: true,
},
{
name: "sum(Scalar[Scalar, Quantity, ..]) -> error",
test: "sum([`12`, '13Ki'])",
err: true,
},
{
name: "sum(Scalar[Scalar, Quatity, ..]) -> error",
test: "sum([`12`, '13'])",
err: true,
},
// Quantity
{
name: "sum([]) -> error",
test: "sum([])",
err: true,
},
{
name: "sum(Quantity[]) -> Quantity",
test: "sum(['12Ki'])",
expectedResult: `12Ki`,
},
{
name: "sum(Quantity[]) -> Quantity",
test: "sum(['12Ki', '13Ki', '1Ki', '4Ki'])",
expectedResult: `30Ki`,
},
{
name: "sum(Quantity[]) -> Quantity",
test: "sum(['12Ki', '13Ki'])",
expectedResult: `25Ki`,
},
{
name: "sum(Quantity[]) -> Quantity",
test: "sum(['12Ki', '13'])",
expectedResult: `12301`,
},
{
name: "sum(Quantity[Quantity, Duration, ..]) -> error",
test: "sum(['12Ki', '13s'])",
err: true,
},
{
name: "sum(Quantity[Quantity, Scalar, ..]) -> error",
test: "sum(['12Ki', `13`])",
err: true,
},
// Duration
{
name: "sum([]) -> error",
test: "sum([])",
err: true,
},
{
name: "sum(Duration[]) -> Duration",
test: "sum(['12s'])",
expectedResult: `12s`,
},
{
name: "sum(Duration[]) -> Duration",
test: "sum(['12s', '13s', '1s', '4s'])",
expectedResult: `30s`,
},
{
name: "sum(Duration[]) -> Duration",
test: "sum(['12s', '13s'])",
expectedResult: `25s`,
},
{
name: "sum(Duration[Duration, Scalar, ..]) -> error",
test: "sum(['12s', `13`])",
err: true,
},
{
name: "sum(Duration[Duration, Quantity, ..]) -> error",
test: "sum(['12s', '13Ki'])",
err: true,
},
{
name: "sum(Duration[Duration, Quantity, ..]) -> error",
test: "sum(['12s', '13'])",
err: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
jp, err := New(tc.test)
assert.NilError(t, err)
result, err := jp.Search("")
if !tc.err {
assert.NilError(t, err)
} else {
assert.Assert(t, err != nil)
return
}
if tc.retFloat {
equal, ok := result.(float64)
assert.Assert(t, ok)
assert.Equal(t, equal, tc.expectedResult.(float64))
} else {
equal, ok := result.(string)
assert.Assert(t, ok)
assert.Equal(t, equal, tc.expectedResult.(string))
}
})
}
}
func Test_Subtract(t *testing.T) {
testCases := []struct {
name string

View file

@ -51,6 +51,7 @@ var (
labelMatch = "label_match"
toBoolean = "to_boolean"
add = "add"
sum = "sum"
subtract = "subtract"
multiply = "multiply"
divide = "divide"
@ -248,6 +249,16 @@ func GetFunctions() []FunctionEntry {
},
ReturnType: []jpType{jpAny},
Note: "does arithmetic addition of two specified values of numbers, quantities, and durations",
}, {
FunctionEntry: gojmespath.FunctionEntry{
Name: sum,
Arguments: []argSpec{
{Types: []jpType{jpArray}},
},
Handler: jpSum,
},
ReturnType: []jpType{jpAny},
Note: "does arithmetic addition of specified array of values of numbers, quantities, and durations",
}, {
FunctionEntry: gojmespath.FunctionEntry{
Name: subtract,
@ -771,6 +782,25 @@ func jpAdd(arguments []interface{}) (interface{}, error) {
return op1.Add(op2)
}
func jpSum(arguments []interface{}) (interface{}, error) {
items, ok := arguments[0].([]interface{})
if !ok {
return nil, formatError(typeMismatchError, sum)
}
if len(items) == 0 {
return nil, formatError(genericError, sum, "at least one element in the array is required")
}
var err error
sum := items[0]
for _, item := range items[1:] {
sum, err = jpAdd([]interface{}{sum, item})
if err != nil {
return nil, err
}
}
return sum, nil
}
func jpSubtract(arguments []interface{}) (interface{}, error) {
op1, op2, err := ParseArithemticOperands(arguments, subtract)
if err != nil {