gitee.com/KyleChenSource/lib-robot@v1.0.2/robottest/testcaseimp/proto_wait_send.go (about) 1 package testcaseimp 2 3 import ( 4 "fmt" 5 "time" 6 7 "gitee.com/KyleChenSource/lib-robot/robottest/robot/statistic" 8 "gitee.com/KyleChenSource/lib-robot/robottest/robot/testcase" 9 10 "gitee.com/KyleChenSource/lib-robot/robottest/protos" 11 12 "gitee.com/KyleChenSource/lib-robot/robottest/log" 13 14 "gitee.com/KyleChenSource/lib-robot/robottest/common" 15 ) 16 17 type ProtoWaitSendCnf struct { 18 WaitId protos.ProtoID `json:"wait_id"` // 预期返回协议ID, 0无返回 19 WaitTimeout int `json:"wait_timeout"` // 预期等待时间,单位ms. ResponseId != 0时有效 20 21 // 预期返回协议的校验. ResponseId != 0时有效. key -> value 22 // key: Respone协议校验路径 23 // value: 对应路径校验逻辑判定 24 // 具体参考logic.y注释说明 25 // 关键字: Length(容器长度) 26 // Value当前值 27 // None: Value==nil 28 // 操作符: <, <=, ==, >, >= 29 // &&, ||, not 30 WaitChecks map[string]protos.CheckData `json:"wait_checks"` 31 32 ProtoSendWaitCnf 33 } 34 35 type ProtoWaitSendFactory struct { 36 } 37 38 func (this *ProtoWaitSendFactory) Cnf() testcase.TestcaseActionCnf { 39 return &ProtoWaitSendCnf{} 40 } 41 42 func (this *ProtoWaitSendFactory) New(id testcase.TestActionID, tf testcase.ITestFlow, cnf testcase.TestcaseActionCnf) (testcase.ITestcaseAction, error) { 43 return &ProtoWaitSend{ 44 _id: id, 45 _tf: tf, 46 _cnf: cnf.(*ProtoWaitSendCnf), 47 _state: ProtoWaitSendState_Wait, 48 }, nil 49 } 50 51 func init() { 52 testcase.TESTCASEACTION_MGR.Register("ProtoWaitSend", &ProtoWaitSendFactory{}) 53 } 54 55 type ProtoWaitSendState int 56 57 const ( 58 ProtoWaitSendState_Wait ProtoWaitSendState = iota // 初始化 59 ProtoWaitSendState_Send 60 ) 61 62 type ProtoWaitSend struct { 63 _id testcase.TestActionID 64 _tf testcase.ITestFlow 65 _cnf *ProtoWaitSendCnf 66 _state ProtoWaitSendState 67 _timer *common.TimeInterface 68 _timeSend int64 // 发送时间 69 } 70 71 // 启动 72 // 目前仅仅支持定时器和消息两种驱动模式 73 func (this *ProtoWaitSend) Start() error { 74 if this._cnf.WaitId <= 0 { 75 return fmt.Errorf("wait_id:%d", this._cnf.WaitId) 76 } 77 78 this._tf.TestCtx().MsgHandleReg(this._cnf.WaitId, this) 79 80 for _, m := range this._cnf.MonitorMsgs { 81 this._tf.TestCtx().MsgHandleReg(m.MsgId, this) 82 } 83 84 if this._cnf.WaitTimeout > 0 { 85 log.LogInfo("%s wait timeOut:%d", this._tf.LogPre(), this._cnf.WaitTimeout) 86 // 定时器超时 87 t, err := this._tf.TestCtx().TimerAdd(int64(this._cnf.WaitTimeout), this.OnTimerWaitTimeout, nil) 88 89 if err != nil { 90 this.end(err) 91 return fmt.Errorf("wait_time err:%s", err.Error()) 92 } 93 94 this._timer = t 95 } 96 97 return nil 98 } 99 100 // 停止,需要删除目前所有的驱动注册 101 func (this *ProtoWaitSend) Stop() { 102 if this._timer != nil { 103 this._tf.TestCtx().TimerDel(this._timer) 104 } 105 106 if this._cnf.WaitId > 0 { 107 this._tf.TestCtx().MsgHandleUnreg(this._cnf.WaitId, this) 108 } 109 110 if this._cnf.ResponseId > 0 { 111 this._tf.TestCtx().MsgHandleUnreg(this._cnf.ResponseId, this) 112 } 113 114 for _, m := range this._cnf.MonitorMsgs { 115 this._tf.TestCtx().MsgHandleUnreg(m.MsgId, this) 116 } 117 } 118 119 func (this *ProtoWaitSend) ID() testcase.TestActionID { 120 return this._id 121 } 122 123 func (this *ProtoWaitSend) Name() string { 124 return this._cnf.ActionName() 125 } 126 127 func (this *ProtoWaitSend) Testflow() testcase.ITestFlow { 128 return this._tf 129 } 130 131 func (this *ProtoWaitSend) onMonitor(protoId protos.ProtoID, header protos.JsonString, data protos.JsonString) { 132 for _, m := range this._cnf.MonitorMsgs { 133 if m.MsgId != protoId { 134 continue 135 } 136 137 err := protos.JsonSet(string(data), &m.Sets, this._tf.TestCtx()) 138 if err != nil { 139 log.LogError("MsgMonitor SetErr. %s action:%d OnMsg:%d header:%s data:%s err:%s", this._tf.LogPre(), this._id, protoId, header, data, err.Error()) 140 this._tf.OnActionEnd(this, err, this._cnf.FailContinue) 141 return 142 } 143 144 log.LogInfo("MsgMonitor OK. %s action:%d OnMsg:%d header:%s data:%s", this._tf.LogPre(), this._id, protoId, header, data) 145 } 146 } 147 148 func (this *ProtoWaitSend) OnMsg(protoId protos.ProtoID, header protos.JsonString, data protos.JsonString) { 149 log.LogDebug("%s action:%d OnMsg:%d header:%s data:%s", this._tf.LogPre(), this._id, protoId, header, data) 150 151 if protoId != this._cnf.ResponseId && protoId != this._cnf.WaitId { 152 this.onMonitor(protoId, header, data) 153 return 154 } 155 156 switch this._state { 157 case ProtoWaitSendState_Wait: 158 if protoId != this._cnf.WaitId { 159 log.LogError("%s action:%d OnMsg:%d header:%s data:%s err:id not %d", this._tf.LogPre(), this._id, protoId, header, data, protoId) 160 this._tf.OnActionEnd(this, fmt.Errorf("id not %d", protoId), this._cnf.FailContinue) 161 return 162 } 163 164 b, _, err := protos.JsonCheck(string(data), this._cnf.WaitChecks, this._tf.TestCtx()) 165 if err != nil { 166 return 167 } 168 169 if !b { 170 return 171 } 172 173 this._tf.TestCtx().MsgHandleUnreg(this._cnf.WaitId, this) 174 this._tf.TestCtx().MsgHandleReg(this._cnf.ResponseId, this) 175 176 this.onMonitor(protoId, header, data) 177 178 // 检测成功,发消息了 179 this.msgSend() 180 return 181 case ProtoWaitSendState_Send: 182 tCost := time.Now().UnixMilli() - this._timeSend 183 b, bContinue, err := protos.JsonCheck(string(data), this._cnf.Checks, this._tf.TestCtx()) 184 if err != nil { 185 log.LogError("MsgResponse CheckErr. %s action:%d OnMsg:%d header:%s data:%s timeCost:%d err:%s", this._tf.LogPre(), this._id, protoId, header, data, tCost, err.Error()) 186 statistic.Record(&statistic.StatisticEvent{ 187 Type: statistic.StatisticType_Msg_Err, 188 ID: int(protoId), 189 }) 190 this._tf.OnActionEnd(this, err, this._cnf.FailContinue) 191 return 192 } 193 194 if !b { 195 if !bContinue { 196 log.LogError("MsgResponse CheckFailed. %s action:%d OnMsg:%d header:%s data:%s timeCost:%d", this._tf.LogPre(), this._id, protoId, header, data, tCost) 197 statistic.Record(&statistic.StatisticEvent{ 198 Type: statistic.StatisticType_Msg_Fail, 199 ID: int(protoId), 200 }) 201 this._tf.OnActionEnd(this, fmt.Errorf("checks failed"), this._cnf.FailContinue) 202 } 203 return 204 } 205 206 this.onMonitor(protoId, header, data) 207 208 log.LogInfo("MsgResponse OK. %s action:%d OnMsg:%d header:%s data:%s timeCost:%d", this._tf.LogPre(), this._id, protoId, header, data, tCost) 209 this._tf.OnActionEnd(this, nil, this._cnf.FailContinue) 210 statistic.Record(&statistic.StatisticEvent{ 211 Type: statistic.StatisticType_Msg_Success, 212 ID: int(protoId), 213 Time: tCost, 214 }) 215 } 216 } 217 218 func (this *ProtoWaitSend) end(err error) { 219 this._tf.OnActionEnd(this, err, this._cnf.FailContinue) 220 } 221 222 func (this *ProtoWaitSend) msgSend() { 223 if this._state != ProtoWaitSendState_Wait { 224 this._tf.OnActionEnd(this, fmt.Errorf("%s SendMsg %s:%s err:state is %d", this._cnf.Name, this._cnf.MsgFile, this._cnf.MsgKey, this._state), this._cnf.FailContinue) 225 return 226 } 227 228 if this._timer != nil { 229 this._tf.TestCtx().TimerDel(this._timer) 230 this._timer = nil 231 } 232 233 this._state = ProtoWaitSendState_Send 234 pCnf, err := protos.NetworkProtoData(this._cnf.MsgFile, this._cnf.MsgKey) 235 if err != nil { 236 this._tf.OnActionEnd(this, fmt.Errorf("%s SendMsg %s:%s err:%s", this._cnf.Name, this._cnf.MsgFile, this._cnf.MsgKey, err.Error()), this._cnf.FailContinue) 237 return 238 } 239 240 if pCnf == nil { 241 this._tf.OnActionEnd(this, fmt.Errorf("%s SendMsg %s:%s NULL", this._cnf.Name, this._cnf.MsgFile, this._cnf.MsgKey), this._cnf.FailContinue) 242 return 243 } 244 245 // 实现json数据替换 246 data, err := protos.JsonReplace(pCnf.Data, this._tf.TestCtx()) 247 if err != nil { 248 this._tf.OnActionEnd(this, fmt.Errorf("%s JsonReplace %s:%s err:%s", this._cnf.Name, this._cnf.MsgFile, this._cnf.MsgKey, err.Error()), this._cnf.FailContinue) 249 return 250 } 251 252 err = this._tf.TestCtx().Send(pCnf.ID, data) 253 if err != nil { 254 this._tf.OnActionEnd(this, fmt.Errorf("%s SendMsg %s:%s err:%s", this._cnf.Name, this._cnf.MsgFile, this._cnf.MsgKey, err.Error()), this._cnf.FailContinue) 255 return 256 } 257 258 log.LogInfo("%s action:%d msgSend:%d data:%s", this._tf.LogPre(), this._id, pCnf.ID, data) 259 // 发送成功,开始等待需要的回包 260 if this._cnf.Timeout == 0 && this._cnf.ResponseId == 0 { 261 // 结束 262 statistic.Record(&statistic.StatisticEvent{ 263 Type: statistic.StatisticType_Msg_Success, 264 ID: int(pCnf.ID), 265 Time: 0, 266 }) 267 this.end(nil) 268 return 269 } 270 271 if this._cnf.Timeout > 0 { 272 log.LogDebug("%s timeOut:%d", this._tf.LogPre(), this._cnf.Timeout) 273 // 定时器超时 274 t, err := this._tf.TestCtx().TimerAdd(int64(this._cnf.Timeout), this.OnTimerResponseTimeout, nil) 275 276 if err != nil { 277 this.end(err) 278 return 279 } 280 281 this._timer = t 282 } 283 284 this._timeSend = time.Now().UnixMilli() 285 } 286 287 func (this *ProtoWaitSend) OnTimerWaitTimeout(t *common.TimeInterface, data any) int64 { 288 log.LogInfo("Wait Timeout. %s action:%d OnMsg:%d timeOut:%d", this._tf.LogPre(), this._id, this._cnf.WaitId, this._cnf.WaitTimeout) 289 this._timer = nil 290 291 this._tf.OnActionEnd(this, fmt.Errorf("timeout:%d msg:%d Wait", this._cnf.Timeout, this._cnf.WaitId), this._cnf.FailContinue) 292 statistic.Record(&statistic.StatisticEvent{ 293 Type: statistic.StatisticType_Msg_Timeout, 294 ID: int(this._cnf.WaitId), 295 }) 296 return 0 297 } 298 299 func (this *ProtoWaitSend) OnTimerResponseTimeout(t *common.TimeInterface, data any) int64 { 300 log.LogInfo("MsgResponse Timeout. %s action:%d OnMsg:%d timeOut:%d", this._tf.LogPre(), this._id, this._cnf.ResponseId, this._cnf.Timeout) 301 this._timer = nil 302 303 this._tf.OnActionEnd(this, fmt.Errorf("timeout:%d msg:%d", this._cnf.Timeout, this._cnf.ResponseId), this._cnf.FailContinue) 304 statistic.Record(&statistic.StatisticEvent{ 305 Type: statistic.StatisticType_Msg_Timeout, 306 ID: int(this._cnf.ResponseId), 307 }) 308 return 0 309 }