Skip to content

Commit

Permalink
fix(datastore): Allow saving nested byte slice (#8540)
Browse files Browse the repository at this point in the history
  • Loading branch information
bhshkh authored Sep 18, 2023
1 parent 25dbb9c commit 8e53787
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 1 deletion.
72 changes: 72 additions & 0 deletions datastore/datastore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,78 @@ func TestPutInvalidEntity(t *testing.T) {
})
}

func TestPutNestedArray(t *testing.T) {
type InnerByte struct {
ArrByte []byte
}

type OuterByte struct {
InnerArr []InnerByte `datastore:"arrbyte,flatten"`
}

type InnerStr struct {
ArrStr []string
}

type OuterStr struct {
InnerArr []InnerStr `datastore:"arrstr,flatten"`
}

ctx := context.Background()
client := &Client{
client: &fakeDatastoreClient{
commit: func(req *pb.CommitRequest) (*pb.CommitResponse, error) {
return &pb.CommitResponse{}, nil
},
},
}

testcases := []struct {
desc string
src interface{}
key *Key
wantFailure bool
wantErrMsg string
}{
{
desc: "Nested byte slice should pass",
src: &OuterByte{
InnerArr: []InnerByte{
{
ArrByte: []byte("Test string"),
},
},
},
key: NameKey("OuterByte", "OuterByte1", nil),
},
{
desc: "Nested slice not of byte type should fail",
src: &OuterStr{
InnerArr: []InnerStr{
{
ArrStr: []string{"a", "b"},
},
},
},
key: NameKey("OuterStr", "OuterStr1", nil),
wantFailure: true,
wantErrMsg: "flattening nested structs leads to a slice of slices",
},
}

for _, tc := range testcases {
gotKey, gotErr := client.Put(ctx, tc.key, tc.src)
gotFailure := gotErr != nil
if gotFailure != tc.wantFailure ||
(gotErr != nil && !strings.Contains(gotErr.Error(), tc.wantErrMsg)) {
t.Errorf("%q: Mismatch in error got: %v, want: %q", tc.desc, gotErr, tc.wantErrMsg)
}
if gotErr == nil && !gotKey.Equal(tc.key) {
t.Errorf("%q: Mismatch in key got: %v, want: %q", tc.desc, gotKey, tc.key)
}
}
}

func TestDeferred(t *testing.T) {
type Ent struct {
A int
Expand Down
3 changes: 2 additions & 1 deletion datastore/prop.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,8 @@ func validateChildType(t reflect.Type, fieldName string, flatten, prevSlice bool

switch t.Kind() {
case reflect.Slice:
if flatten && prevSlice {
// Uint8 is an alias for byte. A slice of bytes is acceptable. A slice of others types is not.
if flatten && prevSlice && t.Elem().Kind() != reflect.Uint8 {
return fmt.Errorf("datastore: flattening nested structs leads to a slice of slices: field %q", fieldName)
}
return validateChildType(t.Elem(), fieldName, flatten, true, prevTypes)
Expand Down

0 comments on commit 8e53787

Please sign in to comment.