varsscope_test.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  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. for211Vs.SetValue("x", ToObject(for211Vs))
  227. sinkVs2.SetValue("g", 2)
  228. // Dump the sinkVs1 scope
  229. if res := sinkVs1.String(); res != `global {
  230. 0 (int) : 0
  231. global2 {
  232. a (int) : 1
  233. sink: 1 {
  234. b (int) : 2
  235. block: for1 {
  236. c (int) : 3
  237. }
  238. block: for2 {
  239. d (int) : 4
  240. block: for2-1 {
  241. e (int) : 5
  242. block: for2-1-1 {
  243. f (int) : 6
  244. x (map[interface {}]interface {}) : {"f":6}
  245. }
  246. }
  247. }
  248. }
  249. }
  250. }` {
  251. t.Error("Unexpected result:", res)
  252. return
  253. }
  254. bytes, _ := json.Marshal(sinkVs1.ToJSONObject())
  255. if res := string(bytes); res != `{"b":2}` {
  256. t.Error("Unexpected result:", res)
  257. return
  258. }
  259. bytes, _ = json.Marshal(for211Vs.ToJSONObject())
  260. if res := string(bytes); res != `{"f":6,"x":{"f":6}}` {
  261. t.Error("Unexpected result:", res)
  262. return
  263. }
  264. if res := globalVS1.Name(); res != "global" {
  265. t.Error("Unexpected result:", res)
  266. return
  267. }
  268. if res := sinkVs2.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. // Dumping the global scope results in the same output as it does not
  278. // track child scopes
  279. if res := globalVS1.String(); res != `global {
  280. 0 (int) : 0
  281. sink: 2 {
  282. g (int) : 2
  283. }
  284. }` {
  285. t.Error("Unexpected result:", res)
  286. return
  287. }
  288. sinkVs1.Clear()
  289. if res := sinkVs1.String(); res != `global {
  290. 0 (int) : 0
  291. global2 {
  292. a (int) : 1
  293. sink: 1 {
  294. }
  295. }
  296. }` {
  297. t.Error("Unexpected result:", res)
  298. return
  299. }
  300. }