gitee.com/KyleChenSource/lib-robot@v1.0.2/robottest/testcaseimp/interaction.go (about) 1 package testcaseimp 2 3 /* 4 实现交互模拟发包功能 5 file(f) filename: 指定发包使用的文件 6 out(o) filename:指定消息格式化输出的文件 7 generator(g) msgid [msgkey]: 生成指定msgId消息, 默认msgid_default作为key 8 send(s) msgkey: 发送file的指定key消息 9 exit(e) [error]: 退出action, 默认error = nil 10 */ 11 12 import ( 13 "flag" 14 "fmt" 15 "regexp" 16 "strconv" 17 "strings" 18 19 "gitee.com/KyleChenSource/lib-robot/robottest/common/interaction" 20 "gitee.com/KyleChenSource/lib-robot/robottest/protos" 21 "gitee.com/KyleChenSource/lib-robot/robottest/robot/testcase" 22 23 "gitee.com/KyleChenSource/lib-robot/robottest/log" 24 25 "gitee.com/KyleChenSource/lib-robot/robottest/common" 26 ) 27 28 type InteractionCnf struct { 29 testcase.TestcaseActionConfig_ 30 } 31 32 type InteractionFactory struct { 33 } 34 35 func (this *InteractionFactory) Cnf() testcase.TestcaseActionCnf { 36 return &InteractionCnf{} 37 } 38 39 func (this *InteractionFactory) New(id testcase.TestActionID, tf testcase.ITestFlow, cnf testcase.TestcaseActionCnf) (testcase.ITestcaseAction, error) { 40 return &Interaction{ 41 _id: id, 42 _tf: tf, 43 _cnf: cnf.(*InteractionCnf), 44 }, nil 45 } 46 47 func init() { 48 testcase.TESTCASEACTION_MGR.Register("Interaction", &InteractionFactory{}) 49 } 50 51 type Interaction struct { 52 _id testcase.TestActionID 53 _tf testcase.ITestFlow 54 _cnf *InteractionCnf 55 _timer *common.TimeInterface 56 _timeSend int64 // 发送时间 57 _monitors []protos.ProtoID 58 } 59 60 // 启动 61 // 目前仅仅支持定时器和消息两种驱动模式 62 func (this *Interaction) Start() error { 63 if this._cnf.Interval <= 0 { 64 return fmt.Errorf("Interval Can't %d", this._cnf.Interval) 65 } 66 67 log.LogInfo("%s Interval:%d", this._tf.LogPre(), this._cnf.Interval) 68 t, err := this._tf.TestCtx().TimerAdd(int64(this._cnf.Interval), this.OnTimer, nil) 69 if err != nil { 70 return err 71 } 72 this._timer = t 73 interaction.Input().Want() 74 75 return nil 76 } 77 78 // 停止,需要删除目前所有的驱动注册 79 func (this *Interaction) Stop() { 80 if this._timer != nil { 81 this._tf.TestCtx().TimerDel(this._timer) 82 this._timer = nil 83 } 84 } 85 86 func (this *Interaction) ID() testcase.TestActionID { 87 return this._id 88 } 89 90 func (this *Interaction) Name() string { 91 return this._cnf.ActionName() 92 } 93 94 func (this *Interaction) Testflow() testcase.ITestFlow { 95 return this._tf 96 } 97 98 func (this *Interaction) OnMsg(protoId protos.ProtoID, header protos.JsonString, data protos.JsonString) { 99 fmt.Printf("\n收到协议 %d: %s\n$请输入指令", protoId, data) 100 } 101 102 func (this *Interaction) end(err error) { 103 this._tf.OnActionEnd(this, err, this._cnf.FailContinue) 104 } 105 106 func (this *Interaction) monitor(idsstring string) []protos.ProtoID { 107 ids := strings.Split(strings.Trim(idsstring, " "), "|") 108 if len(ids) > 0 { 109 for _, id := range this._monitors { 110 this._tf.TestCtx().MsgHandleUnreg(id, this) 111 } 112 113 this._monitors = this._monitors[:0] 114 for _, idstring := range ids { 115 id, err := strconv.ParseInt(idstring, 0, 32) 116 if err != nil { 117 fmt.Printf("%s id:%s not protoid", idsstring, idstring) 118 continue 119 } 120 this._tf.TestCtx().MsgHandleReg(protos.ProtoID(id), this) 121 this._monitors = append(this._monitors, protos.ProtoID(id)) 122 } 123 } 124 125 return this._monitors 126 } 127 128 func (this *Interaction) msgSend(file string, key string) error { 129 pCnf, err := protos.NetworkProtoData(file, key) 130 if err != nil { 131 return err 132 } 133 134 if pCnf == nil { 135 return fmt.Errorf("proto not found") 136 } 137 138 // 实现json数据替换 139 data, err := protos.JsonReplace(pCnf.Data, this._tf.TestCtx()) 140 if err != nil { 141 return err 142 } 143 144 err = this._tf.TestCtx().Send(pCnf.ID, data) 145 if err != nil { 146 return err 147 } 148 149 log.LogInfo("%s action:%d msgSend:%d data:%s", this._tf.LogPre(), this._id, pCnf.ID, data) 150 return nil 151 } 152 153 func (this *Interaction) OnTimer(t *common.TimeInterface, data any) int64 { 154 // log.LogDebug("action:%d OnTimer\n", this.ID()) 155 oldTimer := this._timer 156 this._timer = nil 157 158 var line string 159 exit := false 160 input := false 161 select { 162 case line = <-interaction.Input().Line(): 163 input = true 164 165 default: 166 } 167 168 if input { 169 exit = cmdExe(line, this) 170 if exit { 171 return 0 172 } 173 174 interaction.Input().Want() 175 } 176 177 // 继续timer 178 this._timer = oldTimer 179 return int64(this._cnf.Interval) 180 } 181 182 var ( 183 cmdSplit = regexp.MustCompile(" +") 184 file = "interaction.json" 185 out = "record.json" 186 ) 187 188 func cmdExe(arg string, action *Interaction) (exit bool) { 189 s := flag.NewFlagSet("cmdExe", flag.ContinueOnError) 190 191 bFile := s.Bool("file", false, "file(f) -filename(fn) name: 重新载入发包使用的协议文件") 192 s.BoolVar(bFile, "f", false, "file(f) -filename(fn) name: 重新载入发包使用的协议文件") 193 fileCmd := s.String("filename", file, "file(f) -filename(fn) name: 重新载入发包使用的协议文件") 194 s.StringVar(fileCmd, "fn", file, "file(f) -filename(fn) name: 重新载入发包使用的协议文件") 195 196 outCmd := s.String("out", "", "out(o) filename:指定消息格式化输出的文件") 197 s.StringVar(outCmd, "o", "", "out(o) filename:指定消息格式化输出的文件") 198 gen := s.Bool("generator", false, "generator(g) -id msgid [-key msg_key]: 生成指定msgId消息, 默认msgid_default作为key") 199 s.BoolVar(gen, "g", false, "generator(g) -id msgid [-key msg_key]: 生成指定msgId消息, 默认msgid_default作为key") 200 msgid := s.Int("id", 0, "generator(g) -id msgid [-key msg_key]: 生成指定msgId消息, 默认msgid_default作为key") 201 s.IntVar(msgid, "i", 0, "generator(g) -id msgid [-key msg_key]: 生成指定msgId消息, 默认msgid_default作为key") 202 msgkey := s.String("key", "", "generator(g) -id msgid [-key msg_key]: 生成指定msgId消息, 默认msgid_default作为key") 203 s.StringVar(msgkey, "k", "", "generator(g) -id msgid [-key msg_key]: 生成指定msgId消息, 默认msgid_default作为key") 204 send := s.String("send", "", "send(s) msgkey: 发送file的指定key消息") 205 s.StringVar(send, "s", "", "send(s) msgkey: 发送file的指定key消息") 206 207 bMonitor := s.Bool("monitor", false, "monitor(m) -ids(is) msgid|....: 指定打印的消息内容,如果参数为空,显示当前监控的消息列表") 208 s.BoolVar(bMonitor, "m", false, "monitor(m) -ids(is) msgid|....: 指定打印的消息内容,如果参数为空,显示当前监控的消息列表") 209 monitor := s.String("ids", "", "monitor(m) -ids(is) msgid|....: 指定打印的消息内容,如果参数为空,显示当前监控的消息列表") 210 s.StringVar(monitor, "is", "", "monitor(m) -ids(is) msgid|....: 指定打印的消息内容,如果参数为空,显示当前监控的消息列表") 211 212 s.BoolVar(&exit, "exit", false, "exit(e) -error reason]: 退出action, 默认error = nil") 213 s.BoolVar(&exit, "ex", false, "exit(e) -error reason]: 退出action, 默认error = nil") 214 exitReason := s.String("error", "", "exit(e) [error]: 退出action, 默认error = nil") 215 s.StringVar(exitReason, "er", "", "exit(e) [error]: 退出action, 默认error = nil") 216 217 args := cmdSplit.Split(strings.Trim(arg, " \n"), -1) 218 if args[0] != "-" { 219 args[0] = "-" + args[0] 220 } 221 222 err := s.Parse(args) 223 if err != nil { 224 fmt.Printf("input %v err:%s\n", args, err.Error()) 225 return 226 } 227 228 if *bFile { 229 // 执行file 230 protos.FileReload(*fileCmd) 231 err := protos.FileSave(*fileCmd) 232 if err != nil { 233 fmt.Printf("%s读取错误, err:%s\n", *fileCmd, err.Error()) 234 } else { 235 file = *fileCmd 236 fmt.Printf("发包使用配置文件:%s\n", file) 237 } 238 } 239 240 if len(*outCmd) > 0 { 241 err := protos.FileSave(*outCmd) 242 if err != nil { 243 fmt.Printf("%s读取错误, err:%s\n", *outCmd, err.Error()) 244 } else { 245 out = *outCmd 246 fmt.Printf("输出的文件:%s\n", out) 247 } 248 } 249 250 if *gen { 251 if *msgid == 0 { 252 s.Usage() 253 } else { 254 err := protos.NetworkProtoGen(file, protos.ProtoID(*msgid), *msgkey) 255 if err != nil { 256 fmt.Printf("生成protoid:%d err:%s\n", *msgid, err.Error()) 257 } 258 } 259 } 260 261 if *bMonitor { 262 if len(*monitor) > 0 { 263 action.monitor(*monitor) 264 } 265 266 fmt.Print("监控的协议:") 267 for _, id := range action._monitors { 268 fmt.Printf(" %d", id) 269 } 270 fmt.Print("\n") 271 } 272 273 if len(*send) > 0 { 274 err := action.msgSend(file, *send) 275 if err != nil { 276 fmt.Printf("发送协议 %s protoid:%d err:%s\n", file, *msgid, err.Error()) 277 } 278 } 279 280 if exit { 281 if len(*exitReason) > 0 { 282 action.end(fmt.Errorf(*exitReason)) 283 } else { 284 action.end(nil) 285 } 286 } 287 288 return 289 }