varsscope_test.go 8.3 KB

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