xgo/script/compiled_test.go
Daniel 01fe30f02a
bug fix for function return and if statement (#160)
* fix a bug where function return instruction is missing with if statement

* remove script cancel context test
2019-03-23 12:59:54 -07:00

168 lines
3.7 KiB
Go

package script_test
import (
"context"
"testing"
"time"
"github.com/d5/tengo/assert"
"github.com/d5/tengo/script"
)
type M map[string]interface{}
func TestCompiled_Get(t *testing.T) {
// simple script
c := compile(t, `a := 5`, nil)
compiledRun(t, c)
compiledGet(t, c, "a", int64(5))
// user-defined variables
compileError(t, `a := b`, nil) // compile error because "b" is not defined
c = compile(t, `a := b`, M{"b": "foo"}) // now compile with b = "foo" defined
compiledGet(t, c, "a", nil) // a = undefined; because it's before Compiled.Run()
compiledRun(t, c) // Compiled.Run()
compiledGet(t, c, "a", "foo") // a = "foo"
}
func TestCompiled_GetAll(t *testing.T) {
c := compile(t, `a := 5`, nil)
compiledRun(t, c)
compiledGetAll(t, c, M{"a": int64(5)})
c = compile(t, `a := b`, M{"b": "foo"})
compiledRun(t, c)
compiledGetAll(t, c, M{"a": "foo", "b": "foo"})
c = compile(t, `a := b; b = 5`, M{"b": "foo"})
compiledRun(t, c)
compiledGetAll(t, c, M{"a": "foo", "b": int64(5)})
}
func TestCompiled_IsDefined(t *testing.T) {
c := compile(t, `a := 5`, nil)
compiledIsDefined(t, c, "a", false) // a is not defined before Run()
compiledRun(t, c)
compiledIsDefined(t, c, "a", true)
compiledIsDefined(t, c, "b", false)
}
func TestCompiled_Set(t *testing.T) {
c := compile(t, `a := b`, M{"b": "foo"})
compiledRun(t, c)
compiledGet(t, c, "a", "foo")
// replace value of 'b'
err := c.Set("b", "bar")
assert.NoError(t, err)
compiledRun(t, c)
compiledGet(t, c, "a", "bar")
// try to replace undefined variable
err = c.Set("c", 1984)
assert.Error(t, err) // 'c' is not defined
// case #2
c = compile(t, `
a := func() {
return func() {
return b + 5
}()
}()`, M{"b": 5})
compiledRun(t, c)
compiledGet(t, c, "a", int64(10))
err = c.Set("b", 10)
assert.NoError(t, err)
compiledRun(t, c)
compiledGet(t, c, "a", int64(15))
}
func TestCompiled_RunContext(t *testing.T) {
// machine completes normally
c := compile(t, `a := 5`, nil)
err := c.RunContext(context.Background())
assert.NoError(t, err)
compiledGet(t, c, "a", int64(5))
// timeout
c = compile(t, `for true {}`, nil)
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Millisecond)
defer cancel()
err = c.RunContext(ctx)
assert.Equal(t, context.DeadlineExceeded, err)
}
func compile(t *testing.T, input string, vars M) *script.Compiled {
s := script.New([]byte(input))
for vn, vv := range vars {
err := s.Add(vn, vv)
if !assert.NoError(t, err) {
return nil
}
}
c, err := s.Compile()
if !assert.NoError(t, err) || !assert.NotNil(t, c) {
return nil
}
return c
}
func compileError(t *testing.T, input string, vars M) bool {
s := script.New([]byte(input))
for vn, vv := range vars {
err := s.Add(vn, vv)
if !assert.NoError(t, err) {
return false
}
}
_, err := s.Compile()
return assert.Error(t, err)
}
func compiledRun(t *testing.T, c *script.Compiled) bool {
err := c.Run()
return assert.NoError(t, err)
}
func compiledGet(t *testing.T, c *script.Compiled, name string, expected interface{}) bool {
v := c.Get(name)
if !assert.NotNil(t, v) {
return false
}
return assert.Equal(t, expected, v.Value())
}
func compiledGetAll(t *testing.T, c *script.Compiled, expected M) bool {
vars := c.GetAll()
if !assert.Equal(t, len(expected), len(vars)) {
return false
}
for k, v := range expected {
var found bool
for _, e := range vars {
if e.Name() == k {
if !assert.Equal(t, v, e.Value()) {
return false
}
found = true
}
}
if !found {
assert.Fail(t, "variable '%s' not found", k)
}
}
return true
}
func compiledIsDefined(t *testing.T, c *script.Compiled, name string, expected bool) bool {
return assert.Equal(t, expected, c.IsDefined(name))
}