diff --git a/example/exmaple.go b/example/exmaple.go index c0214d3..4de07e1 100644 --- a/example/exmaple.go +++ b/example/exmaple.go @@ -27,14 +27,14 @@ type User struct { } func main() { - //testMockGORM() + testMockGORM() //testMockGORMV2() - //testMockXORM() - //testMockZORM() - //testMockRedis() - //testMockHttpServer() - testMockDocker() - //testDBUtil() + ////testMockXORM() + ////testMockZORM() + ////testMockRedis() + ////testMockHttpServer() + //testMockDocker() + ////testDBUtil() } @@ -71,36 +71,46 @@ func testMockZORM() { } func testMockGORM() { - var db *gorm.DB - mockdb.DBType = "mysql" - mock := gmock.NewMockGORM("example", func(gorm *mockdb.MockGORM) { - db = gorm.GetGormDB() - }) - fmt.Println(mock.GetDSN()) - mock.RegisterModels(&User{}) - mock.InitSchemas(`CREATE TABLE user ( - id bigint(20) unsigned NOT NULL AUTO_INCREMENT, - age int(3) DEFAULT NULL, - name varchar(255) DEFAULT NULL COMMENT '名称', + // var db *gorm.DB + // mockdb.DBType = "mysql" + // mock := gmock.NewMockGORM("example", "mock") + // db=mock.GetGormDB() + // fmt.Println(mock.GetDSN()) + // mock.RegisterModels(&User{}) + // mock.InitSchemas(`CREATE TABLE user ( + // id bigint(20) unsigned NOT NULL AUTO_INCREMENT, + // age int(3) DEFAULT NULL, + // name varchar(255) DEFAULT NULL COMMENT '名称', + //remark varchar(255) DEFAULT NULL COMMENT '名称', + // PRIMARY KEY (id) + //) ENGINE=InnoDB ;`) + // mock.ResetAndInit() + // + // mock.DoRecord(mock.GetGormDB()) + // + // var user []User + // err := db.Where("id=?", 1).Find(&user).Error + // if err != nil { + // panic(err) + // } + // if user[0].Id != 1 { + // panic(fmt.Errorf("testMockGORM error")) + // } + // + // for _, sql := range mock.GetDBUtil().DumpFromRecordInfo(mock.GetSqlDB(), mock.DumpRecorderInfo()) { + // fmt.Println(sql) + // } + + MockDB := gmock.NewGORMFromDSN("./example/ddl.txt", "mysql", "root:mock@tcp(127.0.0.1:63307)/hello?charset=utf8&parseTime=True&loc=Local") + + MockDB.InitSchemas(`CREATE TABLE user ( + id bigint(20) unsigned NOT NULL AUTO_INCREMENT, + age int(3) DEFAULT NULL, + name varchar(255) DEFAULT NULL COMMENT '名称', remark varchar(255) DEFAULT NULL COMMENT '名称', - PRIMARY KEY (id) + PRIMARY KEY (id) ) ENGINE=InnoDB ;`) - mock.ResetAndInit() - - mock.DoRecord(mock.GetGormDB()) - - var user []User - err := db.Where("id=?", 1).Find(&user).Error - if err != nil { - panic(err) - } - if user[0].Id != 1 { - panic(fmt.Errorf("testMockGORM error")) - } - - for _, sql := range mock.GetDBUtil().DumpFromRecordInfo(mock.GetSqlDB(), mock.DumpRecorderInfo()) { - fmt.Println(sql) - } + MockDB.ResetAndInit() } @@ -121,10 +131,8 @@ func testDBUtil() { func testMockGORMV2() { //mockdb.DBType = "mysql" var db *gormv2.DB - mock := gmock.NewMockGORMV2("example", func(orm *mockdb.MockGORMV2) { - db = orm.GetGormDB() - }) - + mock := gmock.NewMockGORMV2("example", "mock") + db = mock.GetGormDB() mock.DoRecord(mock.GetGormDB()) //注册模型 @@ -244,7 +252,7 @@ func testMockDocker() { default: if !checker() { util.Exec("open /Applications/Docker.app") - time.Sleep(time.Second*25) + time.Sleep(time.Second * 25) } else { c <- true goto BREAK diff --git a/mockdb/mock_gorm.go b/mockdb/mock_gorm.go index 1368705..e450ad8 100644 --- a/mockdb/mock_gorm.go +++ b/mockdb/mock_gorm.go @@ -74,9 +74,29 @@ func NewGORMFromDSN(pathToSqlFileName string, dbType string, dsn string) *MockGO //onceRecorder: sync.Once{}, } mock.dsn = dsn + var dn *util.DSN + var err error db, err := gorm.Open(dbType, mock.dsn) if err != nil { - panic(err) + dsn2 := dbType + "://" + dsn + dn, err = util.Parse(dsn2) + if err != nil { + panic(err) + } + dbName := dn.DatabaseName() + dn.SetDatabaseName("sys") + db, err = gorm.Open(dbType, dn.DSN(false)) + if err != nil { + panic(err) + } + err = db.Exec(fmt.Sprintf("create database %s", dbName)).Error + if err != nil { + panic(err) + } + db, err = gorm.Open(dbType, mock.dsn) + if err!=nil { + panic(err) + } } mock.db = db mock.dbType = dbType @@ -108,7 +128,7 @@ func NewMockGORM(pathToSqlFileName string, dbName string) *MockGORM { } mock.util.RunMySQLServer(dbName, i, false) time.Sleep(time.Second) - mock.dsn = fmt.Sprintf("root:root@tcp(127.0.0.1:%v)/%s?charset=utf8&parseTime=True&loc=Local", i,dbName) + mock.dsn = fmt.Sprintf("root:root@tcp(127.0.0.1:%v)/%s?charset=utf8&parseTime=True&loc=Local", i, dbName) mock.dbType = "mysql" db, err = gorm.Open("mysql", mock.dsn) break diff --git a/mockdb/mock_gormv2.go b/mockdb/mock_gormv2.go index 8a2957b..75759cd 100644 --- a/mockdb/mock_gormv2.go +++ b/mockdb/mock_gormv2.go @@ -49,9 +49,29 @@ func NewGORMV2FromDSN(pathToSqlFileName string, dbType string, dsn string) *Mock ns := schema.NamingStrategy{ SingularTable: true, } + var dn *util.DSN db, err := gorm.Open(mysql.Open(mock.dsn), &gorm.Config{NamingStrategy: ns}) if err != nil { - panic(err) + //panic(err) + dsn2 := dbType + "://" + dsn + dn, err = util.Parse(dsn2) + if err != nil { + panic(err) + } + dbName := dn.DatabaseName() + dn.SetDatabaseName("sys") + db, err = gorm.Open(mysql.Open(dn.DSN(false)), &gorm.Config{NamingStrategy: ns}) + if err != nil { + panic(err) + } + err = db.Exec(fmt.Sprintf("create database %s", dbName)).Error + if err != nil { + panic(err) + } + db, err = gorm.Open(mysql.Open(dn.DSN(false)), &gorm.Config{NamingStrategy: ns}) + if err != nil { + panic(err) + } } mock.db = db mock.dbType = dbType @@ -86,7 +106,7 @@ func NewMockGORMV2(pathToSqlFileName string, dbName string) *MockGORMV2 { } mock.util.RunMySQLServer(dbName, i, false) time.Sleep(time.Second) - mock.dsn = fmt.Sprintf("root:root@tcp(127.0.0.1:%v)/%s?charset=utf8&parseTime=True&loc=Local", i,dbName) + mock.dsn = fmt.Sprintf("root:root@tcp(127.0.0.1:%v)/%s?charset=utf8&parseTime=True&loc=Local", i, dbName) mock.dbType = "mysql" db, err = gorm.Open(mysql.Open(mock.dsn), &gorm.Config{NamingStrategy: ns}) break diff --git a/mockhttp/mock_http_test.go b/mockhttp/mock_http_test.go index 328a8e8..e7711ba 100644 --- a/mockhttp/mock_http_test.go +++ b/mockhttp/mock_http_test.go @@ -6,7 +6,7 @@ import ( ) func TestHttpServer(t *testing.T) { - httpMock := NewMockHttpServer(12345, "./", []string{"wwww.baidu.com"}) + httpMock := NewMockHttpServer(12345, "./", []string{"www.baidu.com"}) httpMock.SetReqRspHandler(func(req *Request, rsp *Response) { req.Method = "POST" req.Endpoint = "/index.html" @@ -16,6 +16,16 @@ func TestHttpServer(t *testing.T) { }) httpMock.InitMockHttpServer() + + resp, er := requests.PostJson("https://www.baidu.com/index.html", `{"name":test}`) + //resp, err := requests.Get("http://www.baidu.com/index.html") + if er != nil { + t.Fail() + } + if resp.Text() != "baidu!" { + t.Fail() + } + resp, err := requests.PostJson("http://www.baidu.com/index.html", `{"name":test}`) //resp, err := requests.Get("http://www.baidu.com/index.html") if err != nil { diff --git a/util/util.go b/util/util.go index 1e1ac37..4ac9fb9 100644 --- a/util/util.go +++ b/util/util.go @@ -5,9 +5,14 @@ import ( "github.com/sjqzhang/goutil" "log" "net" + "net/url" "os" + "regexp" "runtime" "runtime/debug" + "strconv" + "strings" + "time" ) type logger struct { @@ -64,3 +69,165 @@ func Exec(cmd string) (string, int) { } return Util.Exec([]string{"sh", "-c", cmd}, 3600) } + +type DSN struct { + url *url.URL + *DSNValues + isWrapTcp bool +} + +// parses dsn string and returns DSN instance +func Parse(dsn string) (*DSN, error) { + reg := regexp.MustCompile(`tcp\(.*?\)`) //uniform url format + isWrapTcp := false + if m := reg.FindStringSubmatch(dsn); len(m) > 0 { + match := m[0] + match = strings.TrimPrefix(match, "tcp(") + match = strings.TrimSuffix(match, ")") + dsn = reg.ReplaceAllString(dsn, match) + isWrapTcp = true + } + parsed, err := url.Parse(dsn) + if err != nil { + return nil, err + } + d := DSN{ + parsed, + &DSNValues{parsed.Query()}, isWrapTcp, + } + return &d, nil +} + +// Parses query and returns dsn values +func ParseQuery(query string) (*DSNValues, error) { + parsed, err := url.ParseQuery(query) + if err != nil { + return nil, err + } + return &DSNValues{parsed}, nil +} + +// returns DSNValues from url.Values +func NewValues(query url.Values) (*DSNValues, error) { + return &DSNValues{query}, nil +} + +// return Host +func (d *DSN) DSN(withSchema bool) string { + schema := "" + if withSchema { + schema = d.url.Scheme + "://" + } + if d.isWrapTcp { + + return schema + d.Username() + ":" + d.Password() + "@tcp(" + d.url.Host + ")" + d.url.Path + "?" + d.url.RawQuery + } else { + return schema + d.Username() + ":" + d.Password() + "@" + d.url.Host + d.url.Path + "?" + d.url.RawQuery + } +} + +// return Host +func (d *DSN) HostWithPort() string { + return d.url.Host +} + +// return Host +func (d *DSN) Host() string { + return strings.Split(d.url.Host, ":")[0] +} + +// return Host +func (d *DSN) Port() string { + hp := strings.Split(d.url.Host, ":") + if len(hp) == 2 { + return hp[1] + } else { + return "" + } +} + +// return Scheme +func (d *DSN) Scheme() string { + return d.url.Scheme +} + +// returns path +func (d *DSN) Path() string { + return d.url.Path +} + +// returns path +func (d *DSN) DatabaseName() string { + return strings.Replace(d.url.Path, "/", "", -1) +} + +// returns path +func (d *DSN) SetDatabaseName(dbName string) { + d.url.Path = "/" + dbName +} + +// returns user +func (d *DSN) User() *url.Userinfo { + return d.url.User +} + +// returns Username +func (d *DSN) Username() string { + return d.url.User.Username() +} + +// returns Username +func (d *DSN) Password() string { + v, ok := d.url.User.Password() + if ok { + return v + } else { + return "" + } +} + +// DSN Values +type DSNValues struct { + url.Values +} + +// returns int value +func (d *DSNValues) GetInt(paramName string, defaultValue int) int { + value := d.Get(paramName) + if i, err := strconv.Atoi(value); err == nil { + return i + } else { + return defaultValue + } +} + +// returns string value +func (d *DSNValues) GetString(paramName string, defaultValue string) string { + value := d.Get(paramName) + if value == "" { + return defaultValue + } else { + return value + } +} + +// returns string value +func (d *DSNValues) GetBool(paramName string, defaultValue bool) bool { + value := strings.ToLower(d.Get(paramName)) + if value == "true" || value == "1" { + return true + } else if value == "0" || value == "false" { + return false + } else { + return defaultValue + } +} + +// returns string value +func (d *DSNValues) GetSeconds(paramName string, defaultValue time.Duration) time.Duration { + if i, err := strconv.Atoi(d.Get(paramName)); err == nil { + return time.Duration(i) * time.Second + } else { + return defaultValue + } +} diff --git a/util/util_test.go b/util/util_test.go new file mode 100644 index 0000000..9461e19 --- /dev/null +++ b/util/util_test.go @@ -0,0 +1,22 @@ +package util + +import ( + "fmt" + "testing" +) + +func TestDSNParser(t *testing.T) { + dsn := "mysql://root:123456@x@tcp(localhost:3306)/test?charset=utf8mb4&parseTime=True&loc=Local" + + d, err := Parse(dsn) + + if err != nil { + panic(err) + } + + fmt.Println(d.DSN(true)) + if d.DSN(true) != dsn { + t.Fail() + } + +}