|
9 | 9 | package mysql
|
10 | 10 |
|
11 | 11 | import (
|
12 |
| - "bytes" |
| 12 | + "database/sql/driver" |
13 | 13 | "testing"
|
| 14 | + "time" |
14 | 15 | )
|
15 | 16 |
|
16 |
| -func TestConvertDerivedString(t *testing.T) { |
17 |
| - type derived string |
| 17 | +func TestValueThatIsValue(t *testing.T) { |
| 18 | + now := time.Now() |
| 19 | + inputs := []interface{}{nil, float64(1.0), int64(17), "ABC", now} |
18 | 20 |
|
19 |
| - output, err := converter{}.ConvertValue(derived("value")) |
20 |
| - if err != nil { |
21 |
| - t.Fatal("Derived string type not convertible", err) |
22 |
| - } |
23 |
| - |
24 |
| - if output != "value" { |
25 |
| - t.Fatalf("Derived string type not converted, got %#v %T", output, output) |
| 21 | + for _, in := range inputs { |
| 22 | + out, err := converter{}.ConvertValue(in) |
| 23 | + if err != nil { |
| 24 | + t.Fatalf("Value %#v %T not needing conversion caused error: %s", in, in, err) |
| 25 | + } |
| 26 | + if out != in { |
| 27 | + t.Fatalf("Value %#v %T altered in conversion got %#v %T", in, in, out, out) |
| 28 | + } |
26 | 29 | }
|
27 | 30 | }
|
28 | 31 |
|
29 |
| -func TestConvertDerivedByteSlice(t *testing.T) { |
30 |
| - type derived []uint8 |
| 32 | +func TestValueThatIsPtrToValue(t *testing.T) { |
| 33 | + w := "ABC" |
| 34 | + x := &w |
| 35 | + y := &x |
| 36 | + inputs := []interface{}{x, y} |
31 | 37 |
|
32 |
| - output, err := converter{}.ConvertValue(derived("value")) |
33 |
| - if err != nil { |
34 |
| - t.Fatal("Byte slice not convertible", err) |
35 |
| - } |
36 |
| - |
37 |
| - if bytes.Compare(output.([]byte), []byte("value")) != 0 { |
38 |
| - t.Fatalf("Byte slice not converted, got %#v %T", output, output) |
| 38 | + for _, in := range inputs { |
| 39 | + out, err := converter{}.ConvertValue(in) |
| 40 | + if err != nil { |
| 41 | + t.Fatalf("Pointer %#v %T to value not needing conversion caused error: %s", in, in, err) |
| 42 | + } |
| 43 | + if out != w { |
| 44 | + t.Fatalf("Value %#v %T not resolved to string in conversion (got %#v %T)", in, in, out, out) |
| 45 | + } |
39 | 46 | }
|
40 | 47 | }
|
41 | 48 |
|
42 |
| -func TestConvertDerivedUnsupportedSlice(t *testing.T) { |
43 |
| - type derived []int |
| 49 | +func TestValueThatIsTypedPtrToNil(t *testing.T) { |
| 50 | + var w *string |
| 51 | + x := &w |
| 52 | + y := &x |
| 53 | + inputs := []interface{}{x, y} |
44 | 54 |
|
45 |
| - _, err := converter{}.ConvertValue(derived{1}) |
46 |
| - if err == nil || err.Error() != "unsupported type mysql.derived, a slice of int" { |
47 |
| - t.Fatal("Unexpected error", err) |
| 55 | + for _, in := range inputs { |
| 56 | + out, err := converter{}.ConvertValue(in) |
| 57 | + if err != nil { |
| 58 | + t.Fatalf("Pointer %#v %T to nil value caused error: %s", in, in, err) |
| 59 | + } |
| 60 | + if out != nil { |
| 61 | + t.Fatalf("Pointer to nil did not Value as nil") |
| 62 | + } |
48 | 63 | }
|
49 | 64 | }
|
50 | 65 |
|
51 |
| -func TestConvertDerivedBool(t *testing.T) { |
52 |
| - type derived bool |
| 66 | +type implementsValuer uint64 |
53 | 67 |
|
54 |
| - output, err := converter{}.ConvertValue(derived(true)) |
55 |
| - if err != nil { |
56 |
| - t.Fatal("Derived bool type not convertible", err) |
57 |
| - } |
58 |
| - |
59 |
| - if output != true { |
60 |
| - t.Fatalf("Derived bool type not converted, got %#v %T", output, output) |
61 |
| - } |
| 68 | +func (me implementsValuer) Value() (driver.Value, error) { |
| 69 | + return string(me), nil |
62 | 70 | }
|
63 |
| - |
64 |
| -func TestConvertPointer(t *testing.T) { |
65 |
| - str := "value" |
66 |
| - |
67 |
| - output, err := converter{}.ConvertValue(&str) |
68 |
| - if err != nil { |
69 |
| - t.Fatal("Pointer type not convertible", err) |
70 |
| - } |
71 |
| - |
72 |
| - if output != "value" { |
73 |
| - t.Fatalf("Pointer type not converted, got %#v %T", output, output) |
| 71 | +func TestTypesThatImplementValuerAreSkipped(t *testing.T) { |
| 72 | + // Have to test on a uint64 with high bit set - as we skip everything else anyhow |
| 73 | + x := implementsValuer(^uint64(0)) |
| 74 | + y := &x |
| 75 | + z := &y |
| 76 | + var a *implementsValuer |
| 77 | + b := &a |
| 78 | + c := &b |
| 79 | + inputs := []interface{}{x, y, z, a, b, c} |
| 80 | + |
| 81 | + for _, in := range inputs { |
| 82 | + _, err := converter{}.ConvertValue(in) |
| 83 | + if err != driver.ErrSkip { |
| 84 | + t.Fatalf("Conversion of Valuer implementing type %T not skipped", in) |
| 85 | + } |
74 | 86 | }
|
75 | 87 | }
|
76 | 88 |
|
77 |
| -func TestConvertSignedIntegers(t *testing.T) { |
78 |
| - values := []interface{}{ |
79 |
| - int8(-42), |
80 |
| - int16(-42), |
81 |
| - int32(-42), |
82 |
| - int64(-42), |
83 |
| - int(-42), |
84 |
| - } |
85 |
| - |
86 |
| - for _, value := range values { |
87 |
| - output, err := converter{}.ConvertValue(value) |
88 |
| - if err != nil { |
89 |
| - t.Fatalf("%T type not convertible %s", value, err) |
90 |
| - } |
91 |
| - |
92 |
| - if output != int64(-42) { |
93 |
| - t.Fatalf("%T type not converted, got %#v %T", value, output, output) |
| 89 | +func TestTypesThatAreNotValuesAreSkipped(t *testing.T) { |
| 90 | + type derived1 string // convertable |
| 91 | + type derived2 []uint8 // convertable |
| 92 | + type derived3 []int // not convertable |
| 93 | + type derived4 uint64 // without the high bit set |
| 94 | + inputs := []interface{}{derived1("ABC"), derived2([]uint8{'A', 'B'}), derived3([]int{17, 32}), derived3(nil), derived4(26)} |
| 95 | + |
| 96 | + for _, in := range inputs { |
| 97 | + _, err := converter{}.ConvertValue(in) |
| 98 | + if err != driver.ErrSkip { |
| 99 | + t.Fatalf("Conversion of non-value value %#v %T not skipped", in, in) |
94 | 100 | }
|
95 | 101 | }
|
96 | 102 | }
|
97 | 103 |
|
98 |
| -func TestConvertUnsignedIntegers(t *testing.T) { |
99 |
| - values := []interface{}{ |
100 |
| - uint8(42), |
101 |
| - uint16(42), |
102 |
| - uint32(42), |
103 |
| - uint64(42), |
104 |
| - uint(42), |
105 |
| - } |
| 104 | +func TestConvertLargeUnsignedIntegers(t *testing.T) { |
| 105 | + type derived uint64 |
| 106 | + type derived2 *uint64 |
| 107 | + v := ^uint64(0) |
| 108 | + w := &v |
| 109 | + x := derived(v) |
| 110 | + y := &x |
| 111 | + z := derived2(w) |
106 | 112 |
|
107 |
| - for _, value := range values { |
108 |
| - output, err := converter{}.ConvertValue(value) |
| 113 | + inputs := []interface{}{v, w, x, y, z} |
| 114 | + |
| 115 | + for _, in := range inputs { |
| 116 | + out, err := converter{}.ConvertValue(in) |
109 | 117 | if err != nil {
|
110 |
| - t.Fatalf("%T type not convertible %s", value, err) |
| 118 | + t.Fatalf("uint64 high-bit not convertible for type %T", in) |
111 | 119 | }
|
112 |
| - |
113 |
| - if output != int64(42) { |
114 |
| - t.Fatalf("%T type not converted, got %#v %T", value, output, output) |
| 120 | + if out != "18446744073709551615" { |
| 121 | + t.Fatalf("uint64 high-bit not converted, got %#v %T", out, out) |
115 | 122 | }
|
116 | 123 | }
|
117 |
| - |
118 |
| - output, err := converter{}.ConvertValue(^uint64(0)) |
119 |
| - if err != nil { |
120 |
| - t.Fatal("uint64 high-bit not convertible", err) |
121 |
| - } |
122 |
| - |
123 |
| - if output != "18446744073709551615" { |
124 |
| - t.Fatalf("uint64 high-bit not converted, got %#v %T", output, output) |
125 |
| - } |
126 | 124 | }
|
0 commit comments