更新工具
This commit is contained in:
parent
2badc32f70
commit
d1caac0cba
@ -4,6 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"go_dreamfactory/cmd/v2/lib/common"
|
||||||
|
"go_dreamfactory/cmd/v2/service/observer"
|
||||||
"go_dreamfactory/pb"
|
"go_dreamfactory/pb"
|
||||||
"math"
|
"math"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@ -27,9 +29,10 @@ type assistant struct {
|
|||||||
caller Handler //处理器
|
caller Handler //处理器
|
||||||
status uint32 //状态
|
status uint32 //状态
|
||||||
resultCh chan *CallResult //调用结果
|
resultCh chan *CallResult //调用结果
|
||||||
|
obs observer.Observer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAssistant(pm ParamMgr) (Aiassistant, error) {
|
func NewAssistant(obs observer.Observer, pm ParamMgr) (Aiassistant, error) {
|
||||||
|
|
||||||
if err := pm.Check(); err != nil {
|
if err := pm.Check(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -42,6 +45,7 @@ func NewAssistant(pm ParamMgr) (Aiassistant, error) {
|
|||||||
caller: pm.Caller,
|
caller: pm.Caller,
|
||||||
status: STATUS_ORIGINAL,
|
status: STATUS_ORIGINAL,
|
||||||
resultCh: pm.ResultCh,
|
resultCh: pm.ResultCh,
|
||||||
|
obs: obs,
|
||||||
}
|
}
|
||||||
if err := a.init(); err != nil {
|
if err := a.init(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -50,7 +54,7 @@ func NewAssistant(pm ParamMgr) (Aiassistant, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *assistant) init() error {
|
func (a *assistant) init() error {
|
||||||
logrus.Info("AI助手初始化")
|
logrus.Debug("AI助手初始化")
|
||||||
//并发量的计算
|
//并发量的计算
|
||||||
//并发量 ≈ 超时时间 / 发送的间隔时间
|
//并发量 ≈ 超时时间 / 发送的间隔时间
|
||||||
var total = int64(a.timeout)/int64(1e9/a.lps) + 1
|
var total = int64(a.timeout)/int64(1e9/a.lps) + 1
|
||||||
@ -65,12 +69,13 @@ func (a *assistant) init() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
a.goPool = gp
|
a.goPool = gp
|
||||||
logrus.WithField("并发量", a.concurrency).Info("AI助手初始化完成 并发量 ")
|
logrus.WithField("并发量", a.concurrency).Debug("AI助手初始化完成 ")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *assistant) callOne(req *RawReq) *RawResp {
|
func (a *assistant) callOne(req *RawReq) *RawResp {
|
||||||
atomic.AddInt64(&a.callCount, 1)
|
atomic.AddInt64(&a.callCount, 1)
|
||||||
|
logrus.WithField("count", &a.callCount).WithField("Len", len(req.Req)).Debug("调用协议")
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return &RawResp{ID: -1, Err: errors.New("无效的请求")}
|
return &RawResp{ID: -1, Err: errors.New("无效的请求")}
|
||||||
}
|
}
|
||||||
@ -101,6 +106,22 @@ func (a *assistant) asyncCall() {
|
|||||||
a.goPool.Take()
|
a.goPool.Take()
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
|
if p := recover(); p != nil {
|
||||||
|
err, ok := interface{}(p).(error)
|
||||||
|
var errMsg string
|
||||||
|
if ok {
|
||||||
|
errMsg = fmt.Sprintf("Async Call Panic! (error: %s)", err)
|
||||||
|
} else {
|
||||||
|
errMsg = fmt.Sprintf("Async Call Panic! (clue: %#v)", p)
|
||||||
|
}
|
||||||
|
logrus.Errorln(errMsg)
|
||||||
|
result := &CallResult{
|
||||||
|
Id: -1,
|
||||||
|
Code: RES_CODE_FATAL_CALL,
|
||||||
|
Message: errMsg,
|
||||||
|
}
|
||||||
|
a.sendResult(result)
|
||||||
|
}
|
||||||
a.goPool.Return()
|
a.goPool.Return()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -118,12 +139,13 @@ func (a *assistant) asyncCall() {
|
|||||||
Id: req.ID,
|
Id: req.ID,
|
||||||
Req: req,
|
Req: req,
|
||||||
Code: RES_CODE_CALL_TIMEOUT,
|
Code: RES_CODE_CALL_TIMEOUT,
|
||||||
Message: fmt.Sprintf("超时,期望< %v", a.timeout),
|
Message: fmt.Sprintf("超时,期望小于 %v", a.timeout),
|
||||||
Elapse: a.timeout,
|
Elapse: a.timeout,
|
||||||
}
|
}
|
||||||
a.sendResult(result)
|
a.sendResult(result)
|
||||||
})
|
})
|
||||||
resp := a.callOne(&req)
|
resp := a.callOne(&req)
|
||||||
|
|
||||||
logrus.WithField("耗时", resp.Elapse).Debug("实际耗时")
|
logrus.WithField("耗时", resp.Elapse).Debug("实际耗时")
|
||||||
if !atomic.CompareAndSwapUint32(&callStatus, 0, 1) {
|
if !atomic.CompareAndSwapUint32(&callStatus, 0, 1) {
|
||||||
return
|
return
|
||||||
@ -146,14 +168,13 @@ func (a *assistant) asyncCall() {
|
|||||||
}
|
}
|
||||||
a.sendResult(result)
|
a.sendResult(result)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 停止发送
|
// 停止发送
|
||||||
func (a *assistant) prepareStop(ctxErr error) {
|
func (a *assistant) prepareStop(ctxErr error) {
|
||||||
logrus.WithField("cause", ctxErr).Info("准备停止")
|
logrus.WithField("cause", ctxErr).Info("准备停止")
|
||||||
atomic.CompareAndSwapUint32(&a.status, STATUS_STARTED, STATUS_STOPPING)
|
atomic.CompareAndSwapUint32(&a.status, STATUS_STARTED, STATUS_STOPPING)
|
||||||
logrus.Info("关闭结果通道")
|
logrus.Debug("关闭结果通道")
|
||||||
close(a.resultCh)
|
close(a.resultCh)
|
||||||
atomic.StoreUint32(&a.status, STATUS_STOPPED)
|
atomic.StoreUint32(&a.status, STATUS_STOPPED)
|
||||||
}
|
}
|
||||||
@ -181,36 +202,35 @@ func (a *assistant) handleReq(tick <-chan time.Time) {
|
|||||||
|
|
||||||
func (a *assistant) sendResult(result *CallResult) bool {
|
func (a *assistant) sendResult(result *CallResult) bool {
|
||||||
if atomic.LoadUint32(&a.status) != STATUS_STARTED {
|
if atomic.LoadUint32(&a.status) != STATUS_STARTED {
|
||||||
|
a.printResult(result, "已停止")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case a.resultCh <- result:
|
case a.resultCh <- result:
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
|
a.printResult(result, "结果通道已满")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//注册账号
|
func (a *assistant) printResult(result *CallResult, cause string) {
|
||||||
func (a *assistant) registUser() {
|
resultMsg := fmt.Sprintf(
|
||||||
|
"Id:%d,Code=%d,Msg=%s,Elapse=%v",
|
||||||
}
|
result.Id, result.Code, result.Message, result.Elapse)
|
||||||
|
logrus.Warnf("result:%s (cause:%s)", resultMsg, cause)
|
||||||
//登录账号
|
|
||||||
func (a *assistant) login() {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 启动AI助手
|
// 启动AI助手
|
||||||
func (a *assistant) Start() bool {
|
func (a *assistant) Start() bool {
|
||||||
logrus.Infoln("AI助手启动")
|
logrus.Debug("AI助手启动")
|
||||||
|
|
||||||
// 节流 周期性向目标发送
|
// 节流 周期性向目标发送
|
||||||
var ticker <-chan time.Time
|
var ticker <-chan time.Time
|
||||||
if a.lps > 0 {
|
if a.lps > 0 {
|
||||||
//间隔时间
|
//间隔时间
|
||||||
interval := time.Duration(1e9 / a.lps)
|
interval := time.Duration(1e9 / a.lps)
|
||||||
logrus.Infof("启动节流控制 间隔: %v", interval)
|
logrus.Debugf("启动节流控制 间隔: %v", interval)
|
||||||
ticker = time.Tick(interval)
|
ticker = time.Tick(interval)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +244,7 @@ func (a *assistant) Start() bool {
|
|||||||
atomic.StoreUint32(&a.status, STATUS_STARTED)
|
atomic.StoreUint32(&a.status, STATUS_STARTED)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
logrus.Infoln("请求处理...")
|
logrus.Debug("请求处理中...")
|
||||||
a.handleReq(ticker)
|
a.handleReq(ticker)
|
||||||
logrus.Infof("停止 调用次数:%d", a.callCount)
|
logrus.Infof("停止 调用次数:%d", a.callCount)
|
||||||
}()
|
}()
|
||||||
@ -238,6 +258,9 @@ func (a *assistant) Stop() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *assistant) ShowResult() {
|
func (a *assistant) ShowResult() {
|
||||||
|
statistics := &Statistics{}
|
||||||
|
max := statistics.MaxElapse
|
||||||
|
min := statistics.MinElapse
|
||||||
|
|
||||||
for r := range a.resultCh {
|
for r := range a.resultCh {
|
||||||
if r.Code != RES_CODE_SUCCESS {
|
if r.Code != RES_CODE_SUCCESS {
|
||||||
@ -250,6 +273,28 @@ func (a *assistant) ShowResult() {
|
|||||||
logrus.Error("结果解析失败")
|
logrus.Error("结果解析失败")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
logrus.WithFields(logrus.Fields{"mainType": msg.MainType, "subType": msg.SubType}).Debug("读取结果")
|
// 协议名
|
||||||
|
statistics.Route = fmt.Sprintf("%s.%s", msg.MainType, msg.SubType)
|
||||||
|
// 总耗时
|
||||||
|
statistics.ElapseTotal += float64(r.Elapse.Nanoseconds())
|
||||||
|
|
||||||
|
if float64(r.Elapse.Nanoseconds()) > max {
|
||||||
|
max = float64(r.Elapse.Nanoseconds())
|
||||||
|
} else {
|
||||||
|
min = float64(r.Elapse.Nanoseconds())
|
||||||
}
|
}
|
||||||
|
logrus.WithFields(logrus.Fields{"mainType": msg.MainType, "subType": msg.SubType, "耗时": r.Elapse}).Info("结果")
|
||||||
|
}
|
||||||
|
if a.callCount == 1 {
|
||||||
|
min = max
|
||||||
|
}
|
||||||
|
// 调用次数
|
||||||
|
statistics.CallCount = a.callCount
|
||||||
|
statistics.ElapseTotal = common.FormatFloatCommon(statistics.ElapseTotal / 1e6)
|
||||||
|
statistics.MaxElapse = common.FormatFloatCommon(max / 1e6)
|
||||||
|
statistics.MinElapse = common.FormatFloatCommon(min / 1e6)
|
||||||
|
//平均耗时=总耗时/调用次数
|
||||||
|
statistics.AvgElapse = common.FormatFloatCommon(statistics.ElapseTotal / float64(statistics.CallCount))
|
||||||
|
|
||||||
|
a.obs.Notify(observer.EVENT_RESULT, statistics)
|
||||||
}
|
}
|
||||||
|
@ -97,9 +97,12 @@ const (
|
|||||||
TOOLBAR_PB = "protobuf"
|
TOOLBAR_PB = "protobuf"
|
||||||
TOOLBAR_AUTO = "自动化"
|
TOOLBAR_AUTO = "自动化"
|
||||||
|
|
||||||
TOOLBAR_PERF_TIP = "使用说明"
|
TOOLBAR_PERF_TIP = "开始"
|
||||||
TOOLBAR_PERF_CONF = "配置"
|
TOOLBAR_PERF_CONF = "配置"
|
||||||
|
TOOLBAR_PERF_LOGIN = "登陆"
|
||||||
|
TOOLBAR_PERF_CREATE = "创角"
|
||||||
TOOLBAR_PERF_PB = "协议"
|
TOOLBAR_PERF_PB = "协议"
|
||||||
|
TOOLBAR_PERF_RES = "结果"
|
||||||
|
|
||||||
//monitor
|
//monitor
|
||||||
APP_MONITOR_TITLE_ID = "编号"
|
APP_MONITOR_TITLE_ID = "编号"
|
||||||
|
@ -3,6 +3,7 @@ package common
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math"
|
"math"
|
||||||
@ -172,11 +173,63 @@ func Loader(file string) ([]map[string]interface{}, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Json2Pb(jsonString string, pb proto.Message) {
|
func Json2Pb(jsonString string, pb proto.Message) error {
|
||||||
m := pb.ProtoReflect().Interface()
|
m := pb.ProtoReflect().Interface()
|
||||||
protojson.Unmarshal([]byte(jsonString), m)
|
if err := protojson.Unmarshal([]byte(jsonString), m); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Pb2Json(pb proto.Message) string {
|
func Pb2Json(pb proto.Message) string {
|
||||||
return protojson.Format(pb.ProtoReflect().Interface())
|
return protojson.Format(pb.ProtoReflect().Interface())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 保留两位小数 通用
|
||||||
|
func FormatFloatCommon(num float64) float64 {
|
||||||
|
value, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", num), 64)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保留两位小数,舍弃尾数,无进位运算
|
||||||
|
// 主要逻辑就是先乘,trunc之后再除回去,就达到了保留N位小数的效果
|
||||||
|
func FormatFloat(num float64, decimal int) (float64, error) {
|
||||||
|
// 默认乘1
|
||||||
|
d := float64(1)
|
||||||
|
if decimal > 0 {
|
||||||
|
// 10的N次方
|
||||||
|
d = math.Pow10(decimal)
|
||||||
|
}
|
||||||
|
// math.trunc作用就是返回浮点数的整数部分
|
||||||
|
// 再除回去,小数点后无效的0也就不存在了
|
||||||
|
res := strconv.FormatFloat(math.Trunc(num*d)/d, 'f', -1, 64)
|
||||||
|
return strconv.ParseFloat(res, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 强制舍弃尾数
|
||||||
|
func FormatFloatFloor(num float64, decimal int) (float64, error) {
|
||||||
|
// 默认乘1
|
||||||
|
d := float64(1)
|
||||||
|
if decimal > 0 {
|
||||||
|
// 10的N次方
|
||||||
|
d = math.Pow10(decimal)
|
||||||
|
}
|
||||||
|
// math.trunc作用就是返回浮点数的整数部分
|
||||||
|
// 再除回去,小数点后无效的0也就不存在了
|
||||||
|
res := strconv.FormatFloat(math.Floor(num*d)/d, 'f', -1, 64)
|
||||||
|
return strconv.ParseFloat(res, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 舍弃的尾数不为0,强制进位
|
||||||
|
func FormatFloatCeil(num float64, decimal int) (float64, error) {
|
||||||
|
// 默认乘1
|
||||||
|
d := float64(1)
|
||||||
|
if decimal > 0 {
|
||||||
|
// 10的N次方
|
||||||
|
d = math.Pow10(decimal)
|
||||||
|
}
|
||||||
|
// math.trunc作用就是返回浮点数的整数部分
|
||||||
|
// 再除回去,小数点后无效的0也就不存在了
|
||||||
|
res := strconv.FormatFloat(math.Ceil(num*d)/d, 'f', -1, 64)
|
||||||
|
return strconv.ParseFloat(res, 64)
|
||||||
|
}
|
||||||
|
@ -4,8 +4,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"go_dreamfactory/pb"
|
"go_dreamfactory/pb"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSubStr(t *testing.T) {
|
func TestSubStr(t *testing.T) {
|
||||||
@ -33,15 +34,24 @@ func TestJsonToPb(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSpli(t *testing.T) {
|
func TestSpli(t *testing.T) {
|
||||||
pbName := "UserLoginReq"
|
now := time.Now()
|
||||||
route := "user.login"
|
fmt.Println(now.UnixNano())
|
||||||
if strings.HasSuffix(pbName, "Req") {
|
fmt.Println(now.UnixNano() / 1e6) //将纳秒转换为毫秒
|
||||||
s := strings.SplitN(route, ".", 2)
|
|
||||||
low := strings.ToLower(pbName)
|
|
||||||
if strings.Contains(low, s[0]) &&
|
|
||||||
strings.Contains(low, s[1]) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDiv(t *testing.T) {
|
||||||
|
numF := float64(32766600)
|
||||||
|
// 保留两位小数, 通用
|
||||||
|
value, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", numF/1e6), 64)
|
||||||
|
fmt.Println(reflect.TypeOf(value), value)
|
||||||
|
fmt.Println(FormatFloatCommon(numF / 1e6))
|
||||||
|
|
||||||
|
num, _ := FormatFloat(numF, 2)
|
||||||
|
fmt.Println(reflect.TypeOf(num), num)
|
||||||
|
// 舍弃的尾数不为0,强制进位
|
||||||
|
num, _ = FormatFloatCeil(0.2205, 2)
|
||||||
|
fmt.Println(reflect.TypeOf(num), num)
|
||||||
|
// 强制舍弃尾数
|
||||||
|
num, _ = FormatFloatFloor(0.2295, 2)
|
||||||
|
fmt.Println(reflect.TypeOf(num), num)
|
||||||
}
|
}
|
||||||
|
@ -22,3 +22,12 @@ type CallResult struct {
|
|||||||
Message string
|
Message string
|
||||||
Elapse time.Duration
|
Elapse time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Statistics struct {
|
||||||
|
ElapseTotal float64 //总耗时
|
||||||
|
MaxElapse float64 //最大耗时
|
||||||
|
MinElapse float64 //最小耗时
|
||||||
|
AvgElapse float64 //平均耗时
|
||||||
|
CallCount int64 //调用次数
|
||||||
|
Route string //协议名称
|
||||||
|
}
|
||||||
|
@ -52,6 +52,6 @@ func (param *ParamMgr) Check() error {
|
|||||||
|
|
||||||
buf.WriteString(fmt.Sprintf("通过. (timeoutMS=%s, lps=%d, durationS=%s)",
|
buf.WriteString(fmt.Sprintf("通过. (timeoutMS=%s, lps=%d, durationS=%s)",
|
||||||
param.Timeout, param.Lps, param.Duration))
|
param.Timeout, param.Lps, param.Duration))
|
||||||
logrus.Infoln(buf.String())
|
logrus.Debugln(buf.String())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,9 @@ func newDefaultConfig() *Config {
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
Pressure PressureConfig `json:"Pressure,omitempty"`
|
Pressure PressureConfig `json:"Pressure,omitempty"`
|
||||||
UserCount int32 `json:"UserCount,omitempty"` //用户数
|
UserCount int32 `json:"UserCount,omitempty"` //用户数
|
||||||
|
SId string `json:"sid,omitempty"` //区服ID
|
||||||
WsAddr string `json:"wsAddr,omitempty"` //websocket addr
|
WsAddr string `json:"wsAddr,omitempty"` //websocket addr
|
||||||
|
IntervalS int32 `json:"intervalS,omitempty"` //间隔时间s
|
||||||
}
|
}
|
||||||
|
|
||||||
//压测配置
|
//压测配置
|
||||||
|
@ -99,7 +99,7 @@ func main() {
|
|||||||
}),
|
}),
|
||||||
widget.NewButton("自动化测试", func() {
|
widget.NewButton("自动化测试", func() {
|
||||||
perfWindow := ui.NewPerfWindow(appUI, w)
|
perfWindow := ui.NewPerfWindow(appUI, w)
|
||||||
perfWindow.CreateWindow(common.APP_NAME, 600, 800, true)
|
perfWindow.CreateWindow(common.APP_NAME, 800, 600, true)
|
||||||
w.Hide()
|
w.Hide()
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
|
@ -2,26 +2,60 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"go_dreamfactory/cmd/v2/lib"
|
"go_dreamfactory/cmd/v2/lib"
|
||||||
|
"go_dreamfactory/cmd/v2/lib/common"
|
||||||
|
"go_dreamfactory/comm"
|
||||||
|
"go_dreamfactory/pb"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/Pallinder/go-randomdata"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func loginReq() ([]byte, error) {
|
||||||
|
head := &pb.UserMessage{MainType: "user", SubType: "login"}
|
||||||
|
sid := "dfz"
|
||||||
|
account := randomdata.SillyName()
|
||||||
|
head.Sec = common.BuildSecStr(sid, account)
|
||||||
|
if comm.ProtoMarshal(&pb.UserLoginReq{
|
||||||
|
Sid: sid,
|
||||||
|
Account: account,
|
||||||
|
}, head) {
|
||||||
|
data, err := proto.Marshal(head)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestStart(t *testing.T) {
|
func TestStart(t *testing.T) {
|
||||||
wsAddr := "ws://10.0.5.215:7891/gateway"
|
wsAddr := "ws://10.0.0.238:7891/gateway"
|
||||||
|
h, err := NewWsCli(wsAddr, 2*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := loginReq()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
h.SetReq(b)
|
||||||
param := lib.ParamMgr{
|
param := lib.ParamMgr{
|
||||||
Caller: NewWsCli(wsAddr, 2*time.Second),
|
Caller: h,
|
||||||
Timeout: 2 * time.Second,
|
Timeout: 50 * time.Millisecond,
|
||||||
Lps: uint32(10),
|
Lps: uint32(1),
|
||||||
Duration: 3 * time.Second,
|
Duration: 5 * time.Second,
|
||||||
ResultCh: make(chan *lib.CallResult, 50),
|
ResultCh: make(chan *lib.CallResult, 50),
|
||||||
}
|
}
|
||||||
a, err := lib.NewAssistant(param)
|
a, err := lib.NewAssistant(nil, param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("AI助手初始化错误: %v", err)
|
t.Fatalf("AI助手初始化错误: %v", err)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Log("AI助手启动...")
|
|
||||||
a.Start()
|
a.Start()
|
||||||
|
|
||||||
a.ShowResult()
|
a.ShowResult()
|
||||||
|
@ -14,4 +14,8 @@ const (
|
|||||||
EVENT_UI_CLEAN Event = "uiclean"
|
EVENT_UI_CLEAN Event = "uiclean"
|
||||||
// 请求响应计时
|
// 请求响应计时
|
||||||
EVENT_RST = "ctime"
|
EVENT_RST = "ctime"
|
||||||
|
|
||||||
|
// 测试结果
|
||||||
|
EVENT_RESULT = "result"
|
||||||
|
EVENT_FINISH = "finish"
|
||||||
)
|
)
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Pallinder/go-randomdata"
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
@ -16,64 +15,48 @@ import (
|
|||||||
|
|
||||||
type WsCli struct {
|
type WsCli struct {
|
||||||
addr string
|
addr string
|
||||||
ws *websocket.Conn
|
conn *websocket.Conn
|
||||||
reqData []byte //请求数据
|
reqData []byte //请求数据
|
||||||
|
uid string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWsCli(addr string, timeout time.Duration) lib.Handler {
|
func NewWsCli(addr string, timeout time.Duration) (lib.Handler, error) {
|
||||||
cli := &WsCli{addr: addr}
|
cli := &WsCli{addr: addr}
|
||||||
cli.connect(timeout)
|
if err := cli.connect(timeout); err != nil {
|
||||||
return cli
|
return nil, err
|
||||||
|
}
|
||||||
|
return cli, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *WsCli) connect(timeout time.Duration) error {
|
func (cli *WsCli) connect(timeout time.Duration) error {
|
||||||
if cli.ws == nil {
|
if cli.conn == nil {
|
||||||
dialer := &websocket.Dialer{
|
dialer := &websocket.Dialer{
|
||||||
HandshakeTimeout: timeout,
|
HandshakeTimeout: 2 * time.Second,
|
||||||
}
|
}
|
||||||
conn, _, err := dialer.Dial(cli.addr, nil)
|
conn, _, err := dialer.Dial(cli.addr, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("websocket conn err:%v", err)
|
logrus.Errorf("websocket conn err:%v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cli.ws = conn
|
cli.conn = conn
|
||||||
}
|
}
|
||||||
|
|
||||||
// ping
|
// ping
|
||||||
go func() {
|
// go func() {
|
||||||
timer := time.NewTimer(2 * time.Second)
|
// timer := time.NewTimer(2 * time.Second)
|
||||||
for {
|
// for {
|
||||||
timer.Reset(2 * time.Second)
|
// timer.Reset(2 * time.Second)
|
||||||
<-timer.C
|
// <-timer.C
|
||||||
if err := cli.ws.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
|
// if err := cli.ws.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
|
||||||
break
|
// break
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}()
|
// }()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *WsCli) loginReq() ([]byte, error) {
|
|
||||||
head := &pb.UserMessage{MainType: "user", SubType: "login"}
|
|
||||||
sid := "dfz"
|
|
||||||
account := randomdata.SillyName()
|
|
||||||
head.Sec = common.BuildSecStr(sid, account)
|
|
||||||
if comm.ProtoMarshal(&pb.UserLoginReq{
|
|
||||||
Sid: sid,
|
|
||||||
Account: account,
|
|
||||||
}, head) {
|
|
||||||
data, err := proto.Marshal(head)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查登录相应
|
// 检查登录相应
|
||||||
func (cli *WsCli) checkLoginResp(data []byte) bool {
|
func (cli *WsCli) checkResp(data []byte) bool {
|
||||||
msg := &pb.UserMessage{}
|
msg := &pb.UserMessage{}
|
||||||
if err := proto.Unmarshal(data, msg); err != nil {
|
if err := proto.Unmarshal(data, msg); err != nil {
|
||||||
logrus.Error("结果解析失败")
|
logrus.Error("结果解析失败")
|
||||||
@ -89,10 +72,15 @@ func (cli *WsCli) checkLoginResp(data []byte) bool {
|
|||||||
if rsp.Data != nil {
|
if rsp.Data != nil {
|
||||||
if rsp.Data.Uid != "" {
|
if rsp.Data.Uid != "" {
|
||||||
logrus.WithField("uid", rsp.Data.Uid).Debug("登录响应")
|
logrus.WithField("uid", rsp.Data.Uid).Debug("登录响应")
|
||||||
|
cli.uid = rsp.Data.Uid
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
} else {
|
||||||
|
if cli.uid != "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -131,23 +119,21 @@ func (cli *WsCli) BuildReq() lib.RawReq {
|
|||||||
func (cli *WsCli) Call(req []byte) ([]byte, error) {
|
func (cli *WsCli) Call(req []byte) ([]byte, error) {
|
||||||
|
|
||||||
// 向连接写数据
|
// 向连接写数据
|
||||||
cli.ws.WriteMessage(websocket.BinaryMessage, req)
|
cli.conn.WriteMessage(websocket.BinaryMessage, req)
|
||||||
|
|
||||||
// 读数据
|
// 读数据
|
||||||
var res []byte
|
var res []byte
|
||||||
for {
|
for {
|
||||||
_, data, err := cli.ws.ReadMessage()
|
_, data, err := cli.conn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("readMessage err:%v", err)
|
logrus.Errorf("readMessage err:%v", err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if cli.checkLoginResp(data) {
|
if cli.checkResp(data) {
|
||||||
return data, nil
|
return data, nil
|
||||||
} else {
|
} else {
|
||||||
if !cli.checkPush(data) {
|
cli.checkPush(data)
|
||||||
logrus.Debug("登录失败")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,12 +145,12 @@ func (cli *WsCli) Check(req lib.RawReq, resp lib.RawResp) *lib.CallResult {
|
|||||||
result.Id = resp.ID
|
result.Id = resp.ID
|
||||||
result.Req = req
|
result.Req = req
|
||||||
result.Resp = resp
|
result.Resp = resp
|
||||||
//TODO 解析结果
|
|
||||||
msg := &pb.UserMessage{}
|
msg := &pb.UserMessage{}
|
||||||
if err := proto.Unmarshal(resp.Resp, msg); err != nil {
|
if err := proto.Unmarshal(resp.Resp, msg); err != nil {
|
||||||
logrus.Error("结果解析失败")
|
logrus.Error("结果解析失败")
|
||||||
return &result
|
return &result
|
||||||
}
|
}
|
||||||
logrus.WithFields(logrus.Fields{"msg": msg}).Debug("检查结果")
|
// logrus.WithFields(logrus.Fields{"msg": msg}).Debug("检查结果")
|
||||||
return &result
|
return &result
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ var (
|
|||||||
&perfWelcome{},
|
&perfWelcome{},
|
||||||
&perfConf{},
|
&perfConf{},
|
||||||
&perfPb{},
|
&perfPb{},
|
||||||
|
&perfResult{},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/layout"
|
||||||
"fyne.io/fyne/v2/theme"
|
"fyne.io/fyne/v2/theme"
|
||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -50,15 +51,37 @@ func (app *perfConf) LazyInit(ptService service.PttService, obs observer.Observe
|
|||||||
userCountEntry.PlaceHolder = "自动创建的用户数"
|
userCountEntry.PlaceHolder = "自动创建的用户数"
|
||||||
userCountEntry.Text = cast.ToString(app.conf.UserCount)
|
userCountEntry.Text = cast.ToString(app.conf.UserCount)
|
||||||
|
|
||||||
|
sidEntry := widget.NewEntry()
|
||||||
|
sidEntry.PlaceHolder = "区服ID"
|
||||||
|
sidEntry.Text = app.conf.SId
|
||||||
|
|
||||||
|
intervalEntry := widget.NewEntry()
|
||||||
|
intervalEntry.PlaceHolder = "间隔时间(s)"
|
||||||
|
intervalEntry.Text = cast.ToString(app.conf.IntervalS)
|
||||||
|
|
||||||
form := widget.NewForm(
|
form := widget.NewForm(
|
||||||
|
widget.NewFormItem("服务地址", wsAddrEntry),
|
||||||
|
widget.NewFormItem("区服", sidEntry),
|
||||||
|
widget.NewFormItem("用户数", userCountEntry),
|
||||||
widget.NewFormItem("超时(ms)", timeoutEntry),
|
widget.NewFormItem("超时(ms)", timeoutEntry),
|
||||||
widget.NewFormItem("并发量", lpsEntry),
|
widget.NewFormItem("并发量", lpsEntry),
|
||||||
widget.NewFormItem("持续时间(s)", durationEntry),
|
widget.NewFormItem("持续时间(s)", durationEntry),
|
||||||
widget.NewFormItem("用户数", userCountEntry),
|
widget.NewFormItem("间隔时间(s)", intervalEntry),
|
||||||
widget.NewFormItem("服务地址", wsAddrEntry),
|
|
||||||
)
|
)
|
||||||
form.OnSubmit = func() {
|
// btn
|
||||||
|
nextBtn := widget.NewButtonWithIcon("下一步", theme.NavigateNextIcon(), nil)
|
||||||
|
nextBtn.OnTapped = func() {
|
||||||
//校验表单数据
|
//校验表单数据
|
||||||
|
if wsAddrEntry.Text == "" {
|
||||||
|
common.ShowTip("服务地址必填")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if sidEntry.Text == "" {
|
||||||
|
common.ShowTip("区服ID必填")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if timeoutEntry.Text == "" {
|
if timeoutEntry.Text == "" {
|
||||||
common.ShowTip("超时时间必填")
|
common.ShowTip("超时时间必填")
|
||||||
return
|
return
|
||||||
@ -85,25 +108,35 @@ func (app *perfConf) LazyInit(ptService service.PttService, obs observer.Observe
|
|||||||
app.conf.Pressure = pressure
|
app.conf.Pressure = pressure
|
||||||
app.conf.UserCount = cast.ToInt32(userCountEntry.Text)
|
app.conf.UserCount = cast.ToInt32(userCountEntry.Text)
|
||||||
app.conf.WsAddr = wsAddrEntry.Text
|
app.conf.WsAddr = wsAddrEntry.Text
|
||||||
|
app.conf.SId = sidEntry.Text
|
||||||
if err := perfWin.UIImpl.storage.StoreConfig(app.conf); err != nil {
|
if err := perfWin.UIImpl.storage.StoreConfig(app.conf); err != nil {
|
||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//next
|
//next
|
||||||
|
defer closeApp3(perfWin.tabs, common.TOOLBAR_PERF_CONF)
|
||||||
openApp3(perfWin.tabs, common.TOOLBAR_PERF_PB)
|
openApp3(perfWin.tabs, common.TOOLBAR_PERF_PB)
|
||||||
}
|
}
|
||||||
form.SubmitText = "下一步"
|
|
||||||
form.OnCancel = func() {
|
resetBtn := widget.NewButtonWithIcon("重置", theme.ContentRedoIcon(), nil)
|
||||||
|
resetBtn.OnTapped = func() {
|
||||||
timeoutEntry.Text = ""
|
timeoutEntry.Text = ""
|
||||||
lpsEntry.Text = ""
|
lpsEntry.Text = ""
|
||||||
durationEntry.Text = ""
|
durationEntry.Text = ""
|
||||||
userCountEntry.Text = ""
|
userCountEntry.Text = ""
|
||||||
wsAddrEntry.Text = ""
|
wsAddrEntry.Text = ""
|
||||||
|
sidEntry.Text = ""
|
||||||
form.Refresh()
|
form.Refresh()
|
||||||
}
|
}
|
||||||
form.CancelText = "重置"
|
|
||||||
|
|
||||||
content.Objects = append(content.Objects, form)
|
preBtn := widget.NewButtonWithIcon("上一步", theme.NavigateBackIcon(), nil)
|
||||||
|
preBtn.OnTapped = func() {
|
||||||
|
defer closeApp3(perfWin.tabs, common.TOOLBAR_PERF_CONF)
|
||||||
|
openApp3(perfWin.tabs, common.TOOLBAR_PERF_TIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := container.NewBorder(nil, container.NewHBox(layout.NewSpacer(), preBtn, resetBtn, nextBtn), nil, nil, form)
|
||||||
|
content.Objects = append(content.Objects, c)
|
||||||
app.tabItem.Content = content
|
app.tabItem.Content = content
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -111,3 +144,11 @@ func (app *perfConf) LazyInit(ptService service.PttService, obs observer.Observe
|
|||||||
func (a *perfConf) GetAppName() string {
|
func (a *perfConf) GetAppName() string {
|
||||||
return common.TOOLBAR_PERF_CONF
|
return common.TOOLBAR_PERF_CONF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *perfConf) OnClose() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *perfConf) OnDestroy() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
38
cmd/v2/ui/perf_create.go
Normal file
38
cmd/v2/ui/perf_create.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go_dreamfactory/cmd/v2/lib/common"
|
||||||
|
"go_dreamfactory/cmd/v2/lib/storage"
|
||||||
|
"go_dreamfactory/cmd/v2/service"
|
||||||
|
"go_dreamfactory/cmd/v2/service/observer"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/theme"
|
||||||
|
)
|
||||||
|
|
||||||
|
type perfCreate struct {
|
||||||
|
appAdapter
|
||||||
|
|
||||||
|
obs observer.Observer
|
||||||
|
conf *storage.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *perfCreate) LazyInit(ptService service.PttService, obs observer.Observer) error {
|
||||||
|
app.obs = obs
|
||||||
|
app.conf = perfWin.UIImpl.config
|
||||||
|
|
||||||
|
app.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_PERF_CONF, theme.ContentCopyIcon(), nil)
|
||||||
|
content := container.NewMax()
|
||||||
|
content.Objects = []fyne.CanvasObject{}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *perfCreate) GetAppName() string {
|
||||||
|
return common.TOOLBAR_PERF_CREATE
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *perfCreate) OnClose() bool {
|
||||||
|
return false
|
||||||
|
}
|
49
cmd/v2/ui/perf_login.go
Normal file
49
cmd/v2/ui/perf_login.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go_dreamfactory/cmd/v2/lib/common"
|
||||||
|
"go_dreamfactory/cmd/v2/lib/storage"
|
||||||
|
"go_dreamfactory/cmd/v2/service"
|
||||||
|
"go_dreamfactory/cmd/v2/service/observer"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/theme"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
|
)
|
||||||
|
|
||||||
|
type perfLogin struct {
|
||||||
|
appAdapter
|
||||||
|
|
||||||
|
obs observer.Observer
|
||||||
|
conf *storage.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *perfLogin) LazyInit(ptService service.PttService, obs observer.Observer) error {
|
||||||
|
app.obs = obs
|
||||||
|
app.conf = perfWin.UIImpl.config
|
||||||
|
|
||||||
|
app.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_PERF_CONF, theme.ContentCopyIcon(), nil)
|
||||||
|
content := container.NewMax()
|
||||||
|
content.Objects = []fyne.CanvasObject{}
|
||||||
|
|
||||||
|
loginTestBtn := widget.NewButton("登陆/注册", func() {
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
createTestBtn := widget.NewButton("创角", func() {})
|
||||||
|
|
||||||
|
btns := container.NewHBox(loginTestBtn, createTestBtn)
|
||||||
|
c := container.NewBorder(btns, nil, nil, nil)
|
||||||
|
content.Objects = append(content.Objects, c)
|
||||||
|
app.tabItem.Content = content
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *perfLogin) GetAppName() string {
|
||||||
|
return common.TOOLBAR_PERF_LOGIN
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *perfLogin) OnClose() bool {
|
||||||
|
return false
|
||||||
|
}
|
@ -10,6 +10,7 @@ import (
|
|||||||
"go_dreamfactory/cmd/v2/service/observer"
|
"go_dreamfactory/cmd/v2/service/observer"
|
||||||
"go_dreamfactory/comm"
|
"go_dreamfactory/comm"
|
||||||
"go_dreamfactory/pb"
|
"go_dreamfactory/pb"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
@ -68,53 +69,86 @@ func (app *perfPb) LazyInit(ptService service.PttService, obs observer.Observer)
|
|||||||
})
|
})
|
||||||
|
|
||||||
// next按钮
|
// next按钮
|
||||||
nextBtn := widget.NewButtonWithIcon("执行", theme.ConfirmIcon(), func() {
|
nextBtn := widget.NewButtonWithIcon("下一步", theme.NavigateNextIcon(), nil)
|
||||||
|
nextBtn.OnTapped = func() {
|
||||||
|
defer closeApp3(perfWin.tabs, common.TOOLBAR_PERF_PB)
|
||||||
|
openApp3(perfWin.tabs, common.TOOLBAR_PERF_RES)
|
||||||
// 根据填写的用户数创建用户
|
// 根据填写的用户数创建用户
|
||||||
userCount := perfWin.config.UserCount
|
userCount := perfWin.config.UserCount
|
||||||
|
|
||||||
// 遍历时,通过sleep 控制增加的用户数
|
// 遍历时,通过sleep 控制增加的用户数
|
||||||
for i := int32(0); i < userCount; i++ {
|
for i := int32(0); i < userCount; i++ {
|
||||||
handler := service.NewWsCli(perfWin.config.WsAddr, time.Duration(perfWin.config.Pressure.TimeoutMs))
|
handler, err := service.NewWsCli(perfWin.config.WsAddr, time.Duration(perfWin.config.Pressure.TimeoutMs)*time.Millisecond)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var login *UserLogin
|
||||||
|
login, err = app.loginReq(perfWin.config.SId)
|
||||||
|
handler.SetReq(login.req)
|
||||||
|
assist := app.createAssistantWithoutConf(handler)
|
||||||
|
assist.Start()
|
||||||
|
assist.ShowResult()
|
||||||
|
|
||||||
// 遍历测试的协议
|
// 遍历测试的协议
|
||||||
for _, item := range app.itemList.CachedList.Items {
|
for _, item := range app.itemList.CachedList.Items {
|
||||||
if data, ok := item.Data.(*cfg.GameTestFlowData); ok {
|
if data, ok := item.Data.(*cfg.GameTestFlowData); ok {
|
||||||
logrus.Infof("%v %v", data.Route, data.Params)
|
logrus.Debugf("%v %v", data.Route, data.Params)
|
||||||
var (
|
var (
|
||||||
reqData []byte
|
reqData []byte
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if data.Route == "user.login" {
|
// if data.Route == "user.login" {
|
||||||
reqData, err = app.loginReq()
|
// login, err = app.loginReq()
|
||||||
|
// if err != nil {
|
||||||
|
// logrus.Error(err)
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// reqData = login.req
|
||||||
|
// } else {
|
||||||
|
if login == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if v, ok := pbMap[data.Route]; ok {
|
||||||
|
routeStr := strings.SplitN(data.Route, ".", 2)
|
||||||
|
head := &pb.UserMessage{MainType: routeStr[0], SubType: routeStr[1]}
|
||||||
|
head.Sec = common.BuildSecStr(login.sid, login.account)
|
||||||
|
if err := common.Json2Pb(data.Params, v); err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if comm.ProtoMarshal(v, head) {
|
||||||
|
reqData, err = proto.Marshal(head)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
if pb, ok := pbMap[data.Route]; ok {
|
|
||||||
common.Json2Pb(data.Params, pb)
|
|
||||||
reqData, err = proto.Marshal(pb)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// }
|
||||||
|
|
||||||
handler.SetReq(reqData)
|
handler.SetReq(reqData)
|
||||||
assist := app.createAssistant(handler)
|
assist := app.createAssistant(handler)
|
||||||
assist.Start()
|
assist.Start()
|
||||||
assist.ShowResult()
|
assist.ShowResult()
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// time.Sleep(time.Second)
|
// time.Sleep(time.Second)
|
||||||
}
|
}
|
||||||
|
logrus.Info("所有用户执行完毕...")
|
||||||
|
obs.Notify(observer.EVENT_FINISH, true)
|
||||||
|
}
|
||||||
|
|
||||||
})
|
preBtn := widget.NewButtonWithIcon("上一步", theme.NavigateBackIcon(), nil)
|
||||||
|
preBtn.OnTapped = func() {
|
||||||
|
defer closeApp3(perfWin.tabs, common.TOOLBAR_PERF_PB)
|
||||||
|
openApp3(perfWin.tabs, common.TOOLBAR_PERF_CONF)
|
||||||
|
}
|
||||||
|
|
||||||
//layout
|
//layout
|
||||||
c := container.NewBorder(container.NewHBox(refeshBtn), container.NewHBox(layout.NewSpacer(), nextBtn), nil, nil, app.itemList.ItemList)
|
c := container.NewBorder(container.NewHBox(refeshBtn), container.NewHBox(layout.NewSpacer(), preBtn, nextBtn), nil, nil, app.itemList.ItemList)
|
||||||
content.Objects = append(content.Objects, c)
|
content.Objects = append(content.Objects, c)
|
||||||
app.tabItem.Content = content
|
app.tabItem.Content = content
|
||||||
return nil
|
return nil
|
||||||
@ -124,6 +158,27 @@ func (a *perfPb) GetAppName() string {
|
|||||||
return common.TOOLBAR_PERF_PB
|
return common.TOOLBAR_PERF_PB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *perfPb) OnClose() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *perfPb) createAssistantWithoutConf(handler lib.Handler) lib.Aiassistant {
|
||||||
|
|
||||||
|
param := lib.ParamMgr{
|
||||||
|
Caller: handler,
|
||||||
|
Timeout: time.Duration(a.conf.Pressure.TimeoutMs) * time.Millisecond,
|
||||||
|
Lps: 1,
|
||||||
|
Duration: 1,
|
||||||
|
ResultCh: make(chan *lib.CallResult, 50),
|
||||||
|
}
|
||||||
|
assist, err := lib.NewAssistant(a.obs, param)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf("AI助手初始化错误: %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return assist
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
func (a *perfPb) createAssistant(handler lib.Handler) lib.Aiassistant {
|
func (a *perfPb) createAssistant(handler lib.Handler) lib.Aiassistant {
|
||||||
|
|
||||||
@ -134,7 +189,7 @@ func (a *perfPb) createAssistant(handler lib.Handler) lib.Aiassistant {
|
|||||||
Duration: time.Duration(a.conf.Pressure.DurationS) * time.Second,
|
Duration: time.Duration(a.conf.Pressure.DurationS) * time.Second,
|
||||||
ResultCh: make(chan *lib.CallResult, 50),
|
ResultCh: make(chan *lib.CallResult, 50),
|
||||||
}
|
}
|
||||||
assist, err := lib.NewAssistant(param)
|
assist, err := lib.NewAssistant(a.obs, param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("AI助手初始化错误: %v", err)
|
logrus.Errorf("AI助手初始化错误: %v", err)
|
||||||
return nil
|
return nil
|
||||||
@ -142,21 +197,30 @@ func (a *perfPb) createAssistant(handler lib.Handler) lib.Aiassistant {
|
|||||||
return assist
|
return assist
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *perfPb) loginReq() ([]byte, error) {
|
type UserLogin struct {
|
||||||
|
req []byte
|
||||||
|
sid string
|
||||||
|
account string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *perfPb) loginReq(sid string) (*UserLogin, error) {
|
||||||
|
login := &UserLogin{sid: sid}
|
||||||
head := &pb.UserMessage{MainType: "user", SubType: "login"}
|
head := &pb.UserMessage{MainType: "user", SubType: "login"}
|
||||||
sid := "dfz"
|
|
||||||
account := randomdata.SillyName()
|
account := randomdata.SillyName()
|
||||||
head.Sec = common.BuildSecStr(sid, account)
|
login.account = account
|
||||||
|
head.Sec = common.BuildSecStr(login.sid, login.account)
|
||||||
if comm.ProtoMarshal(&pb.UserLoginReq{
|
if comm.ProtoMarshal(&pb.UserLoginReq{
|
||||||
Sid: sid,
|
Sid: login.sid,
|
||||||
Account: account,
|
Account: login.account,
|
||||||
}, head) {
|
}, head) {
|
||||||
|
logrus.WithField("账号", login.account).Info("登录")
|
||||||
data, err := proto.Marshal(head)
|
data, err := proto.Marshal(head)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
login.req = data
|
||||||
|
|
||||||
return data, nil
|
return login, nil
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
103
cmd/v2/ui/perf_result.go
Normal file
103
cmd/v2/ui/perf_result.go
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go_dreamfactory/cmd/v2/lib"
|
||||||
|
"go_dreamfactory/cmd/v2/lib/common"
|
||||||
|
"go_dreamfactory/cmd/v2/lib/storage"
|
||||||
|
"go_dreamfactory/cmd/v2/service"
|
||||||
|
"go_dreamfactory/cmd/v2/service/observer"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/layout"
|
||||||
|
"fyne.io/fyne/v2/theme"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
|
)
|
||||||
|
|
||||||
|
type perfResult struct {
|
||||||
|
appAdapter
|
||||||
|
|
||||||
|
obs observer.Observer
|
||||||
|
conf *storage.Config
|
||||||
|
|
||||||
|
itemList common.ItemList
|
||||||
|
|
||||||
|
resultList func() //结果列表
|
||||||
|
resetBtn *widget.Button
|
||||||
|
report *widget.Card
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *perfResult) LazyInit(ptService service.PttService, obs observer.Observer) error {
|
||||||
|
app.obs = obs
|
||||||
|
app.conf = perfWin.UIImpl.config
|
||||||
|
|
||||||
|
app.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_PERF_RES, theme.ContentCopyIcon(), nil)
|
||||||
|
content := container.NewMax()
|
||||||
|
content.Objects = []fyne.CanvasObject{}
|
||||||
|
|
||||||
|
app.itemList = *common.NewItemList()
|
||||||
|
app.itemList.ItemList = app.itemList.CreateList()
|
||||||
|
|
||||||
|
//重新开始
|
||||||
|
app.resetBtn = widget.NewButtonWithIcon("再来一次", theme.ContentRedoIcon(), nil)
|
||||||
|
app.resetBtn.Hide()
|
||||||
|
app.resetBtn.OnTapped = func() {
|
||||||
|
defer openApp3(perfWin.tabs, common.TOOLBAR_PERF_TIP)
|
||||||
|
app.itemList.Reset()
|
||||||
|
closeApp3(perfWin.tabs, common.TOOLBAR_PERF_RES)
|
||||||
|
}
|
||||||
|
|
||||||
|
//统计Panel
|
||||||
|
app.report = widget.NewCard("测试报告", "登录/创角", container.NewVBox(
|
||||||
|
// widget.NewLabel("结果:"),
|
||||||
|
))
|
||||||
|
app.report.Hide()
|
||||||
|
//layout
|
||||||
|
c := container.NewBorder(app.report, container.NewHBox(layout.NewSpacer(), app.resetBtn), nil, nil, app.itemList.ItemList)
|
||||||
|
content.Objects = append(content.Objects, c)
|
||||||
|
app.tabItem.Content = content
|
||||||
|
app.listen()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *perfResult) listen() {
|
||||||
|
app.obs.AddListener(observer.EVENT_RESULT, observer.Listener{
|
||||||
|
OnNotify: func(data interface{}, args ...interface{}) {
|
||||||
|
res, ok := data.(*lib.Statistics)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
item := common.Item{
|
||||||
|
Text: fmt.Sprintf("协议名称:%s, 调用次数:%d, 总耗时:%vms, 平均耗时:%vms, 最大耗时:%vms, 最小耗时:%vms",
|
||||||
|
res.Route, res.CallCount, res.ElapseTotal, res.AvgElapse, res.MaxElapse, res.MinElapse),
|
||||||
|
Data: res,
|
||||||
|
}
|
||||||
|
app.itemList.AddItem(item)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
app.obs.AddListener(observer.EVENT_FINISH, observer.Listener{
|
||||||
|
OnNotify: func(data interface{}, args ...interface{}) {
|
||||||
|
finish, ok := data.(bool)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if finish {
|
||||||
|
app.resetBtn.Show()
|
||||||
|
app.resetBtn.Refresh()
|
||||||
|
app.report.Show()
|
||||||
|
app.report.Refresh()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *perfResult) GetAppName() string {
|
||||||
|
return common.TOOLBAR_PERF_RES
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *perfResult) OnClose() bool {
|
||||||
|
return false
|
||||||
|
}
|
@ -34,9 +34,11 @@ func (app *perfWelcome) LazyInit(service service.PttService, obs observer.Observ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
goBtn := widget.NewButton("开始测试 >>", func() {
|
goBtn := widget.NewButton("开始测试 >>", nil)
|
||||||
|
goBtn.OnTapped = func() {
|
||||||
|
defer closeApp3(perfWin.tabs, common.TOOLBAR_PERF_TIP)
|
||||||
openApp3(perfWin.tabs, common.TOOLBAR_PERF_CONF)
|
openApp3(perfWin.tabs, common.TOOLBAR_PERF_CONF)
|
||||||
})
|
}
|
||||||
app.tabItem.Content = container.NewCenter(
|
app.tabItem.Content = container.NewCenter(
|
||||||
container.NewVBox(
|
container.NewVBox(
|
||||||
wel,
|
wel,
|
||||||
@ -56,3 +58,7 @@ func (a *perfWelcome) GetAppName() string {
|
|||||||
func (a *perfWelcome) OnClose() bool {
|
func (a *perfWelcome) OnClose() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *perfWelcome) OnDestroy() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
@ -102,6 +102,6 @@ func (ui *PerfWindowImpl) registerPb(route string, pb proto.Message) {
|
|||||||
|
|
||||||
func (ui *PerfWindowImpl) initPb() {
|
func (ui *PerfWindowImpl) initPb() {
|
||||||
ui.registerPb("user.login", &pb.UserLoginReq{})
|
ui.registerPb("user.login", &pb.UserLoginReq{})
|
||||||
ui.registerPb("user.login", &pb.UserCreateReq{})
|
ui.registerPb("user.create", &pb.UserCreateReq{})
|
||||||
ui.registerPb("sys.funclist", &pb.SysFuncListReq{})
|
ui.registerPb("sys.funclist", &pb.SysFuncListReq{})
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,6 @@ func openApp2(ac *appContainer, name string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func openApp3(ac *appContainer, name string) {
|
func openApp3(ac *appContainer, name string) {
|
||||||
for _, app := range perfRegister {
|
for _, app := range perfRegister {
|
||||||
if app.GetAppName() == name {
|
if app.GetAppName() == name {
|
||||||
@ -55,4 +53,10 @@ func openApp3(ac *appContainer, name string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func closeApp3(ac *appContainer, name string) {
|
||||||
|
for _, appItem := range ac.Items {
|
||||||
|
if appItem.Text == name {
|
||||||
|
ac.Remove(appItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user