123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520 |
- /*
- * ECAL
- *
- * Copyright 2020 Matthias Ladkau. All rights reserved.
- *
- * This Source Code Form is subject to the terms of the MIT
- * License, If a copy of the MIT License was not distributed with this
- * file, You can obtain one at https://opensource.org/licenses/MIT.
- */
- package interpreter
- import (
- "fmt"
- "reflect"
- "strings"
- "testing"
- "time"
- "devt.de/krotik/common/errorutil"
- "devt.de/krotik/common/timeutil"
- "devt.de/krotik/ecal/stdlib"
- )
- func TestStdlib(t *testing.T) {
- stdlib.AddStdlibPkg("fmt", "fmt package")
- stdlib.AddStdlibFunc("fmt", "Sprint",
- stdlib.NewECALFunctionAdapter(reflect.ValueOf(fmt.Sprint), "foo"))
- res, err := UnitTestEvalAndAST(
- `fmt.Sprint([1,2,3])`, nil,
- `
- identifier: fmt
- identifier: Sprint
- funccall
- list
- number: 1
- number: 2
- number: 3
- `[1:])
- if err != nil || res != "[1 2 3]" {
- t.Error("Unexpected result: ", res, err)
- return
- }
- res, err = UnitTestEvalAndAST(
- `fmt.Sprint(math.Pi)`, nil,
- `
- identifier: fmt
- identifier: Sprint
- funccall
- identifier: math
- identifier: Pi
- `[1:])
- if err != nil || res != "3.141592653589793" {
- t.Error("Unexpected result: ", res, err)
- return
- }
- // Negative case
- res, err = UnitTestEvalAndAST(
- `a.fmtSprint([1,2,3])`, nil,
- `
- identifier: a
- identifier: fmtSprint
- funccall
- list
- number: 1
- number: 2
- number: 3
- `[1:])
- if err == nil ||
- err.Error() != "ECAL error in ECALTestRuntime (ECALEvalTest): Unknown construct (Unknown function: fmtSprint) (Line:1 Pos:3)" {
- t.Error("Unexpected result: ", res, err)
- return
- }
- }
- func TestSimpleFunctions(t *testing.T) {
- res, err := UnitTestEvalAndAST(
- `len([1,2,3])`, nil,
- `
- identifier: len
- funccall
- list
- number: 1
- number: 2
- number: 3
- `[1:])
- errorutil.AssertOk(err)
- if res != 3. {
- t.Error("Unexpected result: ", res, err)
- return
- }
- res, err = UnitTestEvalAndAST(
- `type({a: [1,2,3]})`, nil,
- `
- identifier: type
- funccall
- map
- kvp
- identifier: a
- list
- number: 1
- number: 2
- number: 3
- `[1:])
- errorutil.AssertOk(err)
- if res != "map[interface {}]interface {}{interface {}(nil):[]interface {}{1, 2, 3}}" {
- t.Error("Unexpected result: ", res, err)
- return
- }
- res, err = UnitTestEvalAndAST(
- `len({"a":1, 2:"b"})`, nil,
- `
- identifier: len
- funccall
- map
- kvp
- string: 'a'
- number: 1
- kvp
- number: 2
- string: 'b'
- `[1:])
- errorutil.AssertOk(err)
- if res != 2. {
- t.Error("Unexpected result: ", res, err)
- return
- }
- res, err = UnitTestEvalAndAST(
- `del([1,2,3], 1)`, nil,
- `
- identifier: del
- funccall
- list
- number: 1
- number: 2
- number: 3
- number: 1
- `[1:])
- errorutil.AssertOk(err)
- if fmt.Sprint(res) != "[1 3]" {
- t.Error("Unexpected result: ", res, err)
- return
- }
- res, err = UnitTestEvalAndAST(
- `del({
- "a" : 1
- "b" : 2
- "c" : 3
- }, "b")`, nil,
- `
- identifier: del
- funccall
- map
- kvp
- string: 'a'
- number: 1
- kvp
- string: 'b'
- number: 2
- kvp
- string: 'c'
- number: 3
- string: 'b'
- `[1:])
- errorutil.AssertOk(err)
- if fmt.Sprint(res) != "map[a:1 c:3]" {
- t.Error("Unexpected result: ", res, err)
- return
- }
- res, err = UnitTestEvalAndAST(
- `add([1,2,3], 4)`, nil,
- `
- identifier: add
- funccall
- list
- number: 1
- number: 2
- number: 3
- number: 4
- `[1:])
- if err != nil || fmt.Sprint(res) != "[1 2 3 4]" {
- t.Error("Unexpected result: ", res, err)
- return
- }
- res, err = UnitTestEvalAndAST(
- `add([1,2,3], 4, 0)`, nil,
- `
- identifier: add
- funccall
- list
- number: 1
- number: 2
- number: 3
- number: 4
- number: 0
- `[1:])
- errorutil.AssertOk(err)
- if fmt.Sprint(res) != "[4 1 2 3]" {
- t.Error("Unexpected result: ", res, err)
- return
- }
- res, err = UnitTestEvalAndAST(
- `add([1,2,3], 4, 1)`, nil,
- `
- identifier: add
- funccall
- list
- number: 1
- number: 2
- number: 3
- number: 4
- number: 1
- `[1:])
- errorutil.AssertOk(err)
- if fmt.Sprint(res) != "[1 4 2 3]" {
- t.Error("Unexpected result: ", res, err)
- return
- }
- }
- func TestSimpleFunctions2(t *testing.T) {
- res, err := UnitTestEvalAndAST(
- `concat([1,2,3], [4,5,6], [7,8,9])`, nil,
- `
- identifier: concat
- funccall
- list
- number: 1
- number: 2
- number: 3
- list
- number: 4
- number: 5
- number: 6
- list
- number: 7
- number: 8
- number: 9
- `[1:])
- errorutil.AssertOk(err)
- if fmt.Sprint(res) != "[1 2 3 4 5 6 7 8 9]" {
- t.Error("Unexpected result: ", res, err)
- return
- }
- res, err = UnitTestEvalAndAST(
- `dumpenv()`, nil,
- `
- identifier: dumpenv
- funccall
- `[1:])
- errorutil.AssertOk(err)
- if fmt.Sprint(res) != `GlobalScope {
- }` {
- t.Error("Unexpected result: ", res, err)
- return
- }
- res, err = UnitTestEvalAndAST(
- `timestamp(now(), "GMT")`, nil,
- `
- identifier: timestamp
- funccall
- identifier: now
- funccall
- string: 'GMT'
- `[1:])
- errorutil.AssertOk(err)
- if !strings.HasSuffix(fmt.Sprint(res), "GMT") {
- t.Error("Unexpected result: ", res, err)
- return
- }
- res, err = UnitTestEval(
- `
- func foo() {
- log("hello")
- }
- doc(foo)`, nil)
- errorutil.AssertOk(err)
- if fmt.Sprint(res) != `Declared function: foo (Line 2, Pos 1)` {
- t.Error("Unexpected result: ", res, err)
- return
- }
- res, err = UnitTestEval(
- `doc(len)`, nil)
- errorutil.AssertOk(err)
- if fmt.Sprint(res) != `Len returns the size of a list or map.` {
- t.Error("Unexpected result: ", res, err)
- return
- }
- stdlib.AddStdlibPkg("fmt", "fmt package")
- stdlib.AddStdlibFunc("fmt", "Println",
- stdlib.NewECALFunctionAdapter(reflect.ValueOf(fmt.Sprint), "foo"))
- res, err = UnitTestEval(
- `doc(fmt.Println)`, nil)
- errorutil.AssertOk(err)
- if res != "foo" {
- t.Error("Unexpected result: ", res, err)
- return
- }
- res, err = UnitTestEval(
- `
- /*
- Foo is my custom function.
- */
- func foo() {
- log("hello")
- }
- doc(foo)`, nil)
- if err != nil || fmt.Sprint(res) != `Foo is my custom function.` {
- t.Error("Unexpected result: ", res, err)
- return
- }
- // Negative case
- res, err = UnitTestEvalAndAST(
- `a.len([1,2,3])`, nil,
- `
- identifier: a
- identifier: len
- funccall
- list
- number: 1
- number: 2
- number: 3
- `[1:])
- if err == nil ||
- err.Error() != "ECAL error in ECALTestRuntime (ECALEvalTest): Unknown construct (Unknown function: len) (Line:1 Pos:3)" {
- t.Error("Unexpected result: ", res, err)
- return
- }
- _, err = UnitTestEval(`sleep(10)`, nil)
- if err != nil {
- t.Error("Unexpected result: ", err)
- return
- }
- }
- func TestCronTrigger(t *testing.T) {
- res, err := UnitTestEval(
- `setCronTrigger("1 * * * *", "foo", "bar")`, nil)
- if err == nil ||
- err.Error() != "ECAL error in ECALTestRuntime (ECALEvalTest): Runtime error (Cron spec must have 6 entries separated by space) (Line:1 Pos:1)" {
- t.Error("Unexpected result: ", res, err)
- return
- }
- _, err = UnitTestEval(
- `
- sink test
- kindmatch [ "foo.*" ],
- {
- log("test rule - Handling request: ", event)
- }
- log("Cron:", setCronTrigger("1 1 *%10 * * *", "cronevent", "foo.bar"))
- `, nil)
- if err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- testcron.Start()
- timeutil.WaitTestingCron(testcron)
- if testlogger.String() != `
- Cron:at second 1 of minute 1 of every 10th hour every day
- test rule - Handling request: {
- "kind": "foo.bar",
- "name": "cronevent",
- "state": {
- "tick": 1,
- "time": "2000-01-01T00:01:01Z",
- "timestamp": "946684861000"
- }
- }
- test rule - Handling request: {
- "kind": "foo.bar",
- "name": "cronevent",
- "state": {
- "tick": 2,
- "time": "2000-01-01T10:01:01Z",
- "timestamp": "946720861000"
- }
- }
- test rule - Handling request: {
- "kind": "foo.bar",
- "name": "cronevent",
- "state": {
- "tick": 3,
- "time": "2000-01-01T20:01:01Z",
- "timestamp": "946756861000"
- }
- }`[1:] {
- t.Error("Unexpected result:", testlogger.String())
- return
- }
- }
- func TestPulseTrigger(t *testing.T) {
- res, err := UnitTestEval(
- `setPulseTrigger("test", "foo", "bar")`, nil)
- if err == nil ||
- err.Error() != "ECAL error in ECALTestRuntime (ECALEvalTest): Runtime error (Parameter 1 should be a number) (Line:1 Pos:1)" {
- t.Error("Unexpected result: ", res, err)
- return
- }
- _, err = UnitTestEval(
- `
- sink test
- kindmatch [ "foo.*" ],
- {
- log("test rule - Handling request: ", event)
- log("Duration: ", event.state.currentMicros - event.state.lastMicros," us (microsecond)")
- }
- setPulseTrigger(100, "pulseevent", "foo.bar")
- `, nil)
- if err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- time.Sleep(100 * time.Millisecond)
- testprocessor.Finish()
- if !strings.Contains(testlogger.String(), "Handling request") {
- t.Error("Unexpected result:", testlogger.String())
- return
- }
- }
- func TestDocstrings(t *testing.T) {
- for k, v := range InbuildFuncMap {
- if res, _ := v.DocString(); res == "" {
- t.Error("Docstring missing for ", k)
- return
- }
- }
- }
- func TestErrorConditions(t *testing.T) {
- ib := &inbuildBaseFunc{}
- if _, err := ib.AssertNumParam(1, "bob"); err == nil || err.Error() != "Parameter 1 should be a number" {
- t.Error("Unexpected result:", err)
- return
- }
- if _, err := ib.AssertMapParam(1, "bob"); err == nil || err.Error() != "Parameter 1 should be a map" {
- t.Error("Unexpected result:", err)
- return
- }
- if _, err := ib.AssertListParam(1, "bob"); err == nil || err.Error() != "Parameter 1 should be a list" {
- t.Error("Unexpected result:", err)
- return
- }
- rf := &rangeFunc{&inbuildBaseFunc{}}
- if _, err := rf.Run("", nil, nil, 0, nil); err == nil || err.Error() != "Need at least an end range as first parameter" {
- t.Error("Unexpected result:", err)
- return
- }
- if _, err := rf.Run("", nil, nil, 0, []interface{}{"bob"}); err == nil || err.Error() != "Parameter 1 should be a number" {
- t.Error("Unexpected result:", err)
- return
- }
- }
|