gitee.com/KyleChenSource/lib-robot@v1.0.2/robottest/testcaseimp/brutetest_task.go (about)

     1  package testcaseimp
     2  
     3  /*
     4  	暴力测试
     5  	配置 [
     6  		// 根据循序进行测试
     7  			{
     8  			'name': // 协议名
     9  			'id': // 协议id, 可以为0
    10  			'notest':
    11  			'data': { //发送的协议
    12  				%INT8%  16,32,64:[min:max:...valid value]
    13  				%RAND_UINT8%  16,32,64:[min:max:...valid value]
    14  				%RAND_FLOAT32%  64:[min:max:...valid value]
    15  				%RAND_BOOL%
    16  				%RAND_STRING% :[min:max:...valid value]
    17  				%RAND_BYTES[m:n]% :[min:max:...valid value]
    18  				%RAND_MSG:msgName%
    19  				%RAND_ARRAY:msgName[minLen:maxLen]% :[min:max:...valid value]
    20  			}
    21  		]
    22  	}
    23  */
    24  import (
    25  	"fmt"
    26  	"time"
    27  
    28  	"gitee.com/KyleChenSource/lib-robot/robottest/common"
    29  	"gitee.com/KyleChenSource/lib-robot/robottest/common/brutetest"
    30  	"gitee.com/KyleChenSource/lib-robot/robottest/robot/statistic"
    31  	"gitee.com/KyleChenSource/lib-robot/robottest/robot/testcase"
    32  
    33  	"gitee.com/KyleChenSource/lib-robot/robottest/protos"
    34  
    35  	"gitee.com/KyleChenSource/lib-robot/robottest/log"
    36  )
    37  
    38  const (
    39  	ctx_register_key = "action_brutetesttask"
    40  )
    41  
    42  type BruteTestTaskFactory struct {
    43  }
    44  
    45  type BruteTestTaskCnf struct {
    46  	testcase.TestcaseActionConfig_
    47  }
    48  
    49  func (this *BruteTestTaskFactory) Cnf() testcase.TestcaseActionCnf {
    50  	return &BruteTestTaskCnf{}
    51  }
    52  
    53  func (this *BruteTestTaskFactory) New(id testcase.TestActionID, tf testcase.ITestFlow, cnf testcase.TestcaseActionCnf) (testcase.ITestcaseAction, error) {
    54  	b, ok := tf.TestCtx().Get(ctx_register_key)
    55  	if ok {
    56  		brute := b.(*BruteTestTask)
    57  		brute._id = id
    58  		brute._tf = tf
    59  
    60  		return b.(*BruteTestTask), nil
    61  	}
    62  
    63  	n := &BruteTestTask{
    64  		_id:  id,
    65  		_tf:  tf,
    66  		_cnf: cnf.(*BruteTestTaskCnf),
    67  	}
    68  	tf.TestCtx().Set(ctx_register_key, n)
    69  	return n, nil
    70  }
    71  
    72  func init() {
    73  	testcase.TESTCASEACTION_MGR.Register("BruteTestTask", &BruteTestTaskFactory{})
    74  }
    75  
    76  type BruteTestTask struct {
    77  	_id  testcase.TestActionID
    78  	_tf  testcase.ITestFlow
    79  	_cnf *BruteTestTaskCnf
    80  
    81  	_task *brutetest.BrutetestTask
    82  
    83  	_brutemsgcnf []*brutetest.BruteMsgCnf
    84  	_gen         *brutetest.BruteMsgGenerator
    85  	_index       int // 当前测试流的索引id
    86  	_logname     string
    87  	_cnt         int // 当前测试流的索引id
    88  	_data        protos.JsonString
    89  	_timeSend    int64 // 发送时间
    90  	_timer       *common.TimeInterface
    91  }
    92  
    93  func (this *BruteTestTask) taskGet() bool {
    94  	task, ok := <-brutetest.BrutetestTaskChan
    95  	if !ok {
    96  		// 通道关闭,结束
    97  		return false
    98  	}
    99  
   100  	this._brutemsgcnf, _ = brutetest.BrutetestCaselistMap[task.Cid]
   101  	this._index = len(this._brutemsgcnf) - 1
   102  	this._task = task
   103  
   104  	this.genGet()
   105  
   106  	log.LogInfo("%s %s BruteTestTask gen:%d cid:%d skip:%d limit:%d",
   107  		this._tf.LogPre(),
   108  		this._logname,
   109  		len(this._brutemsgcnf),
   110  		task.Cid,
   111  		task.Skip,
   112  		task.Limit)
   113  
   114  	return true
   115  }
   116  
   117  func (this *BruteTestTask) genGet() {
   118  	if this._index == 0 {
   119  		this._gen = this._brutemsgcnf[this._index].Generator(this._task.Skip, this._task.Limit)
   120  		this._logname = fmt.Sprintf("%s_%s_fin_%d(%d)", this._cnf.Name, this._brutemsgcnf[this._index].MsgName, this._task.Skip, this._task.Limit)
   121  	} else {
   122  		this._gen = this._brutemsgcnf[this._index].Generator(0, 0)
   123  		this._logname = fmt.Sprintf("%s_%s_mid_%d(%d)", this._cnf.Name, this._brutemsgcnf[this._index].MsgName, len(this._brutemsgcnf)-this._index-1, len(this._brutemsgcnf))
   124  	}
   125  
   126  	log.LogInfo("%s %s BruteTestTask gen:%d msgsendCnt:%d",
   127  		this._tf.LogPre(),
   128  		this._logname,
   129  		len(this._brutemsgcnf),
   130  		this._cnt)
   131  }
   132  
   133  // 启动
   134  // 目前仅仅支持定时器和消息两种驱动模式
   135  func (this *BruteTestTask) Start() error {
   136  	if this._task == nil {
   137  		ok := this.taskGet()
   138  		if !ok {
   139  			// 通道关闭,结束
   140  			this._tf.OnActionEnd(this, nil, this._cnf.FailContinue)
   141  			return nil
   142  		}
   143  	} else if len(this._brutemsgcnf) > 1 {
   144  		this._index = len(this._brutemsgcnf) - 1
   145  		this.genGet()
   146  	}
   147  
   148  	// 初始化配置
   149  	this.msgSend()
   150  	return nil
   151  }
   152  
   153  // 停止,需要删除目前所有的驱动注册
   154  func (this *BruteTestTask) Stop() {
   155  	if this._timer != nil {
   156  		this._tf.TestCtx().TimerDel(this._timer)
   157  		this._timer = nil
   158  	}
   159  }
   160  
   161  func (this *BruteTestTask) ID() testcase.TestActionID {
   162  	return this._id
   163  }
   164  
   165  func (this *BruteTestTask) Name() string {
   166  	return this._logname
   167  }
   168  
   169  func (this *BruteTestTask) Testflow() testcase.ITestFlow {
   170  	return this._tf
   171  }
   172  
   173  func (this *BruteTestTask) OnMsg(protoId protos.ProtoID, header protos.JsonString, data protos.JsonString) {
   174  	tCost := time.Now().UnixMilli() - this._timeSend
   175  	log.LogInfo("MsgResponse OK. %s action:%s OnMsg:%d index:%d header:%s data:%s timeCost:%d",
   176  		this._tf.LogPre(),
   177  		this._logname,
   178  		protoId,
   179  		this._cnt-1,
   180  		header, data, tCost)
   181  
   182  	if this._timer != nil {
   183  		this._tf.TestCtx().TimerDel(this._timer)
   184  		this._timer = nil
   185  	}
   186  
   187  	this._tf.TestCtx().MsgHandleUnreg(protos.ProtoID(this._gen.BruteCnf().ResponeId), this)
   188  	statistic.Record(&statistic.StatisticEvent{
   189  		Type: statistic.StatisticType_Msg_Success,
   190  		ID:   int(protoId),
   191  		Time: tCost,
   192  	})
   193  
   194  	this.msgSend()
   195  }
   196  
   197  func (this *BruteTestTask) msgSend() {
   198  	ok, data := this._gen.Next()
   199  	if !ok {
   200  		this._index--
   201  		if this._index < 0 {
   202  			// 结束了
   203  			ok = this.taskGet()
   204  			if !ok {
   205  				this._tf.OnActionEnd(this, nil, this._cnf.FailContinue)
   206  				return
   207  			}
   208  		} else {
   209  			this.genGet()
   210  		}
   211  
   212  		if this._gen == nil {
   213  			this._tf.OnActionEnd(this, fmt.Errorf("BruteTestTask len:%d cid:%d skip:%d limit:%d index:%d gen nil",
   214  				len(this._brutemsgcnf),
   215  				this._task.Cid,
   216  				this._task.Skip,
   217  				this._task.Limit,
   218  				this._index), this._cnf.FailContinue)
   219  			return
   220  		}
   221  
   222  		ok, data = this._gen.Next()
   223  		if !ok {
   224  			this._tf.OnActionEnd(this, fmt.Errorf("BruteTestTask len:%d cid:%d skip:%d limit:%d index:%d gen first nil",
   225  				len(this._brutemsgcnf),
   226  				this._task.Cid,
   227  				this._task.Skip,
   228  				this._task.Limit,
   229  				this._index), this._cnf.FailContinue)
   230  			return
   231  		}
   232  	}
   233  
   234  	this._data = protos.JsonString(data)
   235  	err := this._tf.TestCtx().Send(protos.ProtoID(this._gen.BruteCnf().MsgId), this._data)
   236  	if err != nil {
   237  		this._tf.OnActionEnd(this, fmt.Errorf("SendMsg %d(%s) err:%s",
   238  			this._gen.BruteCnf().MsgId,
   239  			this._gen.BruteCnf().MsgName,
   240  			err.Error()),
   241  			this._cnf.FailContinue)
   242  		return
   243  	}
   244  
   245  	log.LogInfo("%s action:%s msgSend:%d(%s) index:%d left:%d data:%s",
   246  		this._tf.LogPre(),
   247  		this._logname,
   248  		this._gen.BruteCnf().MsgId,
   249  		this._gen.BruteCnf().MsgName,
   250  		this._cnt,
   251  		this._task.Limit,
   252  		data,
   253  	)
   254  	this._cnt++
   255  
   256  	this._timeSend = time.Now().UnixMilli()
   257  	// 发送成功,开始等待需要的回包
   258  	if this._gen.BruteCnf().ResponeId != 0 {
   259  		this._tf.TestCtx().MsgHandleReg(protos.ProtoID(this._gen.BruteCnf().ResponeId), this)
   260  
   261  		if this._gen.BruteCnf().Timeout != 0 {
   262  			this._timer, err = this._tf.TestCtx().TimerAdd(this._gen.BruteCnf().Timeout,
   263  				this.OnTimerResponseTimeout,
   264  				nil)
   265  		}
   266  	} else if this._gen.BruteCnf().Timeout != 0 {
   267  		statistic.Record(&statistic.StatisticEvent{
   268  			Type: statistic.StatisticType_Msg_Success,
   269  			ID:   int(this._gen.BruteCnf().MsgId),
   270  			Time: 0,
   271  		})
   272  		this._timer, err = this._tf.TestCtx().TimerAdd(this._gen.BruteCnf().Timeout,
   273  			this.OnTimerNext,
   274  			nil)
   275  	} else {
   276  		statistic.Record(&statistic.StatisticEvent{
   277  			Type: statistic.StatisticType_Msg_Success,
   278  			ID:   int(this._gen.BruteCnf().MsgId),
   279  			Time: 0,
   280  		})
   281  		this._timer, err = this._tf.TestCtx().TimerAdd(10,
   282  			this.OnTimerNext,
   283  			nil)
   284  	}
   285  }
   286  
   287  func (this *BruteTestTask) OnTimerNext(t *common.TimeInterface, data any) int64 {
   288  	this._timer = nil
   289  
   290  	this.msgSend()
   291  	return 0
   292  }
   293  
   294  func (this *BruteTestTask) OnTimerResponseTimeout(t *common.TimeInterface, data any) int64 {
   295  	this._timer = nil
   296  	log.LogInfo("MsgResponse Timeout. %s action:%s OnMsg:%d index:%d timeOut:%d data:%s",
   297  		this._tf.LogPre(),
   298  		this._logname,
   299  		this._gen.BruteCnf().ResponeId,
   300  		this._cnt-1,
   301  		this._gen.BruteCnf().Timeout,
   302  		this._data)
   303  
   304  	statistic.Record(&statistic.StatisticEvent{
   305  		Type: statistic.StatisticType_Msg_Timeout,
   306  		ID:   int(this._gen.BruteCnf().ResponeId),
   307  	})
   308  
   309  	this.msgSend()
   310  	return 0
   311  }