github.com/MontFerret/ferret@v0.18.0/pkg/runtime/core/scope_test.go (about) 1 package core_test 2 3 import ( 4 "testing" 5 6 . "github.com/smartystreets/goconvey/convey" 7 8 "github.com/MontFerret/ferret/pkg/runtime/core" 9 "github.com/MontFerret/ferret/pkg/runtime/values" 10 ) 11 12 func TestScope(t *testing.T) { 13 Convey(".SetVariable", t, func() { 14 Convey("Should set a new variable", func() { 15 rs, cf := core.NewRootScope() 16 17 So(cf, ShouldNotBeNil) 18 19 err := rs.SetVariable("foo", values.NewString("bar")) 20 21 So(err, ShouldBeNil) 22 }) 23 24 Convey("Should return an error when a variable is already defined", func() { 25 rs, cf := core.NewRootScope() 26 27 So(cf, ShouldNotBeNil) 28 29 err := rs.SetVariable("foo", values.NewString("bar")) 30 So(err, ShouldBeNil) 31 32 err = rs.SetVariable("foo", values.NewString("bar")) 33 So(err, ShouldHaveSameTypeAs, core.ErrNotUnique) 34 }) 35 }) 36 37 Convey(".GetVariable", t, func() { 38 Convey("Should set and get a variable", func() { 39 rs, cf := core.NewRootScope() 40 41 So(cf, ShouldNotBeNil) 42 43 err := rs.SetVariable("foo", values.NewString("bar")) 44 So(err, ShouldBeNil) 45 46 v, err := rs.GetVariable("foo") 47 48 So(err, ShouldBeNil) 49 So(v, ShouldEqual, "bar") 50 }) 51 52 Convey("Should return an error when variable is not defined", func() { 53 rs, cf := core.NewRootScope() 54 55 So(cf, ShouldNotBeNil) 56 57 _, err := rs.GetVariable("foo") 58 59 So(err, ShouldNotBeNil) 60 }) 61 }) 62 63 Convey(".HasVariable", t, func() { 64 Convey("Should return TRUE when a variable exists", func() { 65 rs, cf := core.NewRootScope() 66 67 So(cf, ShouldNotBeNil) 68 69 err := rs.SetVariable("foo", values.NewString("bar")) 70 So(err, ShouldBeNil) 71 72 exists := rs.HasVariable("foo") 73 74 So(exists, ShouldBeTrue) 75 }) 76 77 Convey("Should return FALSE when a variable exists", func() { 78 rs, cf := core.NewRootScope() 79 80 So(cf, ShouldNotBeNil) 81 82 exists := rs.HasVariable("foo") 83 84 So(exists, ShouldBeFalse) 85 }) 86 }) 87 88 Convey(".Fork", t, func() { 89 Convey("Should create a nested scope", func() { 90 Convey("Should set a variable only in a child scope", func() { 91 rs, cf := core.NewRootScope() 92 So(cf, ShouldNotBeNil) 93 94 cs := rs.Fork() 95 cs.SetVariable("foo", values.NewString("bar")) 96 97 exists := rs.HasVariable("foo") 98 99 So(exists, ShouldBeFalse) 100 }) 101 102 Convey("Should return a variable defined only in a child scope", func() { 103 rs, cf := core.NewRootScope() 104 So(cf, ShouldNotBeNil) 105 106 cs := rs.Fork() 107 err := cs.SetVariable("foo", values.NewString("bar")) 108 So(err, ShouldBeNil) 109 110 v, err := cs.GetVariable("foo") 111 112 So(err, ShouldBeNil) 113 So(v, ShouldEqual, "bar") 114 }) 115 116 Convey("Should return a variable defined only in a parent scope", func() { 117 rs, cf := core.NewRootScope() 118 So(cf, ShouldNotBeNil) 119 120 cs := rs.Fork() 121 err := cs.SetVariable("foo", values.NewString("bar")) 122 So(err, ShouldBeNil) 123 124 err = rs.SetVariable("faz", values.NewString("qaz")) 125 So(err, ShouldBeNil) 126 127 v, err := cs.GetVariable("faz") 128 129 So(err, ShouldBeNil) 130 So(v, ShouldEqual, "qaz") 131 }) 132 133 Convey("Should set a new variable with a same name defined in a parent scope", func() { 134 rs, cf := core.NewRootScope() 135 So(cf, ShouldNotBeNil) 136 137 err := rs.SetVariable("foo", values.NewString("bar")) 138 So(err, ShouldBeNil) 139 140 cs := rs.Fork() 141 err = cs.SetVariable("foo", values.NewString("faz")) 142 So(err, ShouldBeNil) 143 144 rsV, err := rs.GetVariable("foo") 145 So(err, ShouldBeNil) 146 147 csV, err := cs.GetVariable("foo") 148 So(err, ShouldBeNil) 149 150 So(csV, ShouldNotEqual, rsV) 151 }) 152 }) 153 }) 154 } 155 156 func BenchmarkScope(b *testing.B) { 157 root, _ := core.NewRootScope() 158 159 for n := 0; n < b.N; n++ { 160 root.Fork() 161 } 162 } 163 164 type ( 165 TestCloserType struct{} 166 167 TestCloserValue struct { 168 closed bool 169 } 170 ) 171 172 func (tct TestCloserType) ID() int64 { 173 return 99 174 } 175 176 func (tct TestCloserType) String() string { 177 return "TestCloser" 178 } 179 180 func (tct TestCloserType) Equals(other core.Type) bool { 181 return other.ID() == tct.ID() 182 } 183 184 func (tc *TestCloserValue) MarshalJSON() ([]byte, error) { 185 return nil, core.ErrNotImplemented 186 } 187 188 func (tc *TestCloserValue) Type() core.Type { 189 return TestCloserType{} 190 } 191 192 func (tc *TestCloserValue) String() string { 193 return "" 194 } 195 196 func (tc *TestCloserValue) Compare(other core.Value) int64 { 197 return 0 198 } 199 200 func (tc *TestCloserValue) Unwrap() interface{} { 201 return tc 202 } 203 204 func (tc *TestCloserValue) Hash() uint64 { 205 return 0 206 } 207 208 func (tc *TestCloserValue) Copy() core.Value { 209 return &TestCloserValue{} 210 } 211 212 func (tc *TestCloserValue) Close() error { 213 if tc.closed { 214 return core.Error(core.ErrInvalidOperation, "already closed") 215 } 216 217 tc.closed = true 218 219 return nil 220 } 221 222 func TestCloseFunc(t *testing.T) { 223 Convey("Should close root scope and close all io.Closer values", t, func() { 224 rs, cf := core.NewRootScope() 225 226 tc := &TestCloserValue{} 227 228 rs.SetVariable("disposable", tc) 229 So(tc.closed, ShouldBeFalse) 230 231 err := cf() 232 So(err, ShouldBeNil) 233 234 So(tc.closed, ShouldBeTrue) 235 }) 236 237 Convey("Should return error if it's already closed", t, func() { 238 rs, cf := core.NewRootScope() 239 240 tc := &TestCloserValue{} 241 242 rs.SetVariable("disposable", tc) 243 So(tc.closed, ShouldBeFalse) 244 245 err := cf() 246 So(err, ShouldBeNil) 247 248 So(tc.closed, ShouldBeTrue) 249 250 err = cf() 251 So(err, ShouldHaveSameTypeAs, core.ErrInvalidOperation) 252 }) 253 }