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  }