func_provider_test.go 8.9 KB

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