mqls_doaction.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. package mql
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "regexp"
  6. "strconv"
  7. "strings"
  8. "testing"
  9. "git.wecise.com/wecise/odb-go/odb"
  10. "gitee.com/wecisecode/util/cast"
  11. "gitee.com/wecisecode/util/merrs"
  12. "github.com/stretchr/testify/assert"
  13. )
  14. func DoActionMatch(t *testing.T, args []any, mql string, rtn *odb.Result, toption *OnErrorOption) (breakup bool, seriouserror bool, err error) {
  15. if len(args) < 2 {
  16. s := "match(Kn,Mn) 需要至少两个参数"
  17. err = merrs.New("%s", s)
  18. assert.Nil(t, s, err)
  19. seriouserror = true
  20. breakup = true
  21. return
  22. }
  23. ks := []string{}
  24. ms := []any{}
  25. i := 0
  26. for ; i+1 < len(args); i += 2 {
  27. k := strings.TrimSpace(cast.ToString(args[i]))
  28. ks = append(ks, k)
  29. var m any
  30. switch arg := args[i+1].(type) {
  31. case string:
  32. if regexp.MustCompile(`^\(\?[^\)]*\).*`).MatchString(arg) {
  33. r, e := regexp.Compile(arg)
  34. if e != nil {
  35. s := "match参数正则表达式错误:" + e.Error()
  36. err = merrs.New("%s", s)
  37. assert.Nil(t, s, err)
  38. seriouserror = true
  39. breakup = true
  40. return
  41. }
  42. m = r
  43. }
  44. }
  45. if m == nil {
  46. m = fmt.Sprintf("%#v", args[i+1])
  47. }
  48. ms = append(ms, m)
  49. }
  50. if i > len(args) {
  51. err = merrs.New("match(Kn,Mn) 参数 Kn,Mn 需要成对出现")
  52. assert.Nil(t, "参数错误", err)
  53. seriouserror = true
  54. breakup = true
  55. return
  56. }
  57. x := 0
  58. var matchingvalues [][]any
  59. var matchingvalue any
  60. for _, dat := range rtn.Data {
  61. matchingvalues = append(matchingvalues, []any{})
  62. m := false
  63. sv := ""
  64. match := true
  65. for i, k := range ks {
  66. matchingvalue = dat[k]
  67. m, sv = matchvalue(ms[i], matchingvalue)
  68. if !m {
  69. ks := strings.Split(k, ".")
  70. if len(ks) <= 1 {
  71. match = false
  72. break
  73. } else {
  74. k := ""
  75. for i := 0; match && i < len(ks); i++ {
  76. if matchingvalue == nil {
  77. if k != "" {
  78. k += "."
  79. }
  80. k += ks[i]
  81. matchingvalue = dat[k]
  82. if matchingvalue == nil && ks[i] == "len" {
  83. matchingvalue = 0
  84. }
  85. } else {
  86. switch mv := matchingvalue.(type) {
  87. case map[string]any:
  88. matchingvalue = mv[ks[i]]
  89. if matchingvalue == nil && ks[i] == "len" {
  90. matchingvalue = len(mv)
  91. }
  92. case []any:
  93. if ks[i] == "len" {
  94. matchingvalue = len(mv)
  95. } else {
  96. n, e := cast.ToIntE(ks[i])
  97. if e != nil {
  98. match = false
  99. break
  100. }
  101. matchingvalue = mv[n]
  102. }
  103. case string:
  104. if ks[i] == "len" {
  105. matchingvalue = len(mv)
  106. } else {
  107. n, e := cast.ToIntE(ks[i])
  108. if e != nil {
  109. match = false
  110. break
  111. }
  112. matchingvalue = mv[n]
  113. }
  114. default:
  115. if ks[i] == "len" {
  116. matchingvalue = 0
  117. } else {
  118. matchingvalue = nil
  119. }
  120. }
  121. }
  122. }
  123. m, sv = matchvalue(ms[i], matchingvalue)
  124. if !m {
  125. match = false
  126. break
  127. }
  128. }
  129. }
  130. matchingvalues[len(matchingvalues)-1] = append(matchingvalues[len(matchingvalues)-1], sv)
  131. }
  132. if match {
  133. x++
  134. matchingvalues = matchingvalues[:len(matchingvalues)-1]
  135. } else {
  136. matchingvalues[len(matchingvalues)-1] = append(matchingvalues[len(matchingvalues)-1], sv)
  137. }
  138. }
  139. if x == 0 {
  140. if len(rtn.Data) == 0 {
  141. err = merrs.New("%s", "没有找到记录与期望值不符")
  142. } else {
  143. argsbs, _ := json.MarshalIndent(args, "", " ")
  144. matchingbs, _ := json.MarshalIndent(matchingvalues, "", " ")
  145. err = merrs.NewError(fmt.Sprint("共", len(rtn.Data), "记录,没有找到记录与期望值不符"),
  146. merrs.SSMaps{{"mql": mql},
  147. {"match args": fmt.Sprint(string(argsbs))},
  148. {"lastmatchingvalues": string(matchingbs)}})
  149. }
  150. if toption.regex[OnErrorBreak] != nil && toption.regex[OnErrorBreak].MatchString(err.Error()) {
  151. if toption.regex[OnErrorBreak] == matchall && !toption.noerrorinfo {
  152. logger.Info("error:", err)
  153. }
  154. breakup = true
  155. return
  156. }
  157. if toption.regex[OnErrorIgnore] != nil && toption.regex[OnErrorIgnore].MatchString(err.Error()) {
  158. // 直接输出错误信息,不返回错误信息,不中断循环, 不在 testing.T 中报告错误,不中断测试
  159. if toption.regex[OnErrorIgnore] == matchall && !toption.noerrorinfo {
  160. logger.Info("pass_with_error:", err)
  161. }
  162. err = nil
  163. breakup = true
  164. return
  165. }
  166. if !assert.Nil(t, "error", err) {
  167. // 不直接输出错误信息,返回错误信息,中断循环, 在 testing.T 中报告错误,中断测试
  168. breakup = true
  169. return
  170. }
  171. }
  172. return
  173. }
  174. func DoActionEqual(t *testing.T, toption *OnErrorOption, result *odb.Result, args ...string) (breakup bool, seriouserror bool, err error) {
  175. if len(args) < 3 {
  176. err = merrs.New("%s", "equal(N,F,V) 需要三个参数")
  177. assert.Nil(t, "参数错误", err)
  178. seriouserror = true
  179. breakup = true
  180. return
  181. }
  182. n := cast.ToInt(strings.TrimSpace(args[0]))
  183. for kvi := 1; kvi+1 < len(args); kvi += 2 {
  184. field := strings.TrimSpace(args[kvi])
  185. value := strings.TrimSpace(args[kvi+1])
  186. if len(value) > 1 && value[0] == '"' && value[len(value)-1] == '"' {
  187. x, e := strconv.Unquote(value)
  188. if e != nil {
  189. err = merrs.New("%s V:%s", "equal(N,F,V) 参数 V 格式错误", value)
  190. assert.Nil(t, "参数错误", err)
  191. seriouserror = true
  192. breakup = true
  193. return
  194. }
  195. value = x
  196. }
  197. if n < 0 && result.Meta != nil {
  198. dat := result.Meta
  199. breakup, seriouserror, err = DeepEqual(t, toption, dat, field, value)
  200. if breakup {
  201. return
  202. }
  203. } else if len(result.Data) > n && result.Data[n] != nil {
  204. dat := result.Data[n]
  205. breakup, seriouserror, err = DeepEqual(t, toption, dat, field, value)
  206. if breakup {
  207. return
  208. }
  209. } else {
  210. err = merrs.New("%s", fmt.Sprint("字段 ", field, " 实际值(不存在)与期望值(", value, ")不符"))
  211. if toption.regex[OnErrorBreak] != nil && toption.regex[OnErrorBreak].MatchString(err.Error()) {
  212. if toption.regex[OnErrorBreak] == matchall && !toption.noerrorinfo {
  213. logger.Info("error:", err)
  214. }
  215. breakup = true
  216. return
  217. }
  218. if toption.regex[OnErrorIgnore] != nil && toption.regex[OnErrorIgnore].MatchString(err.Error()) {
  219. // 直接输出错误信息,不返回错误信息,不中断循环, 不在 testing.T 中报告错误,不中断测试
  220. if toption.regex[OnErrorIgnore] == matchall && !toption.noerrorinfo {
  221. logger.Info("pass_with_error:", err)
  222. }
  223. err = nil
  224. return
  225. }
  226. if !assert.Equal(t, value, "", err) {
  227. // 不直接输出错误信息,返回错误信息,中断循环, 在 testing.T 中报告错误,中断测试
  228. return
  229. }
  230. }
  231. }
  232. return
  233. }
  234. func DeepEqual(t *testing.T, toption *OnErrorOption, dat map[string]any, field, value string) (breakup bool, seriouserror bool, err error) {
  235. kks := strings.Split(field, ".")
  236. kki := len(kks)
  237. v := ""
  238. var vv any
  239. for ; vv == nil && kki >= 1; kki-- {
  240. kk := strings.Join(kks[:kki], ".")
  241. vv = dat[kk]
  242. for ; vv != nil && kki < len(kks); kki++ {
  243. switch mv := vv.(type) {
  244. case map[string]any:
  245. vv = mv[kks[kki]]
  246. if vv == nil {
  247. if kks[kki] == "len" {
  248. vv = len(mv)
  249. }
  250. }
  251. case map[string][]string:
  252. vvs := mv[kks[kki]]
  253. if vvs == nil {
  254. if kks[kki] == "len" {
  255. vv = len(mv)
  256. }
  257. } else {
  258. vv = vvs
  259. }
  260. case map[string][]any:
  261. vvs := mv[kks[kki]]
  262. if vvs == nil {
  263. if kks[kki] == "len" {
  264. vv = len(mv)
  265. }
  266. } else {
  267. vv = vvs
  268. }
  269. case []any:
  270. if kks[kki] == "len" {
  271. vv = len(mv)
  272. } else {
  273. sik := strings.TrimSpace(kks[kki])
  274. ik, e := strconv.Atoi(sik)
  275. if e != nil {
  276. err = merrs.New("%s V:%s", "equal(N,F,V) 参数 V 格式错误", field)
  277. assert.Nil(t, "参数错误", err)
  278. seriouserror = true
  279. breakup = true
  280. return
  281. }
  282. vv = mv[ik]
  283. }
  284. case []string:
  285. if kks[kki] == "len" {
  286. vv = len(mv)
  287. } else {
  288. sik := strings.TrimSpace(kks[kki])
  289. ik, e := strconv.Atoi(sik)
  290. if e != nil {
  291. err = merrs.New("%s V:%s", "equal(N,F,V) 参数 V 格式错误", field)
  292. assert.Nil(t, "参数错误", err)
  293. seriouserror = true
  294. breakup = true
  295. return
  296. }
  297. vv = mv[ik]
  298. }
  299. }
  300. }
  301. }
  302. v = fmt.Sprint(vv)
  303. if v != value {
  304. err = merrs.New("%s", fmt.Sprint("字段 ", field, " 实际值(", v, ")与期望值(", value, ")不符"))
  305. if toption.regex[OnErrorBreak] != nil && toption.regex[OnErrorBreak].MatchString(err.Error()) {
  306. if toption.regex[OnErrorBreak] == matchall && !toption.noerrorinfo {
  307. logger.Info("error:", err)
  308. }
  309. breakup = true
  310. return
  311. }
  312. if toption.regex[OnErrorIgnore] != nil && toption.regex[OnErrorIgnore].MatchString(err.Error()) {
  313. // 直接输出错误信息,不返回错误信息,不中断循环, 不在 testing.T 中报告错误,不中断测试
  314. if toption.regex[OnErrorIgnore] == matchall && !toption.noerrorinfo {
  315. logger.Info("pass_with_error:", err)
  316. }
  317. err = nil
  318. return
  319. }
  320. if !assert.Equal(t, value, v, err) {
  321. breakup = true
  322. return
  323. }
  324. }
  325. return
  326. }