github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/kit/sqlx/database_test.go (about)

     1  package sqlx_test
     2  
     3  import (
     4  	"context"
     5  	"database/sql/driver"
     6  	"testing"
     7  	"time"
     8  
     9  	// . "github.com/onsi/gomega"
    10  
    11  	"github.com/machinefi/w3bstream/pkg/depends/base/types"
    12  	"github.com/machinefi/w3bstream/pkg/depends/conf/log"
    13  	"github.com/machinefi/w3bstream/pkg/depends/kit/sqlx/builder"
    14  )
    15  
    16  var connectors map[string]driver.Connector
    17  
    18  func init() {
    19  	connectors = make(map[string]driver.Connector)
    20  	// TODO add other database connector for testing
    21  	// mysqlConnector = &mysql.MysqlConnector{
    22  	// 	Host:  "root@tcp(0.0.0.0:3306)",
    23  	// 	Extra: "charset=utf8mb4&parseTime=true&interpolateParams=true&autocommit=true&loc=Local",
    24  	// }
    25  
    26  	// postgres
    27  	/*
    28  		{
    29  			ep := postgrestestutil.Endpoint
    30  			connectors["postgres"] = &postgres.Connector{
    31  				Extra:      "sslmode=disable",
    32  				Extensions: []string{"postgis"},
    33  				Host: fmt.Sprintf(
    34  					"postgresql://%s:%s@127.0.0.1:5432",
    35  					ep.Master.Username, ep.Master.Password,
    36  				),
    37  			}
    38  		}
    39  	*/
    40  }
    41  
    42  func Background() context.Context {
    43  	return log.WithLogger(context.Background(), log.Std())
    44  }
    45  
    46  type OperateTime struct {
    47  	CreatedAt types.Datetime `db:"f_created_at,default=CURRENT_TIMESTAMP,onupdate=CURRENT_TIMESTAMP"`
    48  	UpdatedAt int64          `db:"f_updated_at,default='0'"`
    49  }
    50  
    51  type Gender int
    52  
    53  const (
    54  	GenderMale Gender = iota + 1
    55  	GenderFemale
    56  )
    57  
    58  func (Gender) EnumType() string {
    59  	return "Gender"
    60  }
    61  
    62  func (Gender) Enums() map[int][]string {
    63  	return map[int][]string{
    64  		int(GenderMale):   {"male", "男"},
    65  		int(GenderFemale): {"female", "女"},
    66  	}
    67  }
    68  
    69  func (g Gender) String() string {
    70  	switch g {
    71  	case GenderMale:
    72  		return "male"
    73  	case GenderFemale:
    74  		return "female"
    75  	}
    76  	return ""
    77  }
    78  
    79  type User struct {
    80  	ID       uint64 `db:"f_id,autoincrement"`
    81  	Name     string `db:"f_name,size=255,default=''"`
    82  	Nickname string `db:"f_nickname,size=255,default=''"`
    83  	Username string `db:"f_username,default=''"`
    84  	Gender   Gender `db:"f_gender,default='0'"`
    85  
    86  	OperateTime
    87  }
    88  
    89  func (user *User) Comments() map[string]string {
    90  	return map[string]string{
    91  		"Name": "姓名",
    92  	}
    93  }
    94  
    95  func (user *User) TableName() string {
    96  	return "t_user"
    97  }
    98  
    99  func (user *User) PrimaryKey() []string {
   100  	return []string{"ID"}
   101  }
   102  
   103  func (user *User) Indexes() builder.Indexes {
   104  	return builder.Indexes{
   105  		"i_nickname": {"Nickname"},
   106  	}
   107  }
   108  
   109  func (user *User) UniqueIndexes() builder.Indexes {
   110  	return builder.Indexes{
   111  		"i_name": {"Name"},
   112  	}
   113  }
   114  
   115  type User2 struct {
   116  	ID       uint64 `db:"f_id,autoincrement"`
   117  	Nickname string `db:"f_nickname,size=255,default=''"`
   118  	Gender   Gender `db:"f_gender,default='0'"`
   119  	Name     string `db:"f_name,deprecated=f_real_name"`
   120  	RealName string `db:"f_real_name,size=255,default=''"`
   121  	Age      int32  `db:"f_age,default='0'"`
   122  	Username string `db:"f_username,deprecated"`
   123  }
   124  
   125  func (user *User2) TableName() string {
   126  	return "t_user"
   127  }
   128  
   129  func (user *User2) PrimaryKey() []string {
   130  	return []string{"ID"}
   131  }
   132  
   133  func (user *User2) Indexes() builder.Indexes {
   134  	return builder.Indexes{
   135  		"i_nickname": {"Nickname"},
   136  	}
   137  }
   138  
   139  func (user *User2) UniqueIndexes() builder.Indexes {
   140  	return builder.Indexes{
   141  		"i_name": {"RealName"},
   142  	}
   143  }
   144  
   145  func DISABLED_TestMigrate(t *testing.T) {
   146  	/*
   147  		os.Setenv("PROJECT_FEATURE", "test1")
   148  		defer func() {
   149  			os.Remove("PROJECT_FEATURE")
   150  		}()
   151  
   152  		dbTest := sqlx.NewDatabase("test_for_migrate")
   153  
   154  		for name, connector := range connectors {
   155  			t.Run(name, func(t *testing.T) {
   156  				for _, schema := range []string{"import", "public", "backup"} {
   157  					dbTest.Tables.Range(func(table *builder.Table, idx int) {
   158  						db := dbTest.OpenDB(connector).WithSchema(schema)
   159  						_, _ = db.Exec(db.Dialect().DropTable(table))
   160  					})
   161  
   162  					t.Run("CreateTable_"+schema, func(t *testing.T) {
   163  						dbTest.Register(&User{})
   164  						db := dbTest.OpenDB(connector).WithSchema(schema)
   165  
   166  						t.Run("First", func(t *testing.T) {
   167  							err := migration.Migrate(db, nil)
   168  							NewWithT(t).Expect(err).To(BeNil())
   169  						})
   170  
   171  						t.Run("Again", func(t *testing.T) {
   172  							_ = migration.Migrate(db, os.Stdout)
   173  							err := migration.Migrate(db, nil)
   174  							NewWithT(t).Expect(err).To(BeNil())
   175  						})
   176  					})
   177  
   178  					t.Run("NoMigrate_"+schema, func(t *testing.T) {
   179  						dbTest.Register(&User{})
   180  						db := dbTest.OpenDB(connector).WithSchema(schema)
   181  						err := migration.Migrate(db, nil)
   182  						NewWithT(t).Expect(err).To(BeNil())
   183  
   184  						t.Run("migrate to user2", func(t *testing.T) {
   185  							dbTest.Register(&User2{})
   186  							db := dbTest.OpenDB(connector).WithSchema(schema)
   187  							err := migration.Migrate(db, nil)
   188  							NewWithT(t).Expect(err).To(BeNil())
   189  						})
   190  
   191  						t.Run("migrate to user2 again", func(t *testing.T) {
   192  							dbTest.Register(&User2{})
   193  							db := dbTest.OpenDB(connector).WithSchema(schema)
   194  							err := migration.Migrate(db, nil)
   195  							NewWithT(t).Expect(err).To(BeNil())
   196  						})
   197  					})
   198  
   199  					t.Run("MigrateToUser_"+schema, func(t *testing.T) {
   200  						db := dbTest.OpenDB(connector).WithSchema(schema)
   201  						err := migration.Migrate(db, os.Stdout)
   202  						NewWithT(t).Expect(err).To(BeNil())
   203  						err = migration.Migrate(db, nil)
   204  						NewWithT(t).Expect(err).To(BeNil())
   205  					})
   206  
   207  					dbTest.Tables.Range(func(table *builder.Table, idx int) {
   208  						db := dbTest.OpenDB(connector).WithSchema(schema)
   209  						_, _ = db.Exec(db.Dialect().DropTable(table))
   210  					})
   211  				}
   212  			})
   213  		}
   214  	*/
   215  }
   216  
   217  func DISABLED_TestCRUD(t *testing.T) {
   218  	/*
   219  		dbTest := sqlx.NewDatabase("test_crud")
   220  
   221  		for name, connector := range connectors {
   222  			t.Run(name, func(t *testing.T) {
   223  				d := dbTest.OpenDB(connector)
   224  				db := d.WithContext(metax.ContextWithMeta(d.Context(), metax.ParseMeta("_id=11111")))
   225  				userTable := dbTest.Register(&User{})
   226  				err := migration.Migrate(db, nil)
   227  
   228  				NewWithT(t).Expect(err).To(BeNil())
   229  
   230  				t.Run("InsertSingle", func(t *testing.T) {
   231  					user := User{
   232  						Name:   uuid.New().String(),
   233  						Gender: GenderMale,
   234  					}
   235  
   236  					t.Run("Canceled", func(t *testing.T) {
   237  						ctx, cancel := context.WithCancel(Background())
   238  						db2 := db.WithContext(ctx)
   239  
   240  						go func() {
   241  							time.Sleep(5 * time.Millisecond)
   242  							cancel()
   243  						}()
   244  
   245  						err := sqlx.NewTasks(db2).
   246  							With(
   247  								func(db sqlx.DBExecutor) error {
   248  									_, err := db.Exec(sqlx.InsertToDB(db, &user, nil))
   249  									return err
   250  								},
   251  								func(db sqlx.DBExecutor) error {
   252  									time.Sleep(10 * time.Millisecond)
   253  									return nil
   254  								},
   255  							).
   256  							Do()
   257  
   258  						NewWithT(t).Expect(err).NotTo(BeNil())
   259  					})
   260  
   261  					_, err := db.Exec(sqlx.InsertToDB(db, &user, nil))
   262  					NewWithT(t).Expect(err).To(BeNil())
   263  
   264  					t.Run("Update", func(t *testing.T) {
   265  						user.Gender = GenderFemale
   266  						_, err := db.Exec(
   267  							builder.Update(dbTest.T(&user)).
   268  								Set(sqlx.AsAssignments(db, &user)...).
   269  								Where(
   270  									userTable.ColByFieldName("Name").Eq(user.Name),
   271  								),
   272  						)
   273  						NewWithT(t).Expect(err).To(BeNil())
   274  					})
   275  					t.Run("Select", func(t *testing.T) {
   276  						userForSelect := User{}
   277  						err := db.QueryAndScan(
   278  							builder.Select(nil).From(
   279  								userTable,
   280  								builder.Where(userTable.ColByFieldName("Name").Eq(user.Name)),
   281  								builder.Comment("FindUser"),
   282  							),
   283  							&userForSelect)
   284  
   285  						NewWithT(t).Expect(err).To(BeNil())
   286  
   287  						NewWithT(t).Expect(user.Name).To(Equal(userForSelect.Name))
   288  						NewWithT(t).Expect(user.Gender).To(Equal(userForSelect.Gender))
   289  					})
   290  					t.Run("Conflict", func(t *testing.T) {
   291  						_, err := db.Exec(sqlx.InsertToDB(db, &user, nil))
   292  						NewWithT(t).Expect(sqlx.DBErr(err).IsConflict()).To(BeTrue())
   293  					})
   294  				})
   295  				db.(*sqlx.DB).Tables.Range(func(table *builder.Table, idx int) {
   296  					_, err := db.Exec(db.Dialect().DropTable(table))
   297  					NewWithT(t).Expect(err).To(BeNil())
   298  				})
   299  			})
   300  		}
   301  	*/
   302  }
   303  
   304  type UserSet map[string]*User
   305  
   306  func (UserSet) New() interface{} {
   307  	return &User{}
   308  }
   309  
   310  func (u UserSet) Next(v interface{}) error {
   311  	user := v.(*User)
   312  	u[user.Name] = user
   313  	time.Sleep(500 * time.Microsecond)
   314  	return nil
   315  }
   316  
   317  func DISABLED_TestSelect(t *testing.T) {
   318  	/*
   319  		dbTest := sqlx.NewDatabase("test_for_select")
   320  
   321  		for name, connector := range connectors {
   322  			t.Run(name, func(t *testing.T) {
   323  				db := dbTest.OpenDB(connector)
   324  				table := dbTest.Register(&User{})
   325  
   326  				db.Tables.Range(func(t *builder.Table, idx int) {
   327  					_, _ = db.Exec(db.Dialect().DropTable(t))
   328  				})
   329  
   330  				err := migration.Migrate(db, nil)
   331  				NewWithT(t).Expect(err).To(BeNil())
   332  
   333  				{
   334  					columns := table.MustColsByFieldNames("Name", "Gender")
   335  					values := make([]interface{}, 0)
   336  
   337  					for i := 0; i < 1000; i++ {
   338  						values = append(values, uuid.New().String(), GenderMale)
   339  					}
   340  
   341  					_, err := db.Exec(
   342  						builder.Insert().Into(table).Values(columns, values...),
   343  					)
   344  					NewWithT(t).Expect(err).To(BeNil())
   345  				}
   346  
   347  				t.Run("SelectToSlice", func(t *testing.T) {
   348  					users := make([]User, 0)
   349  					err := db.QueryAndScan(
   350  						builder.Select(nil).From(
   351  							table,
   352  							builder.Where(
   353  								table.ColByFieldName("Gender").Eq(GenderMale),
   354  							),
   355  						),
   356  						&users,
   357  					)
   358  					NewWithT(t).Expect(err).To(BeNil())
   359  					NewWithT(t).Expect(users).To(HaveLen(1000))
   360  				})
   361  
   362  				t.Run("SelectToIter", func(t *testing.T) {
   363  					userSet := UserSet{}
   364  					err := db.QueryAndScan(
   365  						builder.Select(nil).From(
   366  							table,
   367  							builder.Where(
   368  								table.ColByFieldName("Gender").Eq(GenderMale),
   369  							),
   370  						),
   371  						userSet,
   372  					)
   373  					NewWithT(t).Expect(err).To(BeNil())
   374  					NewWithT(t).Expect(userSet).To(HaveLen(1000))
   375  				})
   376  
   377  				t.Run("NotFound", func(t *testing.T) {
   378  					user := User{}
   379  					err := db.QueryAndScan(
   380  						builder.Select(nil).From(
   381  							table,
   382  							builder.Where(
   383  								table.ColByFieldName("ID").Eq(1001),
   384  							),
   385  						),
   386  						&user,
   387  					)
   388  					NewWithT(t).Expect(sqlx.DBErr(err).IsNotFound()).To(BeTrue())
   389  				})
   390  
   391  				t.Run("SelectCount", func(t *testing.T) {
   392  					count := 0
   393  					err := db.QueryAndScan(
   394  						builder.Select(builder.Count()).From(table),
   395  						&count,
   396  					)
   397  					NewWithT(t).Expect(err).To(BeNil())
   398  					NewWithT(t).Expect(count).To(Equal(1000))
   399  				})
   400  
   401  				t.Run("Canceled", func(t *testing.T) {
   402  					ctx, cancel := context.WithCancel(Background())
   403  					db2 := db.WithContext(ctx)
   404  
   405  					go func() {
   406  						time.Sleep(3 * time.Millisecond)
   407  						cancel()
   408  					}()
   409  
   410  					userSet := UserSet{}
   411  					err := db2.QueryAndScan(
   412  						builder.Select(nil).From(
   413  							table,
   414  							builder.Where(
   415  								table.ColByFieldName("Gender").Eq(GenderMale),
   416  							),
   417  						),
   418  						userSet,
   419  					)
   420  					NewWithT(t).Expect(err).NotTo(BeNil())
   421  				})
   422  
   423  				db.Tables.Range(func(tab *builder.Table, idx int) {
   424  					_, _ = db.Exec(db.Dialect().DropTable(tab))
   425  				})
   426  			})
   427  		}
   428  	*/
   429  }