mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-31 15:25:57 +00:00
Add set ext library into Kubernetes and pick up the new option cel provides
This commit is contained in:
parent
70c1f2143f
commit
8d804078f9
@ -230,8 +230,8 @@ func TestCelCostStability(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{name: "listSets",
|
||||
obj: objs([]interface{}{"a", "b", "c"}, []interface{}{"a", "c", "b"}),
|
||||
schema: schemas(listSetType(&stringType), listSetType(&stringType)),
|
||||
obj: objs([]interface{}{"a", "b", "c"}, []interface{}{"a", "c", "b"}, buildLargeArray(1000)),
|
||||
schema: schemas(listSetType(&stringType), listSetType(&stringType), listSetType(&integerType)),
|
||||
expectCost: map[string]int64{
|
||||
// equal even though order is different
|
||||
"self.val1 == ['c', 'b', 'a']": 3,
|
||||
@ -241,6 +241,12 @@ func TestCelCostStability(t *testing.T) {
|
||||
"!('x' in self.val1)": 6,
|
||||
"self.val1 + self.val2 == ['a', 'b', 'c']": 6,
|
||||
"self.val1 + ['c', 'd'] == ['a', 'b', 'c', 'd']": 4,
|
||||
"sets.contains(self.val1, ['a'])": 6,
|
||||
"sets.equivalent(self.val1, ['a', 'b', 'c'])": 21,
|
||||
"sets.intersects(self.val1, ['a'])": 6,
|
||||
"sets.contains(self.val3, [1])": 1003,
|
||||
"!sets.equivalent(self.val3, [1, 2, 3])": 6004,
|
||||
"sets.intersects(self.val3, [1])": 1003,
|
||||
},
|
||||
},
|
||||
{name: "listMaps",
|
||||
@ -1157,6 +1163,14 @@ func TestCelCostStability(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func buildLargeArray(size int) []interface{} {
|
||||
lArray := make([]interface{}, size)
|
||||
for i := 0; i < len(lArray); i++ {
|
||||
lArray[i] = i
|
||||
}
|
||||
return lArray
|
||||
}
|
||||
|
||||
func TestCelEstimatedCostStability(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
|
@ -22,7 +22,9 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/google/cel-go/checker"
|
||||
"github.com/google/cel-go/ext"
|
||||
"github.com/google/cel-go/interpreter"
|
||||
"golang.org/x/sync/singleflight"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
@ -106,6 +108,21 @@ var baseOpts = []VersionedOptions{
|
||||
ext.Strings(ext.StringsVersion(2)),
|
||||
},
|
||||
},
|
||||
// Set library
|
||||
{
|
||||
IntroducedVersion: version.MajorMinor(1, 29),
|
||||
EnvOptions: []cel.EnvOption{
|
||||
ext.Sets(),
|
||||
// cel-go v0.17.7 introduced CostEstimatorOptions.
|
||||
// Previous the presence has a cost of 0 but cel fixed it to 1. We still set to 0 here to avoid breaking changes.
|
||||
cel.CostEstimatorOptions(checker.PresenceTestHasCost(false)),
|
||||
},
|
||||
ProgramOptions: []cel.ProgramOption{
|
||||
// cel-go v0.17.7 introduced CostTrackerOptions.
|
||||
// Previous the presence has a cost of 0 but cel fixed it to 1. We still set to 0 here to avoid breaking changes.
|
||||
cel.CostTrackerOptions(interpreter.PresenceTestHasCost(false)),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// MustBaseEnvSet returns the common CEL base environments for Kubernetes for Version, or panics
|
||||
|
@ -527,6 +527,236 @@ func TestQuantityCost(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetsCost(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
expr string
|
||||
expectEstimatedCost checker.CostEstimate
|
||||
expectRuntimeCost uint64
|
||||
}{
|
||||
{
|
||||
name: "sets",
|
||||
expr: `sets.contains([], [])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 21, Max: 21},
|
||||
expectRuntimeCost: 21,
|
||||
},
|
||||
{
|
||||
expr: `sets.contains([1], [])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 21, Max: 21},
|
||||
expectRuntimeCost: 21,
|
||||
},
|
||||
{
|
||||
expr: `sets.contains([1], [1])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 22, Max: 22},
|
||||
expectRuntimeCost: 22,
|
||||
},
|
||||
{
|
||||
expr: `sets.contains([1], [1, 1])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 23, Max: 23},
|
||||
expectRuntimeCost: 23,
|
||||
},
|
||||
{
|
||||
expr: `sets.contains([1, 1], [1])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 23, Max: 23},
|
||||
expectRuntimeCost: 23,
|
||||
},
|
||||
{
|
||||
expr: `sets.contains([2, 1], [1])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 23, Max: 23},
|
||||
expectRuntimeCost: 23,
|
||||
},
|
||||
{
|
||||
expr: `sets.contains([1, 2, 3, 4], [2, 3])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 29, Max: 29},
|
||||
expectRuntimeCost: 29,
|
||||
},
|
||||
{
|
||||
expr: `sets.contains([1], [1.0, 1])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 23, Max: 23},
|
||||
expectRuntimeCost: 23,
|
||||
},
|
||||
{
|
||||
expr: `sets.contains([1, 2], [2u, 2.0])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 25, Max: 25},
|
||||
expectRuntimeCost: 25,
|
||||
},
|
||||
{
|
||||
expr: `sets.contains([1, 2u], [2, 2.0])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 25, Max: 25},
|
||||
expectRuntimeCost: 25,
|
||||
},
|
||||
{
|
||||
expr: `sets.contains([1, 2.0, 3u], [1.0, 2u, 3])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 30, Max: 30},
|
||||
expectRuntimeCost: 30,
|
||||
},
|
||||
{
|
||||
expr: `sets.contains([[1], [2, 3]], [[2, 3.0]])`,
|
||||
// 10 for each list creation, top-level list sizes are 2, 1
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 53, Max: 53},
|
||||
expectRuntimeCost: 53,
|
||||
},
|
||||
{
|
||||
expr: `!sets.contains([1], [2])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 23, Max: 23},
|
||||
expectRuntimeCost: 23,
|
||||
},
|
||||
{
|
||||
expr: `!sets.contains([1], [1, 2])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 24, Max: 24},
|
||||
expectRuntimeCost: 24,
|
||||
},
|
||||
{
|
||||
expr: `!sets.contains([1], ["1", 1])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 24, Max: 24},
|
||||
expectRuntimeCost: 24,
|
||||
},
|
||||
{
|
||||
expr: `!sets.contains([1], [1.1, 1u])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 24, Max: 24},
|
||||
expectRuntimeCost: 24,
|
||||
},
|
||||
|
||||
// set equivalence (note the cost factor is higher as it's basically two contains checks)
|
||||
{
|
||||
expr: `sets.equivalent([], [])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 21, Max: 21},
|
||||
expectRuntimeCost: 21,
|
||||
},
|
||||
{
|
||||
expr: `sets.equivalent([1], [1])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 23, Max: 23},
|
||||
expectRuntimeCost: 23,
|
||||
},
|
||||
{
|
||||
expr: `sets.equivalent([1], [1, 1])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 25, Max: 25},
|
||||
expectRuntimeCost: 25,
|
||||
},
|
||||
{
|
||||
expr: `sets.equivalent([1, 1], [1])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 25, Max: 25},
|
||||
expectRuntimeCost: 25,
|
||||
},
|
||||
{
|
||||
expr: `sets.equivalent([1], [1u, 1.0])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 25, Max: 25},
|
||||
expectRuntimeCost: 25,
|
||||
},
|
||||
{
|
||||
expr: `sets.equivalent([1], [1u, 1.0])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 25, Max: 25},
|
||||
expectRuntimeCost: 25,
|
||||
},
|
||||
{
|
||||
expr: `sets.equivalent([1, 2, 3], [3u, 2.0, 1])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 39, Max: 39},
|
||||
expectRuntimeCost: 39,
|
||||
},
|
||||
{
|
||||
expr: `sets.equivalent([[1.0], [2, 3]], [[1], [2, 3.0]])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 69, Max: 69},
|
||||
expectRuntimeCost: 69,
|
||||
},
|
||||
{
|
||||
expr: `!sets.equivalent([2, 1], [1])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 26, Max: 26},
|
||||
expectRuntimeCost: 26,
|
||||
},
|
||||
{
|
||||
expr: `!sets.equivalent([1], [1, 2])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 26, Max: 26},
|
||||
expectRuntimeCost: 26,
|
||||
},
|
||||
{
|
||||
expr: `!sets.equivalent([1, 2], [2u, 2, 2.0])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 34, Max: 34},
|
||||
expectRuntimeCost: 34,
|
||||
},
|
||||
{
|
||||
expr: `!sets.equivalent([1, 2], [1u, 2, 2.3])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 34, Max: 34},
|
||||
expectRuntimeCost: 34,
|
||||
},
|
||||
{
|
||||
expr: `sets.intersects([1], [1])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 22, Max: 22},
|
||||
expectRuntimeCost: 22,
|
||||
},
|
||||
{
|
||||
expr: `sets.intersects([1], [1, 1])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 23, Max: 23},
|
||||
expectRuntimeCost: 23,
|
||||
},
|
||||
{
|
||||
expr: `sets.intersects([1, 1], [1])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 23, Max: 23},
|
||||
expectRuntimeCost: 23,
|
||||
},
|
||||
{
|
||||
expr: `sets.intersects([2, 1], [1])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 23, Max: 23},
|
||||
expectRuntimeCost: 23,
|
||||
},
|
||||
{
|
||||
expr: `sets.intersects([1], [1, 2])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 23, Max: 23},
|
||||
expectRuntimeCost: 23,
|
||||
},
|
||||
{
|
||||
expr: `sets.intersects([1], [1.0, 2])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 23, Max: 23},
|
||||
expectRuntimeCost: 23,
|
||||
},
|
||||
{
|
||||
expr: `sets.intersects([1, 2], [2u, 2, 2.0])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 27, Max: 27},
|
||||
expectRuntimeCost: 27,
|
||||
},
|
||||
{
|
||||
expr: `sets.intersects([1, 2], [1u, 2, 2.3])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 27, Max: 27},
|
||||
expectRuntimeCost: 27,
|
||||
},
|
||||
{
|
||||
expr: `sets.intersects([[1], [2, 3]], [[1, 2], [2, 3.0]])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 65, Max: 65},
|
||||
expectRuntimeCost: 65,
|
||||
},
|
||||
{
|
||||
expr: `!sets.intersects([], [])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 22, Max: 22},
|
||||
expectRuntimeCost: 22,
|
||||
},
|
||||
{
|
||||
expr: `!sets.intersects([1], [])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 22, Max: 22},
|
||||
expectRuntimeCost: 22,
|
||||
},
|
||||
{
|
||||
expr: `!sets.intersects([1], [2])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 23, Max: 23},
|
||||
expectRuntimeCost: 23,
|
||||
},
|
||||
{
|
||||
expr: `!sets.intersects([1], ["1", 2])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 24, Max: 24},
|
||||
expectRuntimeCost: 24,
|
||||
},
|
||||
{
|
||||
expr: `!sets.intersects([1], [1.1, 2u])`,
|
||||
expectEstimatedCost: checker.CostEstimate{Min: 24, Max: 24},
|
||||
expectRuntimeCost: 24,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
testCost(t, tc.expr, tc.expectEstimatedCost, tc.expectRuntimeCost)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testCost(t *testing.T, expr string, expectEsimatedCost checker.CostEstimate, expectRuntimeCost uint64) {
|
||||
est := &CostEstimator{SizeEstimator: &testCostEstimator{}}
|
||||
env, err := cel.NewEnv(
|
||||
@ -536,6 +766,10 @@ func testCost(t *testing.T, expr string, expectEsimatedCost checker.CostEstimate
|
||||
Lists(),
|
||||
Authz(),
|
||||
Quantity(),
|
||||
ext.Sets(),
|
||||
// cel-go v0.17.7 introduced CostEstimatorOptions.
|
||||
// Previous the presence has a cost of 0 but cel fixed it to 1. We still set to 0 here to avoid breaking changes.
|
||||
cel.CostEstimatorOptions(checker.PresenceTestHasCost(false)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
|
Loading…
Reference in New Issue
Block a user