mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-30 19:35:06 +00:00
fix: add tests for jp arithmetic funcs (#6240)
* fix: error management in jp functions Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fix: add tests for jp arithmetic funcs Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> --------- Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
dd35ae201b
commit
00387f1015
4 changed files with 731 additions and 636 deletions
|
@ -1,7 +1,6 @@
|
|||
package jmespath
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
|
@ -31,42 +30,24 @@ type Scalar struct {
|
|||
float64
|
||||
}
|
||||
|
||||
var errTypeMismatch = errors.New("types mismatch")
|
||||
|
||||
func ParseArithemticOperands(arguments []interface{}, operator string) (Operand, Operand, error) {
|
||||
op := [2]Operand{nil, nil}
|
||||
t := [2]int{0, 0}
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
tmp, err := validateArg(divide, arguments, i, reflect.Float64)
|
||||
if err == nil {
|
||||
if tmp, err := validateArg(divide, arguments, i, reflect.Float64); err == nil {
|
||||
var sc Scalar
|
||||
sc.float64 = tmp.Float()
|
||||
op[i] = sc
|
||||
}
|
||||
|
||||
tmp, err = validateArg(divide, arguments, i, reflect.String)
|
||||
if err == nil {
|
||||
var q Quantity
|
||||
q.Quantity, err = resource.ParseQuantity(tmp.String())
|
||||
if err == nil {
|
||||
op[i] = q
|
||||
t[i] = 1
|
||||
} else {
|
||||
var d Duration
|
||||
d.Duration, err = time.ParseDuration(tmp.String())
|
||||
if err == nil {
|
||||
op[i] = d
|
||||
t[i] = 2
|
||||
}
|
||||
} else if tmp, err = validateArg(divide, arguments, i, reflect.String); err == nil {
|
||||
if q, err := resource.ParseQuantity(tmp.String()); err == nil {
|
||||
op[i] = Quantity{Quantity: q}
|
||||
} else if d, err := time.ParseDuration(tmp.String()); err == nil {
|
||||
op[i] = Duration{Duration: d}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if op[0] == nil || op[1] == nil || t[0]|t[1] == 3 {
|
||||
if op[0] == nil || op[1] == nil {
|
||||
return nil, nil, formatError(genericError, operator, "invalid operands")
|
||||
}
|
||||
|
||||
return op[0], op[1], nil
|
||||
}
|
||||
|
||||
|
@ -83,7 +64,7 @@ func (op1 Quantity) Add(op2 interface{}) (interface{}, error) {
|
|||
op1.Quantity.Add(v.Quantity)
|
||||
return op1.String(), nil
|
||||
default:
|
||||
return nil, errTypeMismatch
|
||||
return nil, formatError(typeMismatchError, add)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,7 +73,7 @@ func (op1 Duration) Add(op2 interface{}) (interface{}, error) {
|
|||
case Duration:
|
||||
return (op1.Duration + v.Duration).String(), nil
|
||||
default:
|
||||
return nil, errTypeMismatch
|
||||
return nil, formatError(typeMismatchError, add)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,7 +82,7 @@ func (op1 Scalar) Add(op2 interface{}) (interface{}, error) {
|
|||
case Scalar:
|
||||
return op1.float64 + v.float64, nil
|
||||
default:
|
||||
return nil, errTypeMismatch
|
||||
return nil, formatError(typeMismatchError, add)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,7 +92,7 @@ func (op1 Quantity) Subtract(op2 interface{}) (interface{}, error) {
|
|||
op1.Quantity.Sub(v.Quantity)
|
||||
return op1.String(), nil
|
||||
default:
|
||||
return nil, errTypeMismatch
|
||||
return nil, formatError(typeMismatchError, subtract)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,7 +101,7 @@ func (op1 Duration) Subtract(op2 interface{}) (interface{}, error) {
|
|||
case Duration:
|
||||
return (op1.Duration - v.Duration).String(), nil
|
||||
default:
|
||||
return nil, errTypeMismatch
|
||||
return nil, formatError(typeMismatchError, subtract)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,7 +110,7 @@ func (op1 Scalar) Subtract(op2 interface{}) (interface{}, error) {
|
|||
case Scalar:
|
||||
return op1.float64 - v.float64, nil
|
||||
default:
|
||||
return nil, errTypeMismatch
|
||||
return nil, formatError(typeMismatchError, subtract)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,7 +135,7 @@ func (op1 Quantity) Multiply(op2 interface{}) (interface{}, error) {
|
|||
prod.Mul(op1.Quantity.AsDec(), q.AsDec())
|
||||
return resource.NewDecimalQuantity(prod, op1.Quantity.Format).String(), nil
|
||||
default:
|
||||
return nil, errTypeMismatch
|
||||
return nil, formatError(typeMismatchError, multiply)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,7 +145,7 @@ func (op1 Duration) Multiply(op2 interface{}) (interface{}, error) {
|
|||
seconds := op1.Seconds() * v.float64
|
||||
return time.Duration(seconds * float64(time.Second)).String(), nil
|
||||
default:
|
||||
return nil, errTypeMismatch
|
||||
return nil, formatError(typeMismatchError, multiply)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,9 +157,9 @@ func (op1 Scalar) Multiply(op2 interface{}) (interface{}, error) {
|
|||
return v.Multiply(op1)
|
||||
case Duration:
|
||||
return v.Multiply(op1)
|
||||
default:
|
||||
return nil, formatError(typeMismatchError, multiply)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Quantity / Duration -> error
|
||||
|
@ -215,7 +196,7 @@ func (op1 Quantity) Divide(op2 interface{}) (interface{}, error) {
|
|||
quo.QuoRound(op1.AsDec(), q.AsDec(), scale, inf.RoundDown)
|
||||
return resource.NewDecimalQuantity(quo, op1.Quantity.Format).String(), nil
|
||||
default:
|
||||
return nil, errTypeMismatch
|
||||
return nil, formatError(typeMismatchError, divide)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,7 +214,7 @@ func (op1 Duration) Divide(op2 interface{}) (interface{}, error) {
|
|||
seconds := op1.Seconds() / v.float64
|
||||
return time.Duration(seconds * float64(time.Second)).String(), nil
|
||||
default:
|
||||
return nil, errTypeMismatch
|
||||
return nil, formatError(typeMismatchError, divide)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,7 +226,7 @@ func (op1 Scalar) Divide(op2 interface{}) (interface{}, error) {
|
|||
}
|
||||
return op1.float64 / v.float64, nil
|
||||
default:
|
||||
return nil, errTypeMismatch
|
||||
return nil, formatError(typeMismatchError, divide)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,7 +257,7 @@ func (op1 Quantity) Modulo(op2 interface{}) (interface{}, error) {
|
|||
}
|
||||
return resource.NewQuantity(i1%i2, op1.Quantity.Format).String(), nil
|
||||
default:
|
||||
return nil, errTypeMismatch
|
||||
return nil, formatError(typeMismatchError, modulo)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,7 +269,7 @@ func (op1 Duration) Modulo(op2 interface{}) (interface{}, error) {
|
|||
}
|
||||
return (op1.Duration % v.Duration).String(), nil
|
||||
default:
|
||||
return nil, errTypeMismatch
|
||||
return nil, formatError(typeMismatchError, modulo)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -308,6 +289,6 @@ func (op1 Scalar) Modulo(op2 interface{}) (interface{}, error) {
|
|||
}
|
||||
return float64(val1 % val2), nil
|
||||
default:
|
||||
return nil, errTypeMismatch
|
||||
return nil, formatError(typeMismatchError, modulo)
|
||||
}
|
||||
}
|
||||
|
|
707
pkg/engine/jmespath/arithmetic_test.go
Normal file
707
pkg/engine/jmespath/arithmetic_test.go
Normal file
|
@ -0,0 +1,707 @@
|
|||
package jmespath
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
func Test_Add(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
test string
|
||||
expectedResult interface{}
|
||||
err bool
|
||||
retFloat bool
|
||||
}{
|
||||
// Scalar
|
||||
{
|
||||
name: "Scalar + Scalar -> Scalar",
|
||||
test: "add(`12`, `13`)",
|
||||
expectedResult: 25.0,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar + Duration -> error",
|
||||
test: "add('12', '13s')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar + Quantity -> error",
|
||||
test: "add(`12`, '13Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar + Quantity -> error",
|
||||
test: "add(`12`, '13')",
|
||||
err: true,
|
||||
},
|
||||
// Quantity
|
||||
{
|
||||
name: "Quantity + Quantity -> Quantity",
|
||||
test: "add('12Ki', '13Ki')",
|
||||
expectedResult: `25Ki`,
|
||||
},
|
||||
{
|
||||
name: "Quantity + Quantity -> Quantity",
|
||||
test: "add('12Ki', '13')",
|
||||
expectedResult: `12301`,
|
||||
},
|
||||
{
|
||||
name: "Quantity + Duration -> error",
|
||||
test: "add('12Ki', '13s')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity + Scalar -> error",
|
||||
test: "add('12Ki', `13`)",
|
||||
err: true,
|
||||
},
|
||||
// Duration
|
||||
{
|
||||
name: "Duration + Duration -> Duration",
|
||||
test: "add('12s', '13s')",
|
||||
expectedResult: `25s`,
|
||||
},
|
||||
{
|
||||
name: "Duration + Scalar -> error",
|
||||
test: "add('12s', `13`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration + Quantity -> error",
|
||||
test: "add('12s', '13Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration + Quantity -> error",
|
||||
test: "add('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
|
||||
test string
|
||||
expectedResult interface{}
|
||||
err bool
|
||||
retFloat bool
|
||||
}{
|
||||
// Scalar
|
||||
{
|
||||
name: "Scalar - Scalar -> Scalar",
|
||||
test: "subtract(`12`, `13`)",
|
||||
expectedResult: -1.0,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar - Duration -> error",
|
||||
test: "subtract('12', '13s')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar - Quantity -> error",
|
||||
test: "subtract(`12`, '13Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar - Quantity -> error",
|
||||
test: "subtract(`12`, '13')",
|
||||
err: true,
|
||||
},
|
||||
// Quantity
|
||||
{
|
||||
name: "Quantity - Quantity -> Quantity",
|
||||
test: "subtract('12Ki', '13Ki')",
|
||||
expectedResult: `-1Ki`,
|
||||
},
|
||||
{
|
||||
name: "Quantity - Quantity -> Quantity",
|
||||
test: "subtract('12Ki', '13')",
|
||||
expectedResult: `12275`,
|
||||
},
|
||||
{
|
||||
name: "Quantity - Duration -> error",
|
||||
test: "subtract('12Ki', '13s')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity - Scalar -> error",
|
||||
test: "subtract('12Ki', `13`)",
|
||||
err: true,
|
||||
},
|
||||
// Duration
|
||||
{
|
||||
name: "Duration - Duration -> Duration",
|
||||
test: "subtract('12s', '13s')",
|
||||
expectedResult: `-1s`,
|
||||
},
|
||||
{
|
||||
name: "Duration - Scalar -> error",
|
||||
test: "subtract('12s', `13`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration - Quantity -> error",
|
||||
test: "subtract('12s', '13Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration - Quantity -> error",
|
||||
test: "subtract('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_Multiply(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
test string
|
||||
expectedResult interface{}
|
||||
err bool
|
||||
retFloat bool
|
||||
}{
|
||||
// Quantity
|
||||
{
|
||||
name: "Quantity * Scalar -> Quantity",
|
||||
test: "multiply('12Ki', `2`)",
|
||||
expectedResult: `24Ki`,
|
||||
},
|
||||
{
|
||||
name: "Quantity * Quantity -> error",
|
||||
test: "multiply('12Ki', '12Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity * Quantity -> error",
|
||||
test: "multiply('12Ki', '12')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity * Duration -> error",
|
||||
test: "multiply('12Ki', '12s')",
|
||||
err: true,
|
||||
},
|
||||
// Duration
|
||||
{
|
||||
name: "Duration * Scalar -> Duration",
|
||||
test: "multiply('12s', `2`)",
|
||||
expectedResult: `24s`,
|
||||
},
|
||||
{
|
||||
name: "Duration * Quantity -> error",
|
||||
test: "multiply('12s', '12Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration * Quantity -> error",
|
||||
test: "multiply('12s', '12')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration * Duration -> error",
|
||||
test: "multiply('12s', '12s')",
|
||||
err: true,
|
||||
},
|
||||
// Scalar
|
||||
{
|
||||
name: "Scalar * Scalar -> Scalar",
|
||||
test: "multiply(`2.5`, `2.5`)",
|
||||
expectedResult: 2.5 * 2.5,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar * Quantity -> Quantity",
|
||||
test: "multiply(`2.5`, '12Ki')",
|
||||
expectedResult: "30Ki",
|
||||
},
|
||||
{
|
||||
name: "Scalar * Quantity -> Quantity",
|
||||
test: "multiply(`2.5`, '12')",
|
||||
expectedResult: "30",
|
||||
},
|
||||
{
|
||||
name: "Scalar * Duration -> Duration",
|
||||
test: "multiply(`2.5`, '40s')",
|
||||
expectedResult: "1m40s",
|
||||
},
|
||||
}
|
||||
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_Divide(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
test string
|
||||
expectedResult interface{}
|
||||
err bool
|
||||
retFloat bool
|
||||
}{
|
||||
// Quantity
|
||||
{
|
||||
name: "Quantity / Quantity -> Scalar",
|
||||
test: "divide('256M', '256M')",
|
||||
expectedResult: 1.0,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Quantity -> Scalar",
|
||||
test: "divide('512M', '256M')",
|
||||
expectedResult: 2.0,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Quantity -> Scalar",
|
||||
test: "divide('8', '3')",
|
||||
expectedResult: 8.0 / 3.0,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Quantity -> Scalar",
|
||||
test: "divide('128M', '256M')",
|
||||
expectedResult: 0.5,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Scalar -> Quantity",
|
||||
test: "divide('12Ki', `3`)",
|
||||
expectedResult: "4Ki",
|
||||
},
|
||||
{
|
||||
name: "Quantity / Quantity -> Scalar",
|
||||
test: "divide('12Ki', '2Ki')",
|
||||
expectedResult: 6.0,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Quantity -> Scalar",
|
||||
test: "divide('12Ki', '200')",
|
||||
expectedResult: 61.44,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Duration -> error",
|
||||
test: "divide('12Ki', '2s')",
|
||||
err: true,
|
||||
},
|
||||
// Duration
|
||||
{
|
||||
name: "Duration / Scalar -> Duration",
|
||||
test: "divide('12s', `3`)",
|
||||
expectedResult: "4s",
|
||||
},
|
||||
{
|
||||
name: "Duration / Duration -> Scalar",
|
||||
test: "divide('12s', '5s')",
|
||||
expectedResult: 2.4,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Duration / Quantity -> error",
|
||||
test: "divide('12s', '4Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration / Quantity -> error",
|
||||
test: "divide('12s', '4')",
|
||||
err: true,
|
||||
},
|
||||
// Scalar
|
||||
{
|
||||
name: "Scalar / Scalar -> Scalar",
|
||||
test: "divide(`14`, `3`)",
|
||||
expectedResult: 4.666666666666667,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar / Duration -> error",
|
||||
test: "divide(`14`, '5s')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar / Quantity -> error",
|
||||
test: "divide(`14`, '5Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar / Quantity -> error",
|
||||
test: "divide(`14`, '5')",
|
||||
err: true,
|
||||
},
|
||||
// Divide by 0
|
||||
{
|
||||
name: "Scalar / Zero -> error",
|
||||
test: "divide(`14`, `0`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Zero -> error",
|
||||
test: "divide('4Ki', `0`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Zero -> error",
|
||||
test: "divide('4Ki', '0Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Zero -> error",
|
||||
test: "divide('4', `0`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Zero -> error",
|
||||
test: "divide('4', '0')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration / Zero -> error",
|
||||
test: "divide('4s', `0`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration / Zero -> error",
|
||||
test: "divide('4s', '0s')",
|
||||
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_Modulo(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
test string
|
||||
expectedResult interface{}
|
||||
err bool
|
||||
retFloat bool
|
||||
}{
|
||||
// Quantity
|
||||
{
|
||||
name: "Quantity % Duration -> error",
|
||||
test: "modulo('12', '13s')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity % Duration -> error",
|
||||
test: "modulo('12Ki', '13s')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity % Scalar -> error",
|
||||
test: "modulo('12Ki', `13`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity % Quantity -> Quantity",
|
||||
test: "modulo('12Ki', '5Ki')",
|
||||
expectedResult: `2Ki`,
|
||||
},
|
||||
// Duration
|
||||
{
|
||||
name: "Duration % Quantity -> error",
|
||||
test: "modulo('13s', '12')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration % Quantity -> error",
|
||||
test: "modulo('13s', '12Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration % Duration -> Duration",
|
||||
test: "modulo('13s', '2s')",
|
||||
expectedResult: `1s`,
|
||||
},
|
||||
{
|
||||
name: "Duration % Scalar -> error",
|
||||
test: "modulo('13s', `2`)",
|
||||
err: true,
|
||||
},
|
||||
// Scalar
|
||||
{
|
||||
name: "Scalar % Quantity -> error",
|
||||
test: "modulo(`13`, '12')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar % Quantity -> error",
|
||||
test: "modulo(`13`, '12Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar % Duration -> error",
|
||||
test: "modulo(`13`, '5s')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar % Scalar -> Scalar",
|
||||
test: "modulo(`13`, `5`)",
|
||||
expectedResult: 3.0,
|
||||
retFloat: true,
|
||||
},
|
||||
// Modulo by 0
|
||||
{
|
||||
name: "Scalar % Zero -> error",
|
||||
test: "modulo(`14`, `0`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity % Zero -> error",
|
||||
test: "modulo('4Ki', `0`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity % Zero -> error",
|
||||
test: "modulo('4Ki', '0Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity % Zero -> error",
|
||||
test: "modulo('4', `0`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity % Zero -> error",
|
||||
test: "modulo('4', '0')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration % Zero -> error",
|
||||
test: "modulo('4s', `0`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration % Zero -> error",
|
||||
test: "modulo('4s', '0s')",
|
||||
err: true,
|
||||
},
|
||||
// Modulo with non int values
|
||||
{
|
||||
name: "Quantity % Non int -> error",
|
||||
test: "modulo('4', '1.5')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Non int % Quantity -> error",
|
||||
test: "modulo('4.5', '1')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar % Non int -> error",
|
||||
test: "modulo(`14`, `1.5`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Non int % Scalar -> error",
|
||||
test: "modulo(`14.5`, `2`)",
|
||||
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 TestScalar_Multiply(t *testing.T) {
|
||||
type fields struct {
|
||||
float64 float64
|
||||
}
|
||||
type args struct {
|
||||
op2 interface{}
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
want interface{}
|
||||
wantErr bool
|
||||
}{{
|
||||
fields: fields{
|
||||
float64: 123,
|
||||
},
|
||||
args: args{
|
||||
op2: true,
|
||||
},
|
||||
wantErr: true,
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
op1 := Scalar{
|
||||
float64: tt.fields.float64,
|
||||
}
|
||||
got, err := op1.Multiply(tt.args.op2)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Scalar.Multiply() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Scalar.Multiply() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseArithemticOperands(t *testing.T) {
|
||||
type args struct {
|
||||
arguments []interface{}
|
||||
operator string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want Operand
|
||||
want1 Operand
|
||||
wantErr bool
|
||||
}{{
|
||||
args: args{
|
||||
arguments: []interface{}{
|
||||
true,
|
||||
1.0,
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
}, {
|
||||
args: args{
|
||||
arguments: []interface{}{
|
||||
1.0,
|
||||
true,
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, got1, err := ParseArithemticOperands(tt.args.arguments, tt.args.operator)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ParseArithemticOperands() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("ParseArithemticOperands() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
if !reflect.DeepEqual(got1, tt.want1) {
|
||||
t.Errorf("ParseArithemticOperands() got1 = %v, want %v", got1, tt.want1)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ const (
|
|||
argOutOfBoundsError = errorPrefix + "%d argument is out of bounds (%d)"
|
||||
zeroDivisionError = errorPrefix + "Zero divisor passed"
|
||||
nonIntModuloError = errorPrefix + "Non-integer argument(s) passed for modulo"
|
||||
typeMismatchError = errorPrefix + "Types mismatch"
|
||||
)
|
||||
|
||||
func formatError(format string, function string, values ...interface{}) error {
|
||||
|
|
|
@ -538,600 +538,6 @@ func Test_LabelMatch(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func Test_Add(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
test string
|
||||
expectedResult interface{}
|
||||
err bool
|
||||
retFloat bool
|
||||
}{
|
||||
// Scalar
|
||||
{
|
||||
name: "Scalar + Scalar -> Scalar",
|
||||
test: "add(`12`, `13`)",
|
||||
expectedResult: 25.0,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar + Duration -> error",
|
||||
test: "add('12', '13s')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar + Quantity -> error",
|
||||
test: "add(`12`, '13Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar + Quantity -> error",
|
||||
test: "add(`12`, '13')",
|
||||
err: true,
|
||||
},
|
||||
// Quantity
|
||||
{
|
||||
name: "Quantity + Quantity -> Quantity",
|
||||
test: "add('12Ki', '13Ki')",
|
||||
expectedResult: `25Ki`,
|
||||
},
|
||||
{
|
||||
name: "Quantity + Quantity -> Quantity",
|
||||
test: "add('12Ki', '13')",
|
||||
expectedResult: `12301`,
|
||||
},
|
||||
{
|
||||
name: "Quantity + Duration -> error",
|
||||
test: "add('12Ki', '13s')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity + Scalar -> error",
|
||||
test: "add('12Ki', `13`)",
|
||||
err: true,
|
||||
},
|
||||
// Duration
|
||||
{
|
||||
name: "Duration + Duration -> Duration",
|
||||
test: "add('12s', '13s')",
|
||||
expectedResult: `25s`,
|
||||
},
|
||||
{
|
||||
name: "Duration + Scalar -> error",
|
||||
test: "add('12s', '13')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration + Quantity -> error",
|
||||
test: "add('12s', '13Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration + Quantity -> error",
|
||||
test: "add('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
|
||||
test string
|
||||
expectedResult interface{}
|
||||
err bool
|
||||
retFloat bool
|
||||
}{
|
||||
// Scalar
|
||||
{
|
||||
name: "Scalar - Scalar -> Scalar",
|
||||
test: "subtract(`12`, `13`)",
|
||||
expectedResult: -1.0,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar - Duration -> error",
|
||||
test: "subtract('12', '13s')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar - Quantity -> error",
|
||||
test: "subtract(`12`, '13Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar - Quantity -> error",
|
||||
test: "subtract(`12`, '13')",
|
||||
err: true,
|
||||
},
|
||||
// Quantity
|
||||
{
|
||||
name: "Quantity - Quantity -> Quantity",
|
||||
test: "subtract('12Ki', '13Ki')",
|
||||
expectedResult: `-1Ki`,
|
||||
},
|
||||
{
|
||||
name: "Quantity - Quantity -> Quantity",
|
||||
test: "subtract('12Ki', '13')",
|
||||
expectedResult: `12275`,
|
||||
},
|
||||
{
|
||||
name: "Quantity - Duration -> error",
|
||||
test: "subtract('12Ki', '13s')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity - Scalar -> error",
|
||||
test: "subtract('12Ki', `13`)",
|
||||
err: true,
|
||||
},
|
||||
// Duration
|
||||
{
|
||||
name: "Duration - Duration -> Duration",
|
||||
test: "subtract('12s', '13s')",
|
||||
expectedResult: `-1s`,
|
||||
},
|
||||
{
|
||||
name: "Duration - Scalar -> error",
|
||||
test: "subtract('12s', '13')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration - Quantity -> error",
|
||||
test: "subtract('12s', '13Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration - Quantity -> error",
|
||||
test: "subtract('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_Multiply(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
test string
|
||||
expectedResult interface{}
|
||||
err bool
|
||||
retFloat bool
|
||||
}{
|
||||
// Quantity
|
||||
{
|
||||
name: "Quantity * Scalar -> Quantity",
|
||||
test: "multiply('12Ki', `2`)",
|
||||
expectedResult: `24Ki`,
|
||||
},
|
||||
{
|
||||
name: "Quantity * Quantity -> error",
|
||||
test: "multiply('12Ki', '12Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity * Quantity -> error",
|
||||
test: "multiply('12Ki', '12')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity * Duration -> error",
|
||||
test: "multiply('12Ki', '12s')",
|
||||
err: true,
|
||||
},
|
||||
// Duration
|
||||
{
|
||||
name: "Duration * Scalar -> Duration",
|
||||
test: "multiply('12s', `2`)",
|
||||
expectedResult: `24s`,
|
||||
},
|
||||
{
|
||||
name: "Duration * Quantity -> error",
|
||||
test: "multiply('12s', '12Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration * Quantity -> error",
|
||||
test: "multiply('12s', '12')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration * Duration -> error",
|
||||
test: "multiply('12s', '12s')",
|
||||
err: true,
|
||||
},
|
||||
// Scalar
|
||||
{
|
||||
name: "Scalar * Scalar -> Scalar",
|
||||
test: "multiply(`2.5`, `2.5`)",
|
||||
expectedResult: 2.5 * 2.5,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar * Quantity -> Quantity",
|
||||
test: "multiply(`2.5`, '12Ki')",
|
||||
expectedResult: "30Ki",
|
||||
},
|
||||
{
|
||||
name: "Scalar * Quantity -> Quantity",
|
||||
test: "multiply(`2.5`, '12')",
|
||||
expectedResult: "30",
|
||||
},
|
||||
{
|
||||
name: "Scalar * Duration -> Duration",
|
||||
test: "multiply(`2.5`, '40s')",
|
||||
expectedResult: "1m40s",
|
||||
},
|
||||
}
|
||||
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_Divide(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
test string
|
||||
expectedResult interface{}
|
||||
err bool
|
||||
retFloat bool
|
||||
}{
|
||||
// Quantity
|
||||
{
|
||||
name: "Quantity / Quantity -> Scalar",
|
||||
test: "divide('256M', '256M')",
|
||||
expectedResult: 1.0,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Quantity -> Scalar",
|
||||
test: "divide('512M', '256M')",
|
||||
expectedResult: 2.0,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Quantity -> Scalar",
|
||||
test: "divide('8', '3')",
|
||||
expectedResult: 8.0 / 3.0,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Quantity -> Scalar",
|
||||
test: "divide('128M', '256M')",
|
||||
expectedResult: 0.5,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Scalar -> Quantity",
|
||||
test: "divide('12Ki', `3`)",
|
||||
expectedResult: "4Ki",
|
||||
},
|
||||
{
|
||||
name: "Quantity / Quantity -> Scalar",
|
||||
test: "divide('12Ki', '2Ki')",
|
||||
expectedResult: 6.0,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Quantity -> Scalar",
|
||||
test: "divide('12Ki', '200')",
|
||||
expectedResult: 61.44,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Duration -> error",
|
||||
test: "divide('12Ki', '2s')",
|
||||
err: true,
|
||||
},
|
||||
// Duration
|
||||
{
|
||||
name: "Duration / Scalar -> Duration",
|
||||
test: "divide('12s', `3`)",
|
||||
expectedResult: "4s",
|
||||
},
|
||||
{
|
||||
name: "Duration / Duration -> Scalar",
|
||||
test: "divide('12s', '5s')",
|
||||
expectedResult: 2.4,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Duration / Quantity -> error",
|
||||
test: "divide('12s', '4Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration / Quantity -> error",
|
||||
test: "divide('12s', '4')",
|
||||
err: true,
|
||||
},
|
||||
// Scalar
|
||||
{
|
||||
name: "Scalar / Scalar -> Scalar",
|
||||
test: "divide(`14`, `3`)",
|
||||
expectedResult: 4.666666666666667,
|
||||
retFloat: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar / Duration -> error",
|
||||
test: "divide(`14`, '5s')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar / Quantity -> error",
|
||||
test: "divide(`14`, '5Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar / Quantity -> error",
|
||||
test: "divide(`14`, '5')",
|
||||
err: true,
|
||||
},
|
||||
// Divide by 0
|
||||
{
|
||||
name: "Scalar / Zero -> error",
|
||||
test: "divide(`14`, `0`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Zero -> error",
|
||||
test: "divide('4Ki', `0`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Zero -> error",
|
||||
test: "divide('4Ki', '0Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Zero -> error",
|
||||
test: "divide('4', `0`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity / Zero -> error",
|
||||
test: "divide('4', '0')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration / Zero -> error",
|
||||
test: "divide('4s', `0`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration / Zero -> error",
|
||||
test: "divide('4s', '0s')",
|
||||
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_Modulo(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
test string
|
||||
expectedResult interface{}
|
||||
err bool
|
||||
retFloat bool
|
||||
}{
|
||||
// Quantity
|
||||
{
|
||||
name: "Quantity % Duration -> error",
|
||||
test: "modulo('12', '13s')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity % Duration -> error",
|
||||
test: "modulo('12Ki', '13s')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity % Scalar -> error",
|
||||
test: "modulo('12Ki', `13`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity % Quantity -> Quantity",
|
||||
test: "modulo('12Ki', '5Ki')",
|
||||
expectedResult: `2Ki`,
|
||||
},
|
||||
// Duration
|
||||
{
|
||||
name: "Duration % Quantity -> error",
|
||||
test: "modulo('13s', '12')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration % Quantity -> error",
|
||||
test: "modulo('13s', '12Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration % Duration -> Duration",
|
||||
test: "modulo('13s', '2s')",
|
||||
expectedResult: `1s`,
|
||||
},
|
||||
{
|
||||
name: "Duration % Scalar -> error",
|
||||
test: "modulo('13s', `2`)",
|
||||
err: true,
|
||||
},
|
||||
// Scalar
|
||||
{
|
||||
name: "Scalar % Quantity -> error",
|
||||
test: "modulo(`13`, '12')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar % Quantity -> error",
|
||||
test: "modulo(`13`, '12Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar % Duration -> error",
|
||||
test: "modulo(`13`, '5s')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Scalar % Scalar -> Scalar",
|
||||
test: "modulo(`13`, `5`)",
|
||||
expectedResult: 3.0,
|
||||
retFloat: true,
|
||||
},
|
||||
// Modulo by 0
|
||||
{
|
||||
name: "Scalar % Zero -> error",
|
||||
test: "modulo(`14`, `0`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity % Zero -> error",
|
||||
test: "modulo('4Ki', `0`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity % Zero -> error",
|
||||
test: "modulo('4Ki', '0Ki')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity % Zero -> error",
|
||||
test: "modulo('4', `0`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Quantity % Zero -> error",
|
||||
test: "modulo('4', '0')",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration % Zero -> error",
|
||||
test: "modulo('4s', `0`)",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "Duration % Zero -> error",
|
||||
test: "modulo('4s', '0s')",
|
||||
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_Base64Decode(t *testing.T) {
|
||||
jp, err := New("base64_decode('SGVsbG8sIHdvcmxkIQ==')")
|
||||
assert.NilError(t, err)
|
||||
|
|
Loading…
Add table
Reference in a new issue