1/* 2Copyright 2017 Google LLC 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package spanner 18 19import ( 20 "math" 21 "reflect" 22 "testing" 23 "time" 24 25 "cloud.google.com/go/civil" 26 "github.com/golang/protobuf/proto" 27 proto3 "github.com/golang/protobuf/ptypes/struct" 28 sppb "google.golang.org/genproto/googleapis/spanner/v1" 29) 30 31var ( 32 t1 = mustParseTime("2016-11-15T15:04:05.999999999Z") 33 // Boundaries 34 t2 = mustParseTime("0000-01-01T00:00:00.000000000Z") 35 t3 = mustParseTime("9999-12-31T23:59:59.999999999Z") 36 // Local timezone 37 t4 = time.Now() 38 d1 = mustParseDate("2016-11-15") 39 d2 = mustParseDate("1678-01-01") 40) 41 42func mustParseTime(s string) time.Time { 43 t, err := time.Parse(time.RFC3339Nano, s) 44 if err != nil { 45 panic(err) 46 } 47 return t 48} 49 50func mustParseDate(s string) civil.Date { 51 d, err := civil.ParseDate(s) 52 if err != nil { 53 panic(err) 54 } 55 return d 56} 57 58// Test encoding Values. 59func TestEncodeValue(t *testing.T) { 60 var ( 61 tString = stringType() 62 tInt = intType() 63 tBool = boolType() 64 tFloat = floatType() 65 tBytes = bytesType() 66 tTime = timeType() 67 tDate = dateType() 68 ) 69 for i, test := range []struct { 70 in interface{} 71 want *proto3.Value 72 wantType *sppb.Type 73 }{ 74 // STRING / STRING ARRAY 75 {"abc", stringProto("abc"), tString}, 76 {NullString{"abc", true}, stringProto("abc"), tString}, 77 {NullString{"abc", false}, nullProto(), tString}, 78 {[]string(nil), nullProto(), listType(tString)}, 79 {[]string{"abc", "bcd"}, listProto(stringProto("abc"), stringProto("bcd")), listType(tString)}, 80 {[]NullString{{"abcd", true}, {"xyz", false}}, listProto(stringProto("abcd"), nullProto()), listType(tString)}, 81 // BYTES / BYTES ARRAY 82 {[]byte("foo"), bytesProto([]byte("foo")), tBytes}, 83 {[]byte(nil), nullProto(), tBytes}, 84 {[][]byte{nil, []byte("ab")}, listProto(nullProto(), bytesProto([]byte("ab"))), listType(tBytes)}, 85 {[][]byte(nil), nullProto(), listType(tBytes)}, 86 // INT64 / INT64 ARRAY 87 {7, intProto(7), tInt}, 88 {[]int(nil), nullProto(), listType(tInt)}, 89 {[]int{31, 127}, listProto(intProto(31), intProto(127)), listType(tInt)}, 90 {int64(81), intProto(81), tInt}, 91 {[]int64(nil), nullProto(), listType(tInt)}, 92 {[]int64{33, 129}, listProto(intProto(33), intProto(129)), listType(tInt)}, 93 {NullInt64{11, true}, intProto(11), tInt}, 94 {NullInt64{11, false}, nullProto(), tInt}, 95 {[]NullInt64{{35, true}, {131, false}}, listProto(intProto(35), nullProto()), listType(tInt)}, 96 // BOOL / BOOL ARRAY 97 {true, boolProto(true), tBool}, 98 {NullBool{true, true}, boolProto(true), tBool}, 99 {NullBool{true, false}, nullProto(), tBool}, 100 {[]bool{true, false}, listProto(boolProto(true), boolProto(false)), listType(tBool)}, 101 {[]NullBool{{true, true}, {true, false}}, listProto(boolProto(true), nullProto()), listType(tBool)}, 102 // FLOAT64 / FLOAT64 ARRAY 103 {3.14, floatProto(3.14), tFloat}, 104 {NullFloat64{3.1415, true}, floatProto(3.1415), tFloat}, 105 {NullFloat64{math.Inf(1), true}, floatProto(math.Inf(1)), tFloat}, 106 {NullFloat64{3.14159, false}, nullProto(), tFloat}, 107 {[]float64(nil), nullProto(), listType(tFloat)}, 108 {[]float64{3.141, 0.618, math.Inf(-1)}, listProto(floatProto(3.141), floatProto(0.618), floatProto(math.Inf(-1))), listType(tFloat)}, 109 {[]NullFloat64{{3.141, true}, {0.618, false}}, listProto(floatProto(3.141), nullProto()), listType(tFloat)}, 110 // TIMESTAMP / TIMESTAMP ARRAY 111 {t1, timeProto(t1), tTime}, 112 {NullTime{t1, true}, timeProto(t1), tTime}, 113 {NullTime{t1, false}, nullProto(), tTime}, 114 {[]time.Time(nil), nullProto(), listType(tTime)}, 115 {[]time.Time{t1, t2, t3, t4}, listProto(timeProto(t1), timeProto(t2), timeProto(t3), timeProto(t4)), listType(tTime)}, 116 {[]NullTime{{t1, true}, {t1, false}}, listProto(timeProto(t1), nullProto()), listType(tTime)}, 117 // DATE / DATE ARRAY 118 {d1, dateProto(d1), tDate}, 119 {NullDate{d1, true}, dateProto(d1), tDate}, 120 {NullDate{civil.Date{}, false}, nullProto(), tDate}, 121 {[]civil.Date(nil), nullProto(), listType(tDate)}, 122 {[]civil.Date{d1, d2}, listProto(dateProto(d1), dateProto(d2)), listType(tDate)}, 123 {[]NullDate{{d1, true}, {civil.Date{}, false}}, listProto(dateProto(d1), nullProto()), listType(tDate)}, 124 // GenericColumnValue 125 {GenericColumnValue{tString, stringProto("abc")}, stringProto("abc"), tString}, 126 {GenericColumnValue{tString, nullProto()}, nullProto(), tString}, 127 // not actually valid (stringProto inside int list), but demonstrates pass-through. 128 { 129 GenericColumnValue{ 130 Type: listType(tInt), 131 Value: listProto(intProto(5), nullProto(), stringProto("bcd")), 132 }, 133 listProto(intProto(5), nullProto(), stringProto("bcd")), 134 listType(tInt), 135 }, 136 // placeholder 137 {CommitTimestamp, stringProto(commitTimestampPlaceholderString), tTime}, 138 } { 139 got, gotType, err := encodeValue(test.in) 140 if err != nil { 141 t.Fatalf("#%d: got error during encoding: %v, want nil", i, err) 142 } 143 if !testEqual(got, test.want) { 144 t.Errorf("#%d: got encode result: %v, want %v", i, got, test.want) 145 } 146 if !testEqual(gotType, test.wantType) { 147 t.Errorf("#%d: got encode type: %v, want %v", i, gotType, test.wantType) 148 } 149 } 150} 151 152type encodeTest struct { 153 desc string 154 in interface{} 155 want *proto3.Value 156 wantType *sppb.Type 157} 158 159func checkStructEncoding(desc string, got *proto3.Value, gotType *sppb.Type, 160 want *proto3.Value, wantType *sppb.Type, t *testing.T) { 161 if !testEqual(got, want) { 162 t.Errorf("Test %s: got encode result: %v, want %v", desc, got, want) 163 } 164 if !testEqual(gotType, wantType) { 165 t.Errorf("Test %s: got encode type: %v, want %v", desc, gotType, wantType) 166 } 167} 168 169// Testcase code 170func encodeStructValue(test encodeTest, t *testing.T) { 171 got, gotType, err := encodeValue(test.in) 172 if err != nil { 173 t.Fatalf("Test %s: got error during encoding: %v, want nil", test.desc, err) 174 } 175 checkStructEncoding(test.desc, got, gotType, test.want, test.wantType, t) 176} 177 178func TestEncodeStructValuePointers(t *testing.T) { 179 type structf struct { 180 F int `spanner:"ff2"` 181 } 182 nestedStructProto := structType(mkField("ff2", intType())) 183 184 type testType struct { 185 Stringf string 186 Structf *structf 187 ArrStructf []*structf 188 } 189 testTypeProto := structType( 190 mkField("Stringf", stringType()), 191 mkField("Structf", nestedStructProto), 192 mkField("ArrStructf", listType(nestedStructProto))) 193 194 for _, test := range []encodeTest{ 195 { 196 "Pointer to Go struct with pointers-to-(array)-struct fields.", 197 &testType{"hello", &structf{50}, []*structf{{30}, {40}}}, 198 listProto( 199 stringProto("hello"), 200 listProto(intProto(50)), 201 listProto( 202 listProto(intProto(30)), 203 listProto(intProto(40)))), 204 testTypeProto, 205 }, 206 { 207 "Nil pointer to Go struct representing a NULL struct value.", 208 (*testType)(nil), 209 nullProto(), 210 testTypeProto, 211 }, 212 { 213 "Slice of pointers to Go structs with NULL and non-NULL elements.", 214 []*testType{ 215 (*testType)(nil), 216 {"hello", nil, []*structf{nil, {40}}}, 217 {"world", &structf{70}, nil}, 218 }, 219 listProto( 220 nullProto(), 221 listProto( 222 stringProto("hello"), 223 nullProto(), 224 listProto(nullProto(), listProto(intProto(40)))), 225 listProto( 226 stringProto("world"), 227 listProto(intProto(70)), 228 nullProto())), 229 listType(testTypeProto), 230 }, 231 { 232 "Nil slice of pointers to structs representing a NULL array of structs.", 233 []*testType(nil), 234 nullProto(), 235 listType(testTypeProto), 236 }, 237 { 238 "Empty slice of pointers to structs representing an empty array of structs.", 239 []*testType{}, 240 listProto(), 241 listType(testTypeProto), 242 }, 243 } { 244 encodeStructValue(test, t) 245 } 246} 247 248func TestEncodeStructValueErrors(t *testing.T) { 249 type Embedded struct { 250 A int 251 } 252 type embedded struct { 253 B bool 254 } 255 x := 0 256 257 for _, test := range []struct { 258 desc string 259 in interface{} 260 wantErr error 261 }{ 262 { 263 "Unsupported embedded fields.", 264 struct{ Embedded }{Embedded{10}}, 265 errUnsupportedEmbeddedStructFields("Embedded"), 266 }, 267 { 268 "Unsupported pointer to embedded fields.", 269 struct{ *Embedded }{&Embedded{10}}, 270 errUnsupportedEmbeddedStructFields("Embedded"), 271 }, 272 { 273 "Unsupported embedded + unexported fields.", 274 struct { 275 int 276 *bool 277 embedded 278 }{10, nil, embedded{false}}, 279 errUnsupportedEmbeddedStructFields("int"), 280 }, 281 { 282 "Unsupported type.", 283 (**struct{})(nil), 284 errEncoderUnsupportedType((**struct{})(nil)), 285 }, 286 { 287 "Unsupported type.", 288 3, 289 errEncoderUnsupportedType(3), 290 }, 291 { 292 "Unsupported type.", 293 &x, 294 errEncoderUnsupportedType(&x), 295 }, 296 } { 297 _, _, got := encodeStruct(test.in) 298 if got == nil || !testEqual(test.wantErr, got) { 299 t.Errorf("Test: %s, expected error %v during decoding, got %v", test.desc, test.wantErr, got) 300 } 301 } 302} 303 304func TestEncodeStructValueArrayStructFields(t *testing.T) { 305 type structf struct { 306 Intff int 307 } 308 309 structfType := structType(mkField("Intff", intType())) 310 for _, test := range []encodeTest{ 311 { 312 "Unnamed array-of-struct-typed field.", 313 struct { 314 Intf int 315 ArrStructf []structf `spanner:""` 316 }{10, []structf{{1}, {2}}}, 317 listProto( 318 intProto(10), 319 listProto( 320 listProto(intProto(1)), 321 listProto(intProto(2)))), 322 structType( 323 mkField("Intf", intType()), 324 mkField("", listType(structfType))), 325 }, 326 { 327 "Null array-of-struct-typed field.", 328 struct { 329 Intf int 330 ArrStructf []structf 331 }{10, []structf(nil)}, 332 listProto(intProto(10), nullProto()), 333 structType( 334 mkField("Intf", intType()), 335 mkField("ArrStructf", listType(structfType))), 336 }, 337 { 338 "Array-of-struct-typed field representing empty array.", 339 struct { 340 Intf int 341 ArrStructf []structf 342 }{10, []structf{}}, 343 listProto(intProto(10), listProto([]*proto3.Value{}...)), 344 structType( 345 mkField("Intf", intType()), 346 mkField("ArrStructf", listType(structfType))), 347 }, 348 { 349 "Array-of-struct-typed field with nullable struct elements.", 350 struct { 351 Intf int 352 ArrStructf []*structf 353 }{ 354 10, 355 []*structf{(*structf)(nil), {1}}, 356 }, 357 listProto( 358 intProto(10), 359 listProto( 360 nullProto(), 361 listProto(intProto(1)))), 362 structType( 363 mkField("Intf", intType()), 364 mkField("ArrStructf", listType(structfType))), 365 }, 366 } { 367 encodeStructValue(test, t) 368 } 369} 370 371func TestEncodeStructValueStructFields(t *testing.T) { 372 type structf struct { 373 Intff int 374 } 375 structfType := structType(mkField("Intff", intType())) 376 for _, test := range []encodeTest{ 377 { 378 "Named struct-type field.", 379 struct { 380 Intf int 381 Structf structf 382 }{10, structf{10}}, 383 listProto(intProto(10), listProto(intProto(10))), 384 structType( 385 mkField("Intf", intType()), 386 mkField("Structf", structfType)), 387 }, 388 { 389 "Unnamed struct-type field.", 390 struct { 391 Intf int 392 Structf structf `spanner:""` 393 }{10, structf{10}}, 394 listProto(intProto(10), listProto(intProto(10))), 395 structType( 396 mkField("Intf", intType()), 397 mkField("", structfType)), 398 }, 399 { 400 "Duplicate struct-typed field.", 401 struct { 402 Structf1 structf `spanner:""` 403 Structf2 structf `spanner:""` 404 }{structf{10}, structf{20}}, 405 listProto(listProto(intProto(10)), listProto(intProto(20))), 406 structType( 407 mkField("", structfType), 408 mkField("", structfType)), 409 }, 410 { 411 "Null struct-typed field.", 412 struct { 413 Intf int 414 Structf *structf 415 }{10, nil}, 416 listProto(intProto(10), nullProto()), 417 structType( 418 mkField("Intf", intType()), 419 mkField("Structf", structfType)), 420 }, 421 { 422 "Empty struct-typed field.", 423 struct { 424 Intf int 425 Structf struct{} 426 }{10, struct{}{}}, 427 listProto(intProto(10), listProto([]*proto3.Value{}...)), 428 structType( 429 mkField("Intf", intType()), 430 mkField("Structf", structType([]*sppb.StructType_Field{}...))), 431 }, 432 } { 433 encodeStructValue(test, t) 434 } 435} 436 437func TestEncodeStructValueFieldNames(t *testing.T) { 438 type embedded struct { 439 B bool 440 } 441 442 for _, test := range []encodeTest{ 443 { 444 "Duplicate fields.", 445 struct { 446 Field1 int `spanner:"field"` 447 DupField1 int `spanner:"field"` 448 }{10, 20}, 449 listProto(intProto(10), intProto(20)), 450 structType( 451 mkField("field", intType()), 452 mkField("field", intType())), 453 }, 454 { 455 "Duplicate Fields (different types).", 456 struct { 457 IntField int `spanner:"field"` 458 StringField string `spanner:"field"` 459 }{10, "abc"}, 460 listProto(intProto(10), stringProto("abc")), 461 structType( 462 mkField("field", intType()), 463 mkField("field", stringType())), 464 }, 465 { 466 "Duplicate unnamed fields.", 467 struct { 468 Dup int `spanner:""` 469 Dup1 int `spanner:""` 470 }{10, 20}, 471 listProto(intProto(10), intProto(20)), 472 structType( 473 mkField("", intType()), 474 mkField("", intType())), 475 }, 476 { 477 "Named and unnamed fields.", 478 struct { 479 Field string 480 Field1 int `spanner:""` 481 Field2 string `spanner:"field"` 482 }{"abc", 10, "def"}, 483 listProto(stringProto("abc"), intProto(10), stringProto("def")), 484 structType( 485 mkField("Field", stringType()), 486 mkField("", intType()), 487 mkField("field", stringType())), 488 }, 489 { 490 "Ignored unexported fields.", 491 struct { 492 Field int 493 field bool 494 Field1 string `spanner:"field"` 495 }{10, false, "abc"}, 496 listProto(intProto(10), stringProto("abc")), 497 structType( 498 mkField("Field", intType()), 499 mkField("field", stringType())), 500 }, 501 { 502 "Ignored unexported struct/slice fields.", 503 struct { 504 a []*embedded 505 b []embedded 506 c embedded 507 d *embedded 508 Field1 string `spanner:"field"` 509 }{nil, nil, embedded{}, nil, "def"}, 510 listProto(stringProto("def")), 511 structType( 512 mkField("field", stringType())), 513 }, 514 } { 515 encodeStructValue(test, t) 516 } 517} 518 519func TestEncodeStructValueBasicFields(t *testing.T) { 520 StructTypeProto := structType( 521 mkField("Stringf", stringType()), 522 mkField("Intf", intType()), 523 mkField("Boolf", boolType()), 524 mkField("Floatf", floatType()), 525 mkField("Bytef", bytesType()), 526 mkField("Timef", timeType()), 527 mkField("Datef", dateType())) 528 529 for _, test := range []encodeTest{ 530 { 531 "Basic types.", 532 struct { 533 Stringf string 534 Intf int 535 Boolf bool 536 Floatf float64 537 Bytef []byte 538 Timef time.Time 539 Datef civil.Date 540 }{"abc", 300, false, 3.45, []byte("foo"), t1, d1}, 541 listProto( 542 stringProto("abc"), 543 intProto(300), 544 boolProto(false), 545 floatProto(3.45), 546 bytesProto([]byte("foo")), 547 timeProto(t1), 548 dateProto(d1)), 549 StructTypeProto, 550 }, 551 { 552 "Basic types null values.", 553 struct { 554 Stringf NullString 555 Intf NullInt64 556 Boolf NullBool 557 Floatf NullFloat64 558 Bytef []byte 559 Timef NullTime 560 Datef NullDate 561 }{ 562 NullString{"abc", false}, 563 NullInt64{4, false}, 564 NullBool{false, false}, 565 NullFloat64{5.6, false}, 566 nil, 567 NullTime{t1, false}, 568 NullDate{d1, false}, 569 }, 570 listProto( 571 nullProto(), 572 nullProto(), 573 nullProto(), 574 nullProto(), 575 nullProto(), 576 nullProto(), 577 nullProto()), 578 StructTypeProto, 579 }, 580 } { 581 encodeStructValue(test, t) 582 } 583} 584 585func TestEncodeStructValueArrayFields(t *testing.T) { 586 StructTypeProto := structType( 587 mkField("Stringf", listType(stringType())), 588 mkField("Intf", listType(intType())), 589 mkField("Int64f", listType(intType())), 590 mkField("Boolf", listType(boolType())), 591 mkField("Floatf", listType(floatType())), 592 mkField("Bytef", listType(bytesType())), 593 mkField("Timef", listType(timeType())), 594 mkField("Datef", listType(dateType()))) 595 596 for _, test := range []encodeTest{ 597 { 598 "Arrays of basic types with non-nullable elements", 599 struct { 600 Stringf []string 601 Intf []int 602 Int64f []int64 603 Boolf []bool 604 Floatf []float64 605 Bytef [][]byte 606 Timef []time.Time 607 Datef []civil.Date 608 }{ 609 []string{"abc", "def"}, 610 []int{4, 67}, 611 []int64{5, 68}, 612 []bool{false, true}, 613 []float64{3.45, 0.93}, 614 [][]byte{[]byte("foo"), nil}, 615 []time.Time{t1, t2}, 616 []civil.Date{d1, d2}, 617 }, 618 listProto( 619 listProto(stringProto("abc"), stringProto("def")), 620 listProto(intProto(4), intProto(67)), 621 listProto(intProto(5), intProto(68)), 622 listProto(boolProto(false), boolProto(true)), 623 listProto(floatProto(3.45), floatProto(0.93)), 624 listProto(bytesProto([]byte("foo")), nullProto()), 625 listProto(timeProto(t1), timeProto(t2)), 626 listProto(dateProto(d1), dateProto(d2))), 627 StructTypeProto, 628 }, 629 { 630 "Arrays of basic types with nullable elements.", 631 struct { 632 Stringf []NullString 633 Intf []NullInt64 634 Int64f []NullInt64 635 Boolf []NullBool 636 Floatf []NullFloat64 637 Bytef [][]byte 638 Timef []NullTime 639 Datef []NullDate 640 }{ 641 []NullString{{"abc", false}, {"def", true}}, 642 []NullInt64{{4, false}, {67, true}}, 643 []NullInt64{{5, false}, {68, true}}, 644 []NullBool{{true, false}, {false, true}}, 645 []NullFloat64{{3.45, false}, {0.93, true}}, 646 [][]byte{[]byte("foo"), nil}, 647 []NullTime{{t1, false}, {t2, true}}, 648 []NullDate{{d1, false}, {d2, true}}, 649 }, 650 listProto( 651 listProto(nullProto(), stringProto("def")), 652 listProto(nullProto(), intProto(67)), 653 listProto(nullProto(), intProto(68)), 654 listProto(nullProto(), boolProto(false)), 655 listProto(nullProto(), floatProto(0.93)), 656 listProto(bytesProto([]byte("foo")), nullProto()), 657 listProto(nullProto(), timeProto(t2)), 658 listProto(nullProto(), dateProto(d2))), 659 StructTypeProto, 660 }, 661 { 662 "Null arrays of basic types.", 663 struct { 664 Stringf []NullString 665 Intf []NullInt64 666 Int64f []NullInt64 667 Boolf []NullBool 668 Floatf []NullFloat64 669 Bytef [][]byte 670 Timef []NullTime 671 Datef []NullDate 672 }{ 673 nil, 674 nil, 675 nil, 676 nil, 677 nil, 678 nil, 679 nil, 680 nil, 681 }, 682 listProto( 683 nullProto(), 684 nullProto(), 685 nullProto(), 686 nullProto(), 687 nullProto(), 688 nullProto(), 689 nullProto(), 690 nullProto()), 691 StructTypeProto, 692 }, 693 } { 694 encodeStructValue(test, t) 695 } 696} 697 698// Test decoding Values. 699func TestDecodeValue(t *testing.T) { 700 for i, test := range []struct { 701 in *proto3.Value 702 t *sppb.Type 703 want interface{} 704 fail bool 705 }{ 706 // STRING 707 {stringProto("abc"), stringType(), "abc", false}, 708 {nullProto(), stringType(), "abc", true}, 709 {stringProto("abc"), stringType(), NullString{"abc", true}, false}, 710 {nullProto(), stringType(), NullString{}, false}, 711 // STRING ARRAY with []NullString 712 { 713 listProto(stringProto("abc"), nullProto(), stringProto("bcd")), 714 listType(stringType()), 715 []NullString{{"abc", true}, {}, {"bcd", true}}, 716 false, 717 }, 718 {nullProto(), listType(stringType()), []NullString(nil), false}, 719 // STRING ARRAY with []string 720 { 721 listProto(stringProto("abc"), stringProto("bcd")), 722 listType(stringType()), 723 []string{"abc", "bcd"}, 724 false, 725 }, 726 // BYTES 727 {bytesProto([]byte("ab")), bytesType(), []byte("ab"), false}, 728 {nullProto(), bytesType(), []byte(nil), false}, 729 // BYTES ARRAY 730 {listProto(bytesProto([]byte("ab")), nullProto()), listType(bytesType()), [][]byte{[]byte("ab"), nil}, false}, 731 {nullProto(), listType(bytesType()), [][]byte(nil), false}, 732 //INT64 733 {intProto(15), intType(), int64(15), false}, 734 {nullProto(), intType(), int64(0), true}, 735 {intProto(15), intType(), NullInt64{15, true}, false}, 736 {nullProto(), intType(), NullInt64{}, false}, 737 // INT64 ARRAY with []NullInt64 738 {listProto(intProto(91), nullProto(), intProto(87)), listType(intType()), []NullInt64{{91, true}, {}, {87, true}}, false}, 739 {nullProto(), listType(intType()), []NullInt64(nil), false}, 740 // INT64 ARRAY with []int64 741 {listProto(intProto(91), intProto(87)), listType(intType()), []int64{91, 87}, false}, 742 // BOOL 743 {boolProto(true), boolType(), true, false}, 744 {nullProto(), boolType(), true, true}, 745 {boolProto(true), boolType(), NullBool{true, true}, false}, 746 {nullProto(), boolType(), NullBool{}, false}, 747 // BOOL ARRAY with []NullBool 748 {listProto(boolProto(true), boolProto(false), nullProto()), listType(boolType()), []NullBool{{true, true}, {false, true}, {}}, false}, 749 {nullProto(), listType(boolType()), []NullBool(nil), false}, 750 // BOOL ARRAY with []bool 751 {listProto(boolProto(true), boolProto(false)), listType(boolType()), []bool{true, false}, false}, 752 // FLOAT64 753 {floatProto(3.14), floatType(), 3.14, false}, 754 {nullProto(), floatType(), 0.00, true}, 755 {floatProto(3.14), floatType(), NullFloat64{3.14, true}, false}, 756 {nullProto(), floatType(), NullFloat64{}, false}, 757 // FLOAT64 ARRAY with []NullFloat64 758 { 759 listProto(floatProto(math.Inf(1)), floatProto(math.Inf(-1)), nullProto(), floatProto(3.1)), 760 listType(floatType()), 761 []NullFloat64{{math.Inf(1), true}, {math.Inf(-1), true}, {}, {3.1, true}}, 762 false, 763 }, 764 {nullProto(), listType(floatType()), []NullFloat64(nil), false}, 765 // FLOAT64 ARRAY with []float64 766 { 767 listProto(floatProto(math.Inf(1)), floatProto(math.Inf(-1)), floatProto(3.1)), 768 listType(floatType()), 769 []float64{math.Inf(1), math.Inf(-1), 3.1}, 770 false, 771 }, 772 // TIMESTAMP 773 {timeProto(t1), timeType(), t1, false}, 774 {timeProto(t1), timeType(), NullTime{t1, true}, false}, 775 {nullProto(), timeType(), NullTime{}, false}, 776 // TIMESTAMP ARRAY with []NullTime 777 {listProto(timeProto(t1), timeProto(t2), timeProto(t3), nullProto()), listType(timeType()), []NullTime{{t1, true}, {t2, true}, {t3, true}, {}}, false}, 778 {nullProto(), listType(timeType()), []NullTime(nil), false}, 779 // TIMESTAMP ARRAY with []time.Time 780 {listProto(timeProto(t1), timeProto(t2), timeProto(t3)), listType(timeType()), []time.Time{t1, t2, t3}, false}, 781 // DATE 782 {dateProto(d1), dateType(), d1, false}, 783 {dateProto(d1), dateType(), NullDate{d1, true}, false}, 784 {nullProto(), dateType(), NullDate{}, false}, 785 // DATE ARRAY with []NullDate 786 {listProto(dateProto(d1), dateProto(d2), nullProto()), listType(dateType()), []NullDate{{d1, true}, {d2, true}, {}}, false}, 787 {nullProto(), listType(dateType()), []NullDate(nil), false}, 788 // DATE ARRAY with []civil.Date 789 {listProto(dateProto(d1), dateProto(d2)), listType(dateType()), []civil.Date{d1, d2}, false}, 790 // STRUCT ARRAY 791 // STRUCT schema is equal to the following Go struct: 792 // type s struct { 793 // Col1 NullInt64 794 // Col2 []struct { 795 // SubCol1 float64 796 // SubCol2 string 797 // } 798 // } 799 { 800 in: listProto( 801 listProto( 802 intProto(3), 803 listProto( 804 listProto(floatProto(3.14), stringProto("this")), 805 listProto(floatProto(0.57), stringProto("siht")), 806 ), 807 ), 808 listProto( 809 nullProto(), 810 nullProto(), 811 ), 812 nullProto(), 813 ), 814 t: listType( 815 structType( 816 mkField("Col1", intType()), 817 mkField( 818 "Col2", 819 listType( 820 structType( 821 mkField("SubCol1", floatType()), 822 mkField("SubCol2", stringType()), 823 ), 824 ), 825 ), 826 ), 827 ), 828 want: []NullRow{ 829 { 830 Row: Row{ 831 fields: []*sppb.StructType_Field{ 832 mkField("Col1", intType()), 833 mkField( 834 "Col2", 835 listType( 836 structType( 837 mkField("SubCol1", floatType()), 838 mkField("SubCol2", stringType()), 839 ), 840 ), 841 ), 842 }, 843 vals: []*proto3.Value{ 844 intProto(3), 845 listProto( 846 listProto(floatProto(3.14), stringProto("this")), 847 listProto(floatProto(0.57), stringProto("siht")), 848 ), 849 }, 850 }, 851 Valid: true, 852 }, 853 { 854 Row: Row{ 855 fields: []*sppb.StructType_Field{ 856 mkField("Col1", intType()), 857 mkField( 858 "Col2", 859 listType( 860 structType( 861 mkField("SubCol1", floatType()), 862 mkField("SubCol2", stringType()), 863 ), 864 ), 865 ), 866 }, 867 vals: []*proto3.Value{ 868 nullProto(), 869 nullProto(), 870 }, 871 }, 872 Valid: true, 873 }, 874 {}, 875 }, 876 fail: false, 877 }, 878 { 879 in: listProto( 880 listProto( 881 intProto(3), 882 listProto( 883 listProto(floatProto(3.14), stringProto("this")), 884 listProto(floatProto(0.57), stringProto("siht")), 885 ), 886 ), 887 listProto( 888 nullProto(), 889 nullProto(), 890 ), 891 nullProto(), 892 ), 893 t: listType( 894 structType( 895 mkField("Col1", intType()), 896 mkField( 897 "Col2", 898 listType( 899 structType( 900 mkField("SubCol1", floatType()), 901 mkField("SubCol2", stringType()), 902 ), 903 ), 904 ), 905 ), 906 ), 907 want: []*struct { 908 Col1 NullInt64 909 StructCol []*struct { 910 SubCol1 NullFloat64 911 SubCol2 string 912 } `spanner:"Col2"` 913 }{ 914 { 915 Col1: NullInt64{3, true}, 916 StructCol: []*struct { 917 SubCol1 NullFloat64 918 SubCol2 string 919 }{ 920 { 921 SubCol1: NullFloat64{3.14, true}, 922 SubCol2: "this", 923 }, 924 { 925 SubCol1: NullFloat64{0.57, true}, 926 SubCol2: "siht", 927 }, 928 }, 929 }, 930 { 931 Col1: NullInt64{}, 932 StructCol: []*struct { 933 SubCol1 NullFloat64 934 SubCol2 string 935 }(nil), 936 }, 937 nil, 938 }, 939 fail: false, 940 }, 941 // GenericColumnValue 942 {stringProto("abc"), stringType(), GenericColumnValue{stringType(), stringProto("abc")}, false}, 943 {nullProto(), stringType(), GenericColumnValue{stringType(), nullProto()}, false}, 944 // not actually valid (stringProto inside int list), but demonstrates pass-through. 945 { 946 in: listProto(intProto(5), nullProto(), stringProto("bcd")), 947 t: listType(intType()), 948 want: GenericColumnValue{ 949 Type: listType(intType()), 950 Value: listProto(intProto(5), nullProto(), stringProto("bcd")), 951 }, 952 fail: false, 953 }, 954 } { 955 gotp := reflect.New(reflect.TypeOf(test.want)) 956 if err := decodeValue(test.in, test.t, gotp.Interface()); err != nil { 957 if !test.fail { 958 t.Errorf("%d: cannot decode %v(%v): %v", i, test.in, test.t, err) 959 } 960 continue 961 } 962 if test.fail { 963 t.Errorf("%d: decoding %v(%v) succeeds unexpectedly, want error", i, test.in, test.t) 964 continue 965 } 966 got := reflect.Indirect(gotp).Interface() 967 if !testEqual(got, test.want) { 968 t.Errorf("%d: unexpected decoding result - got %v, want %v", i, got, test.want) 969 continue 970 } 971 } 972} 973 974// Test error cases for decodeValue. 975func TestDecodeValueErrors(t *testing.T) { 976 var s string 977 for i, test := range []struct { 978 in *proto3.Value 979 t *sppb.Type 980 v interface{} 981 }{ 982 {nullProto(), stringType(), nil}, 983 {nullProto(), stringType(), 1}, 984 {timeProto(t1), timeType(), &s}, 985 } { 986 err := decodeValue(test.in, test.t, test.v) 987 if err == nil { 988 t.Errorf("#%d: want error, got nil", i) 989 } 990 } 991} 992 993// Test NaN encoding/decoding. 994func TestNaN(t *testing.T) { 995 // Decode NaN value. 996 f := 0.0 997 nf := NullFloat64{} 998 // To float64 999 if err := decodeValue(floatProto(math.NaN()), floatType(), &f); err != nil { 1000 t.Errorf("decodeValue returns %q for %v, want nil", err, floatProto(math.NaN())) 1001 } 1002 if !math.IsNaN(f) { 1003 t.Errorf("f = %v, want %v", f, math.NaN()) 1004 } 1005 // To NullFloat64 1006 if err := decodeValue(floatProto(math.NaN()), floatType(), &nf); err != nil { 1007 t.Errorf("decodeValue returns %q for %v, want nil", err, floatProto(math.NaN())) 1008 } 1009 if !math.IsNaN(nf.Float64) || !nf.Valid { 1010 t.Errorf("f = %v, want %v", f, NullFloat64{math.NaN(), true}) 1011 } 1012 // Encode NaN value 1013 // From float64 1014 v, _, err := encodeValue(math.NaN()) 1015 if err != nil { 1016 t.Errorf("encodeValue returns %q for NaN, want nil", err) 1017 } 1018 x, ok := v.GetKind().(*proto3.Value_NumberValue) 1019 if !ok { 1020 t.Errorf("incorrect type for v.GetKind(): %T, want *proto3.Value_NumberValue", v.GetKind()) 1021 } 1022 if !math.IsNaN(x.NumberValue) { 1023 t.Errorf("x.NumberValue = %v, want %v", x.NumberValue, math.NaN()) 1024 } 1025 // From NullFloat64 1026 v, _, err = encodeValue(NullFloat64{math.NaN(), true}) 1027 if err != nil { 1028 t.Errorf("encodeValue returns %q for NaN, want nil", err) 1029 } 1030 x, ok = v.GetKind().(*proto3.Value_NumberValue) 1031 if !ok { 1032 t.Errorf("incorrect type for v.GetKind(): %T, want *proto3.Value_NumberValue", v.GetKind()) 1033 } 1034 if !math.IsNaN(x.NumberValue) { 1035 t.Errorf("x.NumberValue = %v, want %v", x.NumberValue, math.NaN()) 1036 } 1037} 1038 1039func TestGenericColumnValue(t *testing.T) { 1040 for _, test := range []struct { 1041 in GenericColumnValue 1042 want interface{} 1043 fail bool 1044 }{ 1045 {GenericColumnValue{stringType(), stringProto("abc")}, "abc", false}, 1046 {GenericColumnValue{stringType(), stringProto("abc")}, 5, true}, 1047 {GenericColumnValue{listType(intType()), listProto(intProto(91), nullProto(), intProto(87))}, []NullInt64{{91, true}, {}, {87, true}}, false}, 1048 {GenericColumnValue{intType(), intProto(42)}, GenericColumnValue{intType(), intProto(42)}, false}, // trippy! :-) 1049 } { 1050 gotp := reflect.New(reflect.TypeOf(test.want)) 1051 if err := test.in.Decode(gotp.Interface()); err != nil { 1052 if !test.fail { 1053 t.Errorf("cannot decode %v to %v: %v", test.in, test.want, err) 1054 } 1055 continue 1056 } 1057 if test.fail { 1058 t.Errorf("decoding %v to %v succeeds unexpectedly", test.in, test.want) 1059 } 1060 1061 // Test we can go backwards as well. 1062 v, err := newGenericColumnValue(test.want) 1063 if err != nil { 1064 t.Errorf("NewGenericColumnValue failed: %v", err) 1065 continue 1066 } 1067 if !testEqual(*v, test.in) { 1068 t.Errorf("unexpected encode result - got %v, want %v", v, test.in) 1069 } 1070 } 1071} 1072 1073func TestDecodeStruct(t *testing.T) { 1074 stype := &sppb.StructType{Fields: []*sppb.StructType_Field{ 1075 {Name: "Id", Type: stringType()}, 1076 {Name: "Time", Type: timeType()}, 1077 }} 1078 lv := listValueProto(stringProto("id"), timeProto(t1)) 1079 1080 type ( 1081 S1 struct { 1082 ID string 1083 Time time.Time 1084 } 1085 S2 struct { 1086 ID string 1087 Time string 1088 } 1089 ) 1090 var ( 1091 s1 S1 1092 s2 S2 1093 ) 1094 1095 for i, test := range []struct { 1096 ptr interface{} 1097 want interface{} 1098 fail bool 1099 }{ 1100 { 1101 ptr: &s1, 1102 want: &S1{ID: "id", Time: t1}, 1103 }, 1104 { 1105 ptr: &s2, 1106 fail: true, 1107 }, 1108 } { 1109 err := decodeStruct(stype, lv, test.ptr) 1110 if (err != nil) != test.fail { 1111 t.Errorf("#%d: got error %v, wanted fail: %v", i, err, test.fail) 1112 } 1113 if err == nil && !testEqual(test.ptr, test.want) { 1114 t.Errorf("#%d: got %+v, want %+v", i, test.ptr, test.want) 1115 } 1116 } 1117} 1118 1119func TestEncodeStructValueDynamicStructs(t *testing.T) { 1120 dynStructType := reflect.StructOf([]reflect.StructField{ 1121 {Name: "A", Type: reflect.TypeOf(0), Tag: `spanner:"a"`}, 1122 {Name: "B", Type: reflect.TypeOf(""), Tag: `spanner:"b"`}, 1123 }) 1124 dynNullableStructType := reflect.PtrTo(dynStructType) 1125 dynStructArrType := reflect.SliceOf(dynStructType) 1126 dynNullableStructArrType := reflect.SliceOf(dynNullableStructType) 1127 1128 dynStructValue := reflect.New(dynStructType) 1129 dynStructValue.Elem().Field(0).SetInt(10) 1130 dynStructValue.Elem().Field(1).SetString("abc") 1131 1132 dynStructArrValue := reflect.MakeSlice(dynNullableStructArrType, 2, 2) 1133 dynStructArrValue.Index(0).Set(reflect.Zero(dynNullableStructType)) 1134 dynStructArrValue.Index(1).Set(dynStructValue) 1135 1136 structProtoType := structType( 1137 mkField("a", intType()), 1138 mkField("b", stringType())) 1139 1140 arrProtoType := listType(structProtoType) 1141 1142 for _, test := range []encodeTest{ 1143 { 1144 "Dynanic non-NULL struct value.", 1145 dynStructValue.Elem().Interface(), 1146 listProto(intProto(10), stringProto("abc")), 1147 structProtoType, 1148 }, 1149 { 1150 "Dynanic NULL struct value.", 1151 reflect.Zero(dynNullableStructType).Interface(), 1152 nullProto(), 1153 structProtoType, 1154 }, 1155 { 1156 "Empty array of dynamic structs.", 1157 reflect.MakeSlice(dynStructArrType, 0, 0).Interface(), 1158 listProto([]*proto3.Value{}...), 1159 arrProtoType, 1160 }, 1161 { 1162 "NULL array of non-NULL-able dynamic structs.", 1163 reflect.Zero(dynStructArrType).Interface(), 1164 nullProto(), 1165 arrProtoType, 1166 }, 1167 { 1168 "NULL array of NULL-able(nil) dynamic structs.", 1169 reflect.Zero(dynNullableStructArrType).Interface(), 1170 nullProto(), 1171 arrProtoType, 1172 }, 1173 { 1174 "Array containing NULL(nil) dynamic-typed struct elements.", 1175 dynStructArrValue.Interface(), 1176 listProto( 1177 nullProto(), 1178 listProto(intProto(10), stringProto("abc"))), 1179 arrProtoType, 1180 }, 1181 } { 1182 encodeStructValue(test, t) 1183 } 1184} 1185 1186func TestEncodeStructValueEmptyStruct(t *testing.T) { 1187 emptyListValue := listProto([]*proto3.Value{}...) 1188 emptyStructType := structType([]*sppb.StructType_Field{}...) 1189 emptyStruct := struct{}{} 1190 nullEmptyStruct := (*struct{})(nil) 1191 1192 dynamicEmptyStructType := reflect.StructOf(make([]reflect.StructField, 0, 0)) 1193 dynamicStructArrType := reflect.SliceOf(reflect.PtrTo((dynamicEmptyStructType))) 1194 1195 dynamicEmptyStruct := reflect.New(dynamicEmptyStructType) 1196 dynamicNullEmptyStruct := reflect.Zero(reflect.PtrTo(dynamicEmptyStructType)) 1197 1198 dynamicStructArrValue := reflect.MakeSlice(dynamicStructArrType, 2, 2) 1199 dynamicStructArrValue.Index(0).Set(dynamicNullEmptyStruct) 1200 dynamicStructArrValue.Index(1).Set(dynamicEmptyStruct) 1201 1202 for _, test := range []encodeTest{ 1203 { 1204 "Go empty struct.", 1205 emptyStruct, 1206 emptyListValue, 1207 emptyStructType, 1208 }, 1209 { 1210 "Dynamic empty struct.", 1211 dynamicEmptyStruct.Interface(), 1212 emptyListValue, 1213 emptyStructType, 1214 }, 1215 { 1216 "Go NULL empty struct.", 1217 nullEmptyStruct, 1218 nullProto(), 1219 emptyStructType, 1220 }, 1221 { 1222 "Dynamic NULL empty struct.", 1223 dynamicNullEmptyStruct.Interface(), 1224 nullProto(), 1225 emptyStructType, 1226 }, 1227 { 1228 "Non-empty array of dynamic NULL and non-NULL empty structs.", 1229 dynamicStructArrValue.Interface(), 1230 listProto(nullProto(), emptyListValue), 1231 listType(emptyStructType), 1232 }, 1233 { 1234 "Non-empty array of nullable empty structs.", 1235 []*struct{}{nullEmptyStruct, &emptyStruct}, 1236 listProto(nullProto(), emptyListValue), 1237 listType(emptyStructType), 1238 }, 1239 { 1240 "Empty array of empty struct.", 1241 []struct{}{}, 1242 emptyListValue, 1243 listType(emptyStructType), 1244 }, 1245 { 1246 "Null array of empty structs.", 1247 []struct{}(nil), 1248 nullProto(), 1249 listType(emptyStructType), 1250 }, 1251 } { 1252 encodeStructValue(test, t) 1253 } 1254} 1255 1256func TestEncodeStructValueMixedStructTypes(t *testing.T) { 1257 type staticStruct struct { 1258 F int `spanner:"fStatic"` 1259 } 1260 s1 := staticStruct{10} 1261 s2 := (*staticStruct)(nil) 1262 1263 var f float64 1264 dynStructType := reflect.StructOf([]reflect.StructField{ 1265 {Name: "A", Type: reflect.TypeOf(f), Tag: `spanner:"fDynamic"`}, 1266 }) 1267 s3 := reflect.New(dynStructType) 1268 s3.Elem().Field(0).SetFloat(3.14) 1269 1270 for _, test := range []encodeTest{ 1271 { 1272 "'struct' with static and dynamic *struct, []*struct, []struct fields", 1273 struct { 1274 A []staticStruct 1275 B []*staticStruct 1276 C interface{} 1277 }{ 1278 []staticStruct{s1, s1}, 1279 []*staticStruct{&s1, s2}, 1280 s3.Interface(), 1281 }, 1282 listProto( 1283 listProto(listProto(intProto(10)), listProto(intProto(10))), 1284 listProto(listProto(intProto(10)), nullProto()), 1285 listProto(floatProto(3.14))), 1286 structType( 1287 mkField("A", listType(structType(mkField("fStatic", intType())))), 1288 mkField("B", listType(structType(mkField("fStatic", intType())))), 1289 mkField("C", structType(mkField("fDynamic", floatType())))), 1290 }, 1291 } { 1292 encodeStructValue(test, t) 1293 } 1294} 1295 1296func TestBindParamsDynamic(t *testing.T) { 1297 // Verify Statement.bindParams generates correct values and types. 1298 st := Statement{ 1299 SQL: "SELECT id from t_foo WHERE col = @var", 1300 Params: map[string]interface{}{"var": nil}, 1301 } 1302 want := &sppb.ExecuteSqlRequest{ 1303 Params: &proto3.Struct{ 1304 Fields: map[string]*proto3.Value{"var": nil}, 1305 }, 1306 ParamTypes: map[string]*sppb.Type{"var": nil}, 1307 } 1308 var ( 1309 t1, _ = time.Parse(time.RFC3339Nano, "2016-11-15T15:04:05.999999999Z") 1310 // Boundaries 1311 t2, _ = time.Parse(time.RFC3339Nano, "0001-01-01T00:00:00.000000000Z") 1312 ) 1313 dynamicStructType := reflect.StructOf([]reflect.StructField{ 1314 {Name: "A", Type: reflect.TypeOf(t1), Tag: `spanner:"field"`}, 1315 {Name: "B", Type: reflect.TypeOf(3.14), Tag: `spanner:""`}, 1316 }) 1317 dynamicStructArrType := reflect.SliceOf(reflect.PtrTo(dynamicStructType)) 1318 dynamicEmptyStructType := reflect.StructOf(make([]reflect.StructField, 0, 0)) 1319 1320 dynamicStructTypeProto := structType( 1321 mkField("field", timeType()), 1322 mkField("", floatType())) 1323 1324 s3 := reflect.New(dynamicStructType) 1325 s3.Elem().Field(0).Set(reflect.ValueOf(t1)) 1326 s3.Elem().Field(1).SetFloat(1.4) 1327 1328 s4 := reflect.New(dynamicStructType) 1329 s4.Elem().Field(0).Set(reflect.ValueOf(t2)) 1330 s4.Elem().Field(1).SetFloat(-13.3) 1331 1332 dynamicStructArrayVal := reflect.MakeSlice(dynamicStructArrType, 2, 2) 1333 dynamicStructArrayVal.Index(0).Set(s3) 1334 dynamicStructArrayVal.Index(1).Set(s4) 1335 1336 for _, test := range []struct { 1337 val interface{} 1338 wantField *proto3.Value 1339 wantType *sppb.Type 1340 }{ 1341 { 1342 s3.Interface(), 1343 listProto(timeProto(t1), floatProto(1.4)), 1344 structType( 1345 mkField("field", timeType()), 1346 mkField("", floatType())), 1347 }, 1348 { 1349 reflect.Zero(reflect.PtrTo(dynamicEmptyStructType)).Interface(), 1350 nullProto(), 1351 structType([]*sppb.StructType_Field{}...), 1352 }, 1353 { 1354 dynamicStructArrayVal.Interface(), 1355 listProto( 1356 listProto(timeProto(t1), floatProto(1.4)), 1357 listProto(timeProto(t2), floatProto(-13.3))), 1358 listType(dynamicStructTypeProto), 1359 }, 1360 { 1361 []*struct { 1362 F1 time.Time `spanner:"field"` 1363 F2 float64 `spanner:""` 1364 }{ 1365 nil, 1366 {t1, 1.4}, 1367 }, 1368 listProto( 1369 nullProto(), 1370 listProto(timeProto(t1), floatProto(1.4))), 1371 listType(dynamicStructTypeProto), 1372 }, 1373 } { 1374 st.Params["var"] = test.val 1375 want.Params.Fields["var"] = test.wantField 1376 want.ParamTypes["var"] = test.wantType 1377 gotParams, gotParamTypes, gotErr := st.convertParams() 1378 if gotErr != nil { 1379 t.Error(gotErr) 1380 continue 1381 } 1382 gotParamField := gotParams.Fields["var"] 1383 if !proto.Equal(gotParamField, test.wantField) { 1384 // handle NaN 1385 if test.wantType.Code == floatType().Code && proto.MarshalTextString(gotParamField) == proto.MarshalTextString(test.wantField) { 1386 continue 1387 } 1388 t.Errorf("%#v: got %v, want %v\n", test.val, gotParamField, test.wantField) 1389 } 1390 gotParamType := gotParamTypes["var"] 1391 if !proto.Equal(gotParamType, test.wantType) { 1392 t.Errorf("%#v: got %v, want %v\n", test.val, gotParamType, test.wantField) 1393 } 1394 } 1395} 1396