1 package util_test
2
3 import (
4 "database/sql"
5 "reflect"
6 "strings"
7 "sync"
8 "testing"
9 "time"
10
11 "github.com/doug-martin/goqu/v9/internal/util"
12 "github.com/stretchr/testify/suite"
13 )
14
15 var (
16 uints = []interface{}{
17 uint(10),
18 uint8(10),
19 uint16(10),
20 uint32(10),
21 uint64(10),
22 }
23 ints = []interface{}{
24 int(10),
25 int8(10),
26 int16(10),
27 int32(10),
28 int64(10),
29 }
30 floats = []interface{}{
31 float32(3.14),
32 float64(3.14),
33 }
34 strs = []interface{}{
35 "abc",
36 "",
37 }
38 bools = []interface{}{
39 true,
40 false,
41 }
42 structs = []interface{}{
43 sql.NullString{},
44 }
45 invalids = []interface{}{
46 nil,
47 }
48 pointers = []interface{}{
49 &sql.NullString{},
50 }
51 )
52
53 type (
54 TestInterface interface {
55 A() string
56 }
57 TestInterfaceImpl struct {
58 str string
59 }
60 TestStruct struct {
61 arr [0]string
62 slc []string
63 mp map[string]interface{}
64 str string
65 bl bool
66 i int
67 i8 int8
68 i16 int16
69 i32 int32
70 i64 int64
71 ui uint
72 ui8 uint8
73 ui16 uint16
74 ui32 uint32
75 ui64 uint64
76 f32 float32
77 f64 float64
78 intr TestInterface
79 ptr *sql.NullString
80 }
81 )
82
83 func (t TestInterfaceImpl) A() string {
84 return t.str
85 }
86
87 type reflectTest struct {
88 suite.Suite
89 }
90
91 func (rt *reflectTest) TestIsUint() {
92 for _, v := range uints {
93 rt.True(util.IsUint(reflect.ValueOf(v).Kind()))
94 }
95
96 for _, v := range ints {
97 rt.False(util.IsUint(reflect.ValueOf(v).Kind()))
98 }
99 for _, v := range floats {
100 rt.False(util.IsUint(reflect.ValueOf(v).Kind()))
101 }
102 for _, v := range strs {
103 rt.False(util.IsUint(reflect.ValueOf(v).Kind()))
104 }
105 for _, v := range bools {
106 rt.False(util.IsUint(reflect.ValueOf(v).Kind()))
107 }
108 for _, v := range structs {
109 rt.False(util.IsUint(reflect.ValueOf(v).Kind()))
110 }
111 for _, v := range invalids {
112 rt.False(util.IsUint(reflect.ValueOf(v).Kind()))
113 }
114 for _, v := range pointers {
115 rt.False(util.IsUint(reflect.ValueOf(v).Kind()))
116 }
117 }
118
119 func (rt *reflectTest) TestIsInt() {
120 for _, v := range ints {
121 rt.True(util.IsInt(reflect.ValueOf(v).Kind()))
122 }
123
124 for _, v := range uints {
125 rt.False(util.IsInt(reflect.ValueOf(v).Kind()))
126 }
127 for _, v := range floats {
128 rt.False(util.IsInt(reflect.ValueOf(v).Kind()))
129 }
130 for _, v := range strs {
131 rt.False(util.IsInt(reflect.ValueOf(v).Kind()))
132 }
133 for _, v := range bools {
134 rt.False(util.IsInt(reflect.ValueOf(v).Kind()))
135 }
136 for _, v := range structs {
137 rt.False(util.IsInt(reflect.ValueOf(v).Kind()))
138 }
139 for _, v := range invalids {
140 rt.False(util.IsInt(reflect.ValueOf(v).Kind()))
141 }
142 for _, v := range pointers {
143 rt.False(util.IsInt(reflect.ValueOf(v).Kind()))
144 }
145 }
146
147 func (rt *reflectTest) TestIsFloat() {
148 for _, v := range floats {
149 rt.True(util.IsFloat(reflect.ValueOf(v).Kind()))
150 }
151
152 for _, v := range uints {
153 rt.False(util.IsFloat(reflect.ValueOf(v).Kind()))
154 }
155 for _, v := range ints {
156 rt.False(util.IsFloat(reflect.ValueOf(v).Kind()))
157 }
158 for _, v := range strs {
159 rt.False(util.IsFloat(reflect.ValueOf(v).Kind()))
160 }
161 for _, v := range bools {
162 rt.False(util.IsFloat(reflect.ValueOf(v).Kind()))
163 }
164 for _, v := range structs {
165 rt.False(util.IsFloat(reflect.ValueOf(v).Kind()))
166 }
167 for _, v := range invalids {
168 rt.False(util.IsFloat(reflect.ValueOf(v).Kind()))
169 }
170 for _, v := range pointers {
171 rt.False(util.IsFloat(reflect.ValueOf(v).Kind()))
172 }
173 }
174
175 func (rt *reflectTest) TestIsString() {
176 for _, v := range strs {
177 rt.True(util.IsString(reflect.ValueOf(v).Kind()))
178 }
179
180 for _, v := range uints {
181 rt.False(util.IsString(reflect.ValueOf(v).Kind()))
182 }
183 for _, v := range ints {
184 rt.False(util.IsString(reflect.ValueOf(v).Kind()))
185 }
186 for _, v := range floats {
187 rt.False(util.IsString(reflect.ValueOf(v).Kind()))
188 }
189 for _, v := range bools {
190 rt.False(util.IsString(reflect.ValueOf(v).Kind()))
191 }
192 for _, v := range structs {
193 rt.False(util.IsString(reflect.ValueOf(v).Kind()))
194 }
195 for _, v := range invalids {
196 rt.False(util.IsString(reflect.ValueOf(v).Kind()))
197 }
198 for _, v := range pointers {
199 rt.False(util.IsString(reflect.ValueOf(v).Kind()))
200 }
201 }
202
203 func (rt *reflectTest) TestIsBool() {
204 for _, v := range bools {
205 rt.True(util.IsBool(reflect.ValueOf(v).Kind()))
206 }
207
208 for _, v := range uints {
209 rt.False(util.IsBool(reflect.ValueOf(v).Kind()))
210 }
211 for _, v := range ints {
212 rt.False(util.IsBool(reflect.ValueOf(v).Kind()))
213 }
214 for _, v := range floats {
215 rt.False(util.IsBool(reflect.ValueOf(v).Kind()))
216 }
217 for _, v := range strs {
218 rt.False(util.IsBool(reflect.ValueOf(v).Kind()))
219 }
220 for _, v := range structs {
221 rt.False(util.IsBool(reflect.ValueOf(v).Kind()))
222 }
223 for _, v := range invalids {
224 rt.False(util.IsBool(reflect.ValueOf(v).Kind()))
225 }
226 for _, v := range pointers {
227 rt.False(util.IsBool(reflect.ValueOf(v).Kind()))
228 }
229 }
230
231 func (rt *reflectTest) TestIsStruct() {
232 for _, v := range structs {
233 rt.True(util.IsStruct(reflect.ValueOf(v).Kind()))
234 }
235
236 for _, v := range uints {
237 rt.False(util.IsStruct(reflect.ValueOf(v).Kind()))
238 }
239 for _, v := range ints {
240 rt.False(util.IsStruct(reflect.ValueOf(v).Kind()))
241 }
242 for _, v := range floats {
243 rt.False(util.IsStruct(reflect.ValueOf(v).Kind()))
244 }
245 for _, v := range bools {
246 rt.False(util.IsStruct(reflect.ValueOf(v).Kind()))
247 }
248 for _, v := range strs {
249 rt.False(util.IsStruct(reflect.ValueOf(v).Kind()))
250 }
251 for _, v := range invalids {
252 rt.False(util.IsStruct(reflect.ValueOf(v).Kind()))
253 }
254 for _, v := range pointers {
255 rt.False(util.IsStruct(reflect.ValueOf(v).Kind()))
256 }
257 }
258
259 func (rt *reflectTest) TestIsSlice() {
260 rt.True(util.IsSlice(reflect.ValueOf(uints).Kind()))
261 rt.True(util.IsSlice(reflect.ValueOf(ints).Kind()))
262 rt.True(util.IsSlice(reflect.ValueOf(floats).Kind()))
263 rt.True(util.IsSlice(reflect.ValueOf(structs).Kind()))
264
265 rt.False(util.IsSlice(reflect.ValueOf(structs[0]).Kind()))
266 }
267
268 func (rt *reflectTest) TestIsInvalid() {
269 for _, v := range invalids {
270 rt.True(util.IsInvalid(reflect.ValueOf(v).Kind()))
271 }
272
273 for _, v := range uints {
274 rt.False(util.IsInvalid(reflect.ValueOf(v).Kind()))
275 }
276 for _, v := range ints {
277 rt.False(util.IsInvalid(reflect.ValueOf(v).Kind()))
278 }
279 for _, v := range floats {
280 rt.False(util.IsInvalid(reflect.ValueOf(v).Kind()))
281 }
282 for _, v := range bools {
283 rt.False(util.IsInvalid(reflect.ValueOf(v).Kind()))
284 }
285 for _, v := range strs {
286 rt.False(util.IsInvalid(reflect.ValueOf(v).Kind()))
287 }
288 for _, v := range structs {
289 rt.False(util.IsInvalid(reflect.ValueOf(v).Kind()))
290 }
291 for _, v := range pointers {
292 rt.False(util.IsInvalid(reflect.ValueOf(v).Kind()))
293 }
294 }
295
296 func (rt *reflectTest) TestIsPointer() {
297 for _, v := range pointers {
298 rt.True(util.IsPointer(reflect.ValueOf(v).Kind()))
299 }
300
301 for _, v := range uints {
302 rt.False(util.IsPointer(reflect.ValueOf(v).Kind()))
303 }
304 for _, v := range ints {
305 rt.False(util.IsPointer(reflect.ValueOf(v).Kind()))
306 }
307 for _, v := range floats {
308 rt.False(util.IsPointer(reflect.ValueOf(v).Kind()))
309 }
310 for _, v := range bools {
311 rt.False(util.IsPointer(reflect.ValueOf(v).Kind()))
312 }
313 for _, v := range strs {
314 rt.False(util.IsPointer(reflect.ValueOf(v).Kind()))
315 }
316 for _, v := range structs {
317 rt.False(util.IsPointer(reflect.ValueOf(v).Kind()))
318 }
319 for _, v := range invalids {
320 rt.False(util.IsPointer(reflect.ValueOf(v).Kind()))
321 }
322 }
323
324 func (rt *reflectTest) TestIsEmptyValue_emptyValues() {
325 ts := TestStruct{}
326 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.arr)))
327 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.slc)))
328 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.mp)))
329 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.str)))
330 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.bl)))
331 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.i)))
332 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.i8)))
333 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.i16)))
334 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.i32)))
335 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.i64)))
336 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.ui)))
337 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.ui8)))
338 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.ui16)))
339 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.ui32)))
340 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.ui64)))
341 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.f32)))
342 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.f64)))
343 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.intr)))
344 rt.True(util.IsEmptyValue(reflect.ValueOf(ts.ptr)))
345 }
346
347 func (rt *reflectTest) TestIsEmptyValue_validValues() {
348 ts := TestStruct{intr: TestInterfaceImpl{"hello"}}
349 rt.False(util.IsEmptyValue(reflect.ValueOf([1]string{"a"})))
350 rt.False(util.IsEmptyValue(reflect.ValueOf([]string{"a"})))
351 rt.False(util.IsEmptyValue(reflect.ValueOf(map[string]interface{}{"a": true})))
352 rt.False(util.IsEmptyValue(reflect.ValueOf("str")))
353 rt.False(util.IsEmptyValue(reflect.ValueOf(true)))
354 rt.False(util.IsEmptyValue(reflect.ValueOf(int(1))))
355 rt.False(util.IsEmptyValue(reflect.ValueOf(int8(1))))
356 rt.False(util.IsEmptyValue(reflect.ValueOf(int16(1))))
357 rt.False(util.IsEmptyValue(reflect.ValueOf(int32(1))))
358 rt.False(util.IsEmptyValue(reflect.ValueOf(int64(1))))
359 rt.False(util.IsEmptyValue(reflect.ValueOf(uint(1))))
360 rt.False(util.IsEmptyValue(reflect.ValueOf(uint8(1))))
361 rt.False(util.IsEmptyValue(reflect.ValueOf(uint16(1))))
362 rt.False(util.IsEmptyValue(reflect.ValueOf(uint32(1))))
363 rt.False(util.IsEmptyValue(reflect.ValueOf(uint64(1))))
364 rt.False(util.IsEmptyValue(reflect.ValueOf(float32(0.1))))
365 rt.False(util.IsEmptyValue(reflect.ValueOf(float64(0.2))))
366 rt.False(util.IsEmptyValue(reflect.ValueOf(ts.intr)))
367 rt.False(util.IsEmptyValue(reflect.ValueOf(&TestStruct{str: "a"})))
368 }
369
370 func (rt *reflectTest) TestColumnRename() {
371
372
373
374
375 lowerAnon := struct {
376 FirstLower string
377 LastLower string
378 }{}
379 lowerColumnMap, lowerErr := util.GetColumnMap(&lowerAnon)
380 rt.NoError(lowerErr)
381
382 lowerKeys := make([]string, 0, len(lowerColumnMap))
383 for key := range lowerColumnMap {
384 lowerKeys = append(lowerKeys, key)
385 }
386 rt.Contains(lowerKeys, "firstlower")
387 rt.Contains(lowerKeys, "lastlower")
388
389
390 util.SetColumnRenameFunction(strings.ToUpper)
391
392 upperAnon := struct {
393 FirstUpper string
394 LastUpper string
395 }{}
396 upperColumnMap, upperErr := util.GetColumnMap(&upperAnon)
397 rt.NoError(upperErr)
398
399 upperKeys := make([]string, 0, len(upperColumnMap))
400 for key := range upperColumnMap {
401 upperKeys = append(upperKeys, key)
402 }
403 rt.Contains(upperKeys, "FIRSTUPPER")
404 rt.Contains(upperKeys, "LASTUPPER")
405
406 util.SetColumnRenameFunction(util.DefaultColumnRenameFunction)
407 }
408
409 func (rt *reflectTest) TestParallelGetColumnMap() {
410 type item struct {
411 id uint
412 name string
413 }
414
415 wg := sync.WaitGroup{}
416
417 wg.Add(1)
418 go func() {
419 i := item{id: 1, name: "bob"}
420 m, err := util.GetColumnMap(i)
421 rt.NoError(err)
422 rt.NotNil(m)
423 wg.Done()
424 }()
425
426 wg.Add(1)
427 go func() {
428 i := item{id: 2, name: "sally"}
429 m, err := util.GetColumnMap(i)
430 rt.NoError(err)
431 rt.NotNil(m)
432 wg.Done()
433 }()
434
435 wg.Wait()
436 }
437
438 func (rt *reflectTest) TestAssignStructVals_withStruct() {
439 type TestStruct struct {
440 Str string
441 Int int64
442 Bool bool
443 Valuer sql.NullString
444 }
445 var ts TestStruct
446 cm, err := util.GetColumnMap(&ts)
447 rt.NoError(err)
448 data := map[string]interface{}{
449 "str": "string",
450 "int": int64(10),
451 "bool": true,
452 "valuer": sql.NullString{String: "null_str", Valid: true},
453 }
454
455 util.AssignStructVals(&ts, data, cm)
456 rt.Equal(ts, TestStruct{
457 Str: "string",
458 Int: 10,
459 Bool: true,
460 Valuer: sql.NullString{String: "null_str", Valid: true},
461 })
462 }
463
464 func (rt *reflectTest) TestAssignStructVals_withStructWithPointerVals() {
465 type TestStruct struct {
466 Str string
467 Int int64
468 Bool bool
469 Valuer *sql.NullString
470 }
471 var ts TestStruct
472 cm, err := util.GetColumnMap(&ts)
473 rt.NoError(err)
474 ns := &sql.NullString{String: "null_str1", Valid: true}
475 data := map[string]interface{}{
476 "str": "string",
477 "int": int64(10),
478 "bool": true,
479 "valuer": &ns,
480 }
481 util.AssignStructVals(&ts, data, cm)
482 rt.Equal(ts, TestStruct{
483 Str: "string",
484 Int: 10,
485 Bool: true,
486 Valuer: ns,
487 })
488 }
489
490 func (rt *reflectTest) TestAssignStructVals_withStructWithEmbeddedStruct() {
491 type EmbeddedStruct struct {
492 Str string
493 }
494 type TestStruct struct {
495 EmbeddedStruct
496 Int int64
497 Bool bool
498 Valuer *sql.NullString
499 }
500 var ts TestStruct
501 cm, err := util.GetColumnMap(&ts)
502 rt.NoError(err)
503 ns := &sql.NullString{String: "null_str1", Valid: true}
504 data := map[string]interface{}{
505 "str": "string",
506 "int": int64(10),
507 "bool": true,
508 "valuer": &ns,
509 }
510 util.AssignStructVals(&ts, data, cm)
511 rt.Equal(ts, TestStruct{
512 EmbeddedStruct: EmbeddedStruct{Str: "string"},
513 Int: 10,
514 Bool: true,
515 Valuer: ns,
516 })
517 }
518
519 func (rt *reflectTest) TestAssignStructVals_withStructWithEmbeddedStructPointer() {
520 type EmbeddedStruct struct {
521 Str string
522 }
523 type TestStruct struct {
524 *EmbeddedStruct
525 Int int64
526 Bool bool
527 Valuer *sql.NullString
528 }
529 var ts TestStruct
530 cm, err := util.GetColumnMap(&ts)
531 rt.NoError(err)
532 ns := &sql.NullString{String: "null_str1", Valid: true}
533 data := map[string]interface{}{
534 "str": "string",
535 "int": int64(10),
536 "bool": true,
537 "valuer": &ns,
538 }
539 util.AssignStructVals(&ts, data, cm)
540 rt.Equal(ts, TestStruct{
541 EmbeddedStruct: &EmbeddedStruct{Str: "string"},
542 Int: 10,
543 Bool: true,
544 Valuer: ns,
545 })
546 }
547
548 func (rt *reflectTest) TestAssignStructVals_withStructWithTaggedEmbeddedStruct() {
549 type EmbeddedStruct struct {
550 Str string
551 }
552 type TestStruct struct {
553 EmbeddedStruct `db:"embedded"`
554 Int int64
555 Bool bool
556 Valuer *sql.NullString
557 }
558 var ts TestStruct
559 cm, err := util.GetColumnMap(&ts)
560 rt.NoError(err)
561 ns := &sql.NullString{String: "null_str1", Valid: true}
562 data := map[string]interface{}{
563 "embedded.str": "string",
564 "int": int64(10),
565 "bool": true,
566 "valuer": &ns,
567 }
568 util.AssignStructVals(&ts, data, cm)
569 rt.Equal(ts, TestStruct{
570 EmbeddedStruct: EmbeddedStruct{Str: "string"},
571 Int: 10,
572 Bool: true,
573 Valuer: ns,
574 })
575 }
576
577 func (rt *reflectTest) TestAssignStructVals_withStructWithTaggedEmbeddedPointer() {
578 type EmbeddedStruct struct {
579 Str string
580 }
581 type TestStruct struct {
582 *EmbeddedStruct `db:"embedded"`
583 Int int64
584 Bool bool
585 Valuer *sql.NullString
586 }
587 var ts TestStruct
588 cm, err := util.GetColumnMap(&ts)
589 rt.NoError(err)
590 ns := &sql.NullString{String: "null_str1", Valid: true}
591 data := map[string]interface{}{
592 "embedded.str": "string",
593 "int": int64(10),
594 "bool": true,
595 "valuer": &ns,
596 }
597 util.AssignStructVals(&ts, data, cm)
598 rt.Equal(ts, TestStruct{
599 EmbeddedStruct: &EmbeddedStruct{Str: "string"},
600 Int: 10,
601 Bool: true,
602 Valuer: ns,
603 })
604 }
605
606 func (rt *reflectTest) TestAssignStructVals_withStructWithTaggedStructField() {
607 type EmbeddedStruct struct {
608 Str string
609 }
610 type TestStruct struct {
611 Embedded EmbeddedStruct `db:"embedded"`
612 Int int64
613 Bool bool
614 Valuer *sql.NullString
615 }
616 var ts TestStruct
617 cm, err := util.GetColumnMap(&ts)
618 rt.NoError(err)
619 ns := &sql.NullString{String: "null_str1", Valid: true}
620 data := map[string]interface{}{
621 "embedded.str": "string",
622 "int": int64(10),
623 "bool": true,
624 "valuer": &ns,
625 }
626 util.AssignStructVals(&ts, data, cm)
627 rt.Equal(ts, TestStruct{
628 Embedded: EmbeddedStruct{Str: "string"},
629 Int: 10,
630 Bool: true,
631 Valuer: ns,
632 })
633 }
634
635 func (rt *reflectTest) TestAssignStructVals_withStructWithTaggedPointerField() {
636 type EmbeddedStruct struct {
637 Str string
638 }
639 type TestStruct struct {
640 Embedded *EmbeddedStruct `db:"embedded"`
641 Int int64
642 Bool bool
643 Valuer *sql.NullString
644 }
645 var ts TestStruct
646 cm, err := util.GetColumnMap(&ts)
647 rt.NoError(err)
648 ns := &sql.NullString{String: "null_str1", Valid: true}
649 data := map[string]interface{}{
650 "embedded.str": "string",
651 "int": int64(10),
652 "bool": true,
653 "valuer": &ns,
654 }
655 util.AssignStructVals(&ts, data, cm)
656 rt.Equal(ts, TestStruct{
657 Embedded: &EmbeddedStruct{Str: "string"},
658 Int: 10,
659 Bool: true,
660 Valuer: ns,
661 })
662 }
663
664 func (rt *reflectTest) TestGetColumnMap_withStruct() {
665 type TestStruct struct {
666 Str string
667 Int int64
668 Bool bool
669 Valuer *sql.NullString
670 }
671 var ts TestStruct
672 cm, err := util.GetColumnMap(&ts)
673 rt.NoError(err)
674 rt.Equal(util.ColumnMap{
675 "str": {ColumnName: "str", FieldIndex: []int{0}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf("")},
676 "int": {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
677 "bool": {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
678 "valuer": {ColumnName: "valuer", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
679 }, cm)
680 }
681
682 func (rt *reflectTest) TestGetColumnMap_withStructGoquTags() {
683 type TestStruct struct {
684 Str string `goqu:"skipinsert,skipupdate"`
685 Int int64 `goqu:"skipinsert"`
686 Bool bool `goqu:"skipupdate"`
687 Empty bool `goqu:"defaultifempty"`
688 Valuer *sql.NullString
689 }
690 var ts TestStruct
691 cm, err := util.GetColumnMap(&ts)
692 rt.NoError(err)
693 rt.Equal(util.ColumnMap{
694 "str": {ColumnName: "str", FieldIndex: []int{0}, ShouldInsert: false, ShouldUpdate: false, GoType: reflect.TypeOf("")},
695 "int": {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: false, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
696 "bool": {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: false, GoType: reflect.TypeOf(true)},
697 "empty": {
698 ColumnName: "empty",
699 FieldIndex: []int{3},
700 ShouldInsert: true,
701 ShouldUpdate: true,
702 DefaultIfEmpty: true,
703 GoType: reflect.TypeOf(true),
704 },
705 "valuer": {ColumnName: "valuer", FieldIndex: []int{4}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
706 }, cm)
707 }
708
709 func (rt *reflectTest) TestGetColumnMap_withStructWithIgnoreUntagged() {
710 defer util.SetIgnoreUntaggedFields(false)
711 util.SetIgnoreUntaggedFields(true)
712
713 type EmbeddedStruct struct {
714 Float float64 `db:"f"`
715 Rune rune
716 }
717
718 type TestStruct struct {
719 EmbeddedStruct
720 Str string `db:"s"`
721 Int int64 `db:"i"`
722 Bool bool
723 }
724 var ts TestStruct
725 cm, err := util.GetColumnMap(&ts)
726 rt.NoError(err)
727 rt.Equal(util.ColumnMap{
728 "f": {ColumnName: "f", FieldIndex: []int{0, 0}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(float64(1))},
729 "s": {ColumnName: "s", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf("")},
730 "i": {ColumnName: "i", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
731 }, cm)
732 }
733
734 func (rt *reflectTest) TestGetColumnMap_withStructWithTag() {
735 type TestStruct struct {
736 Str string `db:"s"`
737 Int int64 `db:"i"`
738 Bool bool `db:"b"`
739 Valuer *sql.NullString `db:"v"`
740 Ignored string `db:"-"`
741 }
742 var ts TestStruct
743 cm, err := util.GetColumnMap(&ts)
744 rt.NoError(err)
745 rt.Equal(util.ColumnMap{
746 "s": {ColumnName: "s", FieldIndex: []int{0}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf("")},
747 "i": {ColumnName: "i", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
748 "b": {ColumnName: "b", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
749 "v": {ColumnName: "v", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
750 }, cm)
751 }
752
753 func (rt *reflectTest) TestGetColumnMap_withStructWithTagAndGoquTag() {
754 type TestStruct struct {
755 Str string `db:"s" goqu:"skipinsert,skipupdate"`
756 Int int64 `db:"i" goqu:"skipinsert"`
757 Bool bool `db:"b" goqu:"skipupdate"`
758 Valuer *sql.NullString `db:"v"`
759 }
760 var ts TestStruct
761 cm, err := util.GetColumnMap(&ts)
762 rt.NoError(err)
763 rt.Equal(util.ColumnMap{
764 "s": {ColumnName: "s", FieldIndex: []int{0}, ShouldInsert: false, ShouldUpdate: false, GoType: reflect.TypeOf("")},
765 "i": {ColumnName: "i", FieldIndex: []int{1}, ShouldInsert: false, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
766 "b": {ColumnName: "b", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: false, GoType: reflect.TypeOf(true)},
767 "v": {ColumnName: "v", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
768 }, cm)
769 }
770
771 func (rt *reflectTest) TestGetColumnMap_withStructWithTransientFields() {
772 type TestStruct struct {
773 Str string
774 Int int64
775 Bool bool
776 Valuer *sql.NullString `db:"-"`
777 }
778 var ts TestStruct
779 cm, err := util.GetColumnMap(&ts)
780 rt.NoError(err)
781 rt.Equal(util.ColumnMap{
782 "str": {ColumnName: "str", FieldIndex: []int{0}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf("")},
783 "int": {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
784 "bool": {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
785 }, cm)
786 }
787
788 func (rt *reflectTest) TestGetColumnMap_withSliceOfStructs() {
789 type TestStruct struct {
790 Str string
791 Int int64
792 Bool bool
793 Valuer *sql.NullString
794 }
795 var ts []TestStruct
796 cm, err := util.GetColumnMap(&ts)
797 rt.NoError(err)
798 rt.Equal(util.ColumnMap{
799 "str": {ColumnName: "str", FieldIndex: []int{0}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf("")},
800 "int": {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
801 "bool": {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
802 "valuer": {ColumnName: "valuer", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
803 }, cm)
804 }
805
806 func (rt *reflectTest) TestGetColumnMap_withNonStruct() {
807 var v int64
808 _, err := util.GetColumnMap(&v)
809 rt.EqualError(err, "goqu: cannot scan into this type: int64")
810 }
811
812 func (rt *reflectTest) TestGetColumnMap_withStructWithEmbeddedStruct() {
813 type EmbeddedStruct struct {
814 Str string
815 }
816 type TestStruct struct {
817 EmbeddedStruct
818 Int int64
819 Bool bool
820 Valuer *sql.NullString
821 }
822 var ts TestStruct
823 cm, err := util.GetColumnMap(&ts)
824 rt.NoError(err)
825 rt.Equal(util.ColumnMap{
826 "str": {ColumnName: "str", FieldIndex: []int{0, 0}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf("")},
827 "int": {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
828 "bool": {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
829 "valuer": {ColumnName: "valuer", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
830 }, cm)
831 }
832
833 func (rt *reflectTest) TestGetColumnMap_withStructWithEmbeddedStructPointer() {
834 type EmbeddedStruct struct {
835 Str string
836 }
837 type TestStruct struct {
838 *EmbeddedStruct
839 Int int64
840 Bool bool
841 Valuer *sql.NullString
842 }
843 var ts TestStruct
844 cm, err := util.GetColumnMap(&ts)
845 rt.NoError(err)
846 rt.Equal(util.ColumnMap{
847 "str": {ColumnName: "str", FieldIndex: []int{0, 0}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf("")},
848 "int": {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
849 "bool": {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
850 "valuer": {ColumnName: "valuer", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
851 }, cm)
852 }
853
854 func (rt *reflectTest) TestGetColumnMap_withIgnoredEmbeddedStruct() {
855 type EmbeddedStruct struct {
856 Str string
857 }
858 type TestStruct struct {
859 EmbeddedStruct `db:"-"`
860 Int int64
861 Bool bool
862 Valuer *sql.NullString
863 }
864 var ts TestStruct
865 cm, err := util.GetColumnMap(&ts)
866 rt.NoError(err)
867 rt.Equal(util.ColumnMap{
868 "int": {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
869 "bool": {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
870 "valuer": {ColumnName: "valuer", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
871 }, cm)
872 }
873
874 func (rt *reflectTest) TestGetColumnMap_withIgnoredEmbeddedPointerStruct() {
875 type EmbeddedStruct struct {
876 Str string
877 }
878 type TestStruct struct {
879 *EmbeddedStruct `db:"-"`
880 Int int64
881 Bool bool
882 Valuer *sql.NullString
883 }
884 var ts TestStruct
885 cm, err := util.GetColumnMap(&ts)
886 rt.NoError(err)
887 rt.Equal(util.ColumnMap{
888 "int": {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
889 "bool": {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
890 "valuer": {ColumnName: "valuer", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
891 }, cm)
892 }
893
894 func (rt *reflectTest) TestGetColumnMap_withPrivateFields() {
895 type TestStruct struct {
896 str string
897 Int int64
898 Bool bool
899 Valuer *sql.NullString
900 }
901 var ts TestStruct
902 cm, err := util.GetColumnMap(&ts)
903 rt.NoError(err)
904 rt.Equal(util.ColumnMap{
905 "int": {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
906 "bool": {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
907 "valuer": {ColumnName: "valuer", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
908 }, cm)
909 }
910
911 func (rt *reflectTest) TestGetColumnMap_withPrivateEmbeddedFields() {
912 type TestEmbedded struct {
913 str string
914 Int int64
915 }
916
917 type TestStruct struct {
918 TestEmbedded
919 Bool bool
920 Valuer *sql.NullString
921 }
922 var ts TestStruct
923 cm, err := util.GetColumnMap(&ts)
924 rt.NoError(err)
925 rt.Equal(util.ColumnMap{
926 "int": {ColumnName: "int", FieldIndex: []int{0, 1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
927 "bool": {ColumnName: "bool", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
928 "valuer": {ColumnName: "valuer", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
929 }, cm)
930 }
931
932 func (rt *reflectTest) TestGetColumnMap_withEmbeddedTaggedStruct() {
933 type TestEmbedded struct {
934 Bool bool
935 Valuer *sql.NullString
936 }
937
938 type TestStruct struct {
939 TestEmbedded `db:"test_embedded"`
940 Bool bool
941 Valuer *sql.NullString
942 }
943 var ts TestStruct
944 cm, err := util.GetColumnMap(&ts)
945 rt.NoError(err)
946 rt.Equal(util.ColumnMap{
947 "test_embedded.bool": {
948 ColumnName: "test_embedded.bool",
949 FieldIndex: []int{0, 0},
950 ShouldInsert: true,
951 ShouldUpdate: true,
952 GoType: reflect.TypeOf(true),
953 },
954 "test_embedded.valuer": {
955 ColumnName: "test_embedded.valuer",
956 FieldIndex: []int{0, 1},
957 ShouldInsert: true,
958 ShouldUpdate: true,
959 GoType: reflect.TypeOf(&sql.NullString{}),
960 },
961 "bool": {
962 ColumnName: "bool",
963 FieldIndex: []int{1},
964 ShouldInsert: true,
965 ShouldUpdate: true,
966 GoType: reflect.TypeOf(true),
967 },
968 "valuer": {
969 ColumnName: "valuer",
970 FieldIndex: []int{2},
971 ShouldInsert: true,
972 ShouldUpdate: true,
973 GoType: reflect.TypeOf(&sql.NullString{}),
974 },
975 }, cm)
976 }
977
978 func (rt *reflectTest) TestGetColumnMap_withEmbeddedTaggedStructPointer() {
979 type TestEmbedded struct {
980 Bool bool
981 Valuer *sql.NullString
982 }
983
984 type TestStruct struct {
985 *TestEmbedded `db:"test_embedded"`
986 Bool bool
987 Valuer *sql.NullString
988 }
989 var ts TestStruct
990 cm, err := util.GetColumnMap(&ts)
991 rt.NoError(err)
992 rt.Equal(util.ColumnMap{
993 "test_embedded.bool": {
994 ColumnName: "test_embedded.bool",
995 FieldIndex: []int{0, 0},
996 ShouldInsert: true,
997 ShouldUpdate: true,
998 GoType: reflect.TypeOf(true),
999 },
1000 "test_embedded.valuer": {
1001 ColumnName: "test_embedded.valuer",
1002 FieldIndex: []int{0, 1},
1003 ShouldInsert: true, ShouldUpdate: true,
1004 GoType: reflect.TypeOf(&sql.NullString{}),
1005 },
1006 "bool": {
1007 ColumnName: "bool",
1008 FieldIndex: []int{1},
1009 ShouldInsert: true,
1010 ShouldUpdate: true,
1011 GoType: reflect.TypeOf(true),
1012 },
1013 "valuer": {
1014 ColumnName: "valuer",
1015 FieldIndex: []int{2},
1016 ShouldInsert: true,
1017 ShouldUpdate: true,
1018 GoType: reflect.TypeOf(&sql.NullString{}),
1019 },
1020 }, cm)
1021 }
1022
1023 func (rt *reflectTest) TestGetColumnMap_withTaggedStructField() {
1024 type TestEmbedded struct {
1025 Bool bool
1026 Valuer *sql.NullString
1027 }
1028
1029 type TestStruct struct {
1030 Embedded TestEmbedded `db:"test_embedded"`
1031 Bool bool
1032 Valuer *sql.NullString
1033 }
1034 var ts TestStruct
1035 cm, err := util.GetColumnMap(&ts)
1036 rt.NoError(err)
1037 rt.Equal(util.ColumnMap{
1038 "test_embedded.bool": {
1039 ColumnName: "test_embedded.bool",
1040 FieldIndex: []int{0, 0},
1041 ShouldInsert: true,
1042 ShouldUpdate: true,
1043 GoType: reflect.TypeOf(true),
1044 },
1045 "test_embedded.valuer": {
1046 ColumnName: "test_embedded.valuer",
1047 FieldIndex: []int{0, 1},
1048 ShouldInsert: true,
1049 ShouldUpdate: true,
1050 GoType: reflect.TypeOf(&sql.NullString{}),
1051 },
1052 "bool": {
1053 ColumnName: "bool",
1054 FieldIndex: []int{1},
1055 ShouldInsert: true,
1056 ShouldUpdate: true,
1057 GoType: reflect.TypeOf(true),
1058 },
1059 "valuer": {
1060 ColumnName: "valuer",
1061 FieldIndex: []int{2},
1062 ShouldInsert: true,
1063 ShouldUpdate: true,
1064 GoType: reflect.TypeOf(&sql.NullString{}),
1065 },
1066 }, cm)
1067 }
1068
1069 func (rt *reflectTest) TestGetColumnMap_withTaggedStructPointerField() {
1070 type TestEmbedded struct {
1071 Bool bool
1072 Valuer *sql.NullString
1073 }
1074
1075 type TestStruct struct {
1076 Embedded *TestEmbedded `db:"test_embedded"`
1077 Bool bool
1078 Valuer *sql.NullString
1079 }
1080 var ts TestStruct
1081 cm, err := util.GetColumnMap(&ts)
1082 rt.NoError(err)
1083 rt.Equal(util.ColumnMap{
1084 "test_embedded.bool": {
1085 ColumnName: "test_embedded.bool",
1086 FieldIndex: []int{0, 0},
1087 ShouldInsert: true,
1088 ShouldUpdate: true,
1089 GoType: reflect.TypeOf(true),
1090 },
1091 "test_embedded.valuer": {
1092 ColumnName: "test_embedded.valuer",
1093 FieldIndex: []int{0, 1},
1094 ShouldInsert: true,
1095 ShouldUpdate: true,
1096 GoType: reflect.TypeOf(&sql.NullString{}),
1097 },
1098 "bool": {
1099 ColumnName: "bool",
1100 FieldIndex: []int{1},
1101 ShouldInsert: true,
1102 ShouldUpdate: true,
1103 GoType: reflect.TypeOf(true),
1104 },
1105 "valuer": {
1106 ColumnName: "valuer",
1107 FieldIndex: []int{2},
1108 ShouldInsert: true,
1109 ShouldUpdate: true,
1110 GoType: reflect.TypeOf(&sql.NullString{}),
1111 },
1112 }, cm)
1113 }
1114
1115 func (rt *reflectTest) TestGetTypeInfo() {
1116 var a int64
1117 var b []int64
1118 var c []*time.Time
1119
1120 t, k := util.GetTypeInfo(&a, reflect.ValueOf(a))
1121 rt.Equal(reflect.TypeOf(a), t)
1122 rt.Equal(reflect.Int64, k)
1123
1124 t, k = util.GetTypeInfo(&b, reflect.ValueOf(a))
1125 rt.Equal(reflect.TypeOf(a), t)
1126 rt.Equal(reflect.Int64, k)
1127
1128 t, k = util.GetTypeInfo(c, reflect.ValueOf(c))
1129 rt.Equal(reflect.TypeOf(time.Time{}), t)
1130 rt.Equal(reflect.Struct, k)
1131 }
1132
1133 func (rt *reflectTest) TestSafeGetFieldByIndex() {
1134 type TestEmbedded struct {
1135 FieldA int
1136 }
1137 type TestEmbeddedPointerStruct struct {
1138 *TestEmbedded
1139 FieldB string
1140 }
1141 type TestEmbeddedStruct struct {
1142 TestEmbedded
1143 FieldB string
1144 }
1145 v := reflect.ValueOf(TestEmbeddedPointerStruct{})
1146 f, isAvailable := util.SafeGetFieldByIndex(v, []int{0, 0})
1147 rt.False(isAvailable)
1148 rt.False(f.IsValid())
1149 f, isAvailable = util.SafeGetFieldByIndex(v, []int{1})
1150 rt.True(isAvailable)
1151 rt.True(f.IsValid())
1152 rt.Equal(reflect.String, f.Type().Kind())
1153 f, isAvailable = util.SafeGetFieldByIndex(v, []int{})
1154 rt.True(isAvailable)
1155 rt.Equal(v, f)
1156
1157 v = reflect.ValueOf(TestEmbeddedPointerStruct{TestEmbedded: &TestEmbedded{}})
1158 f, isAvailable = util.SafeGetFieldByIndex(v, []int{0, 0})
1159 rt.True(isAvailable)
1160 rt.True(f.IsValid())
1161 rt.Equal(reflect.Int, f.Type().Kind())
1162 f, isAvailable = util.SafeGetFieldByIndex(v, []int{1})
1163 rt.True(isAvailable)
1164 rt.True(f.IsValid())
1165 rt.Equal(reflect.String, f.Type().Kind())
1166 f, isAvailable = util.SafeGetFieldByIndex(v, []int{})
1167 rt.True(isAvailable)
1168 rt.Equal(v, f)
1169
1170 v = reflect.ValueOf(TestEmbeddedStruct{})
1171 f, isAvailable = util.SafeGetFieldByIndex(v, []int{0, 0})
1172 rt.True(isAvailable)
1173 rt.True(f.IsValid())
1174 rt.Equal(reflect.Int, f.Type().Kind())
1175 f, isAvailable = util.SafeGetFieldByIndex(v, []int{1})
1176 rt.True(isAvailable)
1177 rt.True(f.IsValid())
1178 rt.Equal(reflect.String, f.Type().Kind())
1179 f, isAvailable = util.SafeGetFieldByIndex(v, []int{})
1180 rt.True(isAvailable)
1181 rt.Equal(v, f)
1182
1183 v = reflect.ValueOf(TestEmbeddedStruct{TestEmbedded: TestEmbedded{}})
1184 f, isAvailable = util.SafeGetFieldByIndex(v, []int{0, 0})
1185 rt.True(isAvailable)
1186 rt.True(f.IsValid())
1187 f, isAvailable = util.SafeGetFieldByIndex(v, []int{1})
1188 rt.True(isAvailable)
1189 rt.True(f.IsValid())
1190 rt.Equal(reflect.String, f.Type().Kind())
1191 f, isAvailable = util.SafeGetFieldByIndex(v, []int{})
1192 rt.True(isAvailable)
1193 rt.Equal(v, f)
1194 }
1195
1196 func (rt *reflectTest) TestSafeSetFieldByIndex() {
1197 type TestEmbedded struct {
1198 FieldA int
1199 }
1200 type TestEmbeddedPointerStruct struct {
1201 *TestEmbedded
1202 FieldB string
1203 }
1204 type TestEmbeddedStruct struct {
1205 TestEmbedded
1206 FieldB string
1207 }
1208 var teps TestEmbeddedPointerStruct
1209 v := reflect.ValueOf(&teps)
1210 f := util.SafeSetFieldByIndex(v, []int{}, nil)
1211 rt.Equal(TestEmbeddedPointerStruct{}, f.Interface())
1212
1213 f = util.SafeSetFieldByIndex(v, []int{0, 0}, 1)
1214 rt.Equal(TestEmbeddedPointerStruct{
1215 TestEmbedded: &TestEmbedded{FieldA: 1},
1216 }, f.Interface())
1217
1218 f = util.SafeSetFieldByIndex(v, []int{1}, "hello")
1219 rt.Equal(TestEmbeddedPointerStruct{
1220 TestEmbedded: &TestEmbedded{FieldA: 1},
1221 FieldB: "hello",
1222 }, f.Interface())
1223 rt.Equal(TestEmbeddedPointerStruct{
1224 TestEmbedded: &TestEmbedded{FieldA: 1},
1225 FieldB: "hello",
1226 }, teps)
1227
1228 var tes TestEmbeddedStruct
1229 v = reflect.ValueOf(&tes)
1230 f = util.SafeSetFieldByIndex(v, []int{}, nil)
1231 rt.Equal(TestEmbeddedStruct{}, f.Interface())
1232
1233 f = util.SafeSetFieldByIndex(v, []int{0, 0}, 1)
1234 rt.Equal(TestEmbeddedStruct{
1235 TestEmbedded: TestEmbedded{FieldA: 1},
1236 }, f.Interface())
1237
1238 f = util.SafeSetFieldByIndex(v, []int{1}, "hello")
1239 rt.Equal(TestEmbeddedStruct{
1240 TestEmbedded: TestEmbedded{FieldA: 1},
1241 FieldB: "hello",
1242 }, f.Interface())
1243 rt.Equal(TestEmbeddedStruct{
1244 TestEmbedded: TestEmbedded{FieldA: 1},
1245 FieldB: "hello",
1246 }, tes)
1247 }
1248
1249 func (rt *reflectTest) TestGetSliceElementType() {
1250 type MyStruct struct{}
1251
1252 tests := []struct {
1253 slice interface{}
1254 want reflect.Type
1255 }{
1256 {
1257 slice: []int{},
1258 want: reflect.TypeOf(1),
1259 },
1260 {
1261 slice: []*int{},
1262 want: reflect.TypeOf(1),
1263 },
1264 {
1265 slice: []MyStruct{},
1266 want: reflect.TypeOf(MyStruct{}),
1267 },
1268 {
1269 slice: []*MyStruct{},
1270 want: reflect.TypeOf(MyStruct{}),
1271 },
1272 }
1273
1274 for _, tt := range tests {
1275 sliceVal := reflect.ValueOf(tt.slice)
1276 elementType := util.GetSliceElementType(sliceVal)
1277
1278 rt.Equal(tt.want, elementType)
1279 }
1280 }
1281
1282 func (rt *reflectTest) TestAppendSliceElement() {
1283 type MyStruct struct{}
1284
1285 sliceVal := reflect.Indirect(reflect.ValueOf(&[]MyStruct{}))
1286 util.AppendSliceElement(sliceVal, reflect.ValueOf(&MyStruct{}))
1287
1288 rt.Equal([]MyStruct{{}}, sliceVal.Interface())
1289
1290 sliceVal = reflect.Indirect(reflect.ValueOf(&[]*MyStruct{}))
1291 util.AppendSliceElement(sliceVal, reflect.ValueOf(&MyStruct{}))
1292
1293 rt.Equal([]*MyStruct{{}}, sliceVal.Interface())
1294 }
1295
1296 func TestReflectSuite(t *testing.T) {
1297 suite.Run(t, new(reflectTest))
1298 }
1299
View as plain text