github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/database/sql/convert_test.go (about) 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 wantbytes []byte 26 wantraw RawBytes 27 wantf32 float32 28 wantf64 float64 29 wanttime time.Time 30 wantbool bool // used if d is of type *bool 31 wanterr string 32 wantiface interface{} 33 wantptr *int64 // if non-nil, *d's pointed value must be equal to *wantptr 34 wantnil bool // if true, *d must be *int64(nil) 35 } 36 37 // Target variables for scanning into. 38 var ( 39 scanstr string 40 scanbytes []byte 41 scanraw RawBytes 42 scanint int 43 scanint8 int8 44 scanint16 int16 45 scanint32 int32 46 scanuint8 uint8 47 scanuint16 uint16 48 scanbool bool 49 scanf32 float32 50 scanf64 float64 51 scantime time.Time 52 scanptr *int64 53 scaniface interface{} 54 ) 55 56 var conversionTests = []conversionTest{ 57 // Exact conversions (destination pointer type matches source type) 58 {s: "foo", d: &scanstr, wantstr: "foo"}, 59 {s: 123, d: &scanint, wantint: 123}, 60 {s: someTime, d: &scantime, wanttime: someTime}, 61 62 // To strings 63 {s: "string", d: &scanstr, wantstr: "string"}, 64 {s: []byte("byteslice"), d: &scanstr, wantstr: "byteslice"}, 65 {s: 123, d: &scanstr, wantstr: "123"}, 66 {s: int8(123), d: &scanstr, wantstr: "123"}, 67 {s: int64(123), d: &scanstr, wantstr: "123"}, 68 {s: uint8(123), d: &scanstr, wantstr: "123"}, 69 {s: uint16(123), d: &scanstr, wantstr: "123"}, 70 {s: uint32(123), d: &scanstr, wantstr: "123"}, 71 {s: uint64(123), d: &scanstr, wantstr: "123"}, 72 {s: 1.5, d: &scanstr, wantstr: "1.5"}, 73 74 // To []byte 75 {s: nil, d: &scanbytes, wantbytes: nil}, 76 {s: "string", d: &scanbytes, wantbytes: []byte("string")}, 77 {s: []byte("byteslice"), d: &scanbytes, wantbytes: []byte("byteslice")}, 78 {s: 123, d: &scanbytes, wantbytes: []byte("123")}, 79 {s: int8(123), d: &scanbytes, wantbytes: []byte("123")}, 80 {s: int64(123), d: &scanbytes, wantbytes: []byte("123")}, 81 {s: uint8(123), d: &scanbytes, wantbytes: []byte("123")}, 82 {s: uint16(123), d: &scanbytes, wantbytes: []byte("123")}, 83 {s: uint32(123), d: &scanbytes, wantbytes: []byte("123")}, 84 {s: uint64(123), d: &scanbytes, wantbytes: []byte("123")}, 85 {s: 1.5, d: &scanbytes, wantbytes: []byte("1.5")}, 86 87 // To RawBytes 88 {s: nil, d: &scanraw, wantraw: nil}, 89 {s: []byte("byteslice"), d: &scanraw, wantraw: RawBytes("byteslice")}, 90 {s: 123, d: &scanraw, wantraw: RawBytes("123")}, 91 {s: int8(123), d: &scanraw, wantraw: RawBytes("123")}, 92 {s: int64(123), d: &scanraw, wantraw: RawBytes("123")}, 93 {s: uint8(123), d: &scanraw, wantraw: RawBytes("123")}, 94 {s: uint16(123), d: &scanraw, wantraw: RawBytes("123")}, 95 {s: uint32(123), d: &scanraw, wantraw: RawBytes("123")}, 96 {s: uint64(123), d: &scanraw, wantraw: RawBytes("123")}, 97 {s: 1.5, d: &scanraw, wantraw: RawBytes("1.5")}, 98 99 // Strings to integers 100 {s: "255", d: &scanuint8, wantuint: 255}, 101 {s: "256", d: &scanuint8, wanterr: `converting string "256" to a uint8: strconv.ParseUint: parsing "256": value out of range`}, 102 {s: "256", d: &scanuint16, wantuint: 256}, 103 {s: "-1", d: &scanint, wantint: -1}, 104 {s: "foo", d: &scanint, wanterr: `converting string "foo" to a int: strconv.ParseInt: parsing "foo": invalid syntax`}, 105 106 // True bools 107 {s: true, d: &scanbool, wantbool: true}, 108 {s: "True", d: &scanbool, wantbool: true}, 109 {s: "TRUE", d: &scanbool, wantbool: true}, 110 {s: "1", d: &scanbool, wantbool: true}, 111 {s: 1, d: &scanbool, wantbool: true}, 112 {s: int64(1), d: &scanbool, wantbool: true}, 113 {s: uint16(1), d: &scanbool, wantbool: true}, 114 115 // False bools 116 {s: false, d: &scanbool, wantbool: false}, 117 {s: "false", d: &scanbool, wantbool: false}, 118 {s: "FALSE", d: &scanbool, wantbool: false}, 119 {s: "0", d: &scanbool, wantbool: false}, 120 {s: 0, d: &scanbool, wantbool: false}, 121 {s: int64(0), d: &scanbool, wantbool: false}, 122 {s: uint16(0), d: &scanbool, wantbool: false}, 123 124 // Not bools 125 {s: "yup", d: &scanbool, wanterr: `sql/driver: couldn't convert "yup" into type bool`}, 126 {s: 2, d: &scanbool, wanterr: `sql/driver: couldn't convert 2 into type bool`}, 127 128 // Floats 129 {s: float64(1.5), d: &scanf64, wantf64: float64(1.5)}, 130 {s: int64(1), d: &scanf64, wantf64: float64(1)}, 131 {s: float64(1.5), d: &scanf32, wantf32: float32(1.5)}, 132 {s: "1.5", d: &scanf32, wantf32: float32(1.5)}, 133 {s: "1.5", d: &scanf64, wantf64: float64(1.5)}, 134 135 // Pointers 136 {s: interface{}(nil), d: &scanptr, wantnil: true}, 137 {s: int64(42), d: &scanptr, wantptr: &answer}, 138 139 // To interface{} 140 {s: float64(1.5), d: &scaniface, wantiface: float64(1.5)}, 141 {s: int64(1), d: &scaniface, wantiface: int64(1)}, 142 {s: "str", d: &scaniface, wantiface: "str"}, 143 {s: []byte("byteslice"), d: &scaniface, wantiface: []byte("byteslice")}, 144 {s: true, d: &scaniface, wantiface: true}, 145 {s: nil, d: &scaniface}, 146 {s: []byte(nil), d: &scaniface, wantiface: []byte(nil)}, 147 } 148 149 func intPtrValue(intptr interface{}) interface{} { 150 return reflect.Indirect(reflect.Indirect(reflect.ValueOf(intptr))).Int() 151 } 152 153 func intValue(intptr interface{}) int64 { 154 return reflect.Indirect(reflect.ValueOf(intptr)).Int() 155 } 156 157 func uintValue(intptr interface{}) uint64 { 158 return reflect.Indirect(reflect.ValueOf(intptr)).Uint() 159 } 160 161 func float64Value(ptr interface{}) float64 { 162 return *(ptr.(*float64)) 163 } 164 165 func float32Value(ptr interface{}) float32 { 166 return *(ptr.(*float32)) 167 } 168 169 func timeValue(ptr interface{}) time.Time { 170 return *(ptr.(*time.Time)) 171 } 172 173 func TestConversions(t *testing.T) { 174 for n, ct := range conversionTests { 175 err := convertAssign(ct.d, ct.s) 176 errstr := "" 177 if err != nil { 178 errstr = err.Error() 179 } 180 errf := func(format string, args ...interface{}) { 181 base := fmt.Sprintf("convertAssign #%d: for %v (%T) -> %T, ", n, ct.s, ct.s, ct.d) 182 t.Errorf(base+format, args...) 183 } 184 if errstr != ct.wanterr { 185 errf("got error %q, want error %q", errstr, ct.wanterr) 186 } 187 if ct.wantstr != "" && ct.wantstr != scanstr { 188 errf("want string %q, got %q", ct.wantstr, scanstr) 189 } 190 if ct.wantint != 0 && ct.wantint != intValue(ct.d) { 191 errf("want int %d, got %d", ct.wantint, intValue(ct.d)) 192 } 193 if ct.wantuint != 0 && ct.wantuint != uintValue(ct.d) { 194 errf("want uint %d, got %d", ct.wantuint, uintValue(ct.d)) 195 } 196 if ct.wantf32 != 0 && ct.wantf32 != float32Value(ct.d) { 197 errf("want float32 %v, got %v", ct.wantf32, float32Value(ct.d)) 198 } 199 if ct.wantf64 != 0 && ct.wantf64 != float64Value(ct.d) { 200 errf("want float32 %v, got %v", ct.wantf64, float64Value(ct.d)) 201 } 202 if bp, boolTest := ct.d.(*bool); boolTest && *bp != ct.wantbool && ct.wanterr == "" { 203 errf("want bool %v, got %v", ct.wantbool, *bp) 204 } 205 if !ct.wanttime.IsZero() && !ct.wanttime.Equal(timeValue(ct.d)) { 206 errf("want time %v, got %v", ct.wanttime, timeValue(ct.d)) 207 } 208 if ct.wantnil && *ct.d.(**int64) != nil { 209 errf("want nil, got %v", intPtrValue(ct.d)) 210 } 211 if ct.wantptr != nil { 212 if *ct.d.(**int64) == nil { 213 errf("want pointer to %v, got nil", *ct.wantptr) 214 } else if *ct.wantptr != intPtrValue(ct.d) { 215 errf("want pointer to %v, got %v", *ct.wantptr, intPtrValue(ct.d)) 216 } 217 } 218 if ifptr, ok := ct.d.(*interface{}); ok { 219 if !reflect.DeepEqual(ct.wantiface, scaniface) { 220 errf("want interface %#v, got %#v", ct.wantiface, scaniface) 221 continue 222 } 223 if srcBytes, ok := ct.s.([]byte); ok { 224 dstBytes := (*ifptr).([]byte) 225 if len(srcBytes) > 0 && &dstBytes[0] == &srcBytes[0] { 226 errf("copy into interface{} didn't copy []byte data") 227 } 228 } 229 } 230 } 231 } 232 233 func TestNullString(t *testing.T) { 234 var ns NullString 235 convertAssign(&ns, []byte("foo")) 236 if !ns.Valid { 237 t.Errorf("expecting not null") 238 } 239 if ns.String != "foo" { 240 t.Errorf("expecting foo; got %q", ns.String) 241 } 242 convertAssign(&ns, nil) 243 if ns.Valid { 244 t.Errorf("expecting null on nil") 245 } 246 if ns.String != "" { 247 t.Errorf("expecting blank on nil; got %q", ns.String) 248 } 249 } 250 251 type valueConverterTest struct { 252 c driver.ValueConverter 253 in, out interface{} 254 err string 255 } 256 257 var valueConverterTests = []valueConverterTest{ 258 {driver.DefaultParameterConverter, NullString{"hi", true}, "hi", ""}, 259 {driver.DefaultParameterConverter, NullString{"", false}, nil, ""}, 260 } 261 262 func TestValueConverters(t *testing.T) { 263 for i, tt := range valueConverterTests { 264 out, err := tt.c.ConvertValue(tt.in) 265 goterr := "" 266 if err != nil { 267 goterr = err.Error() 268 } 269 if goterr != tt.err { 270 t.Errorf("test %d: %s(%T(%v)) error = %q; want error = %q", 271 i, tt.c, tt.in, tt.in, goterr, tt.err) 272 } 273 if tt.err != "" { 274 continue 275 } 276 if !reflect.DeepEqual(out, tt.out) { 277 t.Errorf("test %d: %s(%T(%v)) = %v (%T); want %v (%T)", 278 i, tt.c, tt.in, tt.in, out, out, tt.out, tt.out) 279 } 280 } 281 }