math_func_test.go 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. // Copyright 2021 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 operator
  15. import (
  16. "encoding/json"
  17. "fmt"
  18. "github.com/lf-edge/ekuiper/internal/conf"
  19. "github.com/lf-edge/ekuiper/internal/topo/context"
  20. "github.com/lf-edge/ekuiper/internal/xsql"
  21. "reflect"
  22. "strings"
  23. "testing"
  24. )
  25. func TestMathAndConversionFunc_Apply1(t *testing.T) {
  26. var tests = []struct {
  27. sql string
  28. data *xsql.Tuple
  29. result []map[string]interface{}
  30. }{
  31. {
  32. sql: "SELECT abs(a) AS a FROM test",
  33. data: &xsql.Tuple{
  34. Emitter: "test",
  35. Message: xsql.Message{
  36. "a": -1,
  37. },
  38. },
  39. result: []map[string]interface{}{{
  40. "a": float64(1), //Actually it should be 1, it's caused by json Unmarshal method, which convert int to float64
  41. }},
  42. },
  43. {
  44. sql: "SELECT abs(a) AS a FROM test",
  45. data: &xsql.Tuple{
  46. Emitter: "test",
  47. Message: xsql.Message{
  48. "a": -1.1,
  49. },
  50. },
  51. result: []map[string]interface{}{{
  52. "a": 1.1,
  53. }},
  54. },
  55. {
  56. sql: "SELECT abs(a) AS a FROM test",
  57. data: &xsql.Tuple{
  58. Emitter: "test",
  59. Message: xsql.Message{
  60. "a": 1.1,
  61. },
  62. },
  63. result: []map[string]interface{}{{
  64. "a": 1.1,
  65. }},
  66. },
  67. {
  68. sql: "SELECT acos(1) AS a FROM test",
  69. data: &xsql.Tuple{
  70. Emitter: "test",
  71. Message: nil,
  72. },
  73. result: []map[string]interface{}{{
  74. "a": float64(0),
  75. }},
  76. },
  77. {
  78. sql: "SELECT asin(1) AS a FROM test",
  79. data: &xsql.Tuple{
  80. Emitter: "test",
  81. Message: nil,
  82. },
  83. result: []map[string]interface{}{{
  84. "a": float64(1.5707963267948966),
  85. }},
  86. },
  87. {
  88. sql: "SELECT atan(1) AS a FROM test",
  89. data: &xsql.Tuple{
  90. Emitter: "test",
  91. Message: nil,
  92. },
  93. result: []map[string]interface{}{{
  94. "a": float64(0.7853981633974483),
  95. }},
  96. },
  97. {
  98. sql: "SELECT atan2(1,1) AS a FROM test",
  99. data: &xsql.Tuple{
  100. Emitter: "test",
  101. Message: nil,
  102. },
  103. result: []map[string]interface{}{{
  104. "a": float64(0.7853981633974483),
  105. }},
  106. },
  107. {
  108. sql: "SELECT bitand(1,1) AS a FROM test",
  109. data: &xsql.Tuple{
  110. Emitter: "test",
  111. Message: nil,
  112. },
  113. result: []map[string]interface{}{{
  114. "a": float64(1),
  115. }},
  116. },
  117. {
  118. sql: "SELECT bitand(1.0,1) AS a FROM test",
  119. data: &xsql.Tuple{
  120. Emitter: "test",
  121. Message: nil,
  122. },
  123. result: nil,
  124. },
  125. {
  126. sql: "SELECT bitor(1,1) AS a FROM test",
  127. data: &xsql.Tuple{
  128. Emitter: "test",
  129. Message: nil,
  130. },
  131. result: []map[string]interface{}{{
  132. "a": float64(1),
  133. }},
  134. },
  135. {
  136. sql: "SELECT bitxor(1,1) AS a FROM test",
  137. data: &xsql.Tuple{
  138. Emitter: "test",
  139. Message: nil,
  140. },
  141. result: []map[string]interface{}{{
  142. "a": float64(0),
  143. }},
  144. },
  145. {
  146. sql: "SELECT bitnot(1) AS a FROM test",
  147. data: &xsql.Tuple{
  148. Emitter: "test",
  149. Message: nil,
  150. },
  151. result: []map[string]interface{}{{
  152. "a": float64(-2),
  153. }},
  154. },
  155. {
  156. sql: "SELECT ceil(1.6) AS a FROM test",
  157. data: &xsql.Tuple{
  158. Emitter: "test",
  159. Message: nil,
  160. },
  161. result: []map[string]interface{}{{
  162. "a": float64(2),
  163. }},
  164. },
  165. {
  166. sql: "SELECT cos(0) AS a FROM test",
  167. data: &xsql.Tuple{
  168. Emitter: "test",
  169. Message: nil,
  170. },
  171. result: []map[string]interface{}{{
  172. "a": float64(1),
  173. }},
  174. },
  175. {
  176. sql: "SELECT cosh(0) AS a FROM test",
  177. data: &xsql.Tuple{
  178. Emitter: "test",
  179. Message: nil,
  180. },
  181. result: []map[string]interface{}{{
  182. "a": float64(1),
  183. }},
  184. },
  185. {
  186. sql: "SELECT exp(1.2) AS a FROM test",
  187. data: &xsql.Tuple{
  188. Emitter: "test",
  189. Message: nil,
  190. },
  191. result: []map[string]interface{}{{
  192. "a": float64(3.3201169227365472),
  193. }},
  194. },
  195. {
  196. sql: "SELECT ln(1) AS a FROM test",
  197. data: &xsql.Tuple{
  198. Emitter: "test",
  199. Message: nil,
  200. },
  201. result: []map[string]interface{}{{
  202. "a": float64(0),
  203. }},
  204. },
  205. {
  206. sql: "SELECT log(10) AS a FROM test",
  207. data: &xsql.Tuple{
  208. Emitter: "test",
  209. Message: nil,
  210. },
  211. result: []map[string]interface{}{{
  212. "a": float64(1),
  213. }},
  214. },
  215. {
  216. sql: "SELECT mod(10, 3) AS a FROM test",
  217. data: &xsql.Tuple{
  218. Emitter: "test",
  219. Message: nil,
  220. },
  221. result: []map[string]interface{}{{
  222. "a": float64(1),
  223. }},
  224. },
  225. {
  226. sql: "SELECT power(10, 3) AS a FROM test",
  227. data: &xsql.Tuple{
  228. Emitter: "test",
  229. Message: nil,
  230. },
  231. result: []map[string]interface{}{{
  232. "a": float64(1000),
  233. }},
  234. },
  235. {
  236. sql: "SELECT round(10.2) AS a FROM test",
  237. data: &xsql.Tuple{
  238. Emitter: "test",
  239. Message: nil,
  240. },
  241. result: []map[string]interface{}{{
  242. "a": float64(10),
  243. }},
  244. },
  245. {
  246. sql: "SELECT sign(10.2) AS a, sign(-2) as b, sign(0) as c FROM test",
  247. data: &xsql.Tuple{
  248. Emitter: "test",
  249. Message: nil,
  250. },
  251. result: []map[string]interface{}{{
  252. "a": float64(1),
  253. "b": float64(-1),
  254. "c": float64(0),
  255. }},
  256. },
  257. {
  258. sql: "SELECT sin(0) as a FROM test",
  259. data: &xsql.Tuple{
  260. Emitter: "test",
  261. Message: nil,
  262. },
  263. result: []map[string]interface{}{{
  264. "a": float64(0),
  265. }},
  266. },
  267. {
  268. sql: "SELECT sinh(0) as a FROM test",
  269. data: &xsql.Tuple{
  270. Emitter: "test",
  271. Message: nil,
  272. },
  273. result: []map[string]interface{}{{
  274. "a": float64(0),
  275. }},
  276. },
  277. {
  278. sql: "SELECT sqrt(4) as a FROM test",
  279. data: &xsql.Tuple{
  280. Emitter: "test",
  281. Message: nil,
  282. },
  283. result: []map[string]interface{}{{
  284. "a": float64(2),
  285. }},
  286. },
  287. {
  288. sql: "SELECT tan(0) as a FROM test",
  289. data: &xsql.Tuple{
  290. Emitter: "test",
  291. Message: nil,
  292. },
  293. result: []map[string]interface{}{{
  294. "a": float64(0),
  295. }},
  296. },
  297. {
  298. sql: "SELECT tanh(1) as a FROM test",
  299. data: &xsql.Tuple{
  300. Emitter: "test",
  301. Message: nil,
  302. },
  303. result: []map[string]interface{}{{
  304. "a": float64(0.7615941559557649),
  305. }},
  306. },
  307. {
  308. sql: `SELECT cast(1.2, "bigint") as a FROM test`,
  309. data: &xsql.Tuple{
  310. Emitter: "test",
  311. Message: nil,
  312. },
  313. result: []map[string]interface{}{{
  314. "a": float64(1),
  315. }},
  316. },
  317. {
  318. sql: `SELECT cast(5, "bigint") as a FROM test`,
  319. data: &xsql.Tuple{
  320. Emitter: "test",
  321. Message: nil,
  322. },
  323. result: []map[string]interface{}{{
  324. "a": float64(5),
  325. }},
  326. },
  327. {
  328. sql: `SELECT cast(1.2, "string") as a FROM test`,
  329. data: &xsql.Tuple{
  330. Emitter: "test",
  331. Message: nil,
  332. },
  333. result: []map[string]interface{}{{
  334. "a": "1.2",
  335. }},
  336. },
  337. {
  338. sql: `SELECT cast(true, "string") as a FROM test`,
  339. data: &xsql.Tuple{
  340. Emitter: "test",
  341. Message: nil,
  342. },
  343. result: []map[string]interface{}{{
  344. "a": "true",
  345. }},
  346. },
  347. {
  348. sql: `SELECT cast("true", "boolean") as a FROM test`,
  349. data: &xsql.Tuple{
  350. Emitter: "test",
  351. Message: nil,
  352. },
  353. result: []map[string]interface{}{{
  354. "a": true,
  355. }},
  356. },
  357. {
  358. sql: `SELECT cast("1", "boolean") as a FROM test`,
  359. data: &xsql.Tuple{
  360. Emitter: "test",
  361. Message: nil,
  362. },
  363. result: []map[string]interface{}{{
  364. "a": true,
  365. }},
  366. },
  367. {
  368. sql: `SELECT cast(0.0, "boolean") as a FROM test`,
  369. data: &xsql.Tuple{
  370. Emitter: "test",
  371. Message: nil,
  372. },
  373. result: []map[string]interface{}{{
  374. "a": false,
  375. }},
  376. },
  377. {
  378. sql: `SELECT chr(0) as a FROM test`,
  379. data: &xsql.Tuple{
  380. Emitter: "test",
  381. Message: nil,
  382. },
  383. result: []map[string]interface{}{{
  384. "a": float64(0),
  385. }},
  386. },
  387. {
  388. sql: `SELECT chr("a") as a FROM test`,
  389. data: &xsql.Tuple{
  390. Emitter: "test",
  391. Message: nil,
  392. },
  393. result: []map[string]interface{}{{
  394. "a": float64(97),
  395. }},
  396. },
  397. {
  398. sql: `SELECT encode("hello", "base64") as a FROM test`,
  399. data: &xsql.Tuple{
  400. Emitter: "test",
  401. Message: nil,
  402. },
  403. result: []map[string]interface{}{{
  404. "a": "aGVsbG8=",
  405. }},
  406. },
  407. {
  408. sql: `SELECT trunc(3.1415, 2) as a FROM test`,
  409. data: &xsql.Tuple{
  410. Emitter: "test",
  411. Message: nil,
  412. },
  413. result: []map[string]interface{}{{
  414. "a": float64(3.14),
  415. }},
  416. },
  417. {
  418. sql: `SELECT trunc(3, 2) as a FROM test`,
  419. data: &xsql.Tuple{
  420. Emitter: "test",
  421. Message: nil,
  422. },
  423. result: []map[string]interface{}{{
  424. "a": float64(3.00),
  425. }},
  426. },
  427. }
  428. fmt.Printf("The test bucket size is %d.\n\n", len(tests))
  429. contextLogger := conf.Log.WithField("rule", "TestMathAndConversionFunc_Apply1")
  430. ctx := context.WithValue(context.Background(), context.LoggerKey, contextLogger)
  431. for i, tt := range tests {
  432. //fmt.Println("Running test " + strconv.Itoa(i))
  433. stmt, err := xsql.NewParser(strings.NewReader(tt.sql)).Parse()
  434. if err != nil && tt.result == nil {
  435. continue
  436. } else if err != nil && tt.result != nil {
  437. t.Errorf("%q", err)
  438. continue
  439. }
  440. pp := &ProjectOp{Fields: stmt.Fields}
  441. fv, afv := xsql.NewFunctionValuersForOp(nil, xsql.FuncRegisters)
  442. result := pp.Apply(ctx, tt.data, fv, afv)
  443. var mapRes []map[string]interface{}
  444. if v, ok := result.([]byte); ok {
  445. err := json.Unmarshal(v, &mapRes)
  446. if err != nil {
  447. t.Errorf("Failed to parse the input into map.\n")
  448. continue
  449. }
  450. //fmt.Printf("%t\n", mapRes["kuiper_field_0"])
  451. if !reflect.DeepEqual(tt.result, mapRes) {
  452. t.Errorf("%d. %q\n\nresult mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.sql, tt.result, mapRes)
  453. }
  454. } else {
  455. t.Errorf("The returned result is not type of []byte\n")
  456. }
  457. }
  458. }