248 lines
5.4 KiB
Go
248 lines
5.4 KiB
Go
package robot
|
||
|
||
import (
|
||
"bytes"
|
||
"encoding/json"
|
||
"fmt"
|
||
"go_dreamfactory/comm"
|
||
"go_dreamfactory/pb"
|
||
"io/ioutil"
|
||
"log"
|
||
"net/http"
|
||
"sync"
|
||
"time"
|
||
|
||
"github.com/gorilla/websocket"
|
||
jsoniter "github.com/json-iterator/go"
|
||
"google.golang.org/protobuf/proto"
|
||
)
|
||
|
||
type Robot struct {
|
||
ws *websocket.Conn
|
||
opts *Options
|
||
user *pb.DBUser
|
||
builders []*TestCase //测试用例
|
||
|
||
linkCase *LinkCase //测试用例链,适应于用例跑批
|
||
wg sync.WaitGroup
|
||
}
|
||
|
||
func NewRobot(opts *Options) *Robot {
|
||
ws, _, err := websocket.DefaultDialer.Dial(opts.WsUrl, nil)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
r := &Robot{
|
||
ws: ws,
|
||
opts: opts,
|
||
linkCase: NewLinkCase(),
|
||
}
|
||
|
||
return r
|
||
}
|
||
|
||
func (r *Robot) Run() {
|
||
log.Print("Robot running...")
|
||
log.Printf("websocket %s \n", r.opts.WsUrl)
|
||
if r.opts.Create { //创建新用户
|
||
r.AccountRegister(r.opts.Account, int32(r.opts.ServerId))
|
||
} else {
|
||
if r.opts.Account == "" {
|
||
log.Fatal("WARNNING: account is required !!!")
|
||
}
|
||
r.AccountLogin()
|
||
}
|
||
|
||
//处理响应
|
||
go func() {
|
||
for {
|
||
var msg *pb.UserMessage = &pb.UserMessage{}
|
||
_, data, err := r.ws.ReadMessage()
|
||
if err != nil {
|
||
log.Println(err)
|
||
}
|
||
|
||
if err = proto.Unmarshal(data, msg); err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
r.handleRsp(msg)
|
||
}
|
||
}()
|
||
|
||
// select {}
|
||
r.wg.Wait()
|
||
}
|
||
|
||
type TestCase struct {
|
||
Desc string
|
||
mainType string
|
||
subType string
|
||
req proto.Message
|
||
rsp proto.Message
|
||
enabled bool
|
||
start time.Time
|
||
requested bool //请求标识 true已发
|
||
print func(rsp proto.Message)
|
||
}
|
||
|
||
func (r *Robot) addBuilders(builders []*TestCase) {
|
||
for _, b := range builders {
|
||
if b.enabled {
|
||
r.builders = append(r.builders, b)
|
||
}
|
||
}
|
||
}
|
||
|
||
//执行请求
|
||
func (r *Robot) handleReq() {
|
||
for _, b := range r.builders {
|
||
if b.req != nil && !b.requested {
|
||
r.wg.Add(1)
|
||
time.Sleep(time.Second * 1)
|
||
b.requested = true
|
||
b.start = time.Now()
|
||
head := &pb.UserMessage{MainType: b.mainType, SubType: b.subType}
|
||
defer traceFunc(head.MainType, head.SubType, r.user.GetUid(), b.req)
|
||
err := r.SendToClient(head, b.req)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//执行响应
|
||
func (r *Robot) handleRsp(msg *pb.UserMessage) {
|
||
for i, b := range r.builders {
|
||
if b.enabled && (msg.MainType == b.mainType &&
|
||
msg.SubType == b.subType) {
|
||
if !comm.ProtoUnmarshal(msg, b.rsp) {
|
||
return
|
||
}
|
||
if b.print == nil {
|
||
printReply(msg, b)
|
||
} else {
|
||
fmt.Printf("===== %s [%s.%s] =====\n", b.Desc, msg.MainType, msg.SubType)
|
||
b.print(b.rsp)
|
||
fmt.Println("==============================")
|
||
}
|
||
|
||
if msg.MainType == "user" && msg.SubType == "login" {
|
||
r.loginCallback(b.rsp)
|
||
} else {
|
||
if b.requested {
|
||
r.builders = append(r.builders[:i], r.builders[i+1:]...)
|
||
}
|
||
}
|
||
|
||
r.wg.Done()
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
//登录回调
|
||
func (r *Robot) loginCallback(rsp proto.Message) {
|
||
r.builders = append(r.builders[:0], r.builders[1:]...)
|
||
lr := rsp.(*pb.UserLoginResp)
|
||
if lr.Data != nil {
|
||
r.user = lr.Data
|
||
r.onUserLoaded()
|
||
} else {
|
||
r.AccountRegister(r.opts.Account, int32(r.opts.ServerId)) //请求Http接口,模拟创建新账号
|
||
}
|
||
}
|
||
|
||
func (r *Robot) SendToClient(msg *pb.UserMessage, rsp proto.Message) error {
|
||
//模拟客户端 每次请求都会生成新的秘钥
|
||
msg.Sec = r.BuildSecStr()
|
||
if comm.ProtoMarshal(rsp, msg) {
|
||
data, _ := proto.Marshal(msg)
|
||
return r.ws.WriteMessage(websocket.BinaryMessage, data)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
//在这里添加玩家成功登录以后的测试方法
|
||
//次方法在用户登录成功后调用
|
||
func (r *Robot) onUserLoaded() {
|
||
//notify
|
||
r.RunNotify()
|
||
//user
|
||
r.RunUser()
|
||
//hero
|
||
r.RunHero()
|
||
//friend
|
||
r.RunFriend()
|
||
|
||
//pack
|
||
// r.RunPack()
|
||
|
||
}
|
||
|
||
//注册账号
|
||
func (r *Robot) AccountRegister(account string, sid int32) {
|
||
if account == "" {
|
||
log.Fatal("account value is empty")
|
||
}
|
||
//http
|
||
regReq := &pb.UserRegisterReq{Account: account, Sid: sid}
|
||
jsonByte, _ := json.Marshal(regReq)
|
||
req, err := http.NewRequest("POST", r.opts.RegUrl, bytes.NewReader(jsonByte))
|
||
if err != nil {
|
||
log.Fatalf("account register err %v", err)
|
||
}
|
||
req.Header.Set("Content-Type", "application/json;charset=UTF-8")
|
||
httpClient := &http.Client{}
|
||
rsp, err := httpClient.Do(req)
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
defer rsp.Body.Close()
|
||
|
||
body, _ := ioutil.ReadAll(rsp.Body)
|
||
regRsp := &pb.UserRegisterResp{}
|
||
err = jsoniter.Unmarshal(body, regRsp)
|
||
|
||
if regRsp.Code == pb.ErrorCode_Success { //注册成功
|
||
|
||
fmt.Printf("account:%s 注册成功", regRsp.Account)
|
||
//登录
|
||
var user_builders = []*TestCase{
|
||
{
|
||
Desc: "登录",
|
||
mainType: "user",
|
||
subType: "login",
|
||
req: &pb.UserLoginReq{
|
||
Account: account,
|
||
Sid: sid,
|
||
},
|
||
rsp: &pb.UserLoginResp{},
|
||
enabled: true,
|
||
},
|
||
}
|
||
r.addBuilders(user_builders)
|
||
r.handleReq()
|
||
}
|
||
}
|
||
|
||
//打印响应
|
||
func printReply(msg *pb.UserMessage, builder *TestCase) {
|
||
if m, ok := builder.rsp.(*pb.NotifyErrorNotifyPush); ok {
|
||
var tt time.Duration
|
||
if builder.start.IsZero() {
|
||
tt = time.Duration(0)
|
||
} else {
|
||
tt = time.Since(builder.start)
|
||
}
|
||
log.Printf("rsp %s [%v] [%s.%s] [%v:%v]", builder.Desc, tt, m.ReqMainType, m.ReqSubType, int32(m.Code), m.Data)
|
||
} else {
|
||
log.Printf("rsp %s [%v] [%s.%s] [%v]", builder.Desc, time.Since(builder.start), msg.MainType, msg.SubType, builder.rsp)
|
||
}
|
||
}
|
||
|
||
//方法参数跟踪
|
||
func traceFunc(module string, funcName string, uid string, funcArgs interface{}) {
|
||
log.Printf("req [%s.%s] [%s] [%v]", module, funcName, uid, funcArgs)
|
||
}
|