mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
merge develop
This commit is contained in:
24
.example/database/gdb/mysql/gdb_batch_insert.go
Normal file
24
.example/database/gdb/mysql/gdb_batch_insert.go
Normal file
@ -0,0 +1,24 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
)
|
||||
|
||||
func main() {
|
||||
db := g.DB()
|
||||
db.SetDebug(true)
|
||||
list := make(g.List, 0)
|
||||
for i := 0; i < 100; i++ {
|
||||
list = append(list, g.Map{
|
||||
"name": fmt.Sprintf(`name_%d`, i),
|
||||
})
|
||||
}
|
||||
r, e := db.Table("user").Data(list).Batch(2).Insert()
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
if r != nil {
|
||||
fmt.Println(r.LastInsertId())
|
||||
}
|
||||
}
|
||||
@ -690,7 +690,7 @@ func (c *Core) DoBatchInsert(link Link, table string, list interface{}, option i
|
||||
}
|
||||
}
|
||||
valueHolder = append(valueHolder, "("+gstr.Join(values, ",")+")")
|
||||
if len(values) == batchNum || (i == listMapLen-1 && len(values) > 0) {
|
||||
if len(valueHolder) == batchNum || (i == listMapLen-1 && len(valueHolder) > 0) {
|
||||
r, err := c.DB.DoExec(
|
||||
link,
|
||||
fmt.Sprintf(
|
||||
|
||||
@ -42,7 +42,7 @@ func (d *DriverMysql) Open(config *ConfigNode) (*sql.DB, error) {
|
||||
}
|
||||
} else {
|
||||
source = fmt.Sprintf(
|
||||
"%s:%s@tcp(%s:%s)/%s?charset=%s&multiStatements=true&parseTime=true",
|
||||
"%s:%s@tcp(%s:%s)/%s?charset=%s",
|
||||
config.User, config.Pass, config.Host, config.Port, config.Name, config.Charset,
|
||||
)
|
||||
}
|
||||
|
||||
@ -164,6 +164,11 @@ func (m *Model) doInsertWithOption(option int) (result sql.Result, err error) {
|
||||
if m.batch > 0 {
|
||||
batch = m.batch
|
||||
}
|
||||
newData, err := m.filterDataForInsertOrUpdate(list)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list = newData.(List)
|
||||
// Automatic handling for creating/updating time.
|
||||
if !m.unscoped && (fieldNameCreate != "" || fieldNameUpdate != "") {
|
||||
for k, v := range list {
|
||||
@ -177,10 +182,6 @@ func (m *Model) doInsertWithOption(option int) (result sql.Result, err error) {
|
||||
list[k] = v
|
||||
}
|
||||
}
|
||||
newData, err := m.filterDataForInsertOrUpdate(list)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m.db.DoBatchInsert(
|
||||
m.getLink(true),
|
||||
m.tables,
|
||||
@ -191,6 +192,11 @@ func (m *Model) doInsertWithOption(option int) (result sql.Result, err error) {
|
||||
}
|
||||
// Single operation.
|
||||
if data, ok := m.data.(Map); ok {
|
||||
newData, err := m.filterDataForInsertOrUpdate(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data = newData.(Map)
|
||||
// Automatic handling for creating/updating time.
|
||||
if !m.unscoped && (fieldNameCreate != "" || fieldNameUpdate != "") {
|
||||
gutil.MapDelete(data, fieldNameCreate, fieldNameUpdate, fieldNameDelete)
|
||||
@ -201,10 +207,6 @@ func (m *Model) doInsertWithOption(option int) (result sql.Result, err error) {
|
||||
data[fieldNameUpdate] = nowString
|
||||
}
|
||||
}
|
||||
newData, err := m.filterDataForInsertOrUpdate(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m.db.DoInsert(
|
||||
m.getLink(true),
|
||||
m.tables,
|
||||
|
||||
@ -8,11 +8,9 @@ package gdb
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"github.com/gogf/gf/text/gstr"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
"github.com/gogf/gf/util/gutil"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
@ -42,19 +40,19 @@ import (
|
||||
// given <relation> parameter.
|
||||
//
|
||||
// See the example or unit testing cases for clear understanding for this function.
|
||||
func (r Result) ScanList(listPointer interface{}, attributeName string, relation ...string) (err error) {
|
||||
func (r Result) ScanList(listPointer interface{}, bindToAttrName string, relationKV ...string) (err error) {
|
||||
// Necessary checks for parameters.
|
||||
if attributeName == "" {
|
||||
return gerror.New(`attributeName should not be empty`)
|
||||
}
|
||||
if len(relation) > 0 {
|
||||
if len(relation) < 2 {
|
||||
return gerror.New(`relation name and key should are both necessary`)
|
||||
}
|
||||
if relation[0] == "" || relation[1] == "" {
|
||||
return gerror.New(`relation name and key should not be empty`)
|
||||
}
|
||||
if bindToAttrName == "" {
|
||||
return gerror.New(`bindToAttrName should not be empty`)
|
||||
}
|
||||
//if len(relation) > 0 {
|
||||
// if len(relation) < 2 {
|
||||
// return gerror.New(`relation name and key should are both necessary`)
|
||||
// }
|
||||
// if relation[0] == "" || relation[1] == "" {
|
||||
// return gerror.New(`relation name and key should not be empty`)
|
||||
// }
|
||||
//}
|
||||
|
||||
var (
|
||||
reflectValue = reflect.ValueOf(listPointer)
|
||||
@ -65,12 +63,12 @@ func (r Result) ScanList(listPointer interface{}, attributeName string, relation
|
||||
reflectKind = reflectValue.Kind()
|
||||
}
|
||||
if reflectKind != reflect.Ptr {
|
||||
return fmt.Errorf("parameter should be type of *[]struct/*[]*struct, but got: %v", reflectKind)
|
||||
return gerror.Newf("parameter should be type of *[]struct/*[]*struct, but got: %v", reflectKind)
|
||||
}
|
||||
reflectValue = reflectValue.Elem()
|
||||
reflectKind = reflectValue.Kind()
|
||||
if reflectKind != reflect.Slice && reflectKind != reflect.Array {
|
||||
return fmt.Errorf("parameter should be type of *[]struct/*[]*struct, but got: %v", reflectKind)
|
||||
return gerror.Newf("parameter should be type of *[]struct/*[]*struct, but got: %v", reflectKind)
|
||||
}
|
||||
length := len(r)
|
||||
if length == 0 {
|
||||
@ -101,59 +99,61 @@ func (r Result) ScanList(listPointer interface{}, attributeName string, relation
|
||||
|
||||
// Relation variables.
|
||||
var (
|
||||
relationDataMap map[string]Value
|
||||
relationFieldName string
|
||||
relationAttrName string
|
||||
relationKVStr string
|
||||
relationDataMap map[string]Value
|
||||
relationFromAttrName string // Eg: relationKV: User, uid:Uid -> User
|
||||
relationResultFieldName string // Eg: relationKV: uid:Uid -> uid
|
||||
relationBindToSubAttrName string // Eg: relationKV: uid:Uid -> Uid
|
||||
)
|
||||
if len(relation) > 0 {
|
||||
array := gstr.Split(relation[1], ":")
|
||||
if len(array) > 1 {
|
||||
if len(relationKV) > 0 {
|
||||
if len(relationKV) == 1 {
|
||||
relationKVStr = relationKV[0]
|
||||
} else {
|
||||
relationFromAttrName = relationKV[0]
|
||||
relationKVStr = relationKV[1]
|
||||
}
|
||||
array := gstr.SplitAndTrim(relationKVStr, ":")
|
||||
if len(array) == 2 {
|
||||
// Defined table field to relation attribute name.
|
||||
// Like:
|
||||
// uid:Uid
|
||||
// uid:UserId
|
||||
relationFieldName = array[0]
|
||||
relationAttrName = array[1]
|
||||
relationResultFieldName = array[0]
|
||||
relationBindToSubAttrName = array[1]
|
||||
} else {
|
||||
relationAttrName = relation[1]
|
||||
// Find the possible map key by given only struct attribute name.
|
||||
// Like:
|
||||
// Uid
|
||||
if k, _ := gutil.MapPossibleItemByKey(r[0].Map(), relation[1]); k != "" {
|
||||
relationFieldName = k
|
||||
}
|
||||
return gerror.New(`parameter relationKV should be format of "ResultFieldName:BindToAttrName"`)
|
||||
}
|
||||
if relationFieldName != "" {
|
||||
relationDataMap = r.MapKeyValue(relationFieldName)
|
||||
if relationResultFieldName != "" {
|
||||
relationDataMap = r.MapKeyValue(relationResultFieldName)
|
||||
}
|
||||
if len(relationDataMap) == 0 {
|
||||
return fmt.Errorf(`cannot find the relation data map, maybe invalid relation key given: %s`, relation[1])
|
||||
return gerror.Newf(`cannot find the relation data map, maybe invalid relation given "%v"`, relationKV)
|
||||
}
|
||||
}
|
||||
// Bind to target attribute.
|
||||
var (
|
||||
ok bool
|
||||
attrValue reflect.Value
|
||||
attrKind reflect.Kind
|
||||
attrType reflect.Type
|
||||
attrField reflect.StructField
|
||||
ok bool
|
||||
bindToAttrValue reflect.Value
|
||||
bindToAttrKind reflect.Kind
|
||||
bindToAttrType reflect.Type
|
||||
bindToAttrField reflect.StructField
|
||||
)
|
||||
if arrayItemType.Kind() == reflect.Ptr {
|
||||
if attrField, ok = arrayItemType.Elem().FieldByName(attributeName); !ok {
|
||||
return fmt.Errorf(`invalid field name: %s`, attributeName)
|
||||
if bindToAttrField, ok = arrayItemType.Elem().FieldByName(bindToAttrName); !ok {
|
||||
return gerror.Newf(`invalid parameter bindToAttrName: cannot find attribute with name "%s" from slice element`, bindToAttrName)
|
||||
}
|
||||
} else {
|
||||
if attrField, ok = arrayItemType.FieldByName(attributeName); !ok {
|
||||
return fmt.Errorf(`invalid field name: %s`, attributeName)
|
||||
if bindToAttrField, ok = arrayItemType.FieldByName(bindToAttrName); !ok {
|
||||
return gerror.Newf(`invalid parameter bindToAttrName: cannot find attribute with name "%s" from slice element`, bindToAttrName)
|
||||
}
|
||||
}
|
||||
attrType = attrField.Type
|
||||
attrKind = attrType.Kind()
|
||||
bindToAttrType = bindToAttrField.Type
|
||||
bindToAttrKind = bindToAttrType.Kind()
|
||||
|
||||
// Bind to relation conditions.
|
||||
var (
|
||||
relationValue reflect.Value
|
||||
relationField reflect.Value
|
||||
relationFromAttrValue reflect.Value
|
||||
relationFromAttrField reflect.Value
|
||||
)
|
||||
for i := 0; i < arrayValue.Len(); i++ {
|
||||
arrayElemValue := arrayValue.Index(i)
|
||||
@ -173,41 +173,45 @@ func (r Result) ScanList(listPointer interface{}, attributeName string, relation
|
||||
} else {
|
||||
// Like: []Entity
|
||||
}
|
||||
attrValue = arrayElemValue.FieldByName(attributeName)
|
||||
if len(relation) > 0 {
|
||||
relationValue = arrayElemValue.FieldByName(relation[0])
|
||||
if relationValue.Kind() == reflect.Ptr {
|
||||
relationValue = relationValue.Elem()
|
||||
bindToAttrValue = arrayElemValue.FieldByName(bindToAttrName)
|
||||
if relationFromAttrName != "" {
|
||||
// Attribute value of current slice element.
|
||||
relationFromAttrValue = arrayElemValue.FieldByName(relationFromAttrName)
|
||||
if relationFromAttrValue.Kind() == reflect.Ptr {
|
||||
relationFromAttrValue = relationFromAttrValue.Elem()
|
||||
}
|
||||
} else {
|
||||
// Current slice element.
|
||||
relationFromAttrValue = arrayElemValue
|
||||
}
|
||||
if len(relationDataMap) > 0 && !relationValue.IsValid() {
|
||||
return fmt.Errorf(`invalid relation: "%s:%s"`, relation[0], relation[1])
|
||||
if len(relationDataMap) > 0 && !relationFromAttrValue.IsValid() {
|
||||
return gerror.Newf(`invalid relation specified: "%v"`, relationKV)
|
||||
}
|
||||
switch attrKind {
|
||||
switch bindToAttrKind {
|
||||
case reflect.Array, reflect.Slice:
|
||||
if len(relationDataMap) > 0 {
|
||||
relationField = relationValue.FieldByName(relationAttrName)
|
||||
if relationField.IsValid() {
|
||||
relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName)
|
||||
if relationFromAttrField.IsValid() {
|
||||
if err = gconv.Structs(
|
||||
relationDataMap[gconv.String(relationField.Interface())],
|
||||
attrValue.Addr(),
|
||||
relationDataMap[gconv.String(relationFromAttrField.Interface())],
|
||||
bindToAttrValue.Addr(),
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// May be the attribute does not exist yet.
|
||||
return fmt.Errorf(`invalid relation: "%s:%s"`, relation[0], relation[1])
|
||||
return gerror.Newf(`invalid relation specified: "%v"`, relationKV)
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf(`relationKey should not be empty as field "%s" is slice`, attributeName)
|
||||
return gerror.Newf(`relationKey should not be empty as field "%s" is slice`, bindToAttrName)
|
||||
}
|
||||
|
||||
case reflect.Ptr:
|
||||
e := reflect.New(attrType.Elem()).Elem()
|
||||
e := reflect.New(bindToAttrType.Elem()).Elem()
|
||||
if len(relationDataMap) > 0 {
|
||||
relationField = relationValue.FieldByName(relationAttrName)
|
||||
if relationField.IsValid() {
|
||||
v := relationDataMap[gconv.String(relationField.Interface())]
|
||||
relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName)
|
||||
if relationFromAttrField.IsValid() {
|
||||
v := relationDataMap[gconv.String(relationFromAttrField.Interface())]
|
||||
if v == nil {
|
||||
// There's no relational data.
|
||||
continue
|
||||
@ -217,7 +221,7 @@ func (r Result) ScanList(listPointer interface{}, attributeName string, relation
|
||||
}
|
||||
} else {
|
||||
// May be the attribute does not exist yet.
|
||||
return fmt.Errorf(`invalid relation: "%s:%s"`, relation[0], relation[1])
|
||||
return gerror.Newf(`invalid relation specified: "%v"`, relationKV)
|
||||
}
|
||||
} else {
|
||||
v := r[i]
|
||||
@ -229,14 +233,14 @@ func (r Result) ScanList(listPointer interface{}, attributeName string, relation
|
||||
return err
|
||||
}
|
||||
}
|
||||
attrValue.Set(e.Addr())
|
||||
bindToAttrValue.Set(e.Addr())
|
||||
|
||||
case reflect.Struct:
|
||||
e := reflect.New(attrType).Elem()
|
||||
e := reflect.New(bindToAttrType).Elem()
|
||||
if len(relationDataMap) > 0 {
|
||||
relationField = relationValue.FieldByName(relationAttrName)
|
||||
if relationField.IsValid() {
|
||||
relationDataItem := relationDataMap[gconv.String(relationField.Interface())]
|
||||
relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName)
|
||||
if relationFromAttrField.IsValid() {
|
||||
relationDataItem := relationDataMap[gconv.String(relationFromAttrField.Interface())]
|
||||
if relationDataItem == nil {
|
||||
// There's no relational data.
|
||||
continue
|
||||
@ -246,7 +250,7 @@ func (r Result) ScanList(listPointer interface{}, attributeName string, relation
|
||||
}
|
||||
} else {
|
||||
// May be the attribute does not exist yet.
|
||||
return fmt.Errorf(`invalid relation: "%s:%s"`, relation[0], relation[1])
|
||||
return gerror.Newf(`invalid relation specified: "%v"`, relationKV)
|
||||
}
|
||||
} else {
|
||||
relationDataItem := r[i]
|
||||
@ -258,10 +262,10 @@ func (r Result) ScanList(listPointer interface{}, attributeName string, relation
|
||||
return err
|
||||
}
|
||||
}
|
||||
attrValue.Set(e)
|
||||
bindToAttrValue.Set(e)
|
||||
|
||||
default:
|
||||
return fmt.Errorf(`unsupport attribute type: %s`, attrKind.String())
|
||||
return gerror.Newf(`unsupported attribute type: %s`, bindToAttrKind.String())
|
||||
}
|
||||
}
|
||||
reflect.ValueOf(listPointer).Elem().Set(arrayValue)
|
||||
|
||||
@ -472,3 +472,119 @@ CREATE TABLE %s (
|
||||
t.Assert(users[1].UserScores[4].Score, 5)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Table_Relation_EmbedStruct(t *testing.T) {
|
||||
var (
|
||||
tableUser = "user_" + gtime.TimestampMicroStr()
|
||||
tableUserDetail = "user_detail_" + gtime.TimestampMicroStr()
|
||||
tableUserScores = "user_scores_" + gtime.TimestampMicroStr()
|
||||
)
|
||||
if _, err := db.Exec(fmt.Sprintf(`
|
||||
CREATE TABLE %s (
|
||||
uid int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
name varchar(45) NOT NULL,
|
||||
PRIMARY KEY (uid)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
`, tableUser)); err != nil {
|
||||
gtest.Error(err)
|
||||
}
|
||||
defer dropTable(tableUser)
|
||||
|
||||
if _, err := db.Exec(fmt.Sprintf(`
|
||||
CREATE TABLE %s (
|
||||
uid int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
address varchar(45) NOT NULL,
|
||||
PRIMARY KEY (uid)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
`, tableUserDetail)); err != nil {
|
||||
gtest.Error(err)
|
||||
}
|
||||
defer dropTable(tableUserDetail)
|
||||
|
||||
if _, err := db.Exec(fmt.Sprintf(`
|
||||
CREATE TABLE %s (
|
||||
id int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
uid int(10) unsigned NOT NULL,
|
||||
score int(10) unsigned NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
`, tableUserScores)); err != nil {
|
||||
gtest.Error(err)
|
||||
}
|
||||
defer dropTable(tableUserScores)
|
||||
|
||||
type EntityUser struct {
|
||||
Uid int `json:"uid"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
type EntityUserDetail struct {
|
||||
*EntityUser
|
||||
Uid int `json:"uid"`
|
||||
Address string `json:"address"`
|
||||
}
|
||||
type EntityUserScores struct {
|
||||
*EntityUser
|
||||
*EntityUserDetail
|
||||
Id int `json:"id"`
|
||||
Uid int `json:"uid"`
|
||||
Score int `json:"score"`
|
||||
}
|
||||
|
||||
// Initialize the data.
|
||||
var err error
|
||||
for i := 1; i <= 5; i++ {
|
||||
// User.
|
||||
_, err = db.Insert(tableUser, g.Map{
|
||||
"uid": i,
|
||||
"name": fmt.Sprintf(`name_%d`, i),
|
||||
})
|
||||
gtest.Assert(err, nil)
|
||||
// Detail.
|
||||
_, err = db.Insert(tableUserDetail, g.Map{
|
||||
"uid": i,
|
||||
"address": fmt.Sprintf(`address_%d`, i),
|
||||
})
|
||||
gtest.Assert(err, nil)
|
||||
// Scores.
|
||||
for j := 1; j <= 5; j++ {
|
||||
_, err = db.Insert(tableUserScores, g.Map{
|
||||
"uid": i,
|
||||
"score": j,
|
||||
})
|
||||
gtest.Assert(err, nil)
|
||||
}
|
||||
}
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var (
|
||||
err error
|
||||
scores []*EntityUserScores
|
||||
)
|
||||
// SELECT * FROM `user_scores`
|
||||
err = db.Table(tableUserScores).Scan(&scores)
|
||||
t.Assert(err, nil)
|
||||
|
||||
// SELECT * FROM `user_scores` WHERE `uid` IN(1,2,3,4,5)
|
||||
err = db.Table(tableUser).
|
||||
Where("uid", gdb.ListItemValuesUnique(&scores, "Uid")).
|
||||
ScanList(&scores, "EntityUser", "uid:Uid")
|
||||
t.Assert(err, nil)
|
||||
|
||||
// SELECT * FROM `user_detail` WHERE `uid` IN(1,2,3,4,5)
|
||||
err = db.Table(tableUserDetail).
|
||||
Where("uid", gdb.ListItemValuesUnique(&scores, "Uid")).
|
||||
ScanList(&scores, "EntityUserDetail", "uid:Uid")
|
||||
t.Assert(err, nil)
|
||||
|
||||
// Assertions.
|
||||
t.Assert(len(scores), 25)
|
||||
t.Assert(scores[0].Id, 1)
|
||||
t.Assert(scores[0].Uid, 1)
|
||||
t.Assert(scores[0].Name, "name_1")
|
||||
t.Assert(scores[0].Address, "address_1")
|
||||
t.Assert(scores[24].Id, 25)
|
||||
t.Assert(scores[24].Uid, 5)
|
||||
t.Assert(scores[24].Name, "name_5")
|
||||
t.Assert(scores[24].Address, "address_5")
|
||||
})
|
||||
}
|
||||
|
||||
@ -17,8 +17,9 @@ import (
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
)
|
||||
|
||||
// CreateAt/UpdateAt/DeleteAt
|
||||
func Test_SoftCreateUpdateDeleteTime(t *testing.T) {
|
||||
table := "time_test_table"
|
||||
table := "time_test_table_" + gtime.TimestampNanoStr()
|
||||
if _, err := db.Exec(fmt.Sprintf(`
|
||||
CREATE TABLE %s (
|
||||
id int(11) NOT NULL,
|
||||
@ -50,7 +51,7 @@ CREATE TABLE %s (
|
||||
t.Assert(oneInsert["name"].String(), "name_1")
|
||||
t.Assert(oneInsert["delete_at"].String(), "")
|
||||
t.AssertGE(oneInsert["create_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
t.AssertGE(oneInsert["update_at"].GTime().Timestamp(), gtime.Timestamp())
|
||||
t.AssertGE(oneInsert["update_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
|
||||
// For time asserting purpose.
|
||||
time.Sleep(2 * time.Second)
|
||||
@ -72,7 +73,7 @@ CREATE TABLE %s (
|
||||
t.Assert(oneSave["delete_at"].String(), "")
|
||||
t.Assert(oneSave["create_at"].GTime().Timestamp(), oneInsert["create_at"].GTime().Timestamp())
|
||||
t.AssertNE(oneSave["update_at"].GTime().Timestamp(), oneInsert["update_at"].GTime().Timestamp())
|
||||
t.AssertGE(oneSave["update_at"].GTime().Timestamp(), gtime.Now().Timestamp()-2)
|
||||
t.AssertGE(oneSave["update_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
|
||||
// For time asserting purpose.
|
||||
time.Sleep(2 * time.Second)
|
||||
@ -92,7 +93,7 @@ CREATE TABLE %s (
|
||||
t.Assert(oneUpdate["name"].String(), "name_1000")
|
||||
t.Assert(oneUpdate["delete_at"].String(), "")
|
||||
t.Assert(oneUpdate["create_at"].GTime().Timestamp(), oneInsert["create_at"].GTime().Timestamp())
|
||||
t.AssertGE(oneUpdate["update_at"].GTime().Timestamp(), gtime.Now().Timestamp()-2)
|
||||
t.AssertGE(oneUpdate["update_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
|
||||
// Replace
|
||||
dataReplace := g.Map{
|
||||
@ -127,7 +128,282 @@ CREATE TABLE %s (
|
||||
one5, err := db.Table(table).Unscoped().FindOne(1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(one5["id"].Int(), 1)
|
||||
t.AssertGE(one5["delete_at"].GTime().Timestamp(), gtime.Now().Timestamp()-2)
|
||||
t.AssertGE(one5["delete_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
// Delete Count
|
||||
i, err := db.Table(table).FindCount()
|
||||
t.Assert(err, nil)
|
||||
t.Assert(i, 0)
|
||||
i, err = db.Table(table).Unscoped().FindCount()
|
||||
t.Assert(err, nil)
|
||||
t.Assert(i, 1)
|
||||
|
||||
// Delete Unscoped
|
||||
r, err = db.Table(table).Unscoped().Delete("id", 1)
|
||||
t.Assert(err, nil)
|
||||
n, _ = r.RowsAffected()
|
||||
t.Assert(n, 1)
|
||||
one6, err := db.Table(table).Unscoped().FindOne(1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(one6), 0)
|
||||
i, err = db.Table(table).Unscoped().FindCount()
|
||||
t.Assert(err, nil)
|
||||
t.Assert(i, 0)
|
||||
})
|
||||
}
|
||||
|
||||
// CreatedAt/UpdatedAt/DeletedAt
|
||||
func Test_SoftCreatedUpdatedDeletedTime_Map(t *testing.T) {
|
||||
table := "time_test_table_" + gtime.TimestampNanoStr()
|
||||
if _, err := db.Exec(fmt.Sprintf(`
|
||||
CREATE TABLE %s (
|
||||
id int(11) NOT NULL,
|
||||
name varchar(45) DEFAULT NULL,
|
||||
created_at datetime DEFAULT NULL,
|
||||
updated_at datetime DEFAULT NULL,
|
||||
deleted_at datetime DEFAULT NULL,
|
||||
PRIMARY KEY (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
`, table)); err != nil {
|
||||
gtest.Error(err)
|
||||
}
|
||||
defer dropTable(table)
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
// Insert
|
||||
dataInsert := g.Map{
|
||||
"id": 1,
|
||||
"name": "name_1",
|
||||
}
|
||||
r, err := db.Table(table).Data(dataInsert).Insert()
|
||||
t.Assert(err, nil)
|
||||
n, _ := r.RowsAffected()
|
||||
t.Assert(n, 1)
|
||||
|
||||
oneInsert, err := db.Table(table).FindOne(1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(oneInsert["id"].Int(), 1)
|
||||
t.Assert(oneInsert["name"].String(), "name_1")
|
||||
t.Assert(oneInsert["deleted_at"].String(), "")
|
||||
t.AssertGE(oneInsert["created_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
t.AssertGE(oneInsert["updated_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
|
||||
// For time asserting purpose.
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// Save
|
||||
dataSave := g.Map{
|
||||
"id": 1,
|
||||
"name": "name_10",
|
||||
}
|
||||
r, err = db.Table(table).Data(dataSave).Save()
|
||||
t.Assert(err, nil)
|
||||
n, _ = r.RowsAffected()
|
||||
t.Assert(n, 2)
|
||||
|
||||
oneSave, err := db.Table(table).FindOne(1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(oneSave["id"].Int(), 1)
|
||||
t.Assert(oneSave["name"].String(), "name_10")
|
||||
t.Assert(oneSave["deleted_at"].String(), "")
|
||||
t.Assert(oneSave["created_at"].GTime().Timestamp(), oneInsert["created_at"].GTime().Timestamp())
|
||||
t.AssertNE(oneSave["updated_at"].GTime().Timestamp(), oneInsert["updated_at"].GTime().Timestamp())
|
||||
t.AssertGE(oneSave["updated_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
|
||||
// For time asserting purpose.
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// Update
|
||||
dataUpdate := g.Map{
|
||||
"name": "name_1000",
|
||||
}
|
||||
r, err = db.Table(table).Data(dataUpdate).WherePri(1).Update()
|
||||
t.Assert(err, nil)
|
||||
n, _ = r.RowsAffected()
|
||||
t.Assert(n, 1)
|
||||
|
||||
oneUpdate, err := db.Table(table).FindOne(1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(oneUpdate["id"].Int(), 1)
|
||||
t.Assert(oneUpdate["name"].String(), "name_1000")
|
||||
t.Assert(oneUpdate["deleted_at"].String(), "")
|
||||
t.Assert(oneUpdate["created_at"].GTime().Timestamp(), oneInsert["created_at"].GTime().Timestamp())
|
||||
t.AssertGE(oneUpdate["updated_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
|
||||
// Replace
|
||||
dataReplace := g.Map{
|
||||
"id": 1,
|
||||
"name": "name_100",
|
||||
}
|
||||
r, err = db.Table(table).Data(dataReplace).Replace()
|
||||
t.Assert(err, nil)
|
||||
n, _ = r.RowsAffected()
|
||||
t.Assert(n, 2)
|
||||
|
||||
oneReplace, err := db.Table(table).FindOne(1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(oneReplace["id"].Int(), 1)
|
||||
t.Assert(oneReplace["name"].String(), "name_100")
|
||||
t.Assert(oneReplace["deleted_at"].String(), "")
|
||||
t.AssertGE(oneReplace["created_at"].GTime().Timestamp(), oneInsert["created_at"].GTime().Timestamp())
|
||||
t.AssertGE(oneReplace["updated_at"].GTime().Timestamp(), oneInsert["updated_at"].GTime().Timestamp())
|
||||
|
||||
// For time asserting purpose.
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// Delete
|
||||
r, err = db.Table(table).Delete("id", 1)
|
||||
t.Assert(err, nil)
|
||||
n, _ = r.RowsAffected()
|
||||
t.Assert(n, 1)
|
||||
// Delete Select
|
||||
one4, err := db.Table(table).FindOne(1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(one4), 0)
|
||||
one5, err := db.Table(table).Unscoped().FindOne(1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(one5["id"].Int(), 1)
|
||||
t.AssertGE(one5["deleted_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
// Delete Count
|
||||
i, err := db.Table(table).FindCount()
|
||||
t.Assert(err, nil)
|
||||
t.Assert(i, 0)
|
||||
i, err = db.Table(table).Unscoped().FindCount()
|
||||
t.Assert(err, nil)
|
||||
t.Assert(i, 1)
|
||||
|
||||
// Delete Unscoped
|
||||
r, err = db.Table(table).Unscoped().Delete("id", 1)
|
||||
t.Assert(err, nil)
|
||||
n, _ = r.RowsAffected()
|
||||
t.Assert(n, 1)
|
||||
one6, err := db.Table(table).Unscoped().FindOne(1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(one6), 0)
|
||||
i, err = db.Table(table).Unscoped().FindCount()
|
||||
t.Assert(err, nil)
|
||||
t.Assert(i, 0)
|
||||
})
|
||||
}
|
||||
|
||||
// CreatedAt/UpdatedAt/DeletedAt
|
||||
func Test_SoftCreatedUpdatedDeletedTime_Struct(t *testing.T) {
|
||||
table := "time_test_table_" + gtime.TimestampNanoStr()
|
||||
if _, err := db.Exec(fmt.Sprintf(`
|
||||
CREATE TABLE %s (
|
||||
id int(11) NOT NULL,
|
||||
name varchar(45) DEFAULT NULL,
|
||||
created_at datetime DEFAULT NULL,
|
||||
updated_at datetime DEFAULT NULL,
|
||||
deleted_at datetime DEFAULT NULL,
|
||||
PRIMARY KEY (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
`, table)); err != nil {
|
||||
gtest.Error(err)
|
||||
}
|
||||
defer dropTable(table)
|
||||
|
||||
type User struct {
|
||||
Id int
|
||||
Name string
|
||||
CreatedAT *gtime.Time
|
||||
UpdatedAT *gtime.Time
|
||||
DeletedAT *gtime.Time
|
||||
}
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
// Insert
|
||||
dataInsert := User{
|
||||
Id: 1,
|
||||
Name: "name_1",
|
||||
}
|
||||
r, err := db.Table(table).Data(dataInsert).Insert()
|
||||
t.Assert(err, nil)
|
||||
n, _ := r.RowsAffected()
|
||||
t.Assert(n, 1)
|
||||
|
||||
oneInsert, err := db.Table(table).FindOne(1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(oneInsert["id"].Int(), 1)
|
||||
t.Assert(oneInsert["name"].String(), "name_1")
|
||||
t.Assert(oneInsert["deleted_at"].String(), "")
|
||||
t.AssertGE(oneInsert["created_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
t.AssertGE(oneInsert["updated_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
|
||||
// For time asserting purpose.
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// Save
|
||||
dataSave := User{
|
||||
Id: 1,
|
||||
Name: "name_10",
|
||||
}
|
||||
r, err = db.Table(table).Data(dataSave).OmitEmpty().Save()
|
||||
t.Assert(err, nil)
|
||||
n, _ = r.RowsAffected()
|
||||
t.Assert(n, 2)
|
||||
|
||||
oneSave, err := db.Table(table).FindOne(1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(oneSave["id"].Int(), 1)
|
||||
t.Assert(oneSave["name"].String(), "name_10")
|
||||
t.Assert(oneSave["deleted_at"].String(), "")
|
||||
t.Assert(oneSave["created_at"].GTime().Timestamp(), oneInsert["created_at"].GTime().Timestamp())
|
||||
t.AssertNE(oneSave["updated_at"].GTime().Timestamp(), oneInsert["updated_at"].GTime().Timestamp())
|
||||
t.AssertGE(oneSave["updated_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
|
||||
// For time asserting purpose.
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// Update
|
||||
dataUpdate := User{
|
||||
Name: "name_1000",
|
||||
}
|
||||
r, err = db.Table(table).Data(dataUpdate).OmitEmpty().WherePri(1).Update()
|
||||
t.Assert(err, nil)
|
||||
n, _ = r.RowsAffected()
|
||||
t.Assert(n, 1)
|
||||
|
||||
oneUpdate, err := db.Table(table).FindOne(1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(oneUpdate["id"].Int(), 1)
|
||||
t.Assert(oneUpdate["name"].String(), "name_1000")
|
||||
t.Assert(oneUpdate["deleted_at"].String(), "")
|
||||
t.Assert(oneUpdate["created_at"].GTime().Timestamp(), oneInsert["created_at"].GTime().Timestamp())
|
||||
t.AssertGE(oneUpdate["updated_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
|
||||
// Replace
|
||||
dataReplace := User{
|
||||
Id: 1,
|
||||
Name: "name_100",
|
||||
}
|
||||
r, err = db.Table(table).Data(dataReplace).OmitEmpty().Replace()
|
||||
t.Assert(err, nil)
|
||||
n, _ = r.RowsAffected()
|
||||
t.Assert(n, 2)
|
||||
|
||||
oneReplace, err := db.Table(table).FindOne(1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(oneReplace["id"].Int(), 1)
|
||||
t.Assert(oneReplace["name"].String(), "name_100")
|
||||
t.Assert(oneReplace["deleted_at"].String(), "")
|
||||
t.AssertGE(oneReplace["created_at"].GTime().Timestamp(), oneInsert["created_at"].GTime().Timestamp())
|
||||
t.AssertGE(oneReplace["updated_at"].GTime().Timestamp(), oneInsert["updated_at"].GTime().Timestamp())
|
||||
|
||||
// For time asserting purpose.
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// Delete
|
||||
r, err = db.Table(table).Delete("id", 1)
|
||||
t.Assert(err, nil)
|
||||
n, _ = r.RowsAffected()
|
||||
t.Assert(n, 1)
|
||||
// Delete Select
|
||||
one4, err := db.Table(table).FindOne(1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(one4), 0)
|
||||
one5, err := db.Table(table).Unscoped().FindOne(1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(one5["id"].Int(), 1)
|
||||
t.AssertGE(one5["deleted_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
// Delete Count
|
||||
i, err := db.Table(table).FindCount()
|
||||
t.Assert(err, nil)
|
||||
@ -372,7 +648,7 @@ CREATE TABLE %s (
|
||||
t.Assert(oneInsert["name"].String(), "name_1")
|
||||
t.Assert(oneInsert["delete_at"].String(), "")
|
||||
t.AssertGE(oneInsert["create_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
t.AssertGE(oneInsert["update_at"].GTime().Timestamp(), gtime.Timestamp())
|
||||
t.AssertGE(oneInsert["update_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
@ -396,7 +672,7 @@ CREATE TABLE %s (
|
||||
t.Assert(oneSave["delete_at"].String(), "")
|
||||
t.Assert(oneSave["create_at"].GTime().Timestamp(), oneInsert["create_at"].GTime().Timestamp())
|
||||
t.AssertNE(oneSave["update_at"].GTime().Timestamp(), oneInsert["update_at"].GTime().Timestamp())
|
||||
t.AssertGE(oneSave["update_at"].GTime().Timestamp(), gtime.Now().Timestamp()-2)
|
||||
t.AssertGE(oneSave["update_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
@ -419,7 +695,7 @@ CREATE TABLE %s (
|
||||
t.Assert(oneUpdate["name"].String(), "name_1000")
|
||||
t.Assert(oneUpdate["delete_at"].String(), "")
|
||||
t.Assert(oneUpdate["create_at"].GTime().Timestamp(), oneInsert["create_at"].GTime().Timestamp())
|
||||
t.AssertGE(oneUpdate["update_at"].GTime().Timestamp(), gtime.Now().Timestamp()-2)
|
||||
t.AssertGE(oneUpdate["update_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
|
||||
// Replace
|
||||
dataReplace := &Entity{
|
||||
@ -456,7 +732,7 @@ CREATE TABLE %s (
|
||||
one5, err := db.Table(table).Unscoped().FindOne(1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(one5["id"].Int(), 1)
|
||||
t.AssertGE(one5["delete_at"].GTime().Timestamp(), gtime.Now().Timestamp()-2)
|
||||
t.AssertGE(one5["delete_at"].GTime().Timestamp(), gtime.Timestamp()-2)
|
||||
// Delete Count
|
||||
i, err := db.Table(table).FindCount()
|
||||
t.Assert(err, nil)
|
||||
|
||||
@ -15,11 +15,11 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
StatusReady = gtimer.StatusReady
|
||||
StatusRunning = gtimer.StatusRunning
|
||||
StatusStopped = gtimer.StatusStopped
|
||||
StatusClosed = gtimer.StatusClosed
|
||||
gDEFAULT_TIMES = math.MaxInt32
|
||||
StatusReady = gtimer.StatusReady
|
||||
StatusRunning = gtimer.StatusRunning
|
||||
StatusStopped = gtimer.StatusStopped
|
||||
StatusClosed = gtimer.StatusClosed
|
||||
defaultTimes = math.MaxInt32
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@ -43,7 +43,7 @@ func (c *Cron) addEntry(pattern string, job func(), singleton bool, name ...stri
|
||||
cron: c,
|
||||
schedule: schedule,
|
||||
jobName: runtime.FuncForPC(reflect.ValueOf(job).Pointer()).Name(),
|
||||
times: gtype.NewInt(gDEFAULT_TIMES),
|
||||
times: gtype.NewInt(defaultTimes),
|
||||
Job: job,
|
||||
Time: time.Now(),
|
||||
}
|
||||
@ -130,7 +130,7 @@ func (entry *Entry) check() {
|
||||
}
|
||||
}
|
||||
if times < 2000000000 && times > 1000000000 {
|
||||
entry.times.Set(gDEFAULT_TIMES)
|
||||
entry.times.Set(defaultTimes)
|
||||
}
|
||||
glog.Path(path).Level(level).Debugf("[gcron] %s(%s) %s start", entry.Name, entry.schedule.pattern, entry.jobName)
|
||||
defer func() {
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
package gcron_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/os/glog"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -21,34 +21,24 @@ func TestCron_Add_Close(t *testing.T) {
|
||||
cron := gcron.New()
|
||||
array := garray.New(true)
|
||||
_, err1 := cron.Add("* * * * * *", func() {
|
||||
glog.Println("cron1")
|
||||
g.Log().Println("cron1")
|
||||
array.Append(1)
|
||||
})
|
||||
_, err2 := cron.Add("* * * * * *", func() {
|
||||
glog.Println("cron2")
|
||||
g.Log().Println("cron2")
|
||||
array.Append(1)
|
||||
}, "test")
|
||||
_, err3 := cron.Add("* * * * * *", func() {
|
||||
glog.Println("cron3")
|
||||
array.Append(1)
|
||||
}, "test")
|
||||
_, err4 := cron.Add("@every 2s", func() {
|
||||
glog.Println("cron4")
|
||||
array.Append(1)
|
||||
})
|
||||
t.Assert(err1, nil)
|
||||
t.Assert(err2, nil)
|
||||
t.AssertNE(err3, nil)
|
||||
t.Assert(err4, nil)
|
||||
t.Assert(cron.Size(), 3)
|
||||
t.Assert(cron.Size(), 2)
|
||||
time.Sleep(1300 * time.Millisecond)
|
||||
t.Assert(array.Len(), 2)
|
||||
time.Sleep(1400 * time.Millisecond)
|
||||
t.Assert(array.Len(), 5)
|
||||
time.Sleep(1300 * time.Millisecond)
|
||||
t.Assert(array.Len(), 4)
|
||||
cron.Close()
|
||||
time.Sleep(1200 * time.Millisecond)
|
||||
time.Sleep(1300 * time.Millisecond)
|
||||
fixedLength := array.Len()
|
||||
time.Sleep(1200 * time.Millisecond)
|
||||
time.Sleep(1300 * time.Millisecond)
|
||||
t.Assert(array.Len(), fixedLength)
|
||||
})
|
||||
}
|
||||
|
||||
@ -7,21 +7,23 @@
|
||||
package gcron_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/container/garray"
|
||||
"github.com/gogf/gf/os/gcron"
|
||||
"github.com/gogf/gf/os/glog"
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
)
|
||||
|
||||
func TestCron_Entry_Operations(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
cron := gcron.New()
|
||||
array := garray.New(true)
|
||||
var (
|
||||
cron = gcron.New()
|
||||
array = garray.New(true)
|
||||
)
|
||||
cron.DelayAddTimes(500*time.Millisecond, "* * * * * *", 2, func() {
|
||||
glog.Println("add times")
|
||||
g.Log().Println("add times")
|
||||
array.Append(1)
|
||||
})
|
||||
t.Assert(cron.Size(), 0)
|
||||
@ -34,16 +36,18 @@ func TestCron_Entry_Operations(t *testing.T) {
|
||||
})
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
cron := gcron.New()
|
||||
array := garray.New(true)
|
||||
var (
|
||||
cron = gcron.New()
|
||||
array = garray.New(true)
|
||||
)
|
||||
entry, err1 := cron.Add("* * * * * *", func() {
|
||||
glog.Println("add")
|
||||
g.Log().Println("add")
|
||||
array.Append(1)
|
||||
})
|
||||
t.Assert(err1, nil)
|
||||
t.Assert(array.Len(), 0)
|
||||
t.Assert(cron.Size(), 1)
|
||||
time.Sleep(1200 * time.Millisecond)
|
||||
time.Sleep(1300 * time.Millisecond)
|
||||
t.Assert(array.Len(), 1)
|
||||
t.Assert(cron.Size(), 1)
|
||||
entry.Stop()
|
||||
@ -51,8 +55,8 @@ func TestCron_Entry_Operations(t *testing.T) {
|
||||
t.Assert(array.Len(), 1)
|
||||
t.Assert(cron.Size(), 1)
|
||||
entry.Start()
|
||||
glog.Println("start")
|
||||
time.Sleep(1200 * time.Millisecond)
|
||||
g.Log().Println("start")
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
t.Assert(array.Len(), 2)
|
||||
t.Assert(cron.Size(), 1)
|
||||
entry.Close()
|
||||
|
||||
@ -39,20 +39,11 @@ func TestTimer_Proceed(t *testing.T) {
|
||||
timer.AddOnce(2*time.Hour, func() {
|
||||
slice = append(slice, 6)
|
||||
})
|
||||
timer.AddOnce(1000*time.Minute, func() {
|
||||
slice = append(slice, 7)
|
||||
})
|
||||
timer.AddOnce(1100*time.Minute, func() {
|
||||
slice = append(slice, 8)
|
||||
})
|
||||
timer.AddOnce(1200*time.Minute, func() {
|
||||
slice = append(slice, 9)
|
||||
})
|
||||
for i := 0; i < 2000000; i++ {
|
||||
for i := 0; i < 500000; i++ {
|
||||
timer.wheels[0].proceed()
|
||||
time.Sleep(10 * time.Microsecond)
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
t.Assert(slice, []int{1, 2, 3, 4, 5, 6, 7, 8, 9})
|
||||
t.Assert(slice, []int{1, 2, 3, 4, 5, 6})
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user