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.
16 var someTime
= time
.Unix(123, 0)
19 type conversionTest
struct {
20 s
, d
interface{} // source and destination
22 // following are used if they're non-zero
31 wantbool
bool // used if d is of type *bool
34 wantptr
*int64 // if non-nil, *d's pointed value must be equal to *wantptr
35 wantnil
bool // if true, *d must be *int64(nil)
38 // Target variables for scanning into.
57 var conversionTests
= []conversionTest
{
58 // Exact conversions (destination pointer type matches source type)
59 {s
: "foo", d
: &scanstr
, wantstr
: "foo"},
60 {s
: 123, d
: &scanint
, wantint
: 123},
61 {s
: someTime
, d
: &scantime
, wanttime
: someTime
},
64 {s
: "string", d
: &scanstr
, wantstr
: "string"},
65 {s
: []byte("byteslice"), d
: &scanstr
, wantstr
: "byteslice"},
66 {s
: 123, d
: &scanstr
, wantstr
: "123"},
67 {s
: int8(123), d
: &scanstr
, wantstr
: "123"},
68 {s
: int64(123), d
: &scanstr
, wantstr
: "123"},
69 {s
: uint8(123), d
: &scanstr
, wantstr
: "123"},
70 {s
: uint16(123), d
: &scanstr
, wantstr
: "123"},
71 {s
: uint32(123), d
: &scanstr
, wantstr
: "123"},
72 {s
: uint64(123), d
: &scanstr
, wantstr
: "123"},
73 {s
: 1.5, d
: &scanstr
, wantstr
: "1.5"},
76 {s
: nil, d
: &scanbytes
, wantbytes
: nil},
77 {s
: "string", d
: &scanbytes
, wantbytes
: []byte("string")},
78 {s
: []byte("byteslice"), d
: &scanbytes
, wantbytes
: []byte("byteslice")},
79 {s
: 123, d
: &scanbytes
, wantbytes
: []byte("123")},
80 {s
: int8(123), d
: &scanbytes
, wantbytes
: []byte("123")},
81 {s
: int64(123), d
: &scanbytes
, wantbytes
: []byte("123")},
82 {s
: uint8(123), d
: &scanbytes
, wantbytes
: []byte("123")},
83 {s
: uint16(123), d
: &scanbytes
, wantbytes
: []byte("123")},
84 {s
: uint32(123), d
: &scanbytes
, wantbytes
: []byte("123")},
85 {s
: uint64(123), d
: &scanbytes
, wantbytes
: []byte("123")},
86 {s
: 1.5, d
: &scanbytes
, wantbytes
: []byte("1.5")},
89 {s
: nil, d
: &scanraw
, wantraw
: nil},
90 {s
: []byte("byteslice"), d
: &scanraw
, wantraw
: RawBytes("byteslice")},
91 {s
: 123, d
: &scanraw
, wantraw
: RawBytes("123")},
92 {s
: int8(123), d
: &scanraw
, wantraw
: RawBytes("123")},
93 {s
: int64(123), d
: &scanraw
, wantraw
: RawBytes("123")},
94 {s
: uint8(123), d
: &scanraw
, wantraw
: RawBytes("123")},
95 {s
: uint16(123), d
: &scanraw
, wantraw
: RawBytes("123")},
96 {s
: uint32(123), d
: &scanraw
, wantraw
: RawBytes("123")},
97 {s
: uint64(123), d
: &scanraw
, wantraw
: RawBytes("123")},
98 {s
: 1.5, d
: &scanraw
, wantraw
: RawBytes("1.5")},
100 // Strings to integers
101 {s
: "255", d
: &scanuint8
, wantuint
: 255},
102 {s
: "256", d
: &scanuint8
, wanterr
: `converting string "256" to a uint8: strconv.ParseUint: parsing "256": value out of range`},
103 {s
: "256", d
: &scanuint16
, wantuint
: 256},
104 {s
: "-1", d
: &scanint
, wantint
: -1},
105 {s
: "foo", d
: &scanint
, wanterr
: `converting string "foo" to a int: strconv.ParseInt: parsing "foo": invalid syntax`},
108 {s
: true, d
: &scanbool
, wantbool
: true},
109 {s
: "True", d
: &scanbool
, wantbool
: true},
110 {s
: "TRUE", d
: &scanbool
, wantbool
: true},
111 {s
: "1", d
: &scanbool
, wantbool
: true},
112 {s
: 1, d
: &scanbool
, wantbool
: true},
113 {s
: int64(1), d
: &scanbool
, wantbool
: true},
114 {s
: uint16(1), d
: &scanbool
, wantbool
: true},
117 {s
: false, d
: &scanbool
, wantbool
: false},
118 {s
: "false", d
: &scanbool
, wantbool
: false},
119 {s
: "FALSE", d
: &scanbool
, wantbool
: false},
120 {s
: "0", d
: &scanbool
, wantbool
: false},
121 {s
: 0, d
: &scanbool
, wantbool
: false},
122 {s
: int64(0), d
: &scanbool
, wantbool
: false},
123 {s
: uint16(0), d
: &scanbool
, wantbool
: false},
126 {s
: "yup", d
: &scanbool
, wanterr
: `sql/driver: couldn't convert "yup" into type bool`},
127 {s
: 2, d
: &scanbool
, wanterr
: `sql/driver: couldn't convert 2 into type bool`},
130 {s
: float64(1.5), d
: &scanf64
, wantf64
: float64(1.5)},
131 {s
: int64(1), d
: &scanf64
, wantf64
: float64(1)},
132 {s
: float64(1.5), d
: &scanf32
, wantf32
: float32(1.5)},
133 {s
: "1.5", d
: &scanf32
, wantf32
: float32(1.5)},
134 {s
: "1.5", d
: &scanf64
, wantf64
: float64(1.5)},
137 {s
: interface{}(nil), d
: &scanptr
, wantnil
: true},
138 {s
: int64(42), d
: &scanptr
, wantptr
: &answer
},
141 {s
: float64(1.5), d
: &scaniface
, wantiface
: float64(1.5)},
142 {s
: int64(1), d
: &scaniface
, wantiface
: int64(1)},
143 {s
: "str", d
: &scaniface
, wantiface
: "str"},
144 {s
: []byte("byteslice"), d
: &scaniface
, wantiface
: []byte("byteslice")},
145 {s
: true, d
: &scaniface
, wantiface
: true},
146 {s
: nil, d
: &scaniface
},
147 {s
: []byte(nil), d
: &scaniface
, wantiface
: []byte(nil)},
150 func intPtrValue(intptr
interface{}) interface{} {
151 return reflect
.Indirect(reflect
.Indirect(reflect
.ValueOf(intptr
))).Int()
154 func intValue(intptr
interface{}) int64 {
155 return reflect
.Indirect(reflect
.ValueOf(intptr
)).Int()
158 func uintValue(intptr
interface{}) uint64 {
159 return reflect
.Indirect(reflect
.ValueOf(intptr
)).Uint()
162 func float64Value(ptr
interface{}) float64 {
163 return *(ptr
.(*float64))
166 func float32Value(ptr
interface{}) float32 {
167 return *(ptr
.(*float32))
170 func timeValue(ptr
interface{}) time
.Time
{
171 return *(ptr
.(*time
.Time
))
174 func TestConversions(t
*testing
.T
) {
175 for n
, ct
:= range conversionTests
{
176 err
:= convertAssign(ct
.d
, ct
.s
)
181 errf
:= func(format
string, args
...interface{}) {
182 base
:= fmt
.Sprintf("convertAssign #%d: for %v (%T) -> %T, ", n
, ct
.s
, ct
.s
, ct
.d
)
183 t
.Errorf(base
+format
, args
...)
185 if errstr
!= ct
.wanterr
{
186 errf("got error %q, want error %q", errstr
, ct
.wanterr
)
188 if ct
.wantstr
!= "" && ct
.wantstr
!= scanstr
{
189 errf("want string %q, got %q", ct
.wantstr
, scanstr
)
191 if ct
.wantint
!= 0 && ct
.wantint
!= intValue(ct
.d
) {
192 errf("want int %d, got %d", ct
.wantint
, intValue(ct
.d
))
194 if ct
.wantuint
!= 0 && ct
.wantuint
!= uintValue(ct
.d
) {
195 errf("want uint %d, got %d", ct
.wantuint
, uintValue(ct
.d
))
197 if ct
.wantf32
!= 0 && ct
.wantf32
!= float32Value(ct
.d
) {
198 errf("want float32 %v, got %v", ct
.wantf32
, float32Value(ct
.d
))
200 if ct
.wantf64
!= 0 && ct
.wantf64
!= float64Value(ct
.d
) {
201 errf("want float32 %v, got %v", ct
.wantf64
, float64Value(ct
.d
))
203 if bp
, boolTest
:= ct
.d
.(*bool); boolTest
&& *bp
!= ct
.wantbool
&& ct
.wanterr
== "" {
204 errf("want bool %v, got %v", ct
.wantbool
, *bp
)
206 if !ct
.wanttime
.IsZero() && !ct
.wanttime
.Equal(timeValue(ct
.d
)) {
207 errf("want time %v, got %v", ct
.wanttime
, timeValue(ct
.d
))
209 if ct
.wantnil
&& *ct
.d
.(**int64) != nil {
210 errf("want nil, got %v", intPtrValue(ct
.d
))
212 if ct
.wantptr
!= nil {
213 if *ct
.d
.(**int64) == nil {
214 errf("want pointer to %v, got nil", *ct
.wantptr
)
215 } else if *ct
.wantptr
!= intPtrValue(ct
.d
) {
216 errf("want pointer to %v, got %v", *ct
.wantptr
, intPtrValue(ct
.d
))
219 if ifptr
, ok
:= ct
.d
.(*interface{}); ok
{
220 if !reflect
.DeepEqual(ct
.wantiface
, scaniface
) {
221 errf("want interface %#v, got %#v", ct
.wantiface
, scaniface
)
224 if srcBytes
, ok
:= ct
.s
.([]byte); ok
{
225 dstBytes
:= (*ifptr
).([]byte)
226 if len(srcBytes
) > 0 && &dstBytes
[0] == &srcBytes
[0] {
227 errf("copy into interface{} didn't copy []byte data")
234 func TestNullString(t
*testing
.T
) {
236 convertAssign(&ns
, []byte("foo"))
238 t
.Errorf("expecting not null")
240 if ns
.String
!= "foo" {
241 t
.Errorf("expecting foo; got %q", ns
.String
)
243 convertAssign(&ns
, nil)
245 t
.Errorf("expecting null on nil")
248 t
.Errorf("expecting blank on nil; got %q", ns
.String
)
252 type valueConverterTest
struct {
253 c driver
.ValueConverter
258 var valueConverterTests
= []valueConverterTest
{
259 {driver
.DefaultParameterConverter
, NullString
{"hi", true}, "hi", ""},
260 {driver
.DefaultParameterConverter
, NullString
{"", false}, nil, ""},
263 func TestValueConverters(t
*testing
.T
) {
264 for i
, tt
:= range valueConverterTests
{
265 out
, err
:= tt
.c
.ConvertValue(tt
.in
)
270 if goterr
!= tt
.err
{
271 t
.Errorf("test %d: %T(%T(%v)) error = %q; want error = %q",
272 i
, tt
.c
, tt
.in
, tt
.in
, goterr
, tt
.err
)
277 if !reflect
.DeepEqual(out
, tt
.out
) {
278 t
.Errorf("test %d: %T(%T(%v)) = %v (%T); want %v (%T)",
279 i
, tt
.c
, tt
.in
, tt
.in
, out
, out
, tt
.out
, tt
.out
)
284 // Tests that assigning to RawBytes doesn't allocate (and also works).
285 func TestRawBytesAllocs(t
*testing
.T
) {
286 buf
:= make(RawBytes
, 10)
287 test
:= func(name
string, in
interface{}, want
string) {
288 if err
:= convertAssign(&buf
, in
); err
!= nil {
289 t
.Fatalf("%s: convertAssign = %v", name
, err
)
291 match
:= len(buf
) == len(want
)
293 for i
, b
:= range buf
{
301 t
.Fatalf("%s: got %q (len %d); want %q (len %d)", name
, buf
, len(buf
), want
, len(want
))
304 n
:= testing
.AllocsPerRun(100, func() {
305 test("uint64", uint64(12345678), "12345678")
306 test("uint32", uint32(1234), "1234")
307 test("uint16", uint16(12), "12")
308 test("uint8", uint8(1), "1")
309 test("uint", uint(123), "123")
310 test("int", int(123), "123")
311 test("int8", int8(1), "1")
312 test("int16", int16(12), "12")
313 test("int32", int32(1234), "1234")
314 test("int64", int64(12345678), "12345678")
315 test("float32", float32(1.5), "1.5")
316 test("float64", float64(64), "64")
317 test("bool", false, "false")
320 // The numbers below are only valid for 64-bit interface word sizes,
321 // and gc. With 32-bit words there are more convT2E allocs, and
322 // with gccgo, only pointers currently go in interface data.
323 // So only care on amd64 gc for now.
324 measureAllocs
:= runtime
.GOARCH
== "amd64" && runtime
.Compiler
== "gc"
326 if n
> 0.5 && measureAllocs
{
327 t
.Fatalf("allocs = %v; want 0", n
)
330 // This one involves a convT2E allocation, string -> interface{}
331 n
= testing
.AllocsPerRun(100, func() {
332 test("string", "foo", "foo")
334 if n
> 1.5 && measureAllocs
{
335 t
.Fatalf("allocs = %v; want max 1", n
)