mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-31 07:20:13 +00:00
benchmark unstructuredToVal
This commit is contained in:
parent
33a2c50bce
commit
62394b8ab8
@ -619,3 +619,47 @@ func TestMapper(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkUnstructuredToVal(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
if val := UnstructuredToVal([]interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"key": "a",
|
||||||
|
"val": 1,
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"key": "b",
|
||||||
|
"val": 2,
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"key": "@b",
|
||||||
|
"val": 2,
|
||||||
|
},
|
||||||
|
}, &mapListSchema); val == nil {
|
||||||
|
b.Fatal(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkUnstructuredToValWithEscape(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
if val := UnstructuredToVal([]interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"key": "a.1",
|
||||||
|
"val": "__i.1",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"key": "b.1",
|
||||||
|
"val": 2,
|
||||||
|
},
|
||||||
|
}, &mapListSchema); val == nil {
|
||||||
|
b.Fatal(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -36,6 +36,57 @@ var celReservedSymbols = sets.NewString(
|
|||||||
// expandMatcher matches the escape sequence, characters that are escaped, and characters that are unsupported
|
// expandMatcher matches the escape sequence, characters that are escaped, and characters that are unsupported
|
||||||
var expandMatcher = regexp.MustCompile(`(__|[-./]|[^a-zA-Z0-9-./_])`)
|
var expandMatcher = regexp.MustCompile(`(__|[-./]|[^a-zA-Z0-9-./_])`)
|
||||||
|
|
||||||
|
// newCharacterFilter returns a boolean array to indicate the allowed characters
|
||||||
|
func newCharacterFilter(characters string) []bool {
|
||||||
|
maxChar := 0
|
||||||
|
for _, c := range characters {
|
||||||
|
if maxChar < int(c) {
|
||||||
|
maxChar = int(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filter := make([]bool, maxChar+1)
|
||||||
|
|
||||||
|
for _, c := range characters {
|
||||||
|
filter[int(c)] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return filter
|
||||||
|
}
|
||||||
|
|
||||||
|
type escapeCheck struct {
|
||||||
|
canSkipRegex bool
|
||||||
|
invalidCharFound bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// skipRegexCheck checks if escape would be skipped.
|
||||||
|
// if invalidCharFound is true, it must have invalid character; if invalidCharFound is false, not sure if it has invalid character or not
|
||||||
|
func skipRegexCheck(ident string) escapeCheck {
|
||||||
|
escapeCheck := escapeCheck{canSkipRegex: true, invalidCharFound: false}
|
||||||
|
// skip escape if possible
|
||||||
|
previous_underscore := false
|
||||||
|
for _, c := range ident {
|
||||||
|
if c == '/' || c == '-' || c == '.' {
|
||||||
|
escapeCheck.canSkipRegex = false
|
||||||
|
return escapeCheck
|
||||||
|
}
|
||||||
|
intc := int(c)
|
||||||
|
if intc < 0 || intc >= len(validCharacterFilter) || !validCharacterFilter[intc] {
|
||||||
|
escapeCheck.invalidCharFound = true
|
||||||
|
return escapeCheck
|
||||||
|
}
|
||||||
|
if c == '_' && previous_underscore {
|
||||||
|
escapeCheck.canSkipRegex = false
|
||||||
|
return escapeCheck
|
||||||
|
}
|
||||||
|
|
||||||
|
previous_underscore = c == '_'
|
||||||
|
}
|
||||||
|
return escapeCheck
|
||||||
|
}
|
||||||
|
|
||||||
|
// validCharacterFilter indicates the allowed characters.
|
||||||
|
var validCharacterFilter = newCharacterFilter("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_")
|
||||||
|
|
||||||
// Escape escapes ident and returns a CEL identifier (of the form '[a-zA-Z_][a-zA-Z0-9_]*'), or returns
|
// Escape escapes ident and returns a CEL identifier (of the form '[a-zA-Z_][a-zA-Z0-9_]*'), or returns
|
||||||
// false if the ident does not match the supported input format of `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*`.
|
// false if the ident does not match the supported input format of `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*`.
|
||||||
// Escaping Rules:
|
// Escaping Rules:
|
||||||
@ -53,6 +104,15 @@ func Escape(ident string) (string, bool) {
|
|||||||
if celReservedSymbols.Has(ident) {
|
if celReservedSymbols.Has(ident) {
|
||||||
return "__" + ident + "__", true
|
return "__" + ident + "__", true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
escapeCheck := skipRegexCheck(ident)
|
||||||
|
if escapeCheck.invalidCharFound {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
if escapeCheck.canSkipRegex {
|
||||||
|
return ident, true
|
||||||
|
}
|
||||||
|
|
||||||
ok := true
|
ok := true
|
||||||
ident = expandMatcher.ReplaceAllStringFunc(ident, func(s string) string {
|
ident = expandMatcher.ReplaceAllStringFunc(ident, func(s string) string {
|
||||||
switch s {
|
switch s {
|
||||||
|
@ -170,3 +170,37 @@ func TestEscapingFuzz(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var validCelIdent = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`)
|
var validCelIdent = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`)
|
||||||
|
|
||||||
|
func TestCanSkipRegex(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
unescaped string
|
||||||
|
canSkip bool
|
||||||
|
invalidCharFound bool
|
||||||
|
}{
|
||||||
|
{unescaped: "a.a", canSkip: false},
|
||||||
|
{unescaped: "a-a", canSkip: false},
|
||||||
|
{unescaped: "a__a", canSkip: false},
|
||||||
|
{unescaped: "a.-/__a", canSkip: false},
|
||||||
|
{unescaped: "a_a", canSkip: true},
|
||||||
|
{unescaped: "a_a_a", canSkip: true},
|
||||||
|
{unescaped: "@", invalidCharFound: true},
|
||||||
|
{unescaped: "👑", invalidCharFound: true},
|
||||||
|
// if escape keyword is detected before invalid character, invalidCharFound
|
||||||
|
{unescaped: "/👑", canSkip: false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.unescaped, func(t *testing.T) {
|
||||||
|
escapeCheck := skipRegexCheck(tc.unescaped)
|
||||||
|
if escapeCheck.invalidCharFound {
|
||||||
|
if escapeCheck.invalidCharFound != tc.invalidCharFound {
|
||||||
|
t.Errorf("Expected input validation to be %v, but got %t", tc.invalidCharFound, escapeCheck.invalidCharFound)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if escapeCheck.canSkipRegex != tc.canSkip {
|
||||||
|
t.Errorf("Expected %v, but got %t", tc.canSkip, escapeCheck.canSkipRegex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user