varsscope_test.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. /*
  2. * ECAL
  3. *
  4. * Copyright 2020 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the MIT
  7. * License, If a copy of the MIT License was not distributed with this
  8. * file, You can obtain one at https://opensource.org/licenses/MIT.
  9. */
  10. package scope
  11. import (
  12. "encoding/json"
  13. "fmt"
  14. "testing"
  15. )
  16. func TestVarScopeSetMap(t *testing.T) {
  17. parentVS := NewScope("global")
  18. childVs := NewScopeWithParent("c1", parentVS)
  19. // Test map
  20. parentVS.SetValue("xx", map[interface{}]interface{}{
  21. "foo": map[interface{}]interface{}{},
  22. })
  23. childVs.SetValue("xx.foo.bar", map[interface{}]interface{}{})
  24. childVs.SetValue("xx.foo.bar.99", "tester")
  25. if childVs.Parent().String() != `
  26. global {
  27. xx (map[interface {}]interface {}) : {"foo":{"bar":{"99":"tester"}}}
  28. }`[1:] {
  29. t.Error("Unexpected result:", parentVS.String())
  30. return
  31. }
  32. childVs.SetValue("xx.foo.bar.99", []interface{}{1, 2})
  33. if parentVS.String() != `
  34. global {
  35. xx (map[interface {}]interface {}) : {"foo":{"bar":{"99":[1,2]}}}
  36. }`[1:] {
  37. t.Error("Unexpected result:", parentVS.String())
  38. return
  39. }
  40. childVs.SetValue("xx.foo.bar", map[interface{}]interface{}{
  41. float64(22): "foo",
  42. "33": "bar",
  43. })
  44. if res, _, _ := childVs.GetValue("xx.foo.bar.33"); res != "bar" {
  45. t.Error("Unexpected result:", res)
  46. return
  47. }
  48. if res, _, _ := childVs.GetValue("xx.foo.bar.22"); res != "foo" {
  49. t.Error("Unexpected result:", res)
  50. return
  51. }
  52. // Test errors
  53. err := parentVS.SetValue("xx.foo.a.b", 5)
  54. if err == nil || err.Error() != "Container field xx.foo.a does not exist" {
  55. t.Error("Unexpected result:", parentVS.String(), err)
  56. return
  57. }
  58. // Test list (test also overwriting of variables)
  59. parentVS.SetValue("xx", []interface{}{1, 2, []interface{}{3, 4}})
  60. if parentVS.String() != `
  61. global {
  62. xx ([]interface {}) : [1,2,[3,4]]
  63. }`[1:] {
  64. t.Error("Unexpected result:", parentVS.String())
  65. return
  66. }
  67. parentVS.SetValue("xx.2", []interface{}{3, 4, 5})
  68. if parentVS.String() != `
  69. global {
  70. xx ([]interface {}) : [1,2,[3,4,5]]
  71. }`[1:] {
  72. t.Error("Unexpected result:", parentVS.String())
  73. return
  74. }
  75. parentVS.SetValue("xx.-1", []interface{}{3, 4, 6})
  76. if parentVS.String() != `
  77. global {
  78. xx ([]interface {}) : [1,2,[3,4,6]]
  79. }`[1:] {
  80. t.Error("Unexpected result:", parentVS.String())
  81. return
  82. }
  83. parentVS.SetValue("xx.-1.-1", 7)
  84. if parentVS.String() != `
  85. global {
  86. xx ([]interface {}) : [1,2,[3,4,7]]
  87. }`[1:] {
  88. t.Error("Unexpected result:", parentVS.String())
  89. return
  90. }
  91. err = parentVS.SetValue("xx.a", []interface{}{3, 4, 5})
  92. if err == nil || err.Error() != "List xx needs a number index not: a" {
  93. t.Error("Unexpected result:", parentVS.String(), err)
  94. return
  95. }
  96. err = parentVS.SetValue("xx.2.b", []interface{}{3, 4, 5})
  97. if err == nil || err.Error() != "List xx.2 needs a number index not: b" {
  98. t.Error("Unexpected result:", parentVS.String(), err)
  99. return
  100. }
  101. err = parentVS.SetValue("xx.2.b.1", []interface{}{3, 4, 5})
  102. if err == nil || err.Error() != "List xx.2 needs a number index not: b" {
  103. t.Error("Unexpected result:", parentVS.String(), err)
  104. return
  105. }
  106. err = parentVS.SetValue("xx.2.1.b.1", []interface{}{3, 4, 5})
  107. if err == nil || err.Error() != "Variable xx.2.1 is not a container" {
  108. t.Error("Unexpected result:", parentVS.String(), err)
  109. return
  110. }
  111. err = parentVS.SetValue("xx.2.1.2", []interface{}{3, 4, 5})
  112. if err == nil || err.Error() != "Variable xx.2.1 is not a container" {
  113. t.Error("Unexpected result:", parentVS.String(), err)
  114. return
  115. }
  116. err = parentVS.SetValue("xx.5", []interface{}{3, 4, 5})
  117. if err == nil || err.Error() != "Out of bounds access to list xx with index: 5" {
  118. t.Error("Unexpected result:", parentVS.String(), err)
  119. return
  120. }
  121. err = parentVS.SetValue("xx.5.1", []interface{}{3, 4, 5})
  122. if err == nil || err.Error() != "Out of bounds access to list xx with index: 5" {
  123. t.Error("Unexpected result:", parentVS.String(), err)
  124. return
  125. }
  126. err = parentVS.SetValue("xx.2.5.1", []interface{}{3, 4, 5})
  127. if err == nil || err.Error() != "Out of bounds access to list xx.2 with index: 5" {
  128. t.Error("Unexpected result:", parentVS.String(), err)
  129. return
  130. }
  131. err = parentVS.SetValue("yy.2.5.1", []interface{}{3, 4, 5})
  132. if err == nil || err.Error() != "Variable yy is not a container" {
  133. t.Error("Unexpected result:", parentVS.String(), err)
  134. return
  135. }
  136. }
  137. func TestVarScopeGet(t *testing.T) {
  138. parentVs := NewScope("")
  139. childVs := parentVs.NewChild("")
  140. parentVs.SetValue("xx", map[interface{}]interface{}{
  141. "foo": map[interface{}]interface{}{
  142. "bar": 99,
  143. },
  144. })
  145. parentVs.SetValue("test", []interface{}{1, 2, []interface{}{3, 4}})
  146. if res := fmt.Sprint(childVs.GetValue("xx")); res != "map[foo:map[bar:99]] true <nil>" {
  147. t.Error("Unexpected result:", res)
  148. return
  149. }
  150. if res := fmt.Sprint(childVs.GetValue("xx.foo")); res != "map[bar:99] true <nil>" {
  151. t.Error("Unexpected result:", res)
  152. return
  153. }
  154. if res := fmt.Sprint(childVs.GetValue("xx.foo.bar")); res != "99 true <nil>" {
  155. t.Error("Unexpected result:", res)
  156. return
  157. }
  158. if res := fmt.Sprint(childVs.GetValue("test")); res != "[1 2 [3 4]] true <nil>" {
  159. t.Error("Unexpected result:", res)
  160. return
  161. }
  162. if res := fmt.Sprint(childVs.GetValue("test.2")); res != "[3 4] true <nil>" {
  163. t.Error("Unexpected result:", res)
  164. return
  165. }
  166. if res := fmt.Sprint(childVs.GetValue("test.2.1")); res != "4 true <nil>" {
  167. t.Error("Unexpected result:", res)
  168. return
  169. }
  170. if res := fmt.Sprint(childVs.GetValue("test.-1.1")); res != "4 true <nil>" {
  171. t.Error("Unexpected result:", res)
  172. return
  173. }
  174. if res := fmt.Sprint(childVs.GetValue("test.-1.-1")); res != "4 true <nil>" {
  175. t.Error("Unexpected result:", res)
  176. return
  177. }
  178. if res := fmt.Sprint(childVs.GetValue("test.-1.-2")); res != "3 true <nil>" {
  179. t.Error("Unexpected result:", res)
  180. return
  181. }
  182. // Test error cases
  183. if res := fmt.Sprint(childVs.GetValue("test.a")); res != "<nil> false List test needs a number index not: a" {
  184. t.Error("Unexpected result:", res)
  185. return
  186. }
  187. if res := fmt.Sprint(childVs.GetValue("test.5")); res != "<nil> false Out of bounds access to list test with index: 5" {
  188. t.Error("Unexpected result:", res)
  189. return
  190. }
  191. if res := fmt.Sprint(childVs.GetValue("test.2.1.1")); res != "<nil> false Variable test.2.1 is not a container" {
  192. t.Error("Unexpected result:", res)
  193. return
  194. }
  195. if res := fmt.Sprint(childVs.GetValue("test.1.1.1")); res != "<nil> false Variable test.1 is not a container" {
  196. t.Error("Unexpected result:", res)
  197. return
  198. }
  199. if res := fmt.Sprint(childVs.GetValue("test2.1.1.1")); res != "<nil> false <nil>" {
  200. t.Error("Unexpected result:", res)
  201. return
  202. }
  203. }
  204. func TestVarScopeDump(t *testing.T) {
  205. // Build a small tree of VS
  206. globalVS1 := NewScope("global")
  207. globalVS2 := NewScopeWithParent("global2", globalVS1)
  208. globalVS3 := NewScopeWithParent("global3", globalVS1)
  209. sinkVs1 := globalVS2.NewChild("sink: 1")
  210. globalVS2.NewChild("sink: 1") // This should have no effect
  211. globalVS2.NewChild("sink: 2") // Reference is provided in the next call
  212. sinkVs2 := globalVS1.NewChild("sink: 2")
  213. for1Vs := sinkVs1.NewChild("block: for1")
  214. for2Vs := sinkVs1.NewChild("block: for2")
  215. for21Vs := for2Vs.NewChild("block: for2-1")
  216. for211Vs := for21Vs.NewChild("block: for2-1-1")
  217. // Populate tree
  218. globalVS1.SetValue("0", 0)
  219. globalVS2.SetValue("a", 1)
  220. globalVS3.SetValue("a", 2)
  221. sinkVs1.SetValue("b", 2)
  222. for1Vs.SetValue("c", 3)
  223. for2Vs.SetValue("d", 4)
  224. for21Vs.SetValue("e", 5)
  225. for211Vs.SetValue("f", 6)
  226. sinkVs2.SetValue("g", 2)
  227. // Dump the sinkVs1 scope
  228. if res := sinkVs1.String(); res != `global {
  229. 0 (int) : 0
  230. global2 {
  231. a (int) : 1
  232. sink: 1 {
  233. b (int) : 2
  234. block: for1 {
  235. c (int) : 3
  236. }
  237. block: for2 {
  238. d (int) : 4
  239. block: for2-1 {
  240. e (int) : 5
  241. block: for2-1-1 {
  242. f (int) : 6
  243. }
  244. }
  245. }
  246. }
  247. }
  248. }` {
  249. t.Error("Unexpected result:", res)
  250. return
  251. }
  252. bytes, _ := json.Marshal(sinkVs1.ToJSONObject())
  253. if res := string(bytes); res != `{"b":2}` {
  254. t.Error("Unexpected result:", res)
  255. return
  256. }
  257. if res := sinkVs2.String(); res != `global {
  258. 0 (int) : 0
  259. sink: 2 {
  260. g (int) : 2
  261. }
  262. }` {
  263. t.Error("Unexpected result:", res)
  264. return
  265. }
  266. // Dumping the global scope results in the same output as it does not
  267. // track child scopes
  268. if res := globalVS1.String(); res != `global {
  269. 0 (int) : 0
  270. sink: 2 {
  271. g (int) : 2
  272. }
  273. }` {
  274. t.Error("Unexpected result:", res)
  275. return
  276. }
  277. }