github.com/Ali-iotechsys/sqlboiler/v4@v4.0.0-20221208124957-6aec9a5f1f71/queries/reflect_test.go (about) 1 package queries 2 3 import ( 4 "bytes" 5 "context" 6 "database/sql" 7 "database/sql/driver" 8 "fmt" 9 "reflect" 10 "strconv" 11 "strings" 12 "testing" 13 "time" 14 15 "github.com/volatiletech/sqlboiler/v4/drivers" 16 "github.com/volatiletech/null/v8" 17 18 "github.com/DATA-DOG/go-sqlmock" 19 ) 20 21 func bin64(i uint64) string { 22 str := strconv.FormatUint(i, 2) 23 pad := 64 - len(str) 24 if pad > 0 { 25 str = strings.Repeat("0", pad) + str 26 } 27 28 var newStr string 29 for i := 0; i < len(str); i += 8 { 30 if i != 0 { 31 newStr += " " 32 } 33 newStr += str[i : i+8] 34 } 35 36 return newStr 37 } 38 39 type mockRowMaker struct { 40 int 41 rows []driver.Value 42 } 43 44 func TestBindStruct(t *testing.T) { 45 t.Parallel() 46 47 testResults := struct { 48 ID int 49 Name string `boil:"test"` 50 }{} 51 52 query := &Query{ 53 from: []string{"fun"}, 54 dialect: &drivers.Dialect{LQ: '"', RQ: '"', UseIndexPlaceholders: true}, 55 } 56 57 db, mock, err := sqlmock.New() 58 if err != nil { 59 t.Error(err) 60 } 61 62 ret := sqlmock.NewRows([]string{"id", "test"}) 63 ret.AddRow(driver.Value(int64(35)), driver.Value("pat")) 64 ret.AddRow(driver.Value(int64(65)), driver.Value("hat")) 65 mock.ExpectQuery(`SELECT \* FROM "fun";`).WillReturnRows(ret) 66 67 err = query.Bind(nil, db, &testResults) 68 if err != nil { 69 t.Error(err) 70 } 71 72 if id := testResults.ID; id != 35 { 73 t.Error("wrong ID:", id) 74 } 75 if name := testResults.Name; name != "pat" { 76 t.Error("wrong name:", name) 77 } 78 79 if err := mock.ExpectationsWereMet(); err != nil { 80 t.Error(err) 81 } 82 } 83 84 func TestBindSlice(t *testing.T) { 85 t.Parallel() 86 87 testResults := []struct { 88 ID int 89 Name string `boil:"test"` 90 }{} 91 92 query := &Query{ 93 from: []string{"fun"}, 94 dialect: &drivers.Dialect{LQ: '"', RQ: '"', UseIndexPlaceholders: true}, 95 } 96 97 db, mock, err := sqlmock.New() 98 if err != nil { 99 t.Error(err) 100 } 101 102 ret := sqlmock.NewRows([]string{"id", "test"}) 103 ret.AddRow(driver.Value(int64(35)), driver.Value("pat")) 104 ret.AddRow(driver.Value(int64(12)), driver.Value("cat")) 105 mock.ExpectQuery(`SELECT \* FROM "fun";`).WillReturnRows(ret) 106 107 err = query.Bind(nil, db, &testResults) 108 if err != nil { 109 t.Error(err) 110 } 111 112 if len(testResults) != 2 { 113 t.Fatal("wrong number of results:", len(testResults)) 114 } 115 if id := testResults[0].ID; id != 35 { 116 t.Error("wrong ID:", id) 117 } 118 if name := testResults[0].Name; name != "pat" { 119 t.Error("wrong name:", name) 120 } 121 122 if id := testResults[1].ID; id != 12 { 123 t.Error("wrong ID:", id) 124 } 125 if name := testResults[1].Name; name != "cat" { 126 t.Error("wrong name:", name) 127 } 128 129 if err := mock.ExpectationsWereMet(); err != nil { 130 t.Error(err) 131 } 132 } 133 134 func TestBindPtrSlice(t *testing.T) { 135 t.Parallel() 136 137 testResults := []*struct { 138 ID int 139 Name string `boil:"test"` 140 }{} 141 142 query := &Query{ 143 from: []string{"fun"}, 144 dialect: &drivers.Dialect{LQ: '"', RQ: '"', UseIndexPlaceholders: true}, 145 } 146 147 db, mock, err := sqlmock.New() 148 if err != nil { 149 t.Error(err) 150 } 151 152 ret := sqlmock.NewRows([]string{"id", "test"}) 153 ret.AddRow(driver.Value(int64(35)), driver.Value("pat")) 154 ret.AddRow(driver.Value(int64(12)), driver.Value("cat")) 155 mock.ExpectQuery(`SELECT \* FROM "fun";`).WillReturnRows(ret) 156 157 err = query.Bind(context.Background(), db, &testResults) 158 if err != nil { 159 t.Error(err) 160 } 161 162 if len(testResults) != 2 { 163 t.Fatal("wrong number of results:", len(testResults)) 164 } 165 if id := testResults[0].ID; id != 35 { 166 t.Error("wrong ID:", id) 167 } 168 if name := testResults[0].Name; name != "pat" { 169 t.Error("wrong name:", name) 170 } 171 172 if id := testResults[1].ID; id != 12 { 173 t.Error("wrong ID:", id) 174 } 175 if name := testResults[1].Name; name != "cat" { 176 t.Error("wrong name:", name) 177 } 178 179 if err := mock.ExpectationsWereMet(); err != nil { 180 t.Error(err) 181 } 182 } 183 184 func testMakeMapping(byt ...byte) uint64 { 185 var x uint64 186 for i, b := range byt { 187 x |= uint64(b) << (uint(i) * 8) 188 } 189 x |= uint64(255) << uint(len(byt)*8) 190 return x 191 } 192 193 func TestMakeStructMapping(t *testing.T) { 194 t.Parallel() 195 196 var testStruct = struct { 197 LastName string `boil:"different"` 198 AwesomeName string `boil:"awesome_name"` 199 Face string `boil:"-"` 200 Nose string 201 202 Nested struct { 203 LastName string `boil:"different"` 204 AwesomeName string `boil:"awesome_name"` 205 Face string `boil:"-"` 206 Nose string 207 208 Nested2 struct { 209 Nose string 210 } `boil:",bind"` 211 } `boil:",bind"` 212 }{} 213 214 got := MakeStructMapping(reflect.TypeOf(testStruct)) 215 216 expectMap := map[string]uint64{ 217 "different": testMakeMapping(0), 218 "awesome_name": testMakeMapping(1), 219 "nose": testMakeMapping(3), 220 "nested.different": testMakeMapping(4, 0), 221 "nested.awesome_name": testMakeMapping(4, 1), 222 "nested.nose": testMakeMapping(4, 3), 223 "nested.nested2.nose": testMakeMapping(4, 4, 0), 224 } 225 226 for expName, expVal := range expectMap { 227 gotVal, ok := got[expName] 228 if !ok { 229 t.Errorf("%s) had no value", expName) 230 continue 231 } 232 233 if gotVal != expVal { 234 t.Errorf("%s) wrong value,\nwant: %x (%s)\ngot: %x (%s)", expName, expVal, bin64(expVal), gotVal, bin64(gotVal)) 235 } 236 } 237 } 238 239 func TestPtrFromMapping(t *testing.T) { 240 t.Parallel() 241 242 type NestedPtrs struct { 243 Int int 244 IntP *int 245 NestedPtrsP *NestedPtrs 246 } 247 248 val := &NestedPtrs{ 249 Int: 5, 250 IntP: new(int), 251 NestedPtrsP: &NestedPtrs{ 252 Int: 6, 253 IntP: new(int), 254 }, 255 } 256 257 v := ptrFromMapping(reflect.Indirect(reflect.ValueOf(val)), testMakeMapping(0), true) 258 if got := *v.Interface().(*int); got != 5 { 259 t.Error("flat int was wrong:", got) 260 } 261 v = ptrFromMapping(reflect.Indirect(reflect.ValueOf(val)), testMakeMapping(1), true) 262 if got := *v.Interface().(*int); got != 0 { 263 t.Error("flat pointer was wrong:", got) 264 } 265 v = ptrFromMapping(reflect.Indirect(reflect.ValueOf(val)), testMakeMapping(2, 0), true) 266 if got := *v.Interface().(*int); got != 6 { 267 t.Error("nested int was wrong:", got) 268 } 269 v = ptrFromMapping(reflect.Indirect(reflect.ValueOf(val)), testMakeMapping(2, 1), true) 270 if got := *v.Interface().(*int); got != 0 { 271 t.Error("nested pointer was wrong:", got) 272 } 273 } 274 275 func TestValuesFromMapping(t *testing.T) { 276 t.Parallel() 277 278 type NestedPtrs struct { 279 Int int 280 IntP *int 281 NestedPtrsP *NestedPtrs 282 } 283 284 val := &NestedPtrs{ 285 Int: 5, 286 IntP: new(int), 287 NestedPtrsP: &NestedPtrs{ 288 Int: 6, 289 IntP: new(int), 290 }, 291 } 292 mapping := []uint64{testMakeMapping(0), testMakeMapping(1), testMakeMapping(2, 0), testMakeMapping(2, 1), 0} 293 v := ValuesFromMapping(reflect.Indirect(reflect.ValueOf(val)), mapping) 294 295 if got := v[0].(int); got != 5 { 296 t.Error("flat int was wrong:", got) 297 } 298 if got := v[1].(int); got != 0 { 299 t.Error("flat pointer was wrong:", got) 300 } 301 if got := v[2].(int); got != 6 { 302 t.Error("nested int was wrong:", got) 303 } 304 if got := v[3].(int); got != 0 { 305 t.Error("nested pointer was wrong:", got) 306 } 307 if got := *v[4].(*interface{}); got != nil { 308 t.Error("nil pointer was not be ignored:", got) 309 } 310 } 311 312 func TestPtrsFromMapping(t *testing.T) { 313 t.Parallel() 314 315 type NestedPtrs struct { 316 Int int 317 IntP *int 318 NestedPtrsP *NestedPtrs 319 } 320 321 val := &NestedPtrs{ 322 Int: 5, 323 IntP: new(int), 324 NestedPtrsP: &NestedPtrs{ 325 Int: 6, 326 IntP: new(int), 327 }, 328 } 329 330 mapping := []uint64{testMakeMapping(0), testMakeMapping(1), testMakeMapping(2, 0), testMakeMapping(2, 1)} 331 v := PtrsFromMapping(reflect.Indirect(reflect.ValueOf(val)), mapping) 332 333 if got := *v[0].(*int); got != 5 { 334 t.Error("flat int was wrong:", got) 335 } 336 if got := *v[1].(*int); got != 0 { 337 t.Error("flat pointer was wrong:", got) 338 } 339 if got := *v[2].(*int); got != 6 { 340 t.Error("nested int was wrong:", got) 341 } 342 if got := *v[3].(*int); got != 0 { 343 t.Error("nested pointer was wrong:", got) 344 } 345 } 346 347 func TestGetBoilTag(t *testing.T) { 348 t.Parallel() 349 350 type TestStruct struct { 351 FirstName string `boil:"test_one,bind"` 352 LastName string `boil:"test_two"` 353 MiddleName string `boil:"middle_name,bind"` 354 AwesomeName string `boil:"awesome_name"` 355 Age string `boil:",bind"` 356 Face string `boil:"-"` 357 Nose string 358 } 359 360 var structFields []reflect.StructField 361 typ := reflect.TypeOf(TestStruct{}) 362 removeOk := func(thing reflect.StructField, ok bool) reflect.StructField { 363 if !ok { 364 panic("Exploded") 365 } 366 return thing 367 } 368 structFields = append(structFields, removeOk(typ.FieldByName("FirstName"))) 369 structFields = append(structFields, removeOk(typ.FieldByName("LastName"))) 370 structFields = append(structFields, removeOk(typ.FieldByName("MiddleName"))) 371 structFields = append(structFields, removeOk(typ.FieldByName("AwesomeName"))) 372 structFields = append(structFields, removeOk(typ.FieldByName("Age"))) 373 structFields = append(structFields, removeOk(typ.FieldByName("Face"))) 374 structFields = append(structFields, removeOk(typ.FieldByName("Nose"))) 375 376 expect := []struct { 377 Name string 378 Recurse bool 379 }{ 380 {"test_one", true}, 381 {"test_two", false}, 382 {"middle_name", true}, 383 {"awesome_name", false}, 384 {"", true}, 385 {"-", false}, 386 {"", false}, 387 } 388 for i, s := range structFields { 389 name, recurse := getBoilTag(s) 390 if expect[i].Name != name { 391 t.Errorf("Invalid name, expect %q, got %q", expect[i].Name, name) 392 } 393 if expect[i].Recurse != recurse { 394 t.Errorf("Invalid recurse, expect %v, got %v", !recurse, recurse) 395 } 396 } 397 } 398 399 func TestBindChecks(t *testing.T) { 400 t.Parallel() 401 402 type useless struct { 403 } 404 405 var tests = []struct { 406 BKind bindKind 407 Fail bool 408 Obj interface{} 409 }{ 410 {BKind: kindStruct, Fail: false, Obj: &useless{}}, 411 {BKind: kindSliceStruct, Fail: false, Obj: &[]useless{}}, 412 {BKind: kindPtrSliceStruct, Fail: false, Obj: &[]*useless{}}, 413 {Fail: true, Obj: 5}, 414 {Fail: true, Obj: useless{}}, 415 {Fail: true, Obj: []useless{}}, 416 } 417 418 for i, test := range tests { 419 str, sli, bk, err := bindChecks(test.Obj) 420 421 if err != nil { 422 if !test.Fail { 423 t.Errorf("%d) should not fail, got: %v", i, err) 424 } 425 continue 426 } else if test.Fail { 427 t.Errorf("%d) should fail, got: %v", i, bk) 428 continue 429 } 430 431 if s := str.Kind(); s != reflect.Struct { 432 t.Error("struct kind was wrong:", s) 433 } 434 if test.BKind != kindStruct { 435 if s := sli.Kind(); s != reflect.Slice { 436 t.Error("slice kind was wrong:", s) 437 } 438 } 439 } 440 } 441 442 func TestBindSingular(t *testing.T) { 443 t.Parallel() 444 445 testResults := struct { 446 ID int 447 Name string `boil:"test"` 448 }{} 449 450 query := &Query{ 451 from: []string{"fun"}, 452 dialect: &drivers.Dialect{LQ: '"', RQ: '"', UseIndexPlaceholders: true}, 453 } 454 455 db, mock, err := sqlmock.New() 456 if err != nil { 457 t.Error(err) 458 } 459 460 ret := sqlmock.NewRows([]string{"id", "test"}) 461 ret.AddRow(driver.Value(int64(35)), driver.Value("pat")) 462 mock.ExpectQuery(`SELECT \* FROM "fun";`).WillReturnRows(ret) 463 464 err = query.Bind(nil, db, &testResults) 465 if err != nil { 466 t.Error(err) 467 } 468 469 if id := testResults.ID; id != 35 { 470 t.Error("wrong ID:", id) 471 } 472 if name := testResults.Name; name != "pat" { 473 t.Error("wrong name:", name) 474 } 475 476 if err := mock.ExpectationsWereMet(); err != nil { 477 t.Error(err) 478 } 479 } 480 481 func TestBind_InnerJoin(t *testing.T) { 482 t.Parallel() 483 484 testResults := []*struct { 485 Happy struct { 486 ID int `boil:"identifier"` 487 } `boil:",bind"` 488 Fun struct { 489 ID int `boil:"id"` 490 } `boil:",bind"` 491 }{} 492 493 query := &Query{ 494 from: []string{"fun"}, 495 joins: []join{{kind: JoinInner, clause: "happy as h on fun.id = h.fun_id"}}, 496 dialect: &drivers.Dialect{LQ: '"', RQ: '"', UseIndexPlaceholders: true}, 497 } 498 499 db, mock, err := sqlmock.New() 500 if err != nil { 501 t.Error(err) 502 } 503 504 ret := sqlmock.NewRows([]string{"id"}) 505 ret.AddRow(driver.Value(int64(10))) 506 ret.AddRow(driver.Value(int64(11))) 507 mock.ExpectQuery(`SELECT "fun"\.\* FROM "fun" INNER JOIN happy as h on fun.id = h.fun_id;`).WillReturnRows(ret) 508 509 err = query.Bind(nil, db, &testResults) 510 if err != nil { 511 t.Error(err) 512 } 513 514 if len(testResults) != 2 { 515 t.Fatal("wrong number of results:", len(testResults)) 516 } 517 if id := testResults[0].Happy.ID; id != 0 { 518 t.Error("wrong ID:", id) 519 } 520 if id := testResults[0].Fun.ID; id != 10 { 521 t.Error("wrong ID:", id) 522 } 523 524 if id := testResults[1].Happy.ID; id != 0 { 525 t.Error("wrong ID:", id) 526 } 527 if id := testResults[1].Fun.ID; id != 11 { 528 t.Error("wrong ID:", id) 529 } 530 531 if err := mock.ExpectationsWereMet(); err != nil { 532 t.Error(err) 533 } 534 } 535 536 func TestBind_InnerJoinSelect(t *testing.T) { 537 t.Parallel() 538 539 testResults := []*struct { 540 Happy struct { 541 ID int 542 } `boil:"h,bind"` 543 Fun struct { 544 ID int 545 } `boil:",bind"` 546 }{} 547 548 query := &Query{ 549 dialect: &drivers.Dialect{LQ: '"', RQ: '"', UseIndexPlaceholders: true}, 550 selectCols: []string{"fun.id", "h.id"}, 551 from: []string{"fun"}, 552 joins: []join{{kind: JoinInner, clause: "happy as h on fun.happy_id = h.id"}}, 553 } 554 555 db, mock, err := sqlmock.New() 556 if err != nil { 557 t.Error(err) 558 } 559 560 ret := sqlmock.NewRows([]string{"fun.id", "h.id"}) 561 ret.AddRow(driver.Value(int64(10)), driver.Value(int64(11))) 562 ret.AddRow(driver.Value(int64(12)), driver.Value(int64(13))) 563 mock.ExpectQuery(`SELECT "fun"."id" as "fun.id", "h"."id" as "h.id" FROM "fun" INNER JOIN happy as h on fun.happy_id = h.id;`).WillReturnRows(ret) 564 565 err = query.Bind(nil, db, &testResults) 566 if err != nil { 567 t.Error(err) 568 } 569 570 if len(testResults) != 2 { 571 t.Fatal("wrong number of results:", len(testResults)) 572 } 573 if id := testResults[0].Happy.ID; id != 11 { 574 t.Error("wrong ID:", id) 575 } 576 if id := testResults[0].Fun.ID; id != 10 { 577 t.Error("wrong ID:", id) 578 } 579 580 if id := testResults[1].Happy.ID; id != 13 { 581 t.Error("wrong ID:", id) 582 } 583 if id := testResults[1].Fun.ID; id != 12 { 584 t.Error("wrong ID:", id) 585 } 586 587 if err := mock.ExpectationsWereMet(); err != nil { 588 t.Error(err) 589 } 590 } 591 592 func TestEqual(t *testing.T) { 593 t.Parallel() 594 595 now := time.Now() 596 597 tests := []struct { 598 A interface{} 599 B interface{} 600 Want bool 601 }{ 602 {A: int(5), B: int(5), Want: true}, 603 {A: int(5), B: int(6), Want: false}, 604 {A: int(5), B: int32(5), Want: true}, 605 {A: []byte("hello"), B: []byte("hello"), Want: true}, 606 {A: []byte("hello"), B: []byte("world"), Want: false}, 607 {A: "hello", B: sql.NullString{String: "hello", Valid: true}, Want: true}, 608 {A: "hello", B: sql.NullString{Valid: false}, Want: false}, 609 {A: now, B: now, Want: true}, 610 {A: now, B: now.Add(time.Hour), Want: false}, 611 {A: null.Uint64From(uint64(9223372036854775808)), B: uint64(9223372036854775808), Want: true}, 612 {A: null.Uint64From(uint64(9223372036854775808)), B: uint64(9223372036854775809), Want: false}, 613 } 614 615 for i, test := range tests { 616 if got := Equal(test.A, test.B); got != test.Want { 617 t.Errorf("%d) compare %#v and %#v resulted in wrong value, want: %t, got %t", i, test.A, test.B, test.Want, got) 618 } 619 } 620 } 621 622 func TestAssignBytes(t *testing.T) { 623 t.Parallel() 624 625 var dst []byte 626 var src = []byte("hello") 627 628 Assign(&dst, src) 629 if !bytes.Equal(dst, src) { 630 t.Error("bytes were not equal!") 631 } 632 } 633 634 func TestAssignScanValue(t *testing.T) { 635 t.Parallel() 636 637 var nsDst sql.NullString 638 var nsSrc sql.NullString 639 640 nsSrc.String = "hello" 641 nsSrc.Valid = true 642 643 Assign(&nsDst, nsSrc) 644 645 if !nsDst.Valid { 646 t.Error("n was still null") 647 } 648 if nsDst.String != "hello" { 649 t.Error("assignment did not occur") 650 } 651 652 var niDst sql.NullInt64 653 var niSrc sql.NullInt64 654 655 niSrc.Valid = true 656 niSrc.Int64 = 5 657 658 Assign(&niDst, niSrc) 659 660 if !niDst.Valid { 661 t.Error("n was still null") 662 } 663 if niDst.Int64 != 5 { 664 t.Error("assignment did not occur") 665 } 666 } 667 668 func TestAssignScanNoValue(t *testing.T) { 669 t.Parallel() 670 671 var ns sql.NullString 672 s := "hello" 673 674 Assign(&ns, s) 675 676 if !ns.Valid { 677 t.Error("n was still null") 678 } 679 if ns.String != "hello" { 680 t.Error("assignment did not occur") 681 } 682 683 var niDst sql.NullInt64 684 i := 5 685 686 Assign(&niDst, i) 687 688 if !niDst.Valid { 689 t.Error("n was still null") 690 } 691 if niDst.Int64 != 5 { 692 t.Error("assignment did not occur") 693 } 694 } 695 696 func TestAssignNoScanValue(t *testing.T) { 697 t.Parallel() 698 699 var ns sql.NullString 700 var s string 701 702 ns.String = "hello" 703 ns.Valid = true 704 Assign(&s, ns) 705 706 if s != "hello" { 707 t.Error("assignment did not occur") 708 } 709 710 var ni sql.NullInt64 711 var i int 712 713 ni.Int64 = 5 714 ni.Valid = true 715 Assign(&i, ni) 716 717 if i != 5 { 718 t.Error("assignment did not occur") 719 } 720 } 721 722 func TestAssignNil(t *testing.T) { 723 t.Parallel() 724 725 var ns sql.NullString 726 s := "hello" 727 728 Assign(&s, ns) 729 if s != "" { 730 t.Errorf("should have assigned a zero value: %q", s) 731 } 732 } 733 734 func TestAssignPanic(t *testing.T) { 735 t.Parallel() 736 737 defer func() { 738 if r := recover(); r == nil { 739 t.Error("expected a panic") 740 } 741 }() 742 743 var aint, bint int 744 Assign(&aint, bint) 745 } 746 747 type nullTime struct { 748 Time time.Time 749 Valid bool 750 } 751 752 func (t *nullTime) Scan(value interface{}) error { 753 var err error 754 switch x := value.(type) { 755 case time.Time: 756 t.Time = x 757 case nil: 758 t.Valid = false 759 return nil 760 default: 761 err = fmt.Errorf("cannot scan type %T into nullTime: %v", value, value) 762 } 763 t.Valid = err == nil 764 return err 765 } 766 767 // Value implements the driver Valuer interface. 768 func (t nullTime) Value() (driver.Value, error) { 769 if !t.Valid { 770 return nil, nil 771 } 772 return t.Time, nil 773 } 774 775 func TestMustTime(t *testing.T) { 776 t.Parallel() 777 778 var nt nullTime 779 780 if !MustTime(nt).IsZero() { 781 t.Error("should be zero") 782 } 783 784 now := time.Now() 785 786 nt.Valid = true 787 nt.Time = now 788 789 if !MustTime(nt).Equal(now) { 790 t.Error("time was wrong") 791 } 792 } 793 794 func TestMustTimePanic(t *testing.T) { 795 t.Parallel() 796 797 defer func() { 798 if r := recover(); r == nil { 799 t.Error("it should have panic'd") 800 } 801 }() 802 803 var ns sql.NullString 804 ns.Valid = true 805 ns.String = "hello" 806 MustTime(ns) 807 } 808 809 func TestIsValuerNil(t *testing.T) { 810 t.Parallel() 811 812 var ns sql.NullString 813 if !IsValuerNil(ns) { 814 t.Error("it should be nil") 815 } 816 817 ns.Valid = true 818 if IsValuerNil(ns) { 819 t.Error("it should not be nil") 820 } 821 } 822 823 func TestSetScanner(t *testing.T) { 824 t.Parallel() 825 826 var ns sql.NullString 827 SetScanner(&ns, "hello") 828 829 if !ns.Valid { 830 t.Error("it should not be null") 831 } 832 if ns.String != "hello" { 833 t.Error("it's value should have been hello") 834 } 835 } 836 837 func TestSetScannerPanic(t *testing.T) { 838 t.Parallel() 839 840 defer func() { 841 if r := recover(); r == nil { 842 t.Error("it should have panic'd") 843 } 844 }() 845 846 var ns nullTime 847 SetScanner(&ns, "hello") 848 } 849 850 func TestUnTitleCase(t *testing.T) { 851 t.Parallel() 852 853 tests := []struct { 854 In string 855 Out string 856 }{ 857 {"HelloThere", "hello_there"}, 858 {"", ""}, 859 {"AA", "aa"}, 860 {"FunID", "fun_id"}, 861 {"UID", "uid"}, 862 {"GUID", "guid"}, 863 {"UID", "uid"}, 864 {"UUID", "uuid"}, 865 {"SSN", "ssn"}, 866 {"TZ", "tz"}, 867 {"ThingGUID", "thing_guid"}, 868 {"GUIDThing", "guid_thing"}, 869 {"ThingGUIDThing", "thing_guid_thing"}, 870 {"ID", "id"}, 871 {"GVZXC", "gvzxc"}, 872 {"IDTRGBID", "id_trgb_id"}, 873 {"ThingZXCStuffVXZ", "thing_zxc_stuff_vxz"}, 874 {"ZXCThingVXZStuff", "zxc_thing_vxz_stuff"}, 875 {"ZXCVDF9C9Hello9", "zxcvdf9_c9_hello9"}, 876 {"ID9UID911GUID9E9", "id9_uid911_guid9_e9"}, 877 {"ZXCVDF0C0Hello0", "zxcvdf0_c0_hello0"}, 878 {"ID0UID000GUID0E0", "id0_uid000_guid0_e0"}, 879 {"Ab5ZXC5D5", "ab5_zxc5_d5"}, 880 {"Identifier", "identifier"}, 881 } 882 883 for i, test := range tests { 884 if out := unTitleCase(test.In); out != test.Out { 885 t.Errorf("[%d] (%s) Out was wrong: %q, want: %q", i, test.In, out, test.Out) 886 } 887 } 888 }