Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / libgo / go / database / sql / convert_test.go
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.
4
5 package sql
6
7 import (
8         "database/sql/driver"
9         "fmt"
10         "reflect"
11         "testing"
12         "time"
13 )
14
15 var someTime = time.Unix(123, 0)
16 var answer int64 = 42
17
18 type conversionTest struct {
19         s, d interface{} // source and destination
20
21         // following are used if they're non-zero
22         wantint   int64
23         wantuint  uint64
24         wantstr   string
25         wantf32   float32
26         wantf64   float64
27         wanttime  time.Time
28         wantbool  bool // used if d is of type *bool
29         wanterr   string
30         wantiface interface{}
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)
33 }
34
35 // Target variables for scanning into.
36 var (
37         scanstr    string
38         scanint    int
39         scanint8   int8
40         scanint16  int16
41         scanint32  int32
42         scanuint8  uint8
43         scanuint16 uint16
44         scanbool   bool
45         scanf32    float32
46         scanf64    float64
47         scantime   time.Time
48         scanptr    *int64
49         scaniface  interface{}
50 )
51
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},
57
58         // To strings
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"},
68
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`},
75
76         // True bools
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},
84
85         // False bools
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},
93
94         // Not bools
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`},
97
98         // Floats
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)},
104
105         // Pointers
106         {s: interface{}(nil), d: &scanptr, wantnil: true},
107         {s: int64(42), d: &scanptr, wantptr: &answer},
108
109         // To interface{}
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},
116 }
117
118 func intPtrValue(intptr interface{}) interface{} {
119         return reflect.Indirect(reflect.Indirect(reflect.ValueOf(intptr))).Int()
120 }
121
122 func intValue(intptr interface{}) int64 {
123         return reflect.Indirect(reflect.ValueOf(intptr)).Int()
124 }
125
126 func uintValue(intptr interface{}) uint64 {
127         return reflect.Indirect(reflect.ValueOf(intptr)).Uint()
128 }
129
130 func float64Value(ptr interface{}) float64 {
131         return *(ptr.(*float64))
132 }
133
134 func float32Value(ptr interface{}) float32 {
135         return *(ptr.(*float32))
136 }
137
138 func timeValue(ptr interface{}) time.Time {
139         return *(ptr.(*time.Time))
140 }
141
142 func TestConversions(t *testing.T) {
143         for n, ct := range conversionTests {
144                 err := convertAssign(ct.d, ct.s)
145                 errstr := ""
146                 if err != nil {
147                         errstr = err.Error()
148                 }
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...)
152                 }
153                 if errstr != ct.wanterr {
154                         errf("got error %q, want error %q", errstr, ct.wanterr)
155                 }
156                 if ct.wantstr != "" && ct.wantstr != scanstr {
157                         errf("want string %q, got %q", ct.wantstr, scanstr)
158                 }
159                 if ct.wantint != 0 && ct.wantint != intValue(ct.d) {
160                         errf("want int %d, got %d", ct.wantint, intValue(ct.d))
161                 }
162                 if ct.wantuint != 0 && ct.wantuint != uintValue(ct.d) {
163                         errf("want uint %d, got %d", ct.wantuint, uintValue(ct.d))
164                 }
165                 if ct.wantf32 != 0 && ct.wantf32 != float32Value(ct.d) {
166                         errf("want float32 %v, got %v", ct.wantf32, float32Value(ct.d))
167                 }
168                 if ct.wantf64 != 0 && ct.wantf64 != float64Value(ct.d) {
169                         errf("want float32 %v, got %v", ct.wantf64, float64Value(ct.d))
170                 }
171                 if bp, boolTest := ct.d.(*bool); boolTest && *bp != ct.wantbool && ct.wanterr == "" {
172                         errf("want bool %v, got %v", ct.wantbool, *bp)
173                 }
174                 if !ct.wanttime.IsZero() && !ct.wanttime.Equal(timeValue(ct.d)) {
175                         errf("want time %v, got %v", ct.wanttime, timeValue(ct.d))
176                 }
177                 if ct.wantnil && *ct.d.(**int64) != nil {
178                         errf("want nil, got %v", intPtrValue(ct.d))
179                 }
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))
185                         }
186                 }
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)
190                                 continue
191                         }
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")
196                                 }
197                         }
198                 }
199         }
200 }
201
202 func TestNullString(t *testing.T) {
203         var ns NullString
204         convertAssign(&ns, []byte("foo"))
205         if !ns.Valid {
206                 t.Errorf("expecting not null")
207         }
208         if ns.String != "foo" {
209                 t.Errorf("expecting foo; got %q", ns.String)
210         }
211         convertAssign(&ns, nil)
212         if ns.Valid {
213                 t.Errorf("expecting null on nil")
214         }
215         if ns.String != "" {
216                 t.Errorf("expecting blank on nil; got %q", ns.String)
217         }
218 }
219
220 type valueConverterTest struct {
221         c       driver.ValueConverter
222         in, out interface{}
223         err     string
224 }
225
226 var valueConverterTests = []valueConverterTest{
227         {driver.DefaultParameterConverter, NullString{"hi", true}, "hi", ""},
228         {driver.DefaultParameterConverter, NullString{"", false}, nil, ""},
229 }
230
231 func TestValueConverters(t *testing.T) {
232         for i, tt := range valueConverterTests {
233                 out, err := tt.c.ConvertValue(tt.in)
234                 goterr := ""
235                 if err != nil {
236                         goterr = err.Error()
237                 }
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)
241                 }
242                 if tt.err != "" {
243                         continue
244                 }
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)
248                 }
249         }
250 }