Update env version, Add cost for previous func, add tests, etc.

This commit is contained in:
Cici Huang 2023-12-05 23:26:13 +00:00 committed by cici37
parent 5cf72fbfae
commit 3fb6790164
4 changed files with 72 additions and 1 deletions

View File

@ -1130,6 +1130,26 @@ func TestCelCostStability(t *testing.T) {
"optional.ofNonZeroValue(1).hasValue()": 2,
},
},
{name: "quantity",
obj: objs("20", "200M"),
schema: schemas(stringType, stringType),
expectCost: map[string]int64{
`isQuantity(self.val1)`: 3,
`isQuantity(self.val2)`: 3,
`isQuantity("200M")`: 1,
`isQuantity("20Mi")`: 1,
`quantity("200M") == quantity("0.2G") && quantity("0.2G") == quantity("200M")`: 6,
`quantity("2M") == quantity("0.002G") && quantity("2000k") == quantity("2M") && quantity("0.002G") == quantity("2000k")`: 9,
`quantity(self.val1).isLessThan(quantity(self.val2))`: 7,
`quantity("50M").isLessThan(quantity("100M"))`: 3,
`quantity("50Mi").isGreaterThan(quantity("50M"))`: 3,
`quantity("200M").compareTo(quantity("0.2G")) == 0`: 4,
`quantity("50k").add(quantity("20")) == quantity("50.02k")`: 5,
`quantity("50k").sub(20) == quantity("49980")`: 4,
`quantity("50").isInteger()`: 2,
`quantity(self.val1).isInteger()`: 4,
},
},
}
for _, tt := range cases {
@ -1939,6 +1959,25 @@ func TestCelEstimatedCostStability(t *testing.T) {
"optional.ofNonZeroValue(1).hasValue()": 2,
},
},
{name: "quantity",
schema: schemas(stringType, stringType),
expectCost: map[string]uint64{
`isQuantity(self.val1)`: 314575,
`isQuantity(self.val2)`: 314575,
`isQuantity("200M")`: 1,
`isQuantity("20Mi")`: 1,
`quantity("200M") == quantity("0.2G") && quantity("0.2G") == quantity("200M")`: uint64(3689348814741910532),
`quantity("2M") == quantity("0.002G") && quantity("2000k") == quantity("2M") && quantity("0.002G") == quantity("2000k")`: uint64(5534023222112865798),
`quantity(self.val1).isLessThan(quantity(self.val2))`: 629151,
`quantity("50M").isLessThan(quantity("100M"))`: 3,
`quantity("50Mi").isGreaterThan(quantity("50M"))`: 3,
`quantity("200M").compareTo(quantity("0.2G")) == 0`: 4,
`quantity("50k").add(quantity("20")) == quantity("50.02k")`: uint64(1844674407370955268),
`quantity("50k").sub(20) == quantity("49980")`: uint64(1844674407370955267),
`quantity("50").isInteger()`: 2,
`quantity(self.val1).isInteger()`: 314576,
},
},
}
for _, tt := range cases {

View File

@ -1952,6 +1952,23 @@ func TestValidationExpressions(t *testing.T) {
"self.absentObj.?absentStr == optional.none()": "no such key: absentObj", // missing ?. operator on first deref is an error
},
},
{name: "quantity",
obj: objs("20", "200M"),
schema: schemas(stringType, stringType),
valid: []string{
"isQuantity(self.val1)",
"isQuantity(self.val2)",
`isQuantity("20Mi")`,
`quantity(self.val2) == quantity("0.2G") && quantity("0.2G") == quantity("200M")`,
`quantity("2M") == quantity("0.002G") && quantity("2000k") == quantity("2M") && quantity("0.002G") == quantity("2000k")`,
`quantity(self.val1).isLessThan(quantity("100M"))`,
`quantity(self.val2).isGreaterThan(quantity("50M"))`,
`quantity(self.val2).compareTo(quantity("0.2G")) == 0`,
`quantity("50k").add(quantity(self.val1)) == quantity("50.02k")`,
`quantity("50k").sub(quantity(self.val1)) == quantity("49980")`,
`quantity(self.val1).isInteger()`,
},
},
}
for i := range tests {

View File

@ -43,7 +43,7 @@ import (
// desirable because it means that CEL expressions are portable across a wider range
// of Kubernetes versions.
func DefaultCompatibilityVersion() *version.Version {
return version.MajorMinor(1, 28)
return version.MajorMinor(1, 29)
}
var baseOpts = []VersionedOptions{

View File

@ -147,6 +147,14 @@ func (l *CostEstimator) CallCost(function, overloadId string, args []ref.Val, re
return &cost
}
case "quantity", "isQuantity":
if len(args) >= 1 {
cost := uint64(math.Ceil(float64(actualSize(args[0])) * common.StringTraversalCostFactor))
return &cost
}
case "sign", "asInteger", "isInteger", "asApproximateFloat", "isGreaterThan", "isLessThan", "compareTo", "add", "sub":
cost := uint64(1)
return &cost
}
return nil
}
@ -360,6 +368,13 @@ func (l *CostEstimator) EstimateCallCost(function, overloadId string, target *ch
return &checker.CallEstimate{CostEstimate: ipCompCost}
}
case "quantity", "isQuantity":
if target != nil {
sz := l.sizeEstimate(args[0])
return &checker.CallEstimate{CostEstimate: sz.MultiplyByCostFactor(common.StringTraversalCostFactor)}
}
case "sign", "asInteger", "isInteger", "asApproximateFloat", "isGreaterThan", "isLessThan", "compareTo", "add", "sub":
return &checker.CallEstimate{CostEstimate: checker.CostEstimate{Min: 1, Max: 1}}
}
return nil
}