1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
15 var someTime = time.Unix(123, 0)
18 type conversionTest struct {
19 s, d interface{} // source and destination
21 // following are used if they're non-zero
28 wantbool bool // used if d is of type *bool
31 wantptr *int64 // if non-nil, *d's pointed value must be equal to *wantptr
32 wantnil bool // if true, *d must be *int64(nil)
35 // Target variables for scanning into.
52 var conversionTests = []conversionTest{
53 // Exact conversions (destination pointer type matches source type)
54 {s: "foo", d: &scanstr, wantstr: "foo"},
55 {s: 123, d: &scanint, wantint: 123},
56 {s: someTime, d: &scantime, wanttime: someTime},
59 {s: []byte("byteslice"), d: &scanstr, wantstr: "byteslice"},
60 {s: 123, d: &scanstr, wantstr: "123"},
61 {s: int8(123), d: &scanstr, wantstr: "123"},
62 {s: int64(123), d: &scanstr, wantstr: "123"},
63 {s: uint8(123), d: &scanstr, wantstr: "123"},
64 {s: uint16(123), d: &scanstr, wantstr: "123"},
65 {s: uint32(123), d: &scanstr, wantstr: "123"},
66 {s: uint64(123), d: &scanstr, wantstr: "123"},
67 {s: 1.5, d: &scanstr, wantstr: "1.5"},
69 // Strings to integers
70 {s: "255", d: &scanuint8, wantuint: 255},
71 {s: "256", d: &scanuint8, wanterr: `converting string "256" to a uint8: strconv.ParseUint: parsing "256": value out of range`},
72 {s: "256", d: &scanuint16, wantuint: 256},
73 {s: "-1", d: &scanint, wantint: -1},
74 {s: "foo", d: &scanint, wanterr: `converting string "foo" to a int: strconv.ParseInt: parsing "foo": invalid syntax`},
77 {s: true, d: &scanbool, wantbool: true},
78 {s: "True", d: &scanbool, wantbool: true},
79 {s: "TRUE", d: &scanbool, wantbool: true},
80 {s: "1", d: &scanbool, wantbool: true},
81 {s: 1, d: &scanbool, wantbool: true},
82 {s: int64(1), d: &scanbool, wantbool: true},
83 {s: uint16(1), d: &scanbool, wantbool: true},
86 {s: false, d: &scanbool, wantbool: false},
87 {s: "false", d: &scanbool, wantbool: false},
88 {s: "FALSE", d: &scanbool, wantbool: false},
89 {s: "0", d: &scanbool, wantbool: false},
90 {s: 0, d: &scanbool, wantbool: false},
91 {s: int64(0), d: &scanbool, wantbool: false},
92 {s: uint16(0), d: &scanbool, wantbool: false},
95 {s: "yup", d: &scanbool, wanterr: `sql/driver: couldn't convert "yup" into type bool`},
96 {s: 2, d: &scanbool, wanterr: `sql/driver: couldn't convert 2 into type bool`},
99 {s: float64(1.5), d: &scanf64, wantf64: float64(1.5)},
100 {s: int64(1), d: &scanf64, wantf64: float64(1)},
101 {s: float64(1.5), d: &scanf32, wantf32: float32(1.5)},
102 {s: "1.5", d: &scanf32, wantf32: float32(1.5)},
103 {s: "1.5", d: &scanf64, wantf64: float64(1.5)},
106 {s: interface{}(nil), d: &scanptr, wantnil: true},
107 {s: int64(42), d: &scanptr, wantptr: &answer},
110 {s: float64(1.5), d: &scaniface, wantiface: float64(1.5)},
111 {s: int64(1), d: &scaniface, wantiface: int64(1)},
112 {s: "str", d: &scaniface, wantiface: "str"},
113 {s: []byte("byteslice"), d: &scaniface, wantiface: []byte("byteslice")},
114 {s: true, d: &scaniface, wantiface: true},
115 {s: nil, d: &scaniface},
118 func intPtrValue(intptr interface{}) interface{} {
119 return reflect.Indirect(reflect.Indirect(reflect.ValueOf(intptr))).Int()
122 func intValue(intptr interface{}) int64 {
123 return reflect.Indirect(reflect.ValueOf(intptr)).Int()
126 func uintValue(intptr interface{}) uint64 {
127 return reflect.Indirect(reflect.ValueOf(intptr)).Uint()
130 func float64Value(ptr interface{}) float64 {
131 return *(ptr.(*float64))
134 func float32Value(ptr interface{}) float32 {
135 return *(ptr.(*float32))
138 func timeValue(ptr interface{}) time.Time {
139 return *(ptr.(*time.Time))
142 func TestConversions(t *testing.T) {
143 for n, ct := range conversionTests {
144 err := convertAssign(ct.d, ct.s)
149 errf := func(format string, args ...interface{}) {
150 base := fmt.Sprintf("convertAssign #%d: for %v (%T) -> %T, ", n, ct.s, ct.s, ct.d)
151 t.Errorf(base+format, args...)
153 if errstr != ct.wanterr {
154 errf("got error %q, want error %q", errstr, ct.wanterr)
156 if ct.wantstr != "" && ct.wantstr != scanstr {
157 errf("want string %q, got %q", ct.wantstr, scanstr)
159 if ct.wantint != 0 && ct.wantint != intValue(ct.d) {
160 errf("want int %d, got %d", ct.wantint, intValue(ct.d))
162 if ct.wantuint != 0 && ct.wantuint != uintValue(ct.d) {
163 errf("want uint %d, got %d", ct.wantuint, uintValue(ct.d))
165 if ct.wantf32 != 0 && ct.wantf32 != float32Value(ct.d) {
166 errf("want float32 %v, got %v", ct.wantf32, float32Value(ct.d))
168 if ct.wantf64 != 0 && ct.wantf64 != float64Value(ct.d) {
169 errf("want float32 %v, got %v", ct.wantf64, float64Value(ct.d))
171 if bp, boolTest := ct.d.(*bool); boolTest && *bp != ct.wantbool && ct.wanterr == "" {
172 errf("want bool %v, got %v", ct.wantbool, *bp)
174 if !ct.wanttime.IsZero() && !ct.wanttime.Equal(timeValue(ct.d)) {
175 errf("want time %v, got %v", ct.wanttime, timeValue(ct.d))
177 if ct.wantnil && *ct.d.(**int64) != nil {
178 errf("want nil, got %v", intPtrValue(ct.d))
180 if ct.wantptr != nil {
181 if *ct.d.(**int64) == nil {
182 errf("want pointer to %v, got nil", *ct.wantptr)
183 } else if *ct.wantptr != intPtrValue(ct.d) {
184 errf("want pointer to %v, got %v", *ct.wantptr, intPtrValue(ct.d))
187 if ifptr, ok := ct.d.(*interface{}); ok {
188 if !reflect.DeepEqual(ct.wantiface, scaniface) {
189 errf("want interface %#v, got %#v", ct.wantiface, scaniface)
192 if srcBytes, ok := ct.s.([]byte); ok {
193 dstBytes := (*ifptr).([]byte)
194 if &dstBytes[0] == &srcBytes[0] {
195 errf("copy into interface{} didn't copy []byte data")
202 func TestNullString(t *testing.T) {
204 convertAssign(&ns, []byte("foo"))
206 t.Errorf("expecting not null")
208 if ns.String != "foo" {
209 t.Errorf("expecting foo; got %q", ns.String)
211 convertAssign(&ns, nil)
213 t.Errorf("expecting null on nil")
216 t.Errorf("expecting blank on nil; got %q", ns.String)
220 type valueConverterTest struct {
221 c driver.ValueConverter
226 var valueConverterTests = []valueConverterTest{
227 {driver.DefaultParameterConverter, NullString{"hi", true}, "hi", ""},
228 {driver.DefaultParameterConverter, NullString{"", false}, nil, ""},
231 func TestValueConverters(t *testing.T) {
232 for i, tt := range valueConverterTests {
233 out, err := tt.c.ConvertValue(tt.in)
238 if goterr != tt.err {
239 t.Errorf("test %d: %s(%T(%v)) error = %q; want error = %q",
240 i, tt.c, tt.in, tt.in, goterr, tt.err)
245 if !reflect.DeepEqual(out, tt.out) {
246 t.Errorf("test %d: %s(%T(%v)) = %v (%T); want %v (%T)",
247 i, tt.c, tt.in, tt.in, out, out, tt.out, tt.out)