Skip to content

Commit 488d827

Browse files
committed
Additional testing.
1 parent 398dd58 commit 488d827

File tree

1 file changed

+310
-1
lines changed

1 file changed

+310
-1
lines changed

reflectx/reflect_test.go

Lines changed: 310 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ func TestFieldsEmbedded(t *testing.T) {
251251
m := NewMapper("db")
252252

253253
type Person struct {
254-
Name string `db:"name"`
254+
Name string `db:"name,size=64"`
255255
}
256256
type Place struct {
257257
Name string `db:"name"`
@@ -311,6 +311,9 @@ func TestFieldsEmbedded(t *testing.T) {
311311
if fi.Path != "person.name" {
312312
t.Errorf("Expecting %s, got %s", "person.name", fi.Path)
313313
}
314+
if fi.Options["size"] != "64" {
315+
t.Errorf("Expecting %s, got %s", "64", fi.Options["size"])
316+
}
314317

315318
fi = fields.GetByTraversal([]int{1, 0})
316319
if fi == nil {
@@ -508,6 +511,312 @@ func TestMapping(t *testing.T) {
508511
}
509512
}
510513

514+
func TestGetByTraversal(t *testing.T) {
515+
type C struct {
516+
C0 int
517+
C1 int
518+
}
519+
type B struct {
520+
B0 string
521+
B1 *C
522+
}
523+
type A struct {
524+
A0 int
525+
A1 B
526+
}
527+
528+
testCases := []struct {
529+
Index []int
530+
ExpectedName string
531+
ExpectNil bool
532+
}{
533+
{
534+
Index: []int{0},
535+
ExpectedName: "A0",
536+
},
537+
{
538+
Index: []int{1, 0},
539+
ExpectedName: "B0",
540+
},
541+
{
542+
Index: []int{1, 1, 1},
543+
ExpectedName: "C1",
544+
},
545+
{
546+
Index: []int{3, 4, 5},
547+
ExpectNil: true,
548+
},
549+
{
550+
Index: []int{},
551+
ExpectNil: true,
552+
},
553+
{
554+
Index: nil,
555+
ExpectNil: true,
556+
},
557+
}
558+
559+
m := NewMapperFunc("db", func(n string) string { return n })
560+
tm := m.TypeMap(reflect.TypeOf(A{}))
561+
562+
for i, tc := range testCases {
563+
fi := tm.GetByTraversal(tc.Index)
564+
if tc.ExpectNil {
565+
if fi != nil {
566+
t.Errorf("%d: expected nil, got %v", i, fi)
567+
}
568+
continue
569+
}
570+
571+
if fi == nil {
572+
t.Errorf("%d: expected %s, got nil", i, tc.ExpectedName)
573+
continue
574+
}
575+
576+
if fi.Name != tc.ExpectedName {
577+
t.Errorf("%d: expected %s, got %s", i, tc.ExpectedName, fi.Name)
578+
}
579+
}
580+
}
581+
582+
// TestMapperMethodsByName tests Mapper methods FieldByName and TraversalsByName
583+
func TestMapperMethodsByName(t *testing.T) {
584+
type C struct {
585+
C0 string
586+
C1 int
587+
}
588+
type B struct {
589+
B0 *C `db:"B0"`
590+
B1 C `db:"B1"`
591+
B2 string `db:"B2"`
592+
}
593+
type A struct {
594+
A0 *B `db:"A0"`
595+
B `db:"A1"`
596+
A2 int
597+
a3 int
598+
}
599+
600+
val := &A{
601+
A0: &B{
602+
B0: &C{C0: "0", C1: 1},
603+
B1: C{C0: "2", C1: 3},
604+
B2: "4",
605+
},
606+
B: B{
607+
B0: nil,
608+
B1: C{C0: "5", C1: 6},
609+
B2: "7",
610+
},
611+
A2: 8,
612+
}
613+
614+
testCases := []struct {
615+
Name string
616+
ExpectInvalid bool
617+
ExpectedValue interface{}
618+
ExpectedIndexes []int
619+
}{
620+
{
621+
Name: "A0.B0.C0",
622+
ExpectedValue: "0",
623+
ExpectedIndexes: []int{0, 0, 0},
624+
},
625+
{
626+
Name: "A0.B0.C1",
627+
ExpectedValue: 1,
628+
ExpectedIndexes: []int{0, 0, 1},
629+
},
630+
{
631+
Name: "A0.B1.C0",
632+
ExpectedValue: "2",
633+
ExpectedIndexes: []int{0, 1, 0},
634+
},
635+
{
636+
Name: "A0.B1.C1",
637+
ExpectedValue: 3,
638+
ExpectedIndexes: []int{0, 1, 1},
639+
},
640+
{
641+
Name: "A0.B2",
642+
ExpectedValue: "4",
643+
ExpectedIndexes: []int{0, 2},
644+
},
645+
{
646+
Name: "A1.B0.C0",
647+
ExpectedValue: "",
648+
ExpectedIndexes: []int{1, 0, 0},
649+
},
650+
{
651+
Name: "A1.B0.C1",
652+
ExpectedValue: 0,
653+
ExpectedIndexes: []int{1, 0, 1},
654+
},
655+
{
656+
Name: "A1.B1.C0",
657+
ExpectedValue: "5",
658+
ExpectedIndexes: []int{1, 1, 0},
659+
},
660+
{
661+
Name: "A1.B1.C1",
662+
ExpectedValue: 6,
663+
ExpectedIndexes: []int{1, 1, 1},
664+
},
665+
{
666+
Name: "A1.B2",
667+
ExpectedValue: "7",
668+
ExpectedIndexes: []int{1, 2},
669+
},
670+
{
671+
Name: "A2",
672+
ExpectedValue: 8,
673+
ExpectedIndexes: []int{2},
674+
},
675+
{
676+
Name: "XYZ",
677+
ExpectInvalid: true,
678+
ExpectedIndexes: []int{},
679+
},
680+
{
681+
Name: "a3",
682+
ExpectInvalid: true,
683+
ExpectedIndexes: []int{},
684+
},
685+
}
686+
687+
// build the names array from the test cases
688+
names := make([]string, len(testCases))
689+
for i, tc := range testCases {
690+
names[i] = tc.Name
691+
}
692+
m := NewMapperFunc("db", func(n string) string { return n })
693+
v := reflect.ValueOf(val)
694+
values := m.FieldsByName(v, names)
695+
if len(values) != len(testCases) {
696+
t.Errorf("expected %d values, got %d", len(testCases), len(values))
697+
t.FailNow()
698+
}
699+
indexes := m.TraversalsByName(v.Type(), names)
700+
if len(indexes) != len(testCases) {
701+
t.Errorf("expected %d traversals, got %d", len(testCases), len(indexes))
702+
t.FailNow()
703+
}
704+
for i, val := range values {
705+
tc := testCases[i]
706+
traversal := indexes[i]
707+
if !reflect.DeepEqual(tc.ExpectedIndexes, traversal) {
708+
t.Errorf("%d: expected %v, got %v", tc.ExpectedIndexes, traversal)
709+
t.FailNow()
710+
}
711+
val = reflect.Indirect(val)
712+
if tc.ExpectInvalid {
713+
if val.IsValid() {
714+
t.Errorf("%d: expected zero value, got %v", i, val)
715+
}
716+
continue
717+
}
718+
if !val.IsValid() {
719+
t.Errorf("%d: expected valid value, got %v", i, val)
720+
continue
721+
}
722+
actualValue := reflect.Indirect(val).Interface()
723+
if !reflect.DeepEqual(tc.ExpectedValue, actualValue) {
724+
t.Errorf("%d: expected %v, got %v", i, tc.ExpectedValue, actualValue)
725+
}
726+
}
727+
}
728+
729+
func TestFieldByIndexes(t *testing.T) {
730+
type C struct {
731+
C0 bool
732+
C1 string
733+
C2 int
734+
C3 map[string]int
735+
}
736+
type B struct {
737+
B1 C
738+
B2 *C
739+
}
740+
type A struct {
741+
A1 B
742+
A2 *B
743+
}
744+
testCases := []struct {
745+
value interface{}
746+
indexes []int
747+
expectedValue interface{}
748+
readOnly bool
749+
}{
750+
{
751+
value: A{
752+
A1: B{B1: C{C0: true}},
753+
},
754+
indexes: []int{0, 0, 0},
755+
expectedValue: true,
756+
readOnly: true,
757+
},
758+
{
759+
value: A{
760+
A2: &B{B2: &C{C1: "answer"}},
761+
},
762+
indexes: []int{1, 1, 1},
763+
expectedValue: "answer",
764+
readOnly: true,
765+
},
766+
{
767+
value: &A{},
768+
indexes: []int{1, 1, 3},
769+
expectedValue: map[string]int{},
770+
},
771+
}
772+
773+
for i, tc := range testCases {
774+
checkResults := func(v reflect.Value) {
775+
if tc.expectedValue == nil {
776+
if !v.IsNil() {
777+
t.Errorf("%d: expected nil, actual %v", i, v.Interface())
778+
}
779+
} else {
780+
if !reflect.DeepEqual(tc.expectedValue, v.Interface()) {
781+
t.Errorf("%d: expected %v, actual %v", i, tc.expectedValue, v.Interface())
782+
}
783+
}
784+
}
785+
786+
checkResults(FieldByIndexes(reflect.ValueOf(tc.value), tc.indexes))
787+
if tc.readOnly {
788+
checkResults(FieldByIndexesReadOnly(reflect.ValueOf(tc.value), tc.indexes))
789+
}
790+
}
791+
}
792+
793+
func TestMustBe(t *testing.T) {
794+
typ := reflect.TypeOf(E1{})
795+
mustBe(typ, reflect.Struct)
796+
797+
defer func() {
798+
if r := recover(); r != nil {
799+
valueErr, ok := r.(*reflect.ValueError)
800+
if !ok {
801+
t.Errorf("unexpected Method: %s", valueErr.Method)
802+
t.Error("expected panic with *reflect.ValueError")
803+
return
804+
}
805+
if valueErr.Method != "github.com/jmoiron/sqlx/reflectx.TestMustBe" {
806+
}
807+
if valueErr.Kind != reflect.String {
808+
t.Errorf("unexpected Kind: %s", valueErr.Kind)
809+
}
810+
} else {
811+
t.Error("expected panic")
812+
}
813+
}()
814+
815+
typ = reflect.TypeOf("string")
816+
mustBe(typ, reflect.Struct)
817+
t.Error("got here, didn't expect to")
818+
}
819+
511820
type E1 struct {
512821
A int
513822
}

0 commit comments

Comments
 (0)