github.com/Ali-iotechsys/sqlboiler/v4@v4.0.0-20221208124957-6aec9a5f1f71/queries/reflect_test.go (about)

     1  package queries
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"database/sql"
     7  	"database/sql/driver"
     8  	"fmt"
     9  	"reflect"
    10  	"strconv"
    11  	"strings"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/volatiletech/sqlboiler/v4/drivers"
    16  	"github.com/volatiletech/null/v8"
    17  
    18  	"github.com/DATA-DOG/go-sqlmock"
    19  )
    20  
    21  func bin64(i uint64) string {
    22  	str := strconv.FormatUint(i, 2)
    23  	pad := 64 - len(str)
    24  	if pad > 0 {
    25  		str = strings.Repeat("0", pad) + str
    26  	}
    27  
    28  	var newStr string
    29  	for i := 0; i < len(str); i += 8 {
    30  		if i != 0 {
    31  			newStr += " "
    32  		}
    33  		newStr += str[i : i+8]
    34  	}
    35  
    36  	return newStr
    37  }
    38  
    39  type mockRowMaker struct {
    40  	int
    41  	rows []driver.Value
    42  }
    43  
    44  func TestBindStruct(t *testing.T) {
    45  	t.Parallel()
    46  
    47  	testResults := struct {
    48  		ID   int
    49  		Name string `boil:"test"`
    50  	}{}
    51  
    52  	query := &Query{
    53  		from:    []string{"fun"},
    54  		dialect: &drivers.Dialect{LQ: '"', RQ: '"', UseIndexPlaceholders: true},
    55  	}
    56  
    57  	db, mock, err := sqlmock.New()
    58  	if err != nil {
    59  		t.Error(err)
    60  	}
    61  
    62  	ret := sqlmock.NewRows([]string{"id", "test"})
    63  	ret.AddRow(driver.Value(int64(35)), driver.Value("pat"))
    64  	ret.AddRow(driver.Value(int64(65)), driver.Value("hat"))
    65  	mock.ExpectQuery(`SELECT \* FROM "fun";`).WillReturnRows(ret)
    66  
    67  	err = query.Bind(nil, db, &testResults)
    68  	if err != nil {
    69  		t.Error(err)
    70  	}
    71  
    72  	if id := testResults.ID; id != 35 {
    73  		t.Error("wrong ID:", id)
    74  	}
    75  	if name := testResults.Name; name != "pat" {
    76  		t.Error("wrong name:", name)
    77  	}
    78  
    79  	if err := mock.ExpectationsWereMet(); err != nil {
    80  		t.Error(err)
    81  	}
    82  }
    83  
    84  func TestBindSlice(t *testing.T) {
    85  	t.Parallel()
    86  
    87  	testResults := []struct {
    88  		ID   int
    89  		Name string `boil:"test"`
    90  	}{}
    91  
    92  	query := &Query{
    93  		from:    []string{"fun"},
    94  		dialect: &drivers.Dialect{LQ: '"', RQ: '"', UseIndexPlaceholders: true},
    95  	}
    96  
    97  	db, mock, err := sqlmock.New()
    98  	if err != nil {
    99  		t.Error(err)
   100  	}
   101  
   102  	ret := sqlmock.NewRows([]string{"id", "test"})
   103  	ret.AddRow(driver.Value(int64(35)), driver.Value("pat"))
   104  	ret.AddRow(driver.Value(int64(12)), driver.Value("cat"))
   105  	mock.ExpectQuery(`SELECT \* FROM "fun";`).WillReturnRows(ret)
   106  
   107  	err = query.Bind(nil, db, &testResults)
   108  	if err != nil {
   109  		t.Error(err)
   110  	}
   111  
   112  	if len(testResults) != 2 {
   113  		t.Fatal("wrong number of results:", len(testResults))
   114  	}
   115  	if id := testResults[0].ID; id != 35 {
   116  		t.Error("wrong ID:", id)
   117  	}
   118  	if name := testResults[0].Name; name != "pat" {
   119  		t.Error("wrong name:", name)
   120  	}
   121  
   122  	if id := testResults[1].ID; id != 12 {
   123  		t.Error("wrong ID:", id)
   124  	}
   125  	if name := testResults[1].Name; name != "cat" {
   126  		t.Error("wrong name:", name)
   127  	}
   128  
   129  	if err := mock.ExpectationsWereMet(); err != nil {
   130  		t.Error(err)
   131  	}
   132  }
   133  
   134  func TestBindPtrSlice(t *testing.T) {
   135  	t.Parallel()
   136  
   137  	testResults := []*struct {
   138  		ID   int
   139  		Name string `boil:"test"`
   140  	}{}
   141  
   142  	query := &Query{
   143  		from:    []string{"fun"},
   144  		dialect: &drivers.Dialect{LQ: '"', RQ: '"', UseIndexPlaceholders: true},
   145  	}
   146  
   147  	db, mock, err := sqlmock.New()
   148  	if err != nil {
   149  		t.Error(err)
   150  	}
   151  
   152  	ret := sqlmock.NewRows([]string{"id", "test"})
   153  	ret.AddRow(driver.Value(int64(35)), driver.Value("pat"))
   154  	ret.AddRow(driver.Value(int64(12)), driver.Value("cat"))
   155  	mock.ExpectQuery(`SELECT \* FROM "fun";`).WillReturnRows(ret)
   156  
   157  	err = query.Bind(context.Background(), db, &testResults)
   158  	if err != nil {
   159  		t.Error(err)
   160  	}
   161  
   162  	if len(testResults) != 2 {
   163  		t.Fatal("wrong number of results:", len(testResults))
   164  	}
   165  	if id := testResults[0].ID; id != 35 {
   166  		t.Error("wrong ID:", id)
   167  	}
   168  	if name := testResults[0].Name; name != "pat" {
   169  		t.Error("wrong name:", name)
   170  	}
   171  
   172  	if id := testResults[1].ID; id != 12 {
   173  		t.Error("wrong ID:", id)
   174  	}
   175  	if name := testResults[1].Name; name != "cat" {
   176  		t.Error("wrong name:", name)
   177  	}
   178  
   179  	if err := mock.ExpectationsWereMet(); err != nil {
   180  		t.Error(err)
   181  	}
   182  }
   183  
   184  func testMakeMapping(byt ...byte) uint64 {
   185  	var x uint64
   186  	for i, b := range byt {
   187  		x |= uint64(b) << (uint(i) * 8)
   188  	}
   189  	x |= uint64(255) << uint(len(byt)*8)
   190  	return x
   191  }
   192  
   193  func TestMakeStructMapping(t *testing.T) {
   194  	t.Parallel()
   195  
   196  	var testStruct = struct {
   197  		LastName    string `boil:"different"`
   198  		AwesomeName string `boil:"awesome_name"`
   199  		Face        string `boil:"-"`
   200  		Nose        string
   201  
   202  		Nested struct {
   203  			LastName    string `boil:"different"`
   204  			AwesomeName string `boil:"awesome_name"`
   205  			Face        string `boil:"-"`
   206  			Nose        string
   207  
   208  			Nested2 struct {
   209  				Nose string
   210  			} `boil:",bind"`
   211  		} `boil:",bind"`
   212  	}{}
   213  
   214  	got := MakeStructMapping(reflect.TypeOf(testStruct))
   215  
   216  	expectMap := map[string]uint64{
   217  		"different":           testMakeMapping(0),
   218  		"awesome_name":        testMakeMapping(1),
   219  		"nose":                testMakeMapping(3),
   220  		"nested.different":    testMakeMapping(4, 0),
   221  		"nested.awesome_name": testMakeMapping(4, 1),
   222  		"nested.nose":         testMakeMapping(4, 3),
   223  		"nested.nested2.nose": testMakeMapping(4, 4, 0),
   224  	}
   225  
   226  	for expName, expVal := range expectMap {
   227  		gotVal, ok := got[expName]
   228  		if !ok {
   229  			t.Errorf("%s) had no value", expName)
   230  			continue
   231  		}
   232  
   233  		if gotVal != expVal {
   234  			t.Errorf("%s) wrong value,\nwant: %x (%s)\ngot:  %x (%s)", expName, expVal, bin64(expVal), gotVal, bin64(gotVal))
   235  		}
   236  	}
   237  }
   238  
   239  func TestPtrFromMapping(t *testing.T) {
   240  	t.Parallel()
   241  
   242  	type NestedPtrs struct {
   243  		Int         int
   244  		IntP        *int
   245  		NestedPtrsP *NestedPtrs
   246  	}
   247  
   248  	val := &NestedPtrs{
   249  		Int:  5,
   250  		IntP: new(int),
   251  		NestedPtrsP: &NestedPtrs{
   252  			Int:  6,
   253  			IntP: new(int),
   254  		},
   255  	}
   256  
   257  	v := ptrFromMapping(reflect.Indirect(reflect.ValueOf(val)), testMakeMapping(0), true)
   258  	if got := *v.Interface().(*int); got != 5 {
   259  		t.Error("flat int was wrong:", got)
   260  	}
   261  	v = ptrFromMapping(reflect.Indirect(reflect.ValueOf(val)), testMakeMapping(1), true)
   262  	if got := *v.Interface().(*int); got != 0 {
   263  		t.Error("flat pointer was wrong:", got)
   264  	}
   265  	v = ptrFromMapping(reflect.Indirect(reflect.ValueOf(val)), testMakeMapping(2, 0), true)
   266  	if got := *v.Interface().(*int); got != 6 {
   267  		t.Error("nested int was wrong:", got)
   268  	}
   269  	v = ptrFromMapping(reflect.Indirect(reflect.ValueOf(val)), testMakeMapping(2, 1), true)
   270  	if got := *v.Interface().(*int); got != 0 {
   271  		t.Error("nested pointer was wrong:", got)
   272  	}
   273  }
   274  
   275  func TestValuesFromMapping(t *testing.T) {
   276  	t.Parallel()
   277  
   278  	type NestedPtrs struct {
   279  		Int         int
   280  		IntP        *int
   281  		NestedPtrsP *NestedPtrs
   282  	}
   283  
   284  	val := &NestedPtrs{
   285  		Int:  5,
   286  		IntP: new(int),
   287  		NestedPtrsP: &NestedPtrs{
   288  			Int:  6,
   289  			IntP: new(int),
   290  		},
   291  	}
   292  	mapping := []uint64{testMakeMapping(0), testMakeMapping(1), testMakeMapping(2, 0), testMakeMapping(2, 1), 0}
   293  	v := ValuesFromMapping(reflect.Indirect(reflect.ValueOf(val)), mapping)
   294  
   295  	if got := v[0].(int); got != 5 {
   296  		t.Error("flat int was wrong:", got)
   297  	}
   298  	if got := v[1].(int); got != 0 {
   299  		t.Error("flat pointer was wrong:", got)
   300  	}
   301  	if got := v[2].(int); got != 6 {
   302  		t.Error("nested int was wrong:", got)
   303  	}
   304  	if got := v[3].(int); got != 0 {
   305  		t.Error("nested pointer was wrong:", got)
   306  	}
   307  	if got := *v[4].(*interface{}); got != nil {
   308  		t.Error("nil pointer was not be ignored:", got)
   309  	}
   310  }
   311  
   312  func TestPtrsFromMapping(t *testing.T) {
   313  	t.Parallel()
   314  
   315  	type NestedPtrs struct {
   316  		Int         int
   317  		IntP        *int
   318  		NestedPtrsP *NestedPtrs
   319  	}
   320  
   321  	val := &NestedPtrs{
   322  		Int:  5,
   323  		IntP: new(int),
   324  		NestedPtrsP: &NestedPtrs{
   325  			Int:  6,
   326  			IntP: new(int),
   327  		},
   328  	}
   329  
   330  	mapping := []uint64{testMakeMapping(0), testMakeMapping(1), testMakeMapping(2, 0), testMakeMapping(2, 1)}
   331  	v := PtrsFromMapping(reflect.Indirect(reflect.ValueOf(val)), mapping)
   332  
   333  	if got := *v[0].(*int); got != 5 {
   334  		t.Error("flat int was wrong:", got)
   335  	}
   336  	if got := *v[1].(*int); got != 0 {
   337  		t.Error("flat pointer was wrong:", got)
   338  	}
   339  	if got := *v[2].(*int); got != 6 {
   340  		t.Error("nested int was wrong:", got)
   341  	}
   342  	if got := *v[3].(*int); got != 0 {
   343  		t.Error("nested pointer was wrong:", got)
   344  	}
   345  }
   346  
   347  func TestGetBoilTag(t *testing.T) {
   348  	t.Parallel()
   349  
   350  	type TestStruct struct {
   351  		FirstName   string `boil:"test_one,bind"`
   352  		LastName    string `boil:"test_two"`
   353  		MiddleName  string `boil:"middle_name,bind"`
   354  		AwesomeName string `boil:"awesome_name"`
   355  		Age         string `boil:",bind"`
   356  		Face        string `boil:"-"`
   357  		Nose        string
   358  	}
   359  
   360  	var structFields []reflect.StructField
   361  	typ := reflect.TypeOf(TestStruct{})
   362  	removeOk := func(thing reflect.StructField, ok bool) reflect.StructField {
   363  		if !ok {
   364  			panic("Exploded")
   365  		}
   366  		return thing
   367  	}
   368  	structFields = append(structFields, removeOk(typ.FieldByName("FirstName")))
   369  	structFields = append(structFields, removeOk(typ.FieldByName("LastName")))
   370  	structFields = append(structFields, removeOk(typ.FieldByName("MiddleName")))
   371  	structFields = append(structFields, removeOk(typ.FieldByName("AwesomeName")))
   372  	structFields = append(structFields, removeOk(typ.FieldByName("Age")))
   373  	structFields = append(structFields, removeOk(typ.FieldByName("Face")))
   374  	structFields = append(structFields, removeOk(typ.FieldByName("Nose")))
   375  
   376  	expect := []struct {
   377  		Name    string
   378  		Recurse bool
   379  	}{
   380  		{"test_one", true},
   381  		{"test_two", false},
   382  		{"middle_name", true},
   383  		{"awesome_name", false},
   384  		{"", true},
   385  		{"-", false},
   386  		{"", false},
   387  	}
   388  	for i, s := range structFields {
   389  		name, recurse := getBoilTag(s)
   390  		if expect[i].Name != name {
   391  			t.Errorf("Invalid name, expect %q, got %q", expect[i].Name, name)
   392  		}
   393  		if expect[i].Recurse != recurse {
   394  			t.Errorf("Invalid recurse, expect %v, got %v", !recurse, recurse)
   395  		}
   396  	}
   397  }
   398  
   399  func TestBindChecks(t *testing.T) {
   400  	t.Parallel()
   401  
   402  	type useless struct {
   403  	}
   404  
   405  	var tests = []struct {
   406  		BKind bindKind
   407  		Fail  bool
   408  		Obj   interface{}
   409  	}{
   410  		{BKind: kindStruct, Fail: false, Obj: &useless{}},
   411  		{BKind: kindSliceStruct, Fail: false, Obj: &[]useless{}},
   412  		{BKind: kindPtrSliceStruct, Fail: false, Obj: &[]*useless{}},
   413  		{Fail: true, Obj: 5},
   414  		{Fail: true, Obj: useless{}},
   415  		{Fail: true, Obj: []useless{}},
   416  	}
   417  
   418  	for i, test := range tests {
   419  		str, sli, bk, err := bindChecks(test.Obj)
   420  
   421  		if err != nil {
   422  			if !test.Fail {
   423  				t.Errorf("%d) should not fail, got: %v", i, err)
   424  			}
   425  			continue
   426  		} else if test.Fail {
   427  			t.Errorf("%d) should fail, got: %v", i, bk)
   428  			continue
   429  		}
   430  
   431  		if s := str.Kind(); s != reflect.Struct {
   432  			t.Error("struct kind was wrong:", s)
   433  		}
   434  		if test.BKind != kindStruct {
   435  			if s := sli.Kind(); s != reflect.Slice {
   436  				t.Error("slice kind was wrong:", s)
   437  			}
   438  		}
   439  	}
   440  }
   441  
   442  func TestBindSingular(t *testing.T) {
   443  	t.Parallel()
   444  
   445  	testResults := struct {
   446  		ID   int
   447  		Name string `boil:"test"`
   448  	}{}
   449  
   450  	query := &Query{
   451  		from:    []string{"fun"},
   452  		dialect: &drivers.Dialect{LQ: '"', RQ: '"', UseIndexPlaceholders: true},
   453  	}
   454  
   455  	db, mock, err := sqlmock.New()
   456  	if err != nil {
   457  		t.Error(err)
   458  	}
   459  
   460  	ret := sqlmock.NewRows([]string{"id", "test"})
   461  	ret.AddRow(driver.Value(int64(35)), driver.Value("pat"))
   462  	mock.ExpectQuery(`SELECT \* FROM "fun";`).WillReturnRows(ret)
   463  
   464  	err = query.Bind(nil, db, &testResults)
   465  	if err != nil {
   466  		t.Error(err)
   467  	}
   468  
   469  	if id := testResults.ID; id != 35 {
   470  		t.Error("wrong ID:", id)
   471  	}
   472  	if name := testResults.Name; name != "pat" {
   473  		t.Error("wrong name:", name)
   474  	}
   475  
   476  	if err := mock.ExpectationsWereMet(); err != nil {
   477  		t.Error(err)
   478  	}
   479  }
   480  
   481  func TestBind_InnerJoin(t *testing.T) {
   482  	t.Parallel()
   483  
   484  	testResults := []*struct {
   485  		Happy struct {
   486  			ID int `boil:"identifier"`
   487  		} `boil:",bind"`
   488  		Fun struct {
   489  			ID int `boil:"id"`
   490  		} `boil:",bind"`
   491  	}{}
   492  
   493  	query := &Query{
   494  		from:    []string{"fun"},
   495  		joins:   []join{{kind: JoinInner, clause: "happy as h on fun.id = h.fun_id"}},
   496  		dialect: &drivers.Dialect{LQ: '"', RQ: '"', UseIndexPlaceholders: true},
   497  	}
   498  
   499  	db, mock, err := sqlmock.New()
   500  	if err != nil {
   501  		t.Error(err)
   502  	}
   503  
   504  	ret := sqlmock.NewRows([]string{"id"})
   505  	ret.AddRow(driver.Value(int64(10)))
   506  	ret.AddRow(driver.Value(int64(11)))
   507  	mock.ExpectQuery(`SELECT "fun"\.\* FROM "fun" INNER JOIN happy as h on fun.id = h.fun_id;`).WillReturnRows(ret)
   508  
   509  	err = query.Bind(nil, db, &testResults)
   510  	if err != nil {
   511  		t.Error(err)
   512  	}
   513  
   514  	if len(testResults) != 2 {
   515  		t.Fatal("wrong number of results:", len(testResults))
   516  	}
   517  	if id := testResults[0].Happy.ID; id != 0 {
   518  		t.Error("wrong ID:", id)
   519  	}
   520  	if id := testResults[0].Fun.ID; id != 10 {
   521  		t.Error("wrong ID:", id)
   522  	}
   523  
   524  	if id := testResults[1].Happy.ID; id != 0 {
   525  		t.Error("wrong ID:", id)
   526  	}
   527  	if id := testResults[1].Fun.ID; id != 11 {
   528  		t.Error("wrong ID:", id)
   529  	}
   530  
   531  	if err := mock.ExpectationsWereMet(); err != nil {
   532  		t.Error(err)
   533  	}
   534  }
   535  
   536  func TestBind_InnerJoinSelect(t *testing.T) {
   537  	t.Parallel()
   538  
   539  	testResults := []*struct {
   540  		Happy struct {
   541  			ID int
   542  		} `boil:"h,bind"`
   543  		Fun struct {
   544  			ID int
   545  		} `boil:",bind"`
   546  	}{}
   547  
   548  	query := &Query{
   549  		dialect:    &drivers.Dialect{LQ: '"', RQ: '"', UseIndexPlaceholders: true},
   550  		selectCols: []string{"fun.id", "h.id"},
   551  		from:       []string{"fun"},
   552  		joins:      []join{{kind: JoinInner, clause: "happy as h on fun.happy_id = h.id"}},
   553  	}
   554  
   555  	db, mock, err := sqlmock.New()
   556  	if err != nil {
   557  		t.Error(err)
   558  	}
   559  
   560  	ret := sqlmock.NewRows([]string{"fun.id", "h.id"})
   561  	ret.AddRow(driver.Value(int64(10)), driver.Value(int64(11)))
   562  	ret.AddRow(driver.Value(int64(12)), driver.Value(int64(13)))
   563  	mock.ExpectQuery(`SELECT "fun"."id" as "fun.id", "h"."id" as "h.id" FROM "fun" INNER JOIN happy as h on fun.happy_id = h.id;`).WillReturnRows(ret)
   564  
   565  	err = query.Bind(nil, db, &testResults)
   566  	if err != nil {
   567  		t.Error(err)
   568  	}
   569  
   570  	if len(testResults) != 2 {
   571  		t.Fatal("wrong number of results:", len(testResults))
   572  	}
   573  	if id := testResults[0].Happy.ID; id != 11 {
   574  		t.Error("wrong ID:", id)
   575  	}
   576  	if id := testResults[0].Fun.ID; id != 10 {
   577  		t.Error("wrong ID:", id)
   578  	}
   579  
   580  	if id := testResults[1].Happy.ID; id != 13 {
   581  		t.Error("wrong ID:", id)
   582  	}
   583  	if id := testResults[1].Fun.ID; id != 12 {
   584  		t.Error("wrong ID:", id)
   585  	}
   586  
   587  	if err := mock.ExpectationsWereMet(); err != nil {
   588  		t.Error(err)
   589  	}
   590  }
   591  
   592  func TestEqual(t *testing.T) {
   593  	t.Parallel()
   594  
   595  	now := time.Now()
   596  
   597  	tests := []struct {
   598  		A    interface{}
   599  		B    interface{}
   600  		Want bool
   601  	}{
   602  		{A: int(5), B: int(5), Want: true},
   603  		{A: int(5), B: int(6), Want: false},
   604  		{A: int(5), B: int32(5), Want: true},
   605  		{A: []byte("hello"), B: []byte("hello"), Want: true},
   606  		{A: []byte("hello"), B: []byte("world"), Want: false},
   607  		{A: "hello", B: sql.NullString{String: "hello", Valid: true}, Want: true},
   608  		{A: "hello", B: sql.NullString{Valid: false}, Want: false},
   609  		{A: now, B: now, Want: true},
   610  		{A: now, B: now.Add(time.Hour), Want: false},
   611  		{A: null.Uint64From(uint64(9223372036854775808)), B: uint64(9223372036854775808), Want: true},
   612  		{A: null.Uint64From(uint64(9223372036854775808)), B: uint64(9223372036854775809), Want: false},
   613  	}
   614  
   615  	for i, test := range tests {
   616  		if got := Equal(test.A, test.B); got != test.Want {
   617  			t.Errorf("%d) compare %#v and %#v resulted in wrong value, want: %t, got %t", i, test.A, test.B, test.Want, got)
   618  		}
   619  	}
   620  }
   621  
   622  func TestAssignBytes(t *testing.T) {
   623  	t.Parallel()
   624  
   625  	var dst []byte
   626  	var src = []byte("hello")
   627  
   628  	Assign(&dst, src)
   629  	if !bytes.Equal(dst, src) {
   630  		t.Error("bytes were not equal!")
   631  	}
   632  }
   633  
   634  func TestAssignScanValue(t *testing.T) {
   635  	t.Parallel()
   636  
   637  	var nsDst sql.NullString
   638  	var nsSrc sql.NullString
   639  
   640  	nsSrc.String = "hello"
   641  	nsSrc.Valid = true
   642  
   643  	Assign(&nsDst, nsSrc)
   644  
   645  	if !nsDst.Valid {
   646  		t.Error("n was still null")
   647  	}
   648  	if nsDst.String != "hello" {
   649  		t.Error("assignment did not occur")
   650  	}
   651  
   652  	var niDst sql.NullInt64
   653  	var niSrc sql.NullInt64
   654  
   655  	niSrc.Valid = true
   656  	niSrc.Int64 = 5
   657  
   658  	Assign(&niDst, niSrc)
   659  
   660  	if !niDst.Valid {
   661  		t.Error("n was still null")
   662  	}
   663  	if niDst.Int64 != 5 {
   664  		t.Error("assignment did not occur")
   665  	}
   666  }
   667  
   668  func TestAssignScanNoValue(t *testing.T) {
   669  	t.Parallel()
   670  
   671  	var ns sql.NullString
   672  	s := "hello"
   673  
   674  	Assign(&ns, s)
   675  
   676  	if !ns.Valid {
   677  		t.Error("n was still null")
   678  	}
   679  	if ns.String != "hello" {
   680  		t.Error("assignment did not occur")
   681  	}
   682  
   683  	var niDst sql.NullInt64
   684  	i := 5
   685  
   686  	Assign(&niDst, i)
   687  
   688  	if !niDst.Valid {
   689  		t.Error("n was still null")
   690  	}
   691  	if niDst.Int64 != 5 {
   692  		t.Error("assignment did not occur")
   693  	}
   694  }
   695  
   696  func TestAssignNoScanValue(t *testing.T) {
   697  	t.Parallel()
   698  
   699  	var ns sql.NullString
   700  	var s string
   701  
   702  	ns.String = "hello"
   703  	ns.Valid = true
   704  	Assign(&s, ns)
   705  
   706  	if s != "hello" {
   707  		t.Error("assignment did not occur")
   708  	}
   709  
   710  	var ni sql.NullInt64
   711  	var i int
   712  
   713  	ni.Int64 = 5
   714  	ni.Valid = true
   715  	Assign(&i, ni)
   716  
   717  	if i != 5 {
   718  		t.Error("assignment did not occur")
   719  	}
   720  }
   721  
   722  func TestAssignNil(t *testing.T) {
   723  	t.Parallel()
   724  
   725  	var ns sql.NullString
   726  	s := "hello"
   727  
   728  	Assign(&s, ns)
   729  	if s != "" {
   730  		t.Errorf("should have assigned a zero value: %q", s)
   731  	}
   732  }
   733  
   734  func TestAssignPanic(t *testing.T) {
   735  	t.Parallel()
   736  
   737  	defer func() {
   738  		if r := recover(); r == nil {
   739  			t.Error("expected a panic")
   740  		}
   741  	}()
   742  
   743  	var aint, bint int
   744  	Assign(&aint, bint)
   745  }
   746  
   747  type nullTime struct {
   748  	Time  time.Time
   749  	Valid bool
   750  }
   751  
   752  func (t *nullTime) Scan(value interface{}) error {
   753  	var err error
   754  	switch x := value.(type) {
   755  	case time.Time:
   756  		t.Time = x
   757  	case nil:
   758  		t.Valid = false
   759  		return nil
   760  	default:
   761  		err = fmt.Errorf("cannot scan type %T into nullTime: %v", value, value)
   762  	}
   763  	t.Valid = err == nil
   764  	return err
   765  }
   766  
   767  // Value implements the driver Valuer interface.
   768  func (t nullTime) Value() (driver.Value, error) {
   769  	if !t.Valid {
   770  		return nil, nil
   771  	}
   772  	return t.Time, nil
   773  }
   774  
   775  func TestMustTime(t *testing.T) {
   776  	t.Parallel()
   777  
   778  	var nt nullTime
   779  
   780  	if !MustTime(nt).IsZero() {
   781  		t.Error("should be zero")
   782  	}
   783  
   784  	now := time.Now()
   785  
   786  	nt.Valid = true
   787  	nt.Time = now
   788  
   789  	if !MustTime(nt).Equal(now) {
   790  		t.Error("time was wrong")
   791  	}
   792  }
   793  
   794  func TestMustTimePanic(t *testing.T) {
   795  	t.Parallel()
   796  
   797  	defer func() {
   798  		if r := recover(); r == nil {
   799  			t.Error("it should have panic'd")
   800  		}
   801  	}()
   802  
   803  	var ns sql.NullString
   804  	ns.Valid = true
   805  	ns.String = "hello"
   806  	MustTime(ns)
   807  }
   808  
   809  func TestIsValuerNil(t *testing.T) {
   810  	t.Parallel()
   811  
   812  	var ns sql.NullString
   813  	if !IsValuerNil(ns) {
   814  		t.Error("it should be nil")
   815  	}
   816  
   817  	ns.Valid = true
   818  	if IsValuerNil(ns) {
   819  		t.Error("it should not be nil")
   820  	}
   821  }
   822  
   823  func TestSetScanner(t *testing.T) {
   824  	t.Parallel()
   825  
   826  	var ns sql.NullString
   827  	SetScanner(&ns, "hello")
   828  
   829  	if !ns.Valid {
   830  		t.Error("it should not be null")
   831  	}
   832  	if ns.String != "hello" {
   833  		t.Error("it's value should have been hello")
   834  	}
   835  }
   836  
   837  func TestSetScannerPanic(t *testing.T) {
   838  	t.Parallel()
   839  
   840  	defer func() {
   841  		if r := recover(); r == nil {
   842  			t.Error("it should have panic'd")
   843  		}
   844  	}()
   845  
   846  	var ns nullTime
   847  	SetScanner(&ns, "hello")
   848  }
   849  
   850  func TestUnTitleCase(t *testing.T) {
   851  	t.Parallel()
   852  
   853  	tests := []struct {
   854  		In  string
   855  		Out string
   856  	}{
   857  		{"HelloThere", "hello_there"},
   858  		{"", ""},
   859  		{"AA", "aa"},
   860  		{"FunID", "fun_id"},
   861  		{"UID", "uid"},
   862  		{"GUID", "guid"},
   863  		{"UID", "uid"},
   864  		{"UUID", "uuid"},
   865  		{"SSN", "ssn"},
   866  		{"TZ", "tz"},
   867  		{"ThingGUID", "thing_guid"},
   868  		{"GUIDThing", "guid_thing"},
   869  		{"ThingGUIDThing", "thing_guid_thing"},
   870  		{"ID", "id"},
   871  		{"GVZXC", "gvzxc"},
   872  		{"IDTRGBID", "id_trgb_id"},
   873  		{"ThingZXCStuffVXZ", "thing_zxc_stuff_vxz"},
   874  		{"ZXCThingVXZStuff", "zxc_thing_vxz_stuff"},
   875  		{"ZXCVDF9C9Hello9", "zxcvdf9_c9_hello9"},
   876  		{"ID9UID911GUID9E9", "id9_uid911_guid9_e9"},
   877  		{"ZXCVDF0C0Hello0", "zxcvdf0_c0_hello0"},
   878  		{"ID0UID000GUID0E0", "id0_uid000_guid0_e0"},
   879  		{"Ab5ZXC5D5", "ab5_zxc5_d5"},
   880  		{"Identifier", "identifier"},
   881  	}
   882  
   883  	for i, test := range tests {
   884  		if out := unTitleCase(test.In); out != test.Out {
   885  			t.Errorf("[%d] (%s) Out was wrong: %q, want: %q", i, test.In, out, test.Out)
   886  		}
   887  	}
   888  }