func_provider_test.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. /*
  2. * ECAL
  3. *
  4. * Copyright 2020 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the MIT
  7. * License, If a copy of the MIT License was not distributed with this
  8. * file, You can obtain one at https://opensource.org/licenses/MIT.
  9. */
  10. package interpreter
  11. import (
  12. "fmt"
  13. "reflect"
  14. "strings"
  15. "testing"
  16. "time"
  17. "devt.de/krotik/common/errorutil"
  18. "devt.de/krotik/ecal/stdlib"
  19. )
  20. func TestStdlib(t *testing.T) {
  21. stdlib.AddStdlibPkg("fmt", "fmt package")
  22. stdlib.AddStdlibFunc("fmt", "Sprint",
  23. stdlib.NewECALFunctionAdapter(reflect.ValueOf(fmt.Sprint), "foo"))
  24. res, err := UnitTestEvalAndAST(
  25. `fmt.Sprint([1,2,3])`, nil,
  26. `
  27. identifier: fmt
  28. identifier: Sprint
  29. funccall
  30. list
  31. number: 1
  32. number: 2
  33. number: 3
  34. `[1:])
  35. if err != nil || res != "[1 2 3]" {
  36. t.Error("Unexpected result: ", res, err)
  37. return
  38. }
  39. res, err = UnitTestEvalAndAST(
  40. `fmt.Sprint(math.Pi)`, nil,
  41. `
  42. identifier: fmt
  43. identifier: Sprint
  44. funccall
  45. identifier: math
  46. identifier: Pi
  47. `[1:])
  48. if err != nil || res != "3.141592653589793" {
  49. t.Error("Unexpected result: ", res, err)
  50. return
  51. }
  52. // Negative case
  53. res, err = UnitTestEvalAndAST(
  54. `a.fmtSprint([1,2,3])`, nil,
  55. `
  56. identifier: a
  57. identifier: fmtSprint
  58. funccall
  59. list
  60. number: 1
  61. number: 2
  62. number: 3
  63. `[1:])
  64. if err == nil ||
  65. err.Error() != "ECAL error in ECALTestRuntime: Unknown construct (Unknown function: fmtSprint) (Line:1 Pos:3)" {
  66. t.Error("Unexpected result: ", res, err)
  67. return
  68. }
  69. }
  70. func TestSimpleFunctions(t *testing.T) {
  71. res, err := UnitTestEvalAndAST(
  72. `len([1,2,3])`, nil,
  73. `
  74. identifier: len
  75. funccall
  76. list
  77. number: 1
  78. number: 2
  79. number: 3
  80. `[1:])
  81. errorutil.AssertOk(err)
  82. if res != 3. {
  83. t.Error("Unexpected result: ", res, err)
  84. return
  85. }
  86. res, err = UnitTestEvalAndAST(
  87. `len({"a":1, 2:"b"})`, nil,
  88. `
  89. identifier: len
  90. funccall
  91. map
  92. kvp
  93. string: 'a'
  94. number: 1
  95. kvp
  96. number: 2
  97. string: 'b'
  98. `[1:])
  99. errorutil.AssertOk(err)
  100. if res != 2. {
  101. t.Error("Unexpected result: ", res, err)
  102. return
  103. }
  104. res, err = UnitTestEvalAndAST(
  105. `del([1,2,3], 1)`, nil,
  106. `
  107. identifier: del
  108. funccall
  109. list
  110. number: 1
  111. number: 2
  112. number: 3
  113. number: 1
  114. `[1:])
  115. errorutil.AssertOk(err)
  116. if fmt.Sprint(res) != "[1 3]" {
  117. t.Error("Unexpected result: ", res, err)
  118. return
  119. }
  120. res, err = UnitTestEvalAndAST(
  121. `del({
  122. "a" : 1
  123. "b" : 2
  124. "c" : 3
  125. }, "b")`, nil,
  126. `
  127. identifier: del
  128. funccall
  129. map
  130. kvp
  131. string: 'a'
  132. number: 1
  133. kvp
  134. string: 'b'
  135. number: 2
  136. kvp
  137. string: 'c'
  138. number: 3
  139. string: 'b'
  140. `[1:])
  141. errorutil.AssertOk(err)
  142. if fmt.Sprint(res) != "map[a:1 c:3]" {
  143. t.Error("Unexpected result: ", res, err)
  144. return
  145. }
  146. res, err = UnitTestEvalAndAST(
  147. `add([1,2,3], 4)`, nil,
  148. `
  149. identifier: add
  150. funccall
  151. list
  152. number: 1
  153. number: 2
  154. number: 3
  155. number: 4
  156. `[1:])
  157. if err != nil || fmt.Sprint(res) != "[1 2 3 4]" {
  158. t.Error("Unexpected result: ", res, err)
  159. return
  160. }
  161. res, err = UnitTestEvalAndAST(
  162. `add([1,2,3], 4, 0)`, nil,
  163. `
  164. identifier: add
  165. funccall
  166. list
  167. number: 1
  168. number: 2
  169. number: 3
  170. number: 4
  171. number: 0
  172. `[1:])
  173. errorutil.AssertOk(err)
  174. if fmt.Sprint(res) != "[4 1 2 3]" {
  175. t.Error("Unexpected result: ", res, err)
  176. return
  177. }
  178. res, err = UnitTestEvalAndAST(
  179. `add([1,2,3], 4, 1)`, nil,
  180. `
  181. identifier: add
  182. funccall
  183. list
  184. number: 1
  185. number: 2
  186. number: 3
  187. number: 4
  188. number: 1
  189. `[1:])
  190. errorutil.AssertOk(err)
  191. if fmt.Sprint(res) != "[1 4 2 3]" {
  192. t.Error("Unexpected result: ", res, err)
  193. return
  194. }
  195. }
  196. func TestSimpleFunctions2(t *testing.T) {
  197. res, err := UnitTestEvalAndAST(
  198. `concat([1,2,3], [4,5,6], [7,8,9])`, nil,
  199. `
  200. identifier: concat
  201. funccall
  202. list
  203. number: 1
  204. number: 2
  205. number: 3
  206. list
  207. number: 4
  208. number: 5
  209. number: 6
  210. list
  211. number: 7
  212. number: 8
  213. number: 9
  214. `[1:])
  215. errorutil.AssertOk(err)
  216. if fmt.Sprint(res) != "[1 2 3 4 5 6 7 8 9]" {
  217. t.Error("Unexpected result: ", res, err)
  218. return
  219. }
  220. res, err = UnitTestEvalAndAST(
  221. `dumpenv()`, nil,
  222. `
  223. identifier: dumpenv
  224. funccall
  225. `[1:])
  226. errorutil.AssertOk(err)
  227. if fmt.Sprint(res) != `GlobalScope {
  228. }` {
  229. t.Error("Unexpected result: ", res, err)
  230. return
  231. }
  232. res, err = UnitTestEval(
  233. `
  234. func foo() {
  235. log("hello")
  236. }
  237. doc(foo)`, nil)
  238. errorutil.AssertOk(err)
  239. if fmt.Sprint(res) != `Declared function: foo (Line 2, Pos 1)` {
  240. t.Error("Unexpected result: ", res, err)
  241. return
  242. }
  243. res, err = UnitTestEval(
  244. `doc(len)`, nil)
  245. errorutil.AssertOk(err)
  246. if fmt.Sprint(res) != `Len returns the size of a list or map.` {
  247. t.Error("Unexpected result: ", res, err)
  248. return
  249. }
  250. stdlib.AddStdlibPkg("fmt", "fmt package")
  251. stdlib.AddStdlibFunc("fmt", "Println",
  252. stdlib.NewECALFunctionAdapter(reflect.ValueOf(fmt.Sprint), "foo"))
  253. res, err = UnitTestEval(
  254. `doc(fmt.Println)`, nil)
  255. errorutil.AssertOk(err)
  256. if res != "foo" {
  257. t.Error("Unexpected result: ", res, err)
  258. return
  259. }
  260. res, err = UnitTestEval(
  261. `
  262. /*
  263. Foo is my custom function.
  264. */
  265. func foo() {
  266. log("hello")
  267. }
  268. doc(foo)`, nil)
  269. if err != nil || fmt.Sprint(res) != `Foo is my custom function.` {
  270. t.Error("Unexpected result: ", res, err)
  271. return
  272. }
  273. // Negative case
  274. res, err = UnitTestEvalAndAST(
  275. `a.len([1,2,3])`, nil,
  276. `
  277. identifier: a
  278. identifier: len
  279. funccall
  280. list
  281. number: 1
  282. number: 2
  283. number: 3
  284. `[1:])
  285. if err == nil ||
  286. err.Error() != "ECAL error in ECALTestRuntime: Unknown construct (Unknown function: len) (Line:1 Pos:3)" {
  287. t.Error("Unexpected result: ", res, err)
  288. return
  289. }
  290. _, err = UnitTestEval(`sleep(10)`, nil)
  291. if err != nil {
  292. t.Error("Unexpected result: ", err)
  293. return
  294. }
  295. }
  296. func TestCronTrigger(t *testing.T) {
  297. res, err := UnitTestEval(
  298. `setCronTrigger("1 * * * *", "foo", "bar")`, nil)
  299. if err == nil ||
  300. err.Error() != "ECAL error in ECALTestRuntime: Runtime error (Cron spec must have 6 entries separated by space) (Line:1 Pos:1)" {
  301. t.Error("Unexpected result: ", res, err)
  302. return
  303. }
  304. _, err = UnitTestEval(
  305. `
  306. sink test
  307. kindmatch [ "foo.*" ],
  308. {
  309. log("test rule - Handling request: ", event)
  310. }
  311. log("Cron:", setCronTrigger("1 1 *%10 * * *", "cronevent", "foo.bar"))
  312. `, nil)
  313. if err != nil {
  314. t.Error("Unexpected result:", err)
  315. return
  316. }
  317. testcron.Start()
  318. time.Sleep(200 * time.Millisecond)
  319. if testlogger.String() != `
  320. Cron:at second 1 of minute 1 of every 10th hour every day
  321. test rule - Handling request: {
  322. "kind": "foo.bar",
  323. "name": "cronevent",
  324. "state": {
  325. "tick": 1,
  326. "time": "2000-01-01T00:01:01Z",
  327. "timestamp": "946684861000"
  328. }
  329. }
  330. test rule - Handling request: {
  331. "kind": "foo.bar",
  332. "name": "cronevent",
  333. "state": {
  334. "tick": 2,
  335. "time": "2000-01-01T10:01:01Z",
  336. "timestamp": "946720861000"
  337. }
  338. }
  339. test rule - Handling request: {
  340. "kind": "foo.bar",
  341. "name": "cronevent",
  342. "state": {
  343. "tick": 3,
  344. "time": "2000-01-01T20:01:01Z",
  345. "timestamp": "946756861000"
  346. }
  347. }`[1:] {
  348. t.Error("Unexpected result:", testlogger.String())
  349. return
  350. }
  351. }
  352. func TestPulseTrigger(t *testing.T) {
  353. res, err := UnitTestEval(
  354. `setPulseTrigger("test", "foo", "bar")`, nil)
  355. if err == nil ||
  356. err.Error() != "ECAL error in ECALTestRuntime: Runtime error (Parameter 1 should be a number) (Line:1 Pos:1)" {
  357. t.Error("Unexpected result: ", res, err)
  358. return
  359. }
  360. _, err = UnitTestEval(
  361. `
  362. sink test
  363. kindmatch [ "foo.*" ],
  364. {
  365. log("test rule - Handling request: ", event)
  366. log("Duration: ", event.state.currentMicros - event.state.lastMicros," us (microsecond)")
  367. }
  368. setPulseTrigger(100, "pulseevent", "foo.bar")
  369. `, nil)
  370. if err != nil {
  371. t.Error("Unexpected result:", err)
  372. return
  373. }
  374. time.Sleep(100 * time.Millisecond)
  375. testprocessor.Finish()
  376. if !strings.Contains(testlogger.String(), "Handling request") {
  377. t.Error("Unexpected result:", testlogger.String())
  378. return
  379. }
  380. }
  381. func TestDocstrings(t *testing.T) {
  382. for k, v := range InbuildFuncMap {
  383. if res, _ := v.DocString(); res == "" {
  384. t.Error("Docstring missing for ", k)
  385. return
  386. }
  387. }
  388. }
  389. func TestErrorConditions(t *testing.T) {
  390. ib := &inbuildBaseFunc{}
  391. if _, err := ib.AssertNumParam(1, "bob"); err == nil || err.Error() != "Parameter 1 should be a number" {
  392. t.Error("Unexpected result:", err)
  393. return
  394. }
  395. if _, err := ib.AssertMapParam(1, "bob"); err == nil || err.Error() != "Parameter 1 should be a map" {
  396. t.Error("Unexpected result:", err)
  397. return
  398. }
  399. if _, err := ib.AssertListParam(1, "bob"); err == nil || err.Error() != "Parameter 1 should be a list" {
  400. t.Error("Unexpected result:", err)
  401. return
  402. }
  403. rf := &rangeFunc{&inbuildBaseFunc{}}
  404. if _, err := rf.Run("", nil, nil, 0, nil); err == nil || err.Error() != "Need at least an end range as first parameter" {
  405. t.Error("Unexpected result:", err)
  406. return
  407. }
  408. if _, err := rf.Run("", nil, nil, 0, []interface{}{"bob"}); err == nil || err.Error() != "Parameter 1 should be a number" {
  409. t.Error("Unexpected result:", err)
  410. return
  411. }
  412. }