123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388 |
- /*
- * 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 scope
- import (
- "encoding/json"
- "fmt"
- "testing"
- "devt.de/krotik/ecal/parser"
- )
- func TestVarScopeSetMap(t *testing.T) {
- parentVS := NewScope("global")
- childVs := NewScopeWithParent("c1", parentVS)
- // Test map
- parentVS.SetValue("xx", map[interface{}]interface{}{
- "foo": map[interface{}]interface{}{},
- })
- childVs.SetValue("xx.foo.bar", map[interface{}]interface{}{})
- childVs.SetValue("xx.foo.bar.99", "tester")
- if childVs.Parent().String() != `
- global {
- xx (map[interface {}]interface {}) : {"foo":{"bar":{"99":"tester"}}}
- }`[1:] {
- t.Error("Unexpected result:", parentVS.String())
- return
- }
- childVs.SetValue("xx.foo.bar.99", []interface{}{1, 2})
- if parentVS.String() != `
- global {
- xx (map[interface {}]interface {}) : {"foo":{"bar":{"99":[1,2]}}}
- }`[1:] {
- t.Error("Unexpected result:", parentVS.String())
- return
- }
- childVs.SetValue("xx.foo.bar", map[interface{}]interface{}{
- float64(22): "foo",
- "33": "bar",
- })
- if res, _, _ := childVs.GetValue("xx.foo.bar.33"); res != "bar" {
- t.Error("Unexpected result:", res)
- return
- }
- if res, _, _ := childVs.GetValue("xx.foo.bar.22"); res != "foo" {
- t.Error("Unexpected result:", res)
- return
- }
- // Test errors
- err := parentVS.SetValue("xx.foo.a.b", 5)
- if err == nil || err.Error() != "Container field xx.foo.a does not exist" {
- t.Error("Unexpected result:", parentVS.String(), err)
- return
- }
- // Test list (test also overwriting of variables)
- parentVS.SetValue("xx", []interface{}{1, 2, []interface{}{3, 4}})
- if parentVS.String() != `
- global {
- xx ([]interface {}) : [1,2,[3,4]]
- }`[1:] {
- t.Error("Unexpected result:", parentVS.String())
- return
- }
- parentVS.SetValue("xx.2", []interface{}{3, 4, 5})
- if parentVS.String() != `
- global {
- xx ([]interface {}) : [1,2,[3,4,5]]
- }`[1:] {
- t.Error("Unexpected result:", parentVS.String())
- return
- }
- parentVS.SetValue("xx.-1", []interface{}{3, 4, 6})
- if parentVS.String() != `
- global {
- xx ([]interface {}) : [1,2,[3,4,6]]
- }`[1:] {
- t.Error("Unexpected result:", parentVS.String())
- return
- }
- parentVS.SetValue("xx.-1.-1", 7)
- if parentVS.String() != `
- global {
- xx ([]interface {}) : [1,2,[3,4,7]]
- }`[1:] {
- t.Error("Unexpected result:", parentVS.String())
- return
- }
- testVarScopeSetMapErrors(t, parentVS)
- }
- func testVarScopeSetMapErrors(t *testing.T, parentVS parser.Scope) {
- err := parentVS.SetValue("xx.a", []interface{}{3, 4, 5})
- if err.Error() != "List xx needs a number index not: a" {
- t.Error("Unexpected result:", parentVS.String(), err)
- return
- }
- err = parentVS.SetValue("xx.2.b", []interface{}{3, 4, 5})
- if err.Error() != "List xx.2 needs a number index not: b" {
- t.Error("Unexpected result:", parentVS.String(), err)
- return
- }
- err = parentVS.SetValue("xx.2.b.1", []interface{}{3, 4, 5})
- if err.Error() != "List xx.2 needs a number index not: b" {
- t.Error("Unexpected result:", parentVS.String(), err)
- return
- }
- err = parentVS.SetValue("xx.2.1.b.1", []interface{}{3, 4, 5})
- if err.Error() != "Variable xx.2.1 is not a container" {
- t.Error("Unexpected result:", parentVS.String(), err)
- return
- }
- err = parentVS.SetValue("xx.2.1.2", []interface{}{3, 4, 5})
- if err.Error() != "Variable xx.2.1 is not a container" {
- t.Error("Unexpected result:", parentVS.String(), err)
- return
- }
- err = parentVS.SetValue("xx.5", []interface{}{3, 4, 5})
- if err.Error() != "Out of bounds access to list xx with index: 5" {
- t.Error("Unexpected result:", parentVS.String(), err)
- return
- }
- err = parentVS.SetValue("xx.5.1", []interface{}{3, 4, 5})
- if err.Error() != "Out of bounds access to list xx with index: 5" {
- t.Error("Unexpected result:", parentVS.String(), err)
- return
- }
- err = parentVS.SetValue("xx.2.5.1", []interface{}{3, 4, 5})
- if err.Error() != "Out of bounds access to list xx.2 with index: 5" {
- t.Error("Unexpected result:", parentVS.String(), err)
- return
- }
- err = parentVS.SetValue("yy.2.5.1", []interface{}{3, 4, 5})
- if err.Error() != "Variable yy is not a container" {
- t.Error("Unexpected result:", parentVS.String(), err)
- return
- }
- }
- func TestVarScopeGet(t *testing.T) {
- parentVs := NewScope("")
- childVs := parentVs.NewChild("")
- parentVs.SetValue("xx", map[interface{}]interface{}{
- "foo": map[interface{}]interface{}{
- "bar": 99,
- },
- })
- parentVs.SetValue("test", []interface{}{1, 2, []interface{}{3, 4}})
- if res := fmt.Sprint(childVs.GetValue("xx")); res != "map[foo:map[bar:99]] true <nil>" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := fmt.Sprint(childVs.GetValue("xx.foo")); res != "map[bar:99] true <nil>" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := fmt.Sprint(childVs.GetValue("xx.foo.bar")); res != "99 true <nil>" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := fmt.Sprint(childVs.GetValue("test")); res != "[1 2 [3 4]] true <nil>" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := fmt.Sprint(childVs.GetValue("test.2")); res != "[3 4] true <nil>" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := fmt.Sprint(childVs.GetValue("test.2.1")); res != "4 true <nil>" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := fmt.Sprint(childVs.GetValue("test.-1.1")); res != "4 true <nil>" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := fmt.Sprint(childVs.GetValue("test.-1.-1")); res != "4 true <nil>" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := fmt.Sprint(childVs.GetValue("test.-1.-2")); res != "3 true <nil>" {
- t.Error("Unexpected result:", res)
- return
- }
- // Test error cases
- if res := fmt.Sprint(childVs.GetValue("test.a")); res != "<nil> false List test needs a number index not: a" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := fmt.Sprint(childVs.GetValue("test.5")); res != "<nil> false Out of bounds access to list test with index: 5" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := fmt.Sprint(childVs.GetValue("test.2.1.1")); res != "<nil> false Variable test.2.1 is not a container" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := fmt.Sprint(childVs.GetValue("test.1.1.1")); res != "<nil> false Variable test.1 is not a container" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := fmt.Sprint(childVs.GetValue("test2.1.1.1")); res != "<nil> false <nil>" {
- t.Error("Unexpected result:", res)
- return
- }
- }
- func TestVarScopeDump(t *testing.T) {
- // Build a small tree of VS
- globalVS1 := NewScope("global")
- globalVS2 := NewScopeWithParent("global2", globalVS1)
- globalVS3 := NewScopeWithParent("global3", globalVS1)
- sinkVs1 := globalVS2.NewChild("sink: 1")
- globalVS2.NewChild("sink: 1") // This should have no effect
- globalVS2.NewChild("sink: 2") // Reference is provided in the next call
- sinkVs2 := globalVS1.NewChild("sink: 2")
- for1Vs := sinkVs1.NewChild("block: for1")
- for2Vs := sinkVs1.NewChild("block: for2")
- for21Vs := for2Vs.NewChild("block: for2-1")
- for211Vs := for21Vs.NewChild("block: for2-1-1")
- // Populate tree
- globalVS1.SetValue("0", 0)
- globalVS2.SetValue("a", 1)
- globalVS3.SetValue("a", 2)
- sinkVs1.SetValue("b", 2)
- for1Vs.SetValue("c", 3)
- for2Vs.SetValue("d", 4)
- for21Vs.SetValue("e", 5)
- for211Vs.SetValue("f", 6)
- for211Vs.SetValue("x", ToObject(for211Vs))
- sinkVs2.SetValue("g", 2)
- sinkVs1.SetLocalValue("a", 5)
- // Dump the sinkVs1 scope
- if res := sinkVs1.String(); res != `global {
- 0 (int) : 0
- global2 {
- a (int) : 1
- sink: 1 {
- a (int) : 5
- b (int) : 2
- block: for1 {
- c (int) : 3
- }
- block: for2 {
- d (int) : 4
- block: for2-1 {
- e (int) : 5
- block: for2-1-1 {
- f (int) : 6
- x (map[interface {}]interface {}) : {"f":6}
- }
- }
- }
- }
- }
- }` {
- t.Error("Unexpected result:", res)
- return
- }
- bytes, _ := json.Marshal(sinkVs1.ToJSONObject())
- if res := string(bytes); res != `{"a":5,"b":2}` {
- t.Error("Unexpected result:", res)
- return
- }
- bytes, _ = json.Marshal(for211Vs.ToJSONObject())
- if res := string(bytes); res != `{"f":6,"x":{"f":6}}` {
- t.Error("Unexpected result:", res)
- return
- }
- if res := globalVS1.Name(); res != "global" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := sinkVs2.String(); res != `global {
- 0 (int) : 0
- sink: 2 {
- g (int) : 2
- }
- }` {
- t.Error("Unexpected result:", res)
- return
- }
- // Dumping the global scope results in the same output as it does not
- // track child scopes
- if res := globalVS1.String(); res != `global {
- 0 (int) : 0
- sink: 2 {
- g (int) : 2
- }
- }` {
- t.Error("Unexpected result:", res)
- return
- }
- sinkVs1.Clear()
- if res := sinkVs1.String(); res != `global {
- 0 (int) : 0
- global2 {
- a (int) : 1
- sink: 1 {
- }
- }
- }` {
- t.Error("Unexpected result:", res)
- return
- }
- }
|