mqls_doaction.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. package odbcmql
  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. case *Action:
  45. switch arg.Name {
  46. case "<FUZZY>":
  47. m = arg
  48. }
  49. }
  50. if m == nil {
  51. m = fmt.Sprintf("%#v", args[i+1])
  52. }
  53. ms = append(ms, m)
  54. }
  55. if i > len(args) {
  56. err = merrs.New("match(Kn,Mn) 参数 Kn,Mn 需要成对出现")
  57. assert.Nil(t, "参数错误", err)
  58. seriouserror = true
  59. breakup = true
  60. return
  61. }
  62. x, matchingvalues := MatchValues(rtn, ks, ms)
  63. if x == 0 {
  64. if len(rtn.Data) == 0 {
  65. err = merrs.New("%s", "没有找到记录与期望值不符")
  66. } else {
  67. argsbs, _ := json.MarshalIndent(args, "", " ")
  68. matchingbs, _ := json.MarshalIndent(matchingvalues, "", " ")
  69. err = merrs.NewError(fmt.Sprint("共", len(rtn.Data), "记录,没有找到记录与期望值不符"),
  70. merrs.SSMaps{{"mql": mql},
  71. {"match args": fmt.Sprint(string(argsbs))},
  72. {"lastmatchingvalues": string(matchingbs)}})
  73. }
  74. if toption.regex[OnErrorBreak] != nil && toption.regex[OnErrorBreak].MatchString(err.Error()) {
  75. if toption.regex[OnErrorBreak] == matchall && !toption.noerrorinfo {
  76. logger.Info("error:", err)
  77. }
  78. breakup = true
  79. return
  80. }
  81. if toption.regex[OnErrorIgnore] != nil && toption.regex[OnErrorIgnore].MatchString(err.Error()) {
  82. // 直接输出错误信息,不返回错误信息,不中断循环, 不在 testing.T 中报告错误,不中断测试
  83. if toption.regex[OnErrorIgnore] == matchall && !toption.noerrorinfo {
  84. logger.Info("pass_with_error:", err)
  85. }
  86. err = nil
  87. breakup = true
  88. return
  89. }
  90. if !assert.Nil(t, "error", err) {
  91. // 不直接输出错误信息,返回错误信息,中断循环, 在 testing.T 中报告错误,中断测试
  92. breakup = true
  93. return
  94. }
  95. }
  96. return
  97. }
  98. func DoActionEqual(t *testing.T, toption *OnErrorOption, result *odb.Result, args ...string) (breakup bool, seriouserror bool, err error) {
  99. if len(args) < 3 {
  100. err = merrs.New("%s", "equal(N,F,V) 需要三个参数")
  101. assert.Nil(t, "参数错误", err)
  102. seriouserror = true
  103. breakup = true
  104. return
  105. }
  106. n := cast.ToInt(strings.TrimSpace(args[0]))
  107. for kvi := 1; kvi+1 < len(args); kvi += 2 {
  108. field := strings.TrimSpace(args[kvi])
  109. value := strings.TrimSpace(args[kvi+1])
  110. if len(value) > 1 && value[0] == '"' && value[len(value)-1] == '"' {
  111. x, e := strconv.Unquote(value)
  112. if e != nil {
  113. err = merrs.New("%s V:%s", "equal(N,F,V) 参数 V 格式错误", value)
  114. assert.Nil(t, "参数错误", err)
  115. seriouserror = true
  116. breakup = true
  117. return
  118. }
  119. value = x
  120. }
  121. if n < 0 && result.Meta != nil {
  122. dat := result.Meta
  123. breakup, seriouserror, err = DeepEqual(t, toption, dat, field, value)
  124. if breakup {
  125. return
  126. }
  127. } else if len(result.Data) > n && result.Data[n] != nil {
  128. dat := result.Data[n]
  129. breakup, seriouserror, err = DeepEqual(t, toption, dat, field, value)
  130. if breakup {
  131. return
  132. }
  133. } else {
  134. err = merrs.New("%s", fmt.Sprint("字段 ", field, " 实际值(不存在)与期望值(", value, ")不符"))
  135. if toption.regex[OnErrorBreak] != nil && toption.regex[OnErrorBreak].MatchString(err.Error()) {
  136. if toption.regex[OnErrorBreak] == matchall && !toption.noerrorinfo {
  137. logger.Info("error:", err)
  138. }
  139. breakup = true
  140. return
  141. }
  142. if toption.regex[OnErrorIgnore] != nil && toption.regex[OnErrorIgnore].MatchString(err.Error()) {
  143. // 直接输出错误信息,不返回错误信息,不中断循环, 不在 testing.T 中报告错误,不中断测试
  144. if toption.regex[OnErrorIgnore] == matchall && !toption.noerrorinfo {
  145. logger.Info("pass_with_error:", err)
  146. }
  147. err = nil
  148. return
  149. }
  150. if !assert.Equal(t, value, "", err) {
  151. // 不直接输出错误信息,返回错误信息,中断循环, 在 testing.T 中报告错误,中断测试
  152. return
  153. }
  154. }
  155. }
  156. return
  157. }
  158. func DeepEqual(t *testing.T, toption *OnErrorOption, dat map[string]any, field, value string) (breakup bool, seriouserror bool, err error) {
  159. kks := strings.Split(field, ".")
  160. kki := len(kks)
  161. v := ""
  162. var vv any
  163. for ; vv == nil && kki >= 1; kki-- {
  164. kk := strings.Join(kks[:kki], ".")
  165. vv = dat[kk]
  166. for ; vv != nil && kki < len(kks); kki++ {
  167. switch mv := vv.(type) {
  168. case map[string]any:
  169. vv = mv[kks[kki]]
  170. if vv == nil {
  171. if kks[kki] == "len" {
  172. vv = len(mv)
  173. }
  174. }
  175. case map[string][]string:
  176. vvs := mv[kks[kki]]
  177. if vvs == nil {
  178. if kks[kki] == "len" {
  179. vv = len(mv)
  180. }
  181. } else {
  182. vv = vvs
  183. }
  184. case map[string][]any:
  185. vvs := mv[kks[kki]]
  186. if vvs == nil {
  187. if kks[kki] == "len" {
  188. vv = len(mv)
  189. }
  190. } else {
  191. vv = vvs
  192. }
  193. case []any:
  194. if kks[kki] == "len" {
  195. vv = len(mv)
  196. } else {
  197. sik := strings.TrimSpace(kks[kki])
  198. ik, e := strconv.Atoi(sik)
  199. if e != nil {
  200. err = merrs.New("%s V:%s", "equal(N,F,V) 参数 V 格式错误", field)
  201. assert.Nil(t, "参数错误", err)
  202. seriouserror = true
  203. breakup = true
  204. return
  205. }
  206. vv = mv[ik]
  207. }
  208. case []string:
  209. if kks[kki] == "len" {
  210. vv = len(mv)
  211. } else {
  212. sik := strings.TrimSpace(kks[kki])
  213. ik, e := strconv.Atoi(sik)
  214. if e != nil {
  215. err = merrs.New("%s V:%s", "equal(N,F,V) 参数 V 格式错误", field)
  216. assert.Nil(t, "参数错误", err)
  217. seriouserror = true
  218. breakup = true
  219. return
  220. }
  221. vv = mv[ik]
  222. }
  223. }
  224. }
  225. }
  226. v = fmt.Sprint(vv)
  227. if v != value {
  228. err = merrs.New("%s", fmt.Sprint("字段 ", field, " 实际值(", v, ")与期望值(", value, ")不符"))
  229. if toption.regex[OnErrorBreak] != nil && toption.regex[OnErrorBreak].MatchString(err.Error()) {
  230. if toption.regex[OnErrorBreak] == matchall && !toption.noerrorinfo {
  231. logger.Info("error:", err)
  232. }
  233. breakup = true
  234. return
  235. }
  236. if toption.regex[OnErrorIgnore] != nil && toption.regex[OnErrorIgnore].MatchString(err.Error()) {
  237. // 直接输出错误信息,不返回错误信息,不中断循环, 不在 testing.T 中报告错误,不中断测试
  238. if toption.regex[OnErrorIgnore] == matchall && !toption.noerrorinfo {
  239. logger.Info("pass_with_error:", err)
  240. }
  241. err = nil
  242. return
  243. }
  244. if !assert.Equal(t, value, v, err) {
  245. breakup = true
  246. return
  247. }
  248. }
  249. return
  250. }