2018-10-11 17:39:52 +02:00
|
|
|
package core_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
|
|
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
|
|
|
. "github.com/smartystreets/goconvey/convey"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestScope(t *testing.T) {
|
2018-10-28 07:45:26 +02:00
|
|
|
Convey(".SetVariable", t, func() {
|
|
|
|
Convey("Should set a new variable", func() {
|
|
|
|
rs, cf := core.NewRootScope()
|
2018-10-11 17:39:52 +02:00
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
So(cf, ShouldNotBeNil)
|
2018-10-11 17:39:52 +02:00
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
err := rs.SetVariable("foo", values.NewString("bar"))
|
2018-10-11 17:39:52 +02:00
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
So(err, ShouldBeNil)
|
|
|
|
})
|
2018-10-11 17:39:52 +02:00
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
Convey("Should return an error when a variable is already defined", func() {
|
|
|
|
rs, cf := core.NewRootScope()
|
2018-10-11 17:39:52 +02:00
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
So(cf, ShouldNotBeNil)
|
2018-10-11 17:39:52 +02:00
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
err := rs.SetVariable("foo", values.NewString("bar"))
|
|
|
|
So(err, ShouldBeNil)
|
2018-10-11 17:39:52 +02:00
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
err = rs.SetVariable("foo", values.NewString("bar"))
|
|
|
|
So(err, ShouldHaveSameTypeAs, core.ErrNotUnique)
|
|
|
|
})
|
|
|
|
})
|
2018-10-11 17:39:52 +02:00
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
Convey(".GetVariable", t, func() {
|
|
|
|
Convey("Should set and get a variable", func() {
|
|
|
|
rs, cf := core.NewRootScope()
|
2018-10-11 17:39:52 +02:00
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
So(cf, ShouldNotBeNil)
|
2018-10-11 17:39:52 +02:00
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
err := rs.SetVariable("foo", values.NewString("bar"))
|
|
|
|
So(err, ShouldBeNil)
|
2018-10-11 17:39:52 +02:00
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
v, err := rs.GetVariable("foo")
|
|
|
|
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
So(v, ShouldEqual, "bar")
|
|
|
|
})
|
|
|
|
|
|
|
|
Convey("Should return an error when variable is not defined", func() {
|
|
|
|
rs, cf := core.NewRootScope()
|
|
|
|
|
|
|
|
So(cf, ShouldNotBeNil)
|
|
|
|
|
|
|
|
_, err := rs.GetVariable("foo")
|
|
|
|
|
|
|
|
So(err, ShouldNotBeNil)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
Convey(".HasVariable", t, func() {
|
|
|
|
Convey("Should return TRUE when a variable exists", func() {
|
|
|
|
rs, cf := core.NewRootScope()
|
|
|
|
|
|
|
|
So(cf, ShouldNotBeNil)
|
|
|
|
|
|
|
|
err := rs.SetVariable("foo", values.NewString("bar"))
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
|
|
|
|
exists := rs.HasVariable("foo")
|
|
|
|
|
|
|
|
So(exists, ShouldBeTrue)
|
|
|
|
})
|
|
|
|
|
|
|
|
Convey("Should return FALSE when a variable exists", func() {
|
|
|
|
rs, cf := core.NewRootScope()
|
|
|
|
|
|
|
|
So(cf, ShouldNotBeNil)
|
|
|
|
|
|
|
|
exists := rs.HasVariable("foo")
|
|
|
|
|
|
|
|
So(exists, ShouldBeFalse)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
Convey(".Fork", t, func() {
|
|
|
|
Convey("Should create a nested scope", func() {
|
|
|
|
Convey("Should set a variable only in a child scope", func() {
|
|
|
|
rs, cf := core.NewRootScope()
|
|
|
|
So(cf, ShouldNotBeNil)
|
|
|
|
|
|
|
|
cs := rs.Fork()
|
|
|
|
cs.SetVariable("foo", values.NewString("bar"))
|
|
|
|
|
|
|
|
exists := rs.HasVariable("foo")
|
|
|
|
|
|
|
|
So(exists, ShouldBeFalse)
|
|
|
|
})
|
|
|
|
|
|
|
|
Convey("Should return a variable defined only in a child scope", func() {
|
|
|
|
rs, cf := core.NewRootScope()
|
|
|
|
So(cf, ShouldNotBeNil)
|
|
|
|
|
|
|
|
cs := rs.Fork()
|
|
|
|
err := cs.SetVariable("foo", values.NewString("bar"))
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
|
|
|
|
v, err := cs.GetVariable("foo")
|
|
|
|
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
So(v, ShouldEqual, "bar")
|
|
|
|
})
|
|
|
|
|
|
|
|
Convey("Should return a variable defined only in a parent scope", func() {
|
|
|
|
rs, cf := core.NewRootScope()
|
|
|
|
So(cf, ShouldNotBeNil)
|
|
|
|
|
|
|
|
cs := rs.Fork()
|
|
|
|
err := cs.SetVariable("foo", values.NewString("bar"))
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
|
|
|
|
err = rs.SetVariable("faz", values.NewString("qaz"))
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
|
|
|
|
v, err := cs.GetVariable("faz")
|
|
|
|
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
So(v, ShouldEqual, "qaz")
|
|
|
|
})
|
|
|
|
|
|
|
|
Convey("Should set a new variable with a same name defined in a parent scope", func() {
|
|
|
|
rs, cf := core.NewRootScope()
|
|
|
|
So(cf, ShouldNotBeNil)
|
|
|
|
|
|
|
|
err := rs.SetVariable("foo", values.NewString("bar"))
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
|
|
|
|
cs := rs.Fork()
|
|
|
|
err = cs.SetVariable("foo", values.NewString("faz"))
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
|
|
|
|
rsV, err := rs.GetVariable("foo")
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
|
|
|
|
csV, err := cs.GetVariable("foo")
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
|
|
|
|
So(csV, ShouldNotEqual, rsV)
|
|
|
|
})
|
|
|
|
})
|
2018-10-11 17:39:52 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
func BenchmarkScope(b *testing.B) {
|
|
|
|
root, _ := core.NewRootScope()
|
|
|
|
|
|
|
|
for n := 0; n < b.N; n++ {
|
|
|
|
root.Fork()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-13 19:31:18 +02:00
|
|
|
type (
|
|
|
|
TestCloserType struct{}
|
|
|
|
|
|
|
|
TestCloserValue struct {
|
|
|
|
closed bool
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
func (tct TestCloserType) ID() int64 {
|
|
|
|
return 99
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tct TestCloserType) String() string {
|
|
|
|
return "TestCloser"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tct TestCloserType) Equals(other core.Type) bool {
|
|
|
|
return other.ID() == tct.ID()
|
2018-10-28 07:45:26 +02:00
|
|
|
}
|
|
|
|
|
2019-02-13 19:31:18 +02:00
|
|
|
func (tc *TestCloserValue) MarshalJSON() ([]byte, error) {
|
2018-10-28 07:45:26 +02:00
|
|
|
return nil, core.ErrNotImplemented
|
|
|
|
}
|
|
|
|
|
2019-02-13 19:31:18 +02:00
|
|
|
func (tc *TestCloserValue) Type() core.Type {
|
|
|
|
return TestCloserType{}
|
2018-10-28 07:45:26 +02:00
|
|
|
}
|
|
|
|
|
2019-02-13 19:31:18 +02:00
|
|
|
func (tc *TestCloserValue) String() string {
|
2018-10-28 07:45:26 +02:00
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2019-02-13 19:31:18 +02:00
|
|
|
func (tc *TestCloserValue) Compare(other core.Value) int64 {
|
2018-10-28 07:45:26 +02:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
2019-02-13 19:31:18 +02:00
|
|
|
func (tc *TestCloserValue) Unwrap() interface{} {
|
2018-10-28 07:45:26 +02:00
|
|
|
return tc
|
|
|
|
}
|
|
|
|
|
2019-02-13 19:31:18 +02:00
|
|
|
func (tc *TestCloserValue) Hash() uint64 {
|
2018-10-28 07:45:26 +02:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
2019-02-13 19:31:18 +02:00
|
|
|
func (tc *TestCloserValue) Copy() core.Value {
|
|
|
|
return &TestCloserValue{}
|
2018-10-28 07:45:26 +02:00
|
|
|
}
|
|
|
|
|
2019-02-13 19:31:18 +02:00
|
|
|
func (tc *TestCloserValue) Close() error {
|
2018-10-28 07:45:26 +02:00
|
|
|
if tc.closed {
|
|
|
|
return core.Error(core.ErrInvalidOperation, "already closed")
|
|
|
|
}
|
|
|
|
|
|
|
|
tc.closed = true
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCloseFunc(t *testing.T) {
|
|
|
|
Convey("Should close root scope and close all io.Closer values", t, func() {
|
2018-10-11 17:39:52 +02:00
|
|
|
rs, cf := core.NewRootScope()
|
|
|
|
|
2019-02-13 19:31:18 +02:00
|
|
|
tc := &TestCloserValue{}
|
2018-10-11 17:39:52 +02:00
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
rs.SetVariable("disposable", tc)
|
|
|
|
So(tc.closed, ShouldBeFalse)
|
2018-10-11 17:39:52 +02:00
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
err := cf()
|
2018-10-11 17:39:52 +02:00
|
|
|
So(err, ShouldBeNil)
|
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
So(tc.closed, ShouldBeTrue)
|
|
|
|
})
|
|
|
|
|
|
|
|
Convey("Should return error if it's already closed", t, func() {
|
|
|
|
rs, cf := core.NewRootScope()
|
2018-10-11 17:39:52 +02:00
|
|
|
|
2019-02-13 19:31:18 +02:00
|
|
|
tc := &TestCloserValue{}
|
2018-10-11 17:39:52 +02:00
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
rs.SetVariable("disposable", tc)
|
|
|
|
So(tc.closed, ShouldBeFalse)
|
2018-10-11 17:39:52 +02:00
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
err := cf()
|
2018-10-11 17:39:52 +02:00
|
|
|
So(err, ShouldBeNil)
|
|
|
|
|
2018-10-28 07:45:26 +02:00
|
|
|
So(tc.closed, ShouldBeTrue)
|
|
|
|
|
|
|
|
err = cf()
|
|
|
|
So(err, ShouldHaveSameTypeAs, core.ErrInvalidOperation)
|
2018-10-11 17:39:52 +02:00
|
|
|
})
|
|
|
|
}
|