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  }