Rebase.
[official-gcc.git] / libgo / go / database / sql / convert_test.go
blob6e248301283f9613afc43db8e7f6a8316d1e52de
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.
5 package sql
7 import (
8 "database/sql/driver"
9 "fmt"
10 "reflect"
11 "runtime"
12 "testing"
13 "time"
16 var someTime = time.Unix(123, 0)
17 var answer int64 = 42
19 type conversionTest struct {
20 s, d interface{} // source and destination
22 // following are used if they're non-zero
23 wantint int64
24 wantuint uint64
25 wantstr string
26 wantbytes []byte
27 wantraw RawBytes
28 wantf32 float32
29 wantf64 float64
30 wanttime time.Time
31 wantbool bool // used if d is of type *bool
32 wanterr string
33 wantiface interface{}
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.
39 var (
40 scanstr string
41 scanbytes []byte
42 scanraw RawBytes
43 scanint int
44 scanint8 int8
45 scanint16 int16
46 scanint32 int32
47 scanuint8 uint8
48 scanuint16 uint16
49 scanbool bool
50 scanf32 float32
51 scanf64 float64
52 scantime time.Time
53 scanptr *int64
54 scaniface interface{}
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},
63 // To strings
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"},
75 // To []byte
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")},
88 // To RawBytes
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`},
107 // True bools
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},
116 // False bools
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},
125 // Not bools
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`},
129 // Floats
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)},
136 // Pointers
137 {s: interface{}(nil), d: &scanptr, wantnil: true},
138 {s: int64(42), d: &scanptr, wantptr: &answer},
140 // To interface{}
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)
177 errstr := ""
178 if err != nil {
179 errstr = err.Error()
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)
222 continue
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) {
235 var ns NullString
236 convertAssign(&ns, []byte("foo"))
237 if !ns.Valid {
238 t.Errorf("expecting not null")
240 if ns.String != "foo" {
241 t.Errorf("expecting foo; got %q", ns.String)
243 convertAssign(&ns, nil)
244 if ns.Valid {
245 t.Errorf("expecting null on nil")
247 if ns.String != "" {
248 t.Errorf("expecting blank on nil; got %q", ns.String)
252 type valueConverterTest struct {
253 c driver.ValueConverter
254 in, out interface{}
255 err string
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)
266 goterr := ""
267 if err != nil {
268 goterr = err.Error()
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)
274 if tt.err != "" {
275 continue
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)
292 if match {
293 for i, b := range buf {
294 if want[i] != b {
295 match = false
296 break
300 if !match {
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)