funcs_math_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. // Copyright 2023 EMQ Technologies Co., Ltd.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package function
  15. import (
  16. "fmt"
  17. "math"
  18. "reflect"
  19. "testing"
  20. "github.com/stretchr/testify/require"
  21. "github.com/lf-edge/ekuiper/internal/conf"
  22. kctx "github.com/lf-edge/ekuiper/internal/topo/context"
  23. "github.com/lf-edge/ekuiper/internal/topo/state"
  24. "github.com/lf-edge/ekuiper/pkg/api"
  25. )
  26. func TestFuncMath(t *testing.T) {
  27. fAbs, ok := builtins["abs"]
  28. if !ok {
  29. t.Fatal("builtin not found")
  30. }
  31. fCeil, ok := builtins["ceil"]
  32. if !ok {
  33. t.Fatal("builtin not found")
  34. }
  35. fExp, ok := builtins["exp"]
  36. if !ok {
  37. t.Fatal("builtin not found")
  38. }
  39. fFloor, ok := builtins["floor"]
  40. if !ok {
  41. t.Fatal("builtin not found")
  42. }
  43. fLn, ok := builtins["ln"]
  44. if !ok {
  45. t.Fatal("builtin not found")
  46. }
  47. fLog10, ok := builtins["log"]
  48. if !ok {
  49. t.Fatal("builtin not found")
  50. }
  51. fSqrt, ok := builtins["sqrt"]
  52. if !ok {
  53. t.Fatal("builtin not found")
  54. }
  55. fPow, ok := builtins["power"]
  56. if !ok {
  57. t.Fatal("builtin not found")
  58. }
  59. fBitAnd, ok := builtins["bitand"]
  60. if !ok {
  61. t.Fatal("builtin not found")
  62. }
  63. fBitOr, ok := builtins["bitor"]
  64. if !ok {
  65. t.Fatal("builtin not found")
  66. }
  67. fAcos, ok := builtins["acos"]
  68. if !ok {
  69. t.Fatal("builtin not found")
  70. }
  71. fAsin, ok := builtins["asin"]
  72. if !ok {
  73. t.Fatal("builtin not found")
  74. }
  75. fAtan, ok := builtins["atan"]
  76. if !ok {
  77. t.Fatal("builtin not found")
  78. }
  79. fAtan2, ok := builtins["atan2"]
  80. if !ok {
  81. t.Fatal("builtin not found")
  82. }
  83. fBitXor, ok := builtins["bitxor"]
  84. if !ok {
  85. t.Fatal("builtin not found")
  86. }
  87. fBitNot, ok := builtins["bitnot"]
  88. if !ok {
  89. t.Fatal("builtin not found")
  90. }
  91. fCos, ok := builtins["cos"]
  92. if !ok {
  93. t.Fatal("builtin not found")
  94. }
  95. fCosh, ok := builtins["cosh"]
  96. if !ok {
  97. t.Fatal("builtin not found")
  98. }
  99. fMod, ok := builtins["mod"]
  100. if !ok {
  101. t.Fatal("builtin not found")
  102. }
  103. fPi, ok := builtins["pi"]
  104. if !ok {
  105. t.Fatal("builtin not found")
  106. }
  107. fRound, ok := builtins["round"]
  108. if !ok {
  109. t.Fatal("builtin not found")
  110. }
  111. fSign, ok := builtins["sign"]
  112. if !ok {
  113. t.Fatal("builtin not found")
  114. }
  115. fSin, ok := builtins["sin"]
  116. if !ok {
  117. t.Fatal("builtin not found")
  118. }
  119. fSinh, ok := builtins["sinh"]
  120. if !ok {
  121. t.Fatal("builtin not found")
  122. }
  123. fTan, ok := builtins["tan"]
  124. if !ok {
  125. t.Fatal("builtin not found")
  126. }
  127. fTanh, ok := builtins["tanh"]
  128. if !ok {
  129. t.Fatal("builtin not found")
  130. }
  131. contextLogger := conf.Log.WithField("rule", "testExec")
  132. ctx := kctx.WithValue(kctx.Background(), kctx.LoggerKey, contextLogger)
  133. tempStore, _ := state.CreateStore("mockRule0", api.AtMostOnce)
  134. fctx := kctx.NewDefaultFuncContext(ctx.WithMeta("mockRule0", "test", tempStore), 2)
  135. tests := []struct {
  136. args []interface{}
  137. res []interface{}
  138. }{
  139. { // 0
  140. args: []interface{}{
  141. -10, 2,
  142. },
  143. res: []interface{}{
  144. 10,
  145. float64(-10),
  146. math.Exp(-10),
  147. nil,
  148. nil,
  149. nil,
  150. float64(100),
  151. 2,
  152. -10,
  153. nil,
  154. nil,
  155. math.Atan(-10),
  156. math.Atan2(-10, 2),
  157. -12,
  158. 9,
  159. math.Cos(-10),
  160. math.Cosh(-10),
  161. float64(0),
  162. float64(-10),
  163. -1,
  164. math.Sin(-10),
  165. math.Sinh(-10),
  166. math.Tan(-10),
  167. math.Tanh(-10),
  168. math.Floor(-10),
  169. math.Pi,
  170. },
  171. }, { // 1
  172. args: []interface{}{
  173. 10, 2,
  174. },
  175. res: []interface{}{
  176. 10,
  177. float64(10),
  178. math.Exp(10),
  179. math.Log2(10),
  180. math.Log10(10),
  181. math.Sqrt(10),
  182. float64(100),
  183. 2,
  184. 10,
  185. nil,
  186. nil,
  187. math.Atan(10),
  188. math.Atan2(10, 2),
  189. 8,
  190. -11,
  191. math.Cos(10),
  192. math.Cosh(10),
  193. float64(0),
  194. float64(10),
  195. 1,
  196. math.Sin(10),
  197. math.Sinh(10),
  198. math.Tan(10),
  199. math.Tanh(10),
  200. math.Floor(10),
  201. math.Pi,
  202. },
  203. }, { // 2
  204. args: []interface{}{
  205. -10.5, 2,
  206. },
  207. res: []interface{}{
  208. float64(10.5),
  209. float64(-10),
  210. math.Exp(-10.5),
  211. nil,
  212. nil,
  213. nil,
  214. 110.25,
  215. fmt.Errorf("Expect int type for the first operand but got -10.5"),
  216. fmt.Errorf("Expect int type for the first operand but got -10.5"),
  217. nil,
  218. nil,
  219. math.Atan(-10.5),
  220. math.Atan2(-10.5, 2),
  221. fmt.Errorf("Expect int type for the first operand but got -10.5"),
  222. fmt.Errorf("Expect int type for operand but got -10.5"),
  223. math.Cos(-10.5),
  224. math.Cosh(-10.5),
  225. -0.5,
  226. float64(-11),
  227. -1,
  228. math.Sin(-10.5),
  229. math.Sinh(-10.5),
  230. math.Tan(-10.5),
  231. math.Tanh(-10.5),
  232. math.Floor(-10.5),
  233. math.Pi,
  234. },
  235. }, { // 3
  236. args: []interface{}{
  237. 10.5, 2,
  238. },
  239. res: []interface{}{
  240. 10.5,
  241. float64(11),
  242. math.Exp(10.5),
  243. math.Log2(10.5),
  244. math.Log10(10.5),
  245. math.Sqrt(10.5),
  246. 110.25,
  247. fmt.Errorf("Expect int type for the first operand but got 10.5"),
  248. fmt.Errorf("Expect int type for the first operand but got 10.5"),
  249. nil,
  250. nil,
  251. math.Atan(10.5),
  252. math.Atan2(10.5, 2),
  253. fmt.Errorf("Expect int type for the first operand but got 10.5"),
  254. fmt.Errorf("Expect int type for operand but got 10.5"),
  255. math.Cos(10.5),
  256. math.Cosh(10.5),
  257. 0.5,
  258. float64(11),
  259. 1,
  260. math.Sin(10.5),
  261. math.Sinh(10.5),
  262. math.Tan(10.5),
  263. math.Tanh(10.5),
  264. math.Floor(10.5),
  265. math.Pi,
  266. },
  267. }, { // 4
  268. args: []interface{}{
  269. 0, 2,
  270. },
  271. res: []interface{}{
  272. 0,
  273. float64(0),
  274. float64(1),
  275. math.Inf(-1),
  276. math.Inf(-1),
  277. float64(0),
  278. float64(0),
  279. 0,
  280. 2,
  281. math.Acos(0),
  282. math.Asin(0),
  283. math.Atan(0),
  284. math.Atan2(0, 2),
  285. 2,
  286. -1,
  287. math.Cos(0),
  288. math.Cosh(0),
  289. float64(0),
  290. float64(0),
  291. 0,
  292. math.Sin(0),
  293. math.Sinh(0),
  294. math.Tan(0),
  295. math.Tanh(0),
  296. float64(0),
  297. math.Pi,
  298. },
  299. },
  300. }
  301. for i, tt := range tests {
  302. rAbs, _ := fAbs.exec(fctx, tt.args)
  303. if !reflect.DeepEqual(rAbs, tt.res[0]) {
  304. t.Errorf("%d.0 abs result mismatch,\ngot:\t%v \nwant:\t%v", i, rAbs, tt.res[0])
  305. }
  306. rCeil, _ := fCeil.exec(fctx, tt.args)
  307. if !reflect.DeepEqual(rCeil, tt.res[1]) {
  308. t.Errorf("%d.1 ceil result mismatch,\ngot:\t%v \nwant:\t%v", i, rCeil, tt.res[1])
  309. }
  310. rExp, _ := fExp.exec(fctx, tt.args)
  311. if !reflect.DeepEqual(rExp, tt.res[2]) {
  312. t.Errorf("%d.2 exp result mismatch,\ngot:\t%v \nwant:\t%v", i, rExp, tt.res[2])
  313. }
  314. rLn, _ := fLn.exec(fctx, tt.args)
  315. if !reflect.DeepEqual(rLn, tt.res[3]) {
  316. t.Errorf("%d.3 ln result mismatch,\ngot:\t%v \nwant:\t%v", i, rLn, tt.res[3])
  317. }
  318. rLog10, _ := fLog10.exec(fctx, tt.args[:1])
  319. if !reflect.DeepEqual(rLog10, tt.res[4]) {
  320. t.Errorf("%d.4 log result mismatch,\ngot:\t%v \nwant:\t%v", i, rLog10, tt.res[4])
  321. }
  322. rSqrt, _ := fSqrt.exec(fctx, tt.args)
  323. if !reflect.DeepEqual(rSqrt, tt.res[5]) {
  324. t.Errorf("%d.5 sqrt result mismatch,\ngot:\t%v \nwant:\t%v", i, rSqrt, tt.res[5])
  325. }
  326. rPow, _ := fPow.exec(fctx, tt.args)
  327. if !reflect.DeepEqual(rPow, tt.res[6]) {
  328. t.Errorf("%d.6 power result mismatch,\ngot:\t%v \nwant:\t%v", i, rPow, tt.res[6])
  329. }
  330. rBitAnd, _ := fBitAnd.exec(fctx, tt.args)
  331. if !reflect.DeepEqual(rBitAnd, tt.res[7]) {
  332. t.Errorf("%d.7 bitand result mismatch,\ngot:\t%v \nwant:\t%v", i, rBitAnd, tt.res[7])
  333. }
  334. rBitOr, _ := fBitOr.exec(fctx, tt.args)
  335. if !reflect.DeepEqual(rBitOr, tt.res[8]) {
  336. t.Errorf("%d.8 bitor result mismatch,\ngot:\t%v \nwant:\t%v", i, rBitOr, tt.res[8])
  337. }
  338. rAcos, _ := fAcos.exec(fctx, tt.args)
  339. if !reflect.DeepEqual(rAcos, tt.res[9]) {
  340. t.Errorf("%d.9 acos result mismatch,\ngot:\t%v \nwant:\t%v", i, rAcos, tt.res[9])
  341. }
  342. rAsin, _ := fAsin.exec(fctx, tt.args)
  343. if !reflect.DeepEqual(rAsin, tt.res[10]) {
  344. t.Errorf("%d.10 asin result mismatch,\ngot:\t%v \nwant:\t%v", i, rAsin, tt.res[10])
  345. }
  346. rAtan, _ := fAtan.exec(fctx, tt.args)
  347. if !reflect.DeepEqual(rAtan, tt.res[11]) {
  348. t.Errorf("%d.11 atan result mismatch,\ngot:\t%v \nwant:\t%v", i, rAtan, tt.res[11])
  349. }
  350. rAtan2, _ := fAtan2.exec(fctx, tt.args)
  351. if !reflect.DeepEqual(rAtan2, tt.res[12]) {
  352. t.Errorf("%d.12 atan2 result mismatch,\ngot:\t%v \nwant:\t%v", i, rAtan2, tt.res[12])
  353. }
  354. rBitXor, _ := fBitXor.exec(fctx, tt.args)
  355. if !reflect.DeepEqual(rBitXor, tt.res[13]) {
  356. t.Errorf("%d.13 bitxor result mismatch,\ngot:\t%v \nwant:\t%v", i, rBitXor, tt.res[13])
  357. }
  358. rBitNot, _ := fBitNot.exec(fctx, tt.args)
  359. if !reflect.DeepEqual(rBitNot, tt.res[14]) {
  360. t.Errorf("%d.14 bitnot result mismatch,\ngot:\t%v \nwant:\t%v", i, rBitNot, tt.res[14])
  361. }
  362. rCos, _ := fCos.exec(fctx, tt.args)
  363. if !reflect.DeepEqual(rCos, tt.res[15]) {
  364. t.Errorf("%d.15 cos result mismatch,\ngot:\t%v \nwant:\t%v", i, rCos, tt.res[15])
  365. }
  366. rCosh, _ := fCosh.exec(fctx, tt.args)
  367. if !reflect.DeepEqual(rCosh, tt.res[16]) {
  368. t.Errorf("%d.16 cosh result mismatch,\ngot:\t%v \nwant:\t%v", i, rCosh, tt.res[16])
  369. }
  370. rMod, _ := fMod.exec(fctx, tt.args)
  371. if !reflect.DeepEqual(rMod, tt.res[17]) {
  372. t.Errorf("%d.17 mod result mismatch,\ngot:\t%v \nwant:\t%v", i, rMod, tt.res[17])
  373. }
  374. rRound, _ := fRound.exec(fctx, tt.args)
  375. if !reflect.DeepEqual(rRound, tt.res[18]) {
  376. t.Errorf("%d.18 round result mismatch,\ngot:\t%v \nwant:\t%v", i, rRound, tt.res[18])
  377. }
  378. rSign, _ := fSign.exec(fctx, tt.args)
  379. if !reflect.DeepEqual(rSign, tt.res[19]) {
  380. t.Errorf("%d.19 sign result mismatch,\ngot:\t%v \nwant:\t%v", i, rSign, tt.res[19])
  381. }
  382. rSin, _ := fSin.exec(fctx, tt.args)
  383. if !reflect.DeepEqual(rSin, tt.res[20]) {
  384. t.Errorf("%d.20 sin result mismatch,\ngot:\t%v \nwant:\t%v", i, rSin, tt.res[20])
  385. }
  386. rSinh, _ := fSinh.exec(fctx, tt.args)
  387. if !reflect.DeepEqual(rSinh, tt.res[21]) {
  388. t.Errorf("%d.21 sinh result mismatch,\ngot:\t%v \nwant:\t%v", i, rSinh, tt.res[21])
  389. }
  390. rTan, _ := fTan.exec(fctx, tt.args)
  391. if !reflect.DeepEqual(rTan, tt.res[22]) {
  392. t.Errorf("%d.22 tan result mismatch,\ngot:\t%v \nwant:\t%v", i, rTan, tt.res[22])
  393. }
  394. rTanh, _ := fTanh.exec(fctx, tt.args)
  395. if !reflect.DeepEqual(rTanh, tt.res[23]) {
  396. t.Errorf("%d.23 tanh result mismatch,\ngot:\t%v \nwant:\t%v", i, rTanh, tt.res[23])
  397. }
  398. rFloor, _ := fFloor.exec(fctx, tt.args)
  399. if !reflect.DeepEqual(rFloor, tt.res[24]) {
  400. t.Errorf("%d.24 exp result mismatch,\ngot:\t%v \nwant:\t%v", i, rFloor, tt.res[24])
  401. }
  402. rPi, _ := fPi.exec(fctx, tt.args)
  403. if !reflect.DeepEqual(rPi, tt.res[25]) {
  404. t.Errorf("%d.25 exp result mismatch,\ngot:\t%v \nwant:\t%v", i, rPi, tt.res[25])
  405. }
  406. }
  407. }
  408. func TestFuncMathNil(t *testing.T) {
  409. oldBuiltins := builtins
  410. defer func() {
  411. builtins = oldBuiltins
  412. }()
  413. builtins = map[string]builtinFunc{}
  414. registerMathFunc()
  415. for mathFuncName, mathFunc := range builtins {
  416. switch mathFuncName {
  417. case "rand":
  418. continue
  419. default:
  420. r, b := mathFunc.check([]interface{}{nil})
  421. require.True(t, b, fmt.Sprintf("%v failed", mathFuncName))
  422. require.Nil(t, r, fmt.Sprintf("%v failed", mathFuncName))
  423. }
  424. }
  425. }