set maxLength to longest enum.

This commit is contained in:
Jiahui Feng 2023-10-09 11:00:45 -07:00
parent e196d24910
commit 302d350e88
2 changed files with 54 additions and 1 deletions

View File

@ -989,6 +989,35 @@ func genStringWithRule(rule string) func(maxLength *int64) *schema.Structural {
}
}
// genEnumWithRuleAndValues creates a function that accepts an optional maxLength
// with given validation rule and a set of enum values, following the convention of existing tests.
// The test has two checks, first with maxLength unset to check if maxLength can be concluded from enums,
// second with maxLength set to ensure it takes precedence.
func genEnumWithRuleAndValues(rule string, values ...string) func(maxLength *int64) *schema.Structural {
enums := make([]schema.JSON, 0, len(values))
for _, v := range values {
enums = append(enums, schema.JSON{Object: v})
}
return func(maxLength *int64) *schema.Structural {
return &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
ValueValidation: &schema.ValueValidation{
MaxLength: maxLength,
Enum: enums,
},
Extensions: schema.Extensions{
XValidations: apiextensions.ValidationRules{
{
Rule: rule,
},
},
},
}
}
}
func genBytesWithRule(rule string) func(maxLength *int64) *schema.Structural {
return func(maxLength *int64) *schema.Structural {
return &schema.Structural{
@ -1744,6 +1773,13 @@ func TestCostEstimation(t *testing.T) {
setMaxElements: 42,
expectedSetCost: 8,
},
{
name: "enums with maxLength equals to the longest possible value",
schemaGenerator: genEnumWithRuleAndValues("self.contains('A')", "A", "B", "C", "LongValue"),
expectedCalcCost: 2,
setMaxElements: 1000,
expectedSetCost: 401,
},
}
for _, testCase := range cases {
t.Run(testCase.name, func(t *testing.T) {

View File

@ -164,9 +164,13 @@ func SchemaDeclType(s Schema, isResourceRoot bool) *apiservercel.DeclType {
// but we need to reason about length for things like request size, so we use bytes in this code (and an individual
// unicode code point can be up to 4 bytes long)
strWithMaxLength.MaxElements = zeroIfNegative(*s.MaxLength()) * 4
} else {
if len(s.Enum()) > 0 {
strWithMaxLength.MaxElements = estimateMaxStringEnumLength(s)
} else {
strWithMaxLength.MaxElements = estimateMaxStringLengthPerRequest(s)
}
}
return strWithMaxLength
case "boolean":
return apiservercel.BoolType
@ -239,6 +243,19 @@ func estimateMaxStringLengthPerRequest(s Schema) int64 {
}
}
// estimateMaxStringLengthPerRequest estimates the maximum string length (in characters)
// that has a set of enum values.
// The result of the estimation is the length of the longest possible value.
func estimateMaxStringEnumLength(s Schema) int64 {
var maxLength int64
for _, v := range s.Enum() {
if s, ok := v.(string); ok && int64(len(s)) > maxLength {
maxLength = int64(len(s))
}
}
return maxLength
}
// estimateMaxArrayItemsPerRequest estimates the maximum number of array items with
// the provided minimum serialized size that can fit into a single request.
func estimateMaxArrayItemsFromMinSize(minSize int64) int64 {