func_provider_test.go 7.8 KB

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