varsscope_test.go 9.1 KB

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