-
Notifications
You must be signed in to change notification settings - Fork 1.5k
test(spanner): additional tests for SelectAll() #13360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2288,11 +2288,30 @@ func TestSelectAll(t *testing.T) { | |
| Col3 string `spanner:"taG3"` | ||
| Col4 time.Time `spanner:"TAG4"` | ||
| } | ||
|
|
||
| type Address struct { | ||
| Street string | ||
| ZipCode string | ||
| City string | ||
| } | ||
|
|
||
| type Person struct { | ||
| Name string | ||
| Address Address | ||
| BirthDate civil.Date | ||
| } | ||
| type PersonEmbedded struct { | ||
| Name string | ||
| Address | ||
| BirthDate civil.Date | ||
| } | ||
|
|
||
| tests := []struct { | ||
| name string | ||
| args args | ||
| wantErr bool | ||
| want interface{} | ||
| name string | ||
| args args | ||
| wantErr bool | ||
| wantPanic bool | ||
| want interface{} | ||
| }{ | ||
| { | ||
| name: "success: using slice of primitives", | ||
|
|
@@ -2612,9 +2631,101 @@ func TestSelectAll(t *testing.T) { | |
| want: &[]int64{}, | ||
| wantErr: true, | ||
| }, | ||
| { | ||
| name: "failure: nested named structs", | ||
| args: args{ | ||
| destination: &[]*Person{}, | ||
| mock: newMockIterator( | ||
| &Row{ | ||
| []*sppb.StructType_Field{ | ||
| {Name: "Name", Type: stringType()}, | ||
| {Name: "Street", Type: stringType()}, | ||
| {Name: "ZipCode", Type: stringType()}, | ||
| {Name: "City", Type: stringType()}, | ||
| {Name: "BirthDate", Type: dateType()}, | ||
| }, | ||
| []*proto3.Value{ | ||
| stringProto("Name1"), | ||
| stringProto("Street1"), | ||
| stringProto("ZipCode1"), | ||
| stringProto("City1"), | ||
| dateProto(civil.Date{Year: 2000, Month: 11, Day: 14}), | ||
| }, | ||
| }, | ||
| &Row{ | ||
| []*sppb.StructType_Field{ | ||
| {Name: "Name", Type: stringType()}, | ||
| {Name: "Street", Type: stringType()}, | ||
| {Name: "ZipCode", Type: stringType()}, | ||
| {Name: "City", Type: stringType()}, | ||
| {Name: "BirthDate", Type: dateType()}, | ||
| }, | ||
| []*proto3.Value{ | ||
| stringProto("Name2"), | ||
| stringProto("Street2"), | ||
| stringProto("ZipCode2"), | ||
| stringProto("City2"), | ||
| dateProto(civil.Date{Year: 2001, Month: 11, Day: 14}), | ||
| }, | ||
| }, | ||
| iterator.Done, | ||
| ), | ||
| }, | ||
| want: &[]*Person{}, | ||
| wantErr: true, | ||
| }, | ||
| { | ||
| name: "failure: nested unnamed structs", | ||
| args: args{ | ||
| destination: &[]*PersonEmbedded{}, | ||
| mock: newMockIterator( | ||
| &Row{ | ||
| []*sppb.StructType_Field{ | ||
| {Name: "Name", Type: stringType()}, | ||
| {Name: "Street", Type: stringType()}, | ||
| {Name: "ZipCode", Type: stringType()}, | ||
| {Name: "City", Type: stringType()}, | ||
| {Name: "BirthDate", Type: dateType()}, | ||
| }, | ||
| []*proto3.Value{ | ||
| stringProto("Name1"), | ||
| stringProto("Street1"), | ||
| stringProto("ZipCode1"), | ||
| stringProto("City1"), | ||
| dateProto(civil.Date{Year: 2000, Month: 11, Day: 14}), | ||
| }, | ||
| }, | ||
| &Row{ | ||
| []*sppb.StructType_Field{ | ||
| {Name: "Name", Type: stringType()}, | ||
| {Name: "Street", Type: stringType()}, | ||
| {Name: "ZipCode", Type: stringType()}, | ||
| {Name: "City", Type: stringType()}, | ||
| {Name: "BirthDate", Type: dateType()}, | ||
| }, | ||
| []*proto3.Value{ | ||
| stringProto("Name2"), | ||
| stringProto("Street2"), | ||
| stringProto("ZipCode2"), | ||
| stringProto("City2"), | ||
| dateProto(civil.Date{Year: 2001, Month: 11, Day: 14}), | ||
| }, | ||
| }, | ||
| iterator.Done, | ||
| ), | ||
| }, | ||
| wantPanic: true, | ||
| }, | ||
|
Comment on lines
+2634
to
+2718
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The mock iterator creation logic is duplicated between the For example, you could define a helper function: func newPersonMockIterator() *mockIterator {
personFields := []*sppb.StructType_Field{
{Name: "Name", Type: stringType()},
{Name: "Street", Type: stringType()},
{Name: "ZipCode", Type: stringType()},
{Name: "City", Type: stringType()},
{Name: "BirthDate", Type: dateType()},
}
return newMockIterator(
&Row{
personFields,
[]*proto3.Value{
stringProto("Name1"), stringProto("Street1"), stringProto("ZipCode1"), stringProto("City1"), dateProto(civil.Date{Year: 2000, Month: 11, Day: 14}),
},
},
&Row{
personFields,
[]*proto3.Value{
stringProto("Name2"), stringProto("Street2"), stringProto("ZipCode2"), stringProto("City2"), dateProto(civil.Date{Year: 2001, Month: 11, Day: 14}),
},
},
iterator.Done,
)
}And then call it in your test cases: //...
{
name: "failure: nested named structs",
args: args{
destination: &[]*Person{},
mock: newPersonMockIterator(),
},
want: &[]*Person{},
wantErr: true,
},
{
name: "failure: nested unnamed structs",
args: args{
destination: &[]*PersonEmbedded{},
mock: newPersonMockIterator(),
},
want: &[]*PersonEmbedded{},
wantPanic: true,
},
//... |
||
| } | ||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| if tt.wantPanic { | ||
| defer func() { | ||
| if r := recover(); r == nil { | ||
| t.Error("SelectAll() did not panic") | ||
| } | ||
| }() | ||
| } | ||
| mockIterator := tt.args.mock | ||
| if err := SelectAll(mockIterator, tt.args.destination, tt.args.options...); (err != nil) != tt.wantErr { | ||
| t.Errorf("SelectAll() error = %v, wantErr %v", err, tt.wantErr) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For clarity and to prevent an additional failure message if the code stops panicking in the future, it's good practice to specify the expected state of
destinationeven in a panic test. SinceSelectAllshouldn't modify the destination if it panics (or errors out before completion), the expected valuewantshould be the same as the initialdestination.