gitee.com/KyleChenSource/lib-robot@v1.0.2/robottest/robot/robot_config.go (about) 1 package robot 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io/ioutil" 7 "strings" 8 9 ts "gitee.com/KyleChenSource/lib-robot/robottest/robot/testcase" 10 11 "github.com/valyala/fastjson" 12 "google.golang.org/protobuf/reflect/protoreflect" 13 ) 14 15 const DefaultRobotFile = "robot.json" 16 17 type TestRobots struct { 18 Count int `json:"count"` 19 File string `json:"file"` 20 Robot string `json:"robot"` 21 Monitor bool `json:"msg_monitor"` // 是否打印消息内容 22 Ignores []int32 `json:"msg_ignore"` // 忽略的消息清单 23 Focus []int32 `json:"msg_focus"` // 只显示的msg,如果非空,则Ignores失效 24 } 25 26 type TestConfig struct { 27 Config string `json:"config"` 28 AccountPre string `json:"account_pre"` 29 AccountOffset int32 `json:"account_off"` 30 Server string `json:"server"` 31 Brute *BruteCnf `json:"brutetest"` 32 Statistic StatisticConfig `json:"statistic"` 33 Robots []*TestRobots `json:"robots"` 34 } 35 36 type BruteCnf struct { 37 File string `json:"file"` 38 RobotCnt int `json:"robot_max"` 39 File_Login string `json:"login_file"` 40 Login string `json:"case_login"` 41 Relogin string `json:"case_relogin"` 42 } 43 44 type StatisticConfig struct { 45 StatisticTickInterval int64 `json:"stick"` 46 StatisticTotTime int64 `json:"stot"` 47 ActionTimeOver int64 `json:"action_timeover"` 48 } 49 50 const DefaultTestcaseFile = "testcase.json" 51 52 type TestCaseRunnerConfig struct { 53 File string `json:"file"` 54 Do string `json:"do"` 55 Count int `json:"count"` 56 } 57 58 type RobotConfig struct { 59 Name string 60 Relogin bool `json:"relogin"` // 如果true, 则断开连接后,会保存现场,先进行重连,然后进行login, 然后回复测试流程。 如果false,则直接清理退出 61 File_Login string `json:"login_file"` 62 Case_Login string `json:"case_login"` // 登录case 63 Case_Relogin string `json:"case_relogin"` // 重登case 64 Cases []*TestCaseRunnerConfig `json:"cases"` 65 } 66 67 type ProtoMsgConfig struct { 68 Comment string `json:"comment"` // 备注 69 MsgId int `json:"msg_id"` // 协议id 70 Msg interface{} `json:"msg"` // 协议数据json字符串 71 } 72 73 type ProtoMsg struct { 74 Name string `json:"name"` 75 Comment string `json:"comment"` // 备注 76 MsgId int `json:"msg_id"` // 协议id 77 Msg protoreflect.ProtoMessage `json:"msg"` // 协议数据json字符串 78 } 79 80 var MsgFactory map[int]protoreflect.ProtoMessage 81 82 var msg_cnf map[string]*ProtoMsgConfig 83 var MSG_DATA map[string]*ProtoMsg 84 var TESTCASE_CNF map[string]*ts.TestcaseConfig 85 var ROBOT_CNF map[string]*RobotConfig 86 var TEST_CNF TestConfig 87 88 var loadFiles = make(map[string]bool) 89 90 func testcaseCnfLoad(cnfPath string, file string) error { 91 filename := fmt.Sprintf("%s%s", cnfPath, file) 92 if _, ok := loadFiles[filename]; ok { 93 // 已经加载 94 return nil 95 } 96 loadFiles[filename] = true 97 98 var readFile []byte 99 readFile, err := ioutil.ReadFile(filename) 100 if err != nil { 101 return fmt.Errorf("TestCase:%s ReadFile err:%s", filename, err.Error()) 102 } 103 104 j, err := fastjson.ParseBytes(readFile) 105 if err != nil { 106 return fmt.Errorf("TestCase:%s jsonParse err:%s", filename, err.Error()) 107 } 108 109 objs, err := j.Object() 110 if err != nil { 111 return fmt.Errorf("TestCase:%s Object Root err:%s", filename, err.Error()) 112 } 113 114 var errBuilder strings.Builder 115 bErr := false 116 objs.Visit(func(tsK []byte, tsV *fastjson.Value) { 117 tfs := tsV.GetArray("testflows") 118 if tfs == nil { 119 bErr = true 120 errBuilder.WriteString(fmt.Sprintf("TestCase:%s %s without testflows\n", filename, tsK)) 121 return 122 } 123 124 tsCnf := ts.TestcaseConfig{ 125 Name: string(tsK), 126 TestFlow: make([][]ts.TestcaseActionCnf, 0), 127 } 128 129 for tfK, tfV := range tfs { 130 tf := tfV.GetArray() 131 var tfCnf []ts.TestcaseActionCnf 132 for aK, aV := range tf { 133 aName := aV.GetStringBytes("name") 134 f, ok := ts.TESTCASEACTION_MGR.Find(string(aName)) 135 if !ok { 136 if err == nil { 137 bErr = true 138 errBuilder.WriteString(fmt.Sprintf("TestCase:%s %s[%d][%d] Action:%s nil\n", filename, tsK, tfK, aK, aName)) 139 } else { 140 bErr = true 141 errBuilder.WriteString(fmt.Sprintf("TestCase:%s %s\n%s[%d][%d] Action:%s nil\n", filename, err.Error(), tsK, tfK, aK, aName)) 142 } 143 144 return 145 } 146 147 aCnf := f.Cnf() 148 errUnmarshal := json.Unmarshal([]byte(aV.String()), aCnf) 149 if errUnmarshal != nil { 150 if err == nil { 151 bErr = true 152 errBuilder.WriteString(fmt.Sprintf("TestCase:%s %s[%d][%d] Action:%s Unmarshal err:%s\n", filename, tsK, tfK, aK, aName, errUnmarshal.Error())) 153 } else { 154 bErr = true 155 errBuilder.WriteString(fmt.Sprintf("TestCase:%s %s\n%s[%d][%d] Action:%s Unmarshal err:%s\n", filename, err.Error(), tsK, tfK, aK, aName, errUnmarshal.Error())) 156 } 157 return 158 } 159 160 tfCnf = append(tfCnf, aCnf) 161 } 162 tsCnf.TestFlow = append(tsCnf.TestFlow, tfCnf) 163 } 164 165 TESTCASE_CNF[fmt.Sprintf("%s/%s", file, string(tsK))] = &tsCnf 166 }) 167 168 if bErr { 169 return fmt.Errorf(errBuilder.String()) 170 } 171 172 return nil 173 } 174 175 func robotDescLoad(cnfPath string, file string) error { 176 filename := fmt.Sprintf("%s%s", cnfPath, file) 177 if _, ok := loadFiles[filename]; ok { 178 // 已经加载 179 return nil 180 } 181 loadFiles[filename] = true 182 183 readFile, err := ioutil.ReadFile(filename) 184 if err != nil { 185 return fmt.Errorf("RobotConfig:%s ReadFile err:%s", filename, err.Error()) 186 } 187 188 robotCnf := make(map[string]*RobotConfig) 189 err = json.Unmarshal(readFile, &robotCnf) 190 if err != nil { 191 return fmt.Errorf("RobotConfig:%s Unmarshal err:%s", filename, err.Error()) 192 } 193 194 var errBuilder strings.Builder 195 bErr := false 196 for n, c := range robotCnf { 197 if c.File_Login == "" { 198 c.File_Login = DefaultTestcaseFile 199 } 200 err = testcaseCnfLoad(cnfPath, c.File_Login) 201 if err != nil { 202 bErr = true 203 errBuilder.WriteString(fmt.Sprintf("RobotConfig:%s File_Login:%s testcaseCnfLoad err:%s\n", filename, c.File_Login, err.Error())) 204 } 205 206 for _, t := range c.Cases { 207 if t.File == "" { 208 t.File = DefaultTestcaseFile 209 } 210 err = testcaseCnfLoad(cnfPath, t.File) 211 if err != nil { 212 bErr = true 213 errBuilder.WriteString(fmt.Sprintf("RobotConfig:%s case:%s testcaseCnfLoad err:%s\n", filename, t.File, err.Error())) 214 } 215 } 216 217 ROBOT_CNF[fmt.Sprintf("%s/%s", file, n)] = c 218 } 219 220 if bErr { 221 return fmt.Errorf(errBuilder.String()) 222 } 223 224 return nil 225 } 226 227 func ConfigLoad(cnfPath string, config string) error { 228 readFile, err := ioutil.ReadFile(fmt.Sprintf("%s%s", cnfPath, config)) 229 if err != nil { 230 return err 231 } 232 233 err = json.Unmarshal(readFile, &TEST_CNF) 234 if err != nil { 235 return err 236 } 237 238 // 进行robot文件加载 239 var errBuilder strings.Builder 240 bErr := false 241 ROBOT_CNF = make(map[string]*RobotConfig) 242 TESTCASE_CNF = make(map[string]*ts.TestcaseConfig) 243 if TEST_CNF.Brute != nil { 244 if TEST_CNF.Brute.File_Login == "" { 245 TEST_CNF.Brute.File_Login = DefaultTestcaseFile 246 } 247 248 err = testcaseCnfLoad(cnfPath, TEST_CNF.Brute.File_Login) 249 if err != nil { 250 bErr = true 251 errBuilder.WriteString(fmt.Sprintf("Brute File_Login:%s testcaseCnfLoad err:%s\n", TEST_CNF.Brute.File_Login, err.Error())) 252 } 253 } 254 255 for _, r := range TEST_CNF.Robots { 256 if r.File == "" { 257 r.File = DefaultRobotFile 258 } 259 err = robotDescLoad(cnfPath, r.File) 260 if err != nil { 261 errBuilder.WriteString(fmt.Sprintln(err.Error())) 262 bErr = true 263 } 264 } 265 266 if bErr { 267 return fmt.Errorf(errBuilder.String()) 268 } 269 270 return nil 271 } 272 273 func ProtoMsgLoad(cnfPath string) error { 274 msg_cnf = make(map[string]*ProtoMsgConfig) 275 MSG_DATA = make(map[string]*ProtoMsg) 276 277 readFile, err := ioutil.ReadFile(fmt.Sprintf("%sproto_msg.json", cnfPath)) 278 if err != nil { 279 return err 280 } 281 err = json.Unmarshal(readFile, &msg_cnf) 282 if err != nil { 283 return err 284 } 285 286 for key, cnf := range msg_cnf { 287 msg_bytes, err := json.Marshal(cnf.Msg) 288 if err != nil { 289 return err 290 } 291 292 msgP, ok := MsgFactory[cnf.MsgId] 293 if !ok { 294 return fmt.Errorf("msgId:%d nil", cnf.MsgId) 295 } 296 297 msg := msgP.ProtoReflect().New().Interface() 298 err = json.Unmarshal(msg_bytes, msg) 299 if err != nil { 300 return err 301 } 302 303 MSG_DATA[key] = &ProtoMsg{ 304 Name: key, 305 Comment: cnf.Comment, 306 MsgId: cnf.MsgId, 307 Msg: msg, 308 } 309 } 310 return nil 311 } 312 313 func ProtoMsgSave(file string, data map[string]*ProtoMsg) error { 314 out, err := json.Marshal(data) 315 if err != nil { 316 return err 317 } 318 319 err = ioutil.WriteFile(file, out, 0666) 320 return err 321 }