Always shard structs if they would exceed maxNameSize even if unfiltered

Previously, a struct (anonymous or named) whose fields all matched the
predicate would not be sharded and would simply be reused. However,
that could break the maxNameSize limitation which could cause problems
for the caller.

This change makes sure that the supplied struct is only reused if it
does not exceed the maxNameSize, and otherwise is sharded.

Bug: 183777071
Test: m nothing
Change-Id: I8af272ec121077a43333e72b67cfd0e493c83362
This commit is contained in:
Paul Duffin 2021-03-26 09:09:03 +00:00
parent a9ec69433d
commit 2aa510c27b
2 changed files with 51 additions and 1 deletions

View file

@ -173,7 +173,13 @@ func filterPropertyStruct(prop reflect.Type, prefix string, maxNameSize int,
return nil, true
}
if !filtered {
// If the predicate selected all fields in the structure then it is generally better to reuse the
// original type as it avoids the footprint of creating another type. Also, if the original type
// is a named type then it will reduce the size of any structs the caller may create that include
// fields of this type. However, the original type should only be reused if it does not exceed
// maxNameSize. That is, of course, more likely for an anonymous type than a named one but this
// treats them the same.
if !filtered && (maxNameSize < 0 || len(prop.String()) < maxNameSize) {
if ptr {
return []reflect.Type{reflect.PtrTo(prop)}, false
}

View file

@ -240,6 +240,12 @@ func TestFilterPropertyStruct(t *testing.T) {
}
func TestFilterPropertyStructSharded(t *testing.T) {
type KeepAllWithAReallyLongNameThatExceedsTheMaxNameSize struct {
A *string `keep:"true"`
B *string `keep:"true"`
C *string `keep:"true"`
}
tests := []struct {
name string
maxNameSize int
@ -266,6 +272,44 @@ func TestFilterPropertyStructSharded(t *testing.T) {
},
filtered: true,
},
{
name: "anonymous where all match but still needs sharding",
maxNameSize: 20,
in: &struct {
A *string `keep:"true"`
B *string `keep:"true"`
C *string `keep:"true"`
}{},
out: []interface{}{
&struct {
A *string
}{},
&struct {
B *string
}{},
&struct {
C *string
}{},
},
filtered: true,
},
{
name: "named where all match but still needs sharding",
maxNameSize: 20,
in: &KeepAllWithAReallyLongNameThatExceedsTheMaxNameSize{},
out: []interface{}{
&struct {
A *string
}{},
&struct {
B *string
}{},
&struct {
C *string
}{},
},
filtered: true,
},
}
for _, test := range tests {