1
0
mirror of https://github.com/MontFerret/ferret.git synced 2024-12-16 11:37:36 +02:00
ferret/pkg/runtime/core/scope_test.go
2018-10-28 01:45:26 -04:00

237 lines
4.8 KiB
Go

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) {
Convey(".SetVariable", t, func() {
Convey("Should set a new variable", func() {
rs, cf := core.NewRootScope()
So(cf, ShouldNotBeNil)
err := rs.SetVariable("foo", values.NewString("bar"))
So(err, ShouldBeNil)
})
Convey("Should return an error when a variable is already defined", func() {
rs, cf := core.NewRootScope()
So(cf, ShouldNotBeNil)
err := rs.SetVariable("foo", values.NewString("bar"))
So(err, ShouldBeNil)
err = rs.SetVariable("foo", values.NewString("bar"))
So(err, ShouldHaveSameTypeAs, core.ErrNotUnique)
})
})
Convey(".GetVariable", t, func() {
Convey("Should set and get a variable", func() {
rs, cf := core.NewRootScope()
So(cf, ShouldNotBeNil)
err := rs.SetVariable("foo", values.NewString("bar"))
So(err, ShouldBeNil)
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)
})
})
})
}
func BenchmarkScope(b *testing.B) {
root, _ := core.NewRootScope()
for n := 0; n < b.N; n++ {
root.Fork()
}
}
type TestCloser struct {
closed bool
}
func (tc *TestCloser) MarshalJSON() ([]byte, error) {
return nil, core.ErrNotImplemented
}
func (tc *TestCloser) Type() core.Type {
return core.NoneType
}
func (tc *TestCloser) String() string {
return ""
}
func (tc *TestCloser) Compare(other core.Value) int {
return 0
}
func (tc *TestCloser) Unwrap() interface{} {
return tc
}
func (tc *TestCloser) Hash() uint64 {
return 0
}
func (tc *TestCloser) Copy() core.Value {
return &TestCloser{}
}
func (tc *TestCloser) Close() error {
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() {
rs, cf := core.NewRootScope()
tc := &TestCloser{}
rs.SetVariable("disposable", tc)
So(tc.closed, ShouldBeFalse)
err := cf()
So(err, ShouldBeNil)
So(tc.closed, ShouldBeTrue)
})
Convey("Should return error if it's already closed", t, func() {
rs, cf := core.NewRootScope()
tc := &TestCloser{}
rs.SetVariable("disposable", tc)
So(tc.closed, ShouldBeFalse)
err := cf()
So(err, ShouldBeNil)
So(tc.closed, ShouldBeTrue)
err = cf()
So(err, ShouldHaveSameTypeAs, core.ErrInvalidOperation)
})
}